mirror of https://github.com/opencv/opencv.git
Merge pull request #10789 from mshabunin:split-matrix
commit
292dfc2d72
11 changed files with 5136 additions and 5211 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,384 @@ |
||||
#include "opencv2/core/mat.hpp" |
||||
#include "opencv2/core/types_c.h" |
||||
#include "precomp.hpp" |
||||
|
||||
// glue
|
||||
|
||||
CvMatND::CvMatND(const cv::Mat& m) |
||||
{ |
||||
cvInitMatNDHeader(this, m.dims, m.size, m.type(), m.data ); |
||||
int i, d = m.dims; |
||||
for( i = 0; i < d; i++ ) |
||||
dim[i].step = (int)m.step[i]; |
||||
type |= m.flags & cv::Mat::CONTINUOUS_FLAG; |
||||
} |
||||
|
||||
_IplImage::_IplImage(const cv::Mat& m) |
||||
{ |
||||
CV_Assert( m.dims <= 2 ); |
||||
cvInitImageHeader(this, m.size(), cvIplDepth(m.flags), m.channels()); |
||||
cvSetData(this, m.data, (int)m.step[0]); |
||||
} |
||||
|
||||
namespace cv { |
||||
|
||||
static Mat cvMatToMat(const CvMat* m, bool copyData) |
||||
{ |
||||
Mat thiz; |
||||
|
||||
if( !m ) |
||||
return thiz; |
||||
|
||||
if( !copyData ) |
||||
{ |
||||
thiz.flags = Mat::MAGIC_VAL + (m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG)); |
||||
thiz.dims = 2; |
||||
thiz.rows = m->rows; |
||||
thiz.cols = m->cols; |
||||
thiz.datastart = thiz.data = m->data.ptr; |
||||
size_t esz = CV_ELEM_SIZE(m->type), minstep = thiz.cols*esz, _step = m->step; |
||||
if( _step == 0 ) |
||||
_step = minstep; |
||||
thiz.datalimit = thiz.datastart + _step*thiz.rows; |
||||
thiz.dataend = thiz.datalimit - _step + minstep; |
||||
thiz.step[0] = _step; thiz.step[1] = esz; |
||||
} |
||||
else |
||||
{ |
||||
thiz.datastart = thiz.dataend = thiz.data = 0; |
||||
Mat(m->rows, m->cols, m->type, m->data.ptr, m->step).copyTo(thiz); |
||||
} |
||||
|
||||
return thiz; |
||||
} |
||||
|
||||
static Mat cvMatNDToMat(const CvMatND* m, bool copyData) |
||||
{ |
||||
Mat thiz; |
||||
|
||||
if( !m ) |
||||
return thiz; |
||||
thiz.datastart = thiz.data = m->data.ptr; |
||||
thiz.flags |= CV_MAT_TYPE(m->type); |
||||
int _sizes[CV_MAX_DIM]; |
||||
size_t _steps[CV_MAX_DIM]; |
||||
|
||||
int d = m->dims; |
||||
for( int i = 0; i < d; i++ ) |
||||
{ |
||||
_sizes[i] = m->dim[i].size; |
||||
_steps[i] = m->dim[i].step; |
||||
} |
||||
|
||||
setSize(thiz, d, _sizes, _steps); |
||||
finalizeHdr(thiz); |
||||
|
||||
if( copyData ) |
||||
{ |
||||
Mat temp(thiz); |
||||
thiz.release(); |
||||
temp.copyTo(thiz); |
||||
} |
||||
|
||||
return thiz; |
||||
} |
||||
|
||||
static Mat iplImageToMat(const IplImage* img, bool copyData) |
||||
{ |
||||
Mat m; |
||||
|
||||
if( !img ) |
||||
return m; |
||||
|
||||
m.dims = 2; |
||||
CV_DbgAssert(CV_IS_IMAGE(img) && img->imageData != 0); |
||||
|
||||
int imgdepth = IPL2CV_DEPTH(img->depth); |
||||
size_t esz; |
||||
m.step[0] = img->widthStep; |
||||
|
||||
if(!img->roi) |
||||
{ |
||||
CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL); |
||||
m.flags = Mat::MAGIC_VAL + CV_MAKETYPE(imgdepth, img->nChannels); |
||||
m.rows = img->height; |
||||
m.cols = img->width; |
||||
m.datastart = m.data = (uchar*)img->imageData; |
||||
esz = CV_ELEM_SIZE(m.flags); |
||||
} |
||||
else |
||||
{ |
||||
CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL || img->roi->coi != 0); |
||||
bool selectedPlane = img->roi->coi && img->dataOrder == IPL_DATA_ORDER_PLANE; |
||||
m.flags = Mat::MAGIC_VAL + CV_MAKETYPE(imgdepth, selectedPlane ? 1 : img->nChannels); |
||||
m.rows = img->roi->height; |
||||
m.cols = img->roi->width; |
||||
esz = CV_ELEM_SIZE(m.flags); |
||||
m.datastart = m.data = (uchar*)img->imageData + |
||||
(selectedPlane ? (img->roi->coi - 1)*m.step*img->height : 0) + |
||||
img->roi->yOffset*m.step[0] + img->roi->xOffset*esz; |
||||
} |
||||
m.datalimit = m.datastart + m.step.p[0]*m.rows; |
||||
m.dataend = m.datastart + m.step.p[0]*(m.rows-1) + esz*m.cols; |
||||
m.flags |= (m.cols*esz == m.step.p[0] || m.rows == 1 ? Mat::CONTINUOUS_FLAG : 0); |
||||
m.step[1] = esz; |
||||
|
||||
if( copyData ) |
||||
{ |
||||
Mat m2 = m; |
||||
m.release(); |
||||
if( !img->roi || !img->roi->coi || |
||||
img->dataOrder == IPL_DATA_ORDER_PLANE) |
||||
m2.copyTo(m); |
||||
else |
||||
{ |
||||
int ch[] = {img->roi->coi - 1, 0}; |
||||
m.create(m2.rows, m2.cols, m2.type()); |
||||
mixChannels(&m2, 1, &m, 1, ch, 1); |
||||
} |
||||
} |
||||
|
||||
return m; |
||||
} |
||||
|
||||
Mat cvarrToMat(const CvArr* arr, bool copyData, |
||||
bool /*allowND*/, int coiMode, AutoBuffer<double>* abuf ) |
||||
{ |
||||
if( !arr ) |
||||
return Mat(); |
||||
if( CV_IS_MAT_HDR_Z(arr) ) |
||||
return cvMatToMat((const CvMat*)arr, copyData); |
||||
if( CV_IS_MATND(arr) ) |
||||
return cvMatNDToMat((const CvMatND*)arr, copyData ); |
||||
if( CV_IS_IMAGE(arr) ) |
||||
{ |
||||
const IplImage* iplimg = (const IplImage*)arr; |
||||
if( coiMode == 0 && iplimg->roi && iplimg->roi->coi > 0 ) |
||||
CV_Error(CV_BadCOI, "COI is not supported by the function"); |
||||
return iplImageToMat(iplimg, copyData); |
||||
} |
||||
if( CV_IS_SEQ(arr) ) |
||||
{ |
||||
CvSeq* seq = (CvSeq*)arr; |
||||
int total = seq->total, type = CV_MAT_TYPE(seq->flags), esz = seq->elem_size; |
||||
if( total == 0 ) |
||||
return Mat(); |
||||
CV_Assert(total > 0 && CV_ELEM_SIZE(seq->flags) == esz); |
||||
if(!copyData && seq->first->next == seq->first) |
||||
return Mat(total, 1, type, seq->first->data); |
||||
if( abuf ) |
||||
{ |
||||
abuf->allocate(((size_t)total*esz + sizeof(double)-1)/sizeof(double)); |
||||
double* bufdata = *abuf; |
||||
cvCvtSeqToArray(seq, bufdata, CV_WHOLE_SEQ); |
||||
return Mat(total, 1, type, bufdata); |
||||
} |
||||
|
||||
Mat buf(total, 1, type); |
||||
cvCvtSeqToArray(seq, buf.ptr(), CV_WHOLE_SEQ); |
||||
return buf; |
||||
} |
||||
CV_Error(CV_StsBadArg, "Unknown array type"); |
||||
return Mat(); |
||||
} |
||||
|
||||
void extractImageCOI(const CvArr* arr, OutputArray _ch, int coi) |
||||
{ |
||||
Mat mat = cvarrToMat(arr, false, true, 1); |
||||
_ch.create(mat.dims, mat.size, mat.depth()); |
||||
Mat ch = _ch.getMat(); |
||||
if(coi < 0) |
||||
{ |
||||
CV_Assert( CV_IS_IMAGE(arr) ); |
||||
coi = cvGetImageCOI((const IplImage*)arr)-1; |
||||
} |
||||
CV_Assert(0 <= coi && coi < mat.channels()); |
||||
int _pairs[] = { coi, 0 }; |
||||
mixChannels( &mat, 1, &ch, 1, _pairs, 1 ); |
||||
} |
||||
|
||||
void insertImageCOI(InputArray _ch, CvArr* arr, int coi) |
||||
{ |
||||
Mat ch = _ch.getMat(), mat = cvarrToMat(arr, false, true, 1); |
||||
if(coi < 0) |
||||
{ |
||||
CV_Assert( CV_IS_IMAGE(arr) ); |
||||
coi = cvGetImageCOI((const IplImage*)arr)-1; |
||||
} |
||||
CV_Assert(ch.size == mat.size && ch.depth() == mat.depth() && 0 <= coi && coi < mat.channels()); |
||||
int _pairs[] = { 0, coi }; |
||||
mixChannels( &ch, 1, &mat, 1, _pairs, 1 ); |
||||
} |
||||
|
||||
} // cv::
|
||||
|
||||
// operations
|
||||
|
||||
CV_IMPL void cvSetIdentity( CvArr* arr, CvScalar value ) |
||||
{ |
||||
cv::Mat m = cv::cvarrToMat(arr); |
||||
cv::setIdentity(m, value); |
||||
} |
||||
|
||||
|
||||
CV_IMPL CvScalar cvTrace( const CvArr* arr ) |
||||
{ |
||||
return cv::trace(cv::cvarrToMat(arr)); |
||||
} |
||||
|
||||
|
||||
CV_IMPL void cvTranspose( const CvArr* srcarr, CvArr* dstarr ) |
||||
{ |
||||
cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr); |
||||
|
||||
CV_Assert( src.rows == dst.cols && src.cols == dst.rows && src.type() == dst.type() ); |
||||
transpose( src, dst ); |
||||
} |
||||
|
||||
|
||||
CV_IMPL void cvCompleteSymm( CvMat* matrix, int LtoR ) |
||||
{ |
||||
cv::Mat m = cv::cvarrToMat(matrix); |
||||
cv::completeSymm( m, LtoR != 0 ); |
||||
} |
||||
|
||||
|
||||
CV_IMPL void cvCrossProduct( const CvArr* srcAarr, const CvArr* srcBarr, CvArr* dstarr ) |
||||
{ |
||||
cv::Mat srcA = cv::cvarrToMat(srcAarr), dst = cv::cvarrToMat(dstarr); |
||||
|
||||
CV_Assert( srcA.size() == dst.size() && srcA.type() == dst.type() ); |
||||
srcA.cross(cv::cvarrToMat(srcBarr)).copyTo(dst); |
||||
} |
||||
|
||||
|
||||
CV_IMPL void |
||||
cvReduce( const CvArr* srcarr, CvArr* dstarr, int dim, int op ) |
||||
{ |
||||
cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr); |
||||
|
||||
if( dim < 0 ) |
||||
dim = src.rows > dst.rows ? 0 : src.cols > dst.cols ? 1 : dst.cols == 1; |
||||
|
||||
if( dim > 1 ) |
||||
CV_Error( CV_StsOutOfRange, "The reduced dimensionality index is out of range" ); |
||||
|
||||
if( (dim == 0 && (dst.cols != src.cols || dst.rows != 1)) || |
||||
(dim == 1 && (dst.rows != src.rows || dst.cols != 1)) ) |
||||
CV_Error( CV_StsBadSize, "The output array size is incorrect" ); |
||||
|
||||
if( src.channels() != dst.channels() ) |
||||
CV_Error( CV_StsUnmatchedFormats, "Input and output arrays must have the same number of channels" ); |
||||
|
||||
cv::reduce(src, dst, dim, op, dst.type()); |
||||
} |
||||
|
||||
|
||||
CV_IMPL CvArr* |
||||
cvRange( CvArr* arr, double start, double end ) |
||||
{ |
||||
CvMat stub, *mat = (CvMat*)arr; |
||||
int step; |
||||
double val = start; |
||||
|
||||
if( !CV_IS_MAT(mat) ) |
||||
mat = cvGetMat( mat, &stub); |
||||
|
||||
int rows = mat->rows; |
||||
int cols = mat->cols; |
||||
int type = CV_MAT_TYPE(mat->type); |
||||
double delta = (end-start)/(rows*cols); |
||||
|
||||
if( CV_IS_MAT_CONT(mat->type) ) |
||||
{ |
||||
cols *= rows; |
||||
rows = 1; |
||||
step = 1; |
||||
} |
||||
else |
||||
step = mat->step / CV_ELEM_SIZE(type); |
||||
|
||||
if( type == CV_32SC1 ) |
||||
{ |
||||
int* idata = mat->data.i; |
||||
int ival = cvRound(val), idelta = cvRound(delta); |
||||
|
||||
if( fabs(val - ival) < DBL_EPSILON && |
||||
fabs(delta - idelta) < DBL_EPSILON ) |
||||
{ |
||||
for( int i = 0; i < rows; i++, idata += step ) |
||||
for( int j = 0; j < cols; j++, ival += idelta ) |
||||
idata[j] = ival; |
||||
} |
||||
else |
||||
{ |
||||
for( int i = 0; i < rows; i++, idata += step ) |
||||
for( int j = 0; j < cols; j++, val += delta ) |
||||
idata[j] = cvRound(val); |
||||
} |
||||
} |
||||
else if( type == CV_32FC1 ) |
||||
{ |
||||
float* fdata = mat->data.fl; |
||||
for( int i = 0; i < rows; i++, fdata += step ) |
||||
for( int j = 0; j < cols; j++, val += delta ) |
||||
fdata[j] = (float)val; |
||||
} |
||||
else |
||||
CV_Error( CV_StsUnsupportedFormat, "The function only supports 32sC1 and 32fC1 datatypes" ); |
||||
|
||||
return arr; |
||||
} |
||||
|
||||
|
||||
CV_IMPL void |
||||
cvSort( const CvArr* _src, CvArr* _dst, CvArr* _idx, int flags ) |
||||
{ |
||||
cv::Mat src = cv::cvarrToMat(_src); |
||||
|
||||
if( _idx ) |
||||
{ |
||||
cv::Mat idx0 = cv::cvarrToMat(_idx), idx = idx0; |
||||
CV_Assert( src.size() == idx.size() && idx.type() == CV_32S && src.data != idx.data ); |
||||
cv::sortIdx( src, idx, flags ); |
||||
CV_Assert( idx0.data == idx.data ); |
||||
} |
||||
|
||||
if( _dst ) |
||||
{ |
||||
cv::Mat dst0 = cv::cvarrToMat(_dst), dst = dst0; |
||||
CV_Assert( src.size() == dst.size() && src.type() == dst.type() ); |
||||
cv::sort( src, dst, flags ); |
||||
CV_Assert( dst0.data == dst.data ); |
||||
} |
||||
} |
||||
|
||||
|
||||
CV_IMPL int |
||||
cvKMeans2( const CvArr* _samples, int cluster_count, CvArr* _labels, |
||||
CvTermCriteria termcrit, int attempts, CvRNG*, |
||||
int flags, CvArr* _centers, double* _compactness ) |
||||
{ |
||||
cv::Mat data = cv::cvarrToMat(_samples), labels = cv::cvarrToMat(_labels), centers; |
||||
if( _centers ) |
||||
{ |
||||
centers = cv::cvarrToMat(_centers); |
||||
|
||||
centers = centers.reshape(1); |
||||
data = data.reshape(1); |
||||
|
||||
CV_Assert( !centers.empty() ); |
||||
CV_Assert( centers.rows == cluster_count ); |
||||
CV_Assert( centers.cols == data.cols ); |
||||
CV_Assert( centers.depth() == data.depth() ); |
||||
} |
||||
CV_Assert( labels.isContinuous() && labels.type() == CV_32S && |
||||
(labels.cols == 1 || labels.rows == 1) && |
||||
labels.cols + labels.rows - 1 == data.rows ); |
||||
|
||||
double compactness = cv::kmeans(data, cluster_count, labels, termcrit, attempts, |
||||
flags, _centers ? cv::_OutputArray(centers) : cv::_OutputArray() ); |
||||
if( _compactness ) |
||||
*_compactness = compactness; |
||||
return 1; |
||||
} |
@ -0,0 +1,358 @@ |
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
|
||||
|
||||
#include "opencv2/core/mat.hpp" |
||||
#include "precomp.hpp" |
||||
|
||||
namespace cv { |
||||
|
||||
NAryMatIterator::NAryMatIterator() |
||||
: arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0) |
||||
{ |
||||
} |
||||
|
||||
NAryMatIterator::NAryMatIterator(const Mat** _arrays, Mat* _planes, int _narrays) |
||||
: arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0) |
||||
{ |
||||
init(_arrays, _planes, 0, _narrays); |
||||
} |
||||
|
||||
NAryMatIterator::NAryMatIterator(const Mat** _arrays, uchar** _ptrs, int _narrays) |
||||
: arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0) |
||||
{ |
||||
init(_arrays, 0, _ptrs, _narrays); |
||||
} |
||||
|
||||
void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, uchar** _ptrs, int _narrays) |
||||
{ |
||||
CV_Assert( _arrays && (_ptrs || _planes) ); |
||||
int i, j, d1=0, i0 = -1, d = -1; |
||||
|
||||
arrays = _arrays; |
||||
ptrs = _ptrs; |
||||
planes = _planes; |
||||
narrays = _narrays; |
||||
nplanes = 0; |
||||
size = 0; |
||||
|
||||
if( narrays < 0 ) |
||||
{ |
||||
for( i = 0; _arrays[i] != 0; i++ ) |
||||
; |
||||
narrays = i; |
||||
CV_Assert(narrays <= 1000); |
||||
} |
||||
|
||||
iterdepth = 0; |
||||
|
||||
for( i = 0; i < narrays; i++ ) |
||||
{ |
||||
CV_Assert(arrays[i] != 0); |
||||
const Mat& A = *arrays[i]; |
||||
if( ptrs ) |
||||
ptrs[i] = A.data; |
||||
|
||||
if( !A.data ) |
||||
continue; |
||||
|
||||
if( i0 < 0 ) |
||||
{ |
||||
i0 = i; |
||||
d = A.dims; |
||||
|
||||
// find the first dimensionality which is different from 1;
|
||||
// in any of the arrays the first "d1" step do not affect the continuity
|
||||
for( d1 = 0; d1 < d; d1++ ) |
||||
if( A.size[d1] > 1 ) |
||||
break; |
||||
} |
||||
else |
||||
CV_Assert( A.size == arrays[i0]->size ); |
||||
|
||||
if( !A.isContinuous() ) |
||||
{ |
||||
CV_Assert( A.step[d-1] == A.elemSize() ); |
||||
for( j = d-1; j > d1; j-- ) |
||||
if( A.step[j]*A.size[j] < A.step[j-1] ) |
||||
break; |
||||
iterdepth = std::max(iterdepth, j); |
||||
} |
||||
} |
||||
|
||||
if( i0 >= 0 ) |
||||
{ |
||||
size = arrays[i0]->size[d-1]; |
||||
for( j = d-1; j > iterdepth; j-- ) |
||||
{ |
||||
int64 total1 = (int64)size*arrays[i0]->size[j-1]; |
||||
if( total1 != (int)total1 ) |
||||
break; |
||||
size = (int)total1; |
||||
} |
||||
|
||||
iterdepth = j; |
||||
if( iterdepth == d1 ) |
||||
iterdepth = 0; |
||||
|
||||
nplanes = 1; |
||||
for( j = iterdepth-1; j >= 0; j-- ) |
||||
nplanes *= arrays[i0]->size[j]; |
||||
} |
||||
else |
||||
iterdepth = 0; |
||||
|
||||
idx = 0; |
||||
|
||||
if( !planes ) |
||||
return; |
||||
|
||||
for( i = 0; i < narrays; i++ ) |
||||
{ |
||||
CV_Assert(arrays[i] != 0); |
||||
const Mat& A = *arrays[i]; |
||||
|
||||
if( !A.data ) |
||||
{ |
||||
planes[i] = Mat(); |
||||
continue; |
||||
} |
||||
|
||||
planes[i] = Mat(1, (int)size, A.type(), A.data); |
||||
} |
||||
} |
||||
|
||||
|
||||
NAryMatIterator& NAryMatIterator::operator ++() |
||||
{ |
||||
if( idx >= nplanes-1 ) |
||||
return *this; |
||||
++idx; |
||||
|
||||
if( iterdepth == 1 ) |
||||
{ |
||||
if( ptrs ) |
||||
{ |
||||
for( int i = 0; i < narrays; i++ ) |
||||
{ |
||||
if( !ptrs[i] ) |
||||
continue; |
||||
ptrs[i] = arrays[i]->data + arrays[i]->step[0]*idx; |
||||
} |
||||
} |
||||
if( planes ) |
||||
{ |
||||
for( int i = 0; i < narrays; i++ ) |
||||
{ |
||||
if( !planes[i].data ) |
||||
continue; |
||||
planes[i].data = arrays[i]->data + arrays[i]->step[0]*idx; |
||||
} |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
for( int i = 0; i < narrays; i++ ) |
||||
{ |
||||
const Mat& A = *arrays[i]; |
||||
if( !A.data ) |
||||
continue; |
||||
int _idx = (int)idx; |
||||
uchar* data = A.data; |
||||
for( int j = iterdepth-1; j >= 0 && _idx > 0; j-- ) |
||||
{ |
||||
int szi = A.size[j], t = _idx/szi; |
||||
data += (_idx - t * szi)*A.step[j]; |
||||
_idx = t; |
||||
} |
||||
if( ptrs ) |
||||
ptrs[i] = data; |
||||
if( planes ) |
||||
planes[i].data = data; |
||||
} |
||||
} |
||||
|
||||
return *this; |
||||
} |
||||
|
||||
NAryMatIterator NAryMatIterator::operator ++(int) |
||||
{ |
||||
NAryMatIterator it = *this; |
||||
++*this; |
||||
return it; |
||||
} |
||||
|
||||
//==================================================================================================
|
||||
|
||||
Point MatConstIterator::pos() const |
||||
{ |
||||
if( !m ) |
||||
return Point(); |
||||
CV_DbgAssert(m->dims <= 2); |
||||
|
||||
ptrdiff_t ofs = ptr - m->ptr(); |
||||
int y = (int)(ofs/m->step[0]); |
||||
return Point((int)((ofs - y*m->step[0])/elemSize), y); |
||||
} |
||||
|
||||
void MatConstIterator::pos(int* _idx) const |
||||
{ |
||||
CV_Assert(m != 0 && _idx); |
||||
ptrdiff_t ofs = ptr - m->ptr(); |
||||
for( int i = 0; i < m->dims; i++ ) |
||||
{ |
||||
size_t s = m->step[i], v = ofs/s; |
||||
ofs -= v*s; |
||||
_idx[i] = (int)v; |
||||
} |
||||
} |
||||
|
||||
ptrdiff_t MatConstIterator::lpos() const |
||||
{ |
||||
if(!m) |
||||
return 0; |
||||
if( m->isContinuous() ) |
||||
return (ptr - sliceStart)/elemSize; |
||||
ptrdiff_t ofs = ptr - m->ptr(); |
||||
int i, d = m->dims; |
||||
if( d == 2 ) |
||||
{ |
||||
ptrdiff_t y = ofs/m->step[0]; |
||||
return y*m->cols + (ofs - y*m->step[0])/elemSize; |
||||
} |
||||
ptrdiff_t result = 0; |
||||
for( i = 0; i < d; i++ ) |
||||
{ |
||||
size_t s = m->step[i], v = ofs/s; |
||||
ofs -= v*s; |
||||
result = result*m->size[i] + v; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
void MatConstIterator::seek(ptrdiff_t ofs, bool relative) |
||||
{ |
||||
if( m->isContinuous() ) |
||||
{ |
||||
ptr = (relative ? ptr : sliceStart) + ofs*elemSize; |
||||
if( ptr < sliceStart ) |
||||
ptr = sliceStart; |
||||
else if( ptr > sliceEnd ) |
||||
ptr = sliceEnd; |
||||
return; |
||||
} |
||||
|
||||
int d = m->dims; |
||||
if( d == 2 ) |
||||
{ |
||||
ptrdiff_t ofs0, y; |
||||
if( relative ) |
||||
{ |
||||
ofs0 = ptr - m->ptr(); |
||||
y = ofs0/m->step[0]; |
||||
ofs += y*m->cols + (ofs0 - y*m->step[0])/elemSize; |
||||
} |
||||
y = ofs/m->cols; |
||||
int y1 = std::min(std::max((int)y, 0), m->rows-1); |
||||
sliceStart = m->ptr(y1); |
||||
sliceEnd = sliceStart + m->cols*elemSize; |
||||
ptr = y < 0 ? sliceStart : y >= m->rows ? sliceEnd : |
||||
sliceStart + (ofs - y*m->cols)*elemSize; |
||||
return; |
||||
} |
||||
|
||||
if( relative ) |
||||
ofs += lpos(); |
||||
|
||||
if( ofs < 0 ) |
||||
ofs = 0; |
||||
|
||||
int szi = m->size[d-1]; |
||||
ptrdiff_t t = ofs/szi; |
||||
int v = (int)(ofs - t*szi); |
||||
ofs = t; |
||||
ptr = m->ptr() + v*elemSize; |
||||
sliceStart = m->ptr(); |
||||
|
||||
for( int i = d-2; i >= 0; i-- ) |
||||
{ |
||||
szi = m->size[i]; |
||||
t = ofs/szi; |
||||
v = (int)(ofs - t*szi); |
||||
ofs = t; |
||||
sliceStart += v*m->step[i]; |
||||
} |
||||
|
||||
sliceEnd = sliceStart + m->size[d-1]*elemSize; |
||||
if( ofs > 0 ) |
||||
ptr = sliceEnd; |
||||
else |
||||
ptr = sliceStart + (ptr - m->ptr()); |
||||
} |
||||
|
||||
void MatConstIterator::seek(const int* _idx, bool relative) |
||||
{ |
||||
int d = m->dims; |
||||
ptrdiff_t ofs = 0; |
||||
if( !_idx ) |
||||
; |
||||
else if( d == 2 ) |
||||
ofs = _idx[0]*m->size[1] + _idx[1]; |
||||
else |
||||
{ |
||||
for( int i = 0; i < d; i++ ) |
||||
ofs = ofs*m->size[i] + _idx[i]; |
||||
} |
||||
seek(ofs, relative); |
||||
} |
||||
|
||||
//==================================================================================================
|
||||
|
||||
SparseMatConstIterator::SparseMatConstIterator(const SparseMat* _m) : m((SparseMat*)_m), hashidx(0), ptr(0) |
||||
{ |
||||
if(!_m || !_m->hdr) |
||||
return; |
||||
SparseMat::Hdr& hdr = *m->hdr; |
||||
const std::vector<size_t>& htab = hdr.hashtab; |
||||
size_t i, hsize = htab.size(); |
||||
for( i = 0; i < hsize; i++ ) |
||||
{ |
||||
size_t nidx = htab[i]; |
||||
if( nidx ) |
||||
{ |
||||
hashidx = i; |
||||
ptr = &hdr.pool[nidx] + hdr.valueOffset; |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
|
||||
SparseMatConstIterator& SparseMatConstIterator::operator ++() |
||||
{ |
||||
if( !ptr || !m || !m->hdr ) |
||||
return *this; |
||||
SparseMat::Hdr& hdr = *m->hdr; |
||||
size_t next = ((const SparseMat::Node*)(ptr - hdr.valueOffset))->next; |
||||
if( next ) |
||||
{ |
||||
ptr = &hdr.pool[next] + hdr.valueOffset; |
||||
return *this; |
||||
} |
||||
size_t i = hashidx + 1, sz = hdr.hashtab.size(); |
||||
for( ; i < sz; i++ ) |
||||
{ |
||||
size_t nidx = hdr.hashtab[i]; |
||||
if( nidx ) |
||||
{ |
||||
hashidx = i; |
||||
ptr = &hdr.pool[nidx] + hdr.valueOffset; |
||||
return *this; |
||||
} |
||||
} |
||||
hashidx = sz; |
||||
ptr = 0; |
||||
return *this; |
||||
} |
||||
|
||||
} // cv::
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,802 @@ |
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
|
||||
|
||||
#include "opencv2/core/mat.hpp" |
||||
#include "opencv2/core/types_c.h" |
||||
#include "precomp.hpp" |
||||
|
||||
namespace cv { |
||||
|
||||
template<typename T1, typename T2> void |
||||
convertData_(const void* _from, void* _to, int cn) |
||||
{ |
||||
const T1* from = (const T1*)_from; |
||||
T2* to = (T2*)_to; |
||||
if( cn == 1 ) |
||||
*to = saturate_cast<T2>(*from); |
||||
else |
||||
for( int i = 0; i < cn; i++ ) |
||||
to[i] = saturate_cast<T2>(from[i]); |
||||
} |
||||
|
||||
template<typename T1, typename T2> void |
||||
convertScaleData_(const void* _from, void* _to, int cn, double alpha, double beta) |
||||
{ |
||||
const T1* from = (const T1*)_from; |
||||
T2* to = (T2*)_to; |
||||
if( cn == 1 ) |
||||
*to = saturate_cast<T2>(*from*alpha + beta); |
||||
else |
||||
for( int i = 0; i < cn; i++ ) |
||||
to[i] = saturate_cast<T2>(from[i]*alpha + beta); |
||||
} |
||||
|
||||
typedef void (*ConvertData)(const void* from, void* to, int cn); |
||||
typedef void (*ConvertScaleData)(const void* from, void* to, int cn, double alpha, double beta); |
||||
|
||||
static ConvertData getConvertElem(int fromType, int toType) |
||||
{ |
||||
static ConvertData tab[][8] = |
||||
{{ convertData_<uchar, uchar>, convertData_<uchar, schar>, |
||||
convertData_<uchar, ushort>, convertData_<uchar, short>, |
||||
convertData_<uchar, int>, convertData_<uchar, float>, |
||||
convertData_<uchar, double>, 0 }, |
||||
|
||||
{ convertData_<schar, uchar>, convertData_<schar, schar>, |
||||
convertData_<schar, ushort>, convertData_<schar, short>, |
||||
convertData_<schar, int>, convertData_<schar, float>, |
||||
convertData_<schar, double>, 0 }, |
||||
|
||||
{ convertData_<ushort, uchar>, convertData_<ushort, schar>, |
||||
convertData_<ushort, ushort>, convertData_<ushort, short>, |
||||
convertData_<ushort, int>, convertData_<ushort, float>, |
||||
convertData_<ushort, double>, 0 }, |
||||
|
||||
{ convertData_<short, uchar>, convertData_<short, schar>, |
||||
convertData_<short, ushort>, convertData_<short, short>, |
||||
convertData_<short, int>, convertData_<short, float>, |
||||
convertData_<short, double>, 0 }, |
||||
|
||||
{ convertData_<int, uchar>, convertData_<int, schar>, |
||||
convertData_<int, ushort>, convertData_<int, short>, |
||||
convertData_<int, int>, convertData_<int, float>, |
||||
convertData_<int, double>, 0 }, |
||||
|
||||
{ convertData_<float, uchar>, convertData_<float, schar>, |
||||
convertData_<float, ushort>, convertData_<float, short>, |
||||
convertData_<float, int>, convertData_<float, float>, |
||||
convertData_<float, double>, 0 }, |
||||
|
||||
{ convertData_<double, uchar>, convertData_<double, schar>, |
||||
convertData_<double, ushort>, convertData_<double, short>, |
||||
convertData_<double, int>, convertData_<double, float>, |
||||
convertData_<double, double>, 0 }, |
||||
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0 }}; |
||||
|
||||
ConvertData func = tab[CV_MAT_DEPTH(fromType)][CV_MAT_DEPTH(toType)]; |
||||
CV_Assert( func != 0 ); |
||||
return func; |
||||
} |
||||
|
||||
static ConvertScaleData getConvertScaleElem(int fromType, int toType) |
||||
{ |
||||
static ConvertScaleData tab[][8] = |
||||
{{ convertScaleData_<uchar, uchar>, convertScaleData_<uchar, schar>, |
||||
convertScaleData_<uchar, ushort>, convertScaleData_<uchar, short>, |
||||
convertScaleData_<uchar, int>, convertScaleData_<uchar, float>, |
||||
convertScaleData_<uchar, double>, 0 }, |
||||
|
||||
{ convertScaleData_<schar, uchar>, convertScaleData_<schar, schar>, |
||||
convertScaleData_<schar, ushort>, convertScaleData_<schar, short>, |
||||
convertScaleData_<schar, int>, convertScaleData_<schar, float>, |
||||
convertScaleData_<schar, double>, 0 }, |
||||
|
||||
{ convertScaleData_<ushort, uchar>, convertScaleData_<ushort, schar>, |
||||
convertScaleData_<ushort, ushort>, convertScaleData_<ushort, short>, |
||||
convertScaleData_<ushort, int>, convertScaleData_<ushort, float>, |
||||
convertScaleData_<ushort, double>, 0 }, |
||||
|
||||
{ convertScaleData_<short, uchar>, convertScaleData_<short, schar>, |
||||
convertScaleData_<short, ushort>, convertScaleData_<short, short>, |
||||
convertScaleData_<short, int>, convertScaleData_<short, float>, |
||||
convertScaleData_<short, double>, 0 }, |
||||
|
||||
{ convertScaleData_<int, uchar>, convertScaleData_<int, schar>, |
||||
convertScaleData_<int, ushort>, convertScaleData_<int, short>, |
||||
convertScaleData_<int, int>, convertScaleData_<int, float>, |
||||
convertScaleData_<int, double>, 0 }, |
||||
|
||||
{ convertScaleData_<float, uchar>, convertScaleData_<float, schar>, |
||||
convertScaleData_<float, ushort>, convertScaleData_<float, short>, |
||||
convertScaleData_<float, int>, convertScaleData_<float, float>, |
||||
convertScaleData_<float, double>, 0 }, |
||||
|
||||
{ convertScaleData_<double, uchar>, convertScaleData_<double, schar>, |
||||
convertScaleData_<double, ushort>, convertScaleData_<double, short>, |
||||
convertScaleData_<double, int>, convertScaleData_<double, float>, |
||||
convertScaleData_<double, double>, 0 }, |
||||
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0 }}; |
||||
|
||||
ConvertScaleData func = tab[CV_MAT_DEPTH(fromType)][CV_MAT_DEPTH(toType)]; |
||||
CV_Assert( func != 0 ); |
||||
return func; |
||||
} |
||||
|
||||
enum { HASH_SIZE0 = 8 }; |
||||
|
||||
static inline void copyElem(const uchar* from, uchar* to, size_t elemSize) |
||||
{ |
||||
size_t i; |
||||
for( i = 0; i + sizeof(int) <= elemSize; i += sizeof(int) ) |
||||
*(int*)(to + i) = *(const int*)(from + i); |
||||
for( ; i < elemSize; i++ ) |
||||
to[i] = from[i]; |
||||
} |
||||
|
||||
static inline bool isZeroElem(const uchar* data, size_t elemSize) |
||||
{ |
||||
size_t i; |
||||
for( i = 0; i + sizeof(int) <= elemSize; i += sizeof(int) ) |
||||
if( *(int*)(data + i) != 0 ) |
||||
return false; |
||||
for( ; i < elemSize; i++ ) |
||||
if( data[i] != 0 ) |
||||
return false; |
||||
return true; |
||||
} |
||||
|
||||
SparseMat::Hdr::Hdr( int _dims, const int* _sizes, int _type ) |
||||
{ |
||||
refcount = 1; |
||||
|
||||
dims = _dims; |
||||
valueOffset = (int)alignSize(sizeof(SparseMat::Node) - MAX_DIM*sizeof(int) + |
||||
dims*sizeof(int), CV_ELEM_SIZE1(_type)); |
||||
nodeSize = alignSize(valueOffset + |
||||
CV_ELEM_SIZE(_type), (int)sizeof(size_t)); |
||||
|
||||
int i; |
||||
for( i = 0; i < dims; i++ ) |
||||
size[i] = _sizes[i]; |
||||
for( ; i < CV_MAX_DIM; i++ ) |
||||
size[i] = 0; |
||||
clear(); |
||||
} |
||||
|
||||
void SparseMat::Hdr::clear() |
||||
{ |
||||
hashtab.clear(); |
||||
hashtab.resize(HASH_SIZE0); |
||||
pool.clear(); |
||||
pool.resize(nodeSize); |
||||
nodeCount = freeList = 0; |
||||
} |
||||
|
||||
|
||||
SparseMat::SparseMat(const Mat& m) |
||||
: flags(MAGIC_VAL), hdr(0) |
||||
{ |
||||
create( m.dims, m.size, m.type() ); |
||||
|
||||
int i, idx[CV_MAX_DIM] = {0}, d = m.dims, lastSize = m.size[d - 1]; |
||||
size_t esz = m.elemSize(); |
||||
const uchar* dptr = m.ptr(); |
||||
|
||||
for(;;) |
||||
{ |
||||
for( i = 0; i < lastSize; i++, dptr += esz ) |
||||
{ |
||||
if( isZeroElem(dptr, esz) ) |
||||
continue; |
||||
idx[d-1] = i; |
||||
uchar* to = newNode(idx, hash(idx)); |
||||
copyElem( dptr, to, esz ); |
||||
} |
||||
|
||||
for( i = d - 2; i >= 0; i-- ) |
||||
{ |
||||
dptr += m.step[i] - m.size[i+1]*m.step[i+1]; |
||||
if( ++idx[i] < m.size[i] ) |
||||
break; |
||||
idx[i] = 0; |
||||
} |
||||
if( i < 0 ) |
||||
break; |
||||
} |
||||
} |
||||
|
||||
void SparseMat::create(int d, const int* _sizes, int _type) |
||||
{ |
||||
CV_Assert( _sizes && 0 < d && d <= CV_MAX_DIM ); |
||||
for( int i = 0; i < d; i++ ) |
||||
CV_Assert( _sizes[i] > 0 ); |
||||
_type = CV_MAT_TYPE(_type); |
||||
if( hdr && _type == type() && hdr->dims == d && hdr->refcount == 1 ) |
||||
{ |
||||
int i; |
||||
for( i = 0; i < d; i++ ) |
||||
if( _sizes[i] != hdr->size[i] ) |
||||
break; |
||||
if( i == d ) |
||||
{ |
||||
clear(); |
||||
return; |
||||
} |
||||
} |
||||
int _sizes_backup[CV_MAX_DIM]; // #5991
|
||||
if (_sizes == hdr->size) |
||||
{ |
||||
for(int i = 0; i < d; i++ ) |
||||
_sizes_backup[i] = _sizes[i]; |
||||
_sizes = _sizes_backup; |
||||
} |
||||
release(); |
||||
flags = MAGIC_VAL | _type; |
||||
hdr = new Hdr(d, _sizes, _type); |
||||
} |
||||
|
||||
void SparseMat::copyTo( SparseMat& m ) const |
||||
{ |
||||
if( hdr == m.hdr ) |
||||
return; |
||||
if( !hdr ) |
||||
{ |
||||
m.release(); |
||||
return; |
||||
} |
||||
m.create( hdr->dims, hdr->size, type() ); |
||||
SparseMatConstIterator from = begin(); |
||||
size_t N = nzcount(), esz = elemSize(); |
||||
|
||||
for( size_t i = 0; i < N; i++, ++from ) |
||||
{ |
||||
const Node* n = from.node(); |
||||
uchar* to = m.newNode(n->idx, n->hashval); |
||||
copyElem( from.ptr, to, esz ); |
||||
} |
||||
} |
||||
|
||||
void SparseMat::copyTo( Mat& m ) const |
||||
{ |
||||
CV_Assert( hdr ); |
||||
int ndims = dims(); |
||||
m.create( ndims, hdr->size, type() ); |
||||
m = Scalar(0); |
||||
|
||||
SparseMatConstIterator from = begin(); |
||||
size_t N = nzcount(), esz = elemSize(); |
||||
|
||||
for( size_t i = 0; i < N; i++, ++from ) |
||||
{ |
||||
const Node* n = from.node(); |
||||
copyElem( from.ptr, (ndims > 1 ? m.ptr(n->idx) : m.ptr(n->idx[0])), esz); |
||||
} |
||||
} |
||||
|
||||
|
||||
void SparseMat::convertTo( SparseMat& m, int rtype, double alpha ) const |
||||
{ |
||||
int cn = channels(); |
||||
if( rtype < 0 ) |
||||
rtype = type(); |
||||
rtype = CV_MAKETYPE(rtype, cn); |
||||
if( hdr == m.hdr && rtype != type() ) |
||||
{ |
||||
SparseMat temp; |
||||
convertTo(temp, rtype, alpha); |
||||
m = temp; |
||||
return; |
||||
} |
||||
|
||||
CV_Assert(hdr != 0); |
||||
if( hdr != m.hdr ) |
||||
m.create( hdr->dims, hdr->size, rtype ); |
||||
|
||||
SparseMatConstIterator from = begin(); |
||||
size_t N = nzcount(); |
||||
|
||||
if( alpha == 1 ) |
||||
{ |
||||
ConvertData cvtfunc = getConvertElem(type(), rtype); |
||||
for( size_t i = 0; i < N; i++, ++from ) |
||||
{ |
||||
const Node* n = from.node(); |
||||
uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval); |
||||
cvtfunc( from.ptr, to, cn ); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype); |
||||
for( size_t i = 0; i < N; i++, ++from ) |
||||
{ |
||||
const Node* n = from.node(); |
||||
uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval); |
||||
cvtfunc( from.ptr, to, cn, alpha, 0 ); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
void SparseMat::convertTo( Mat& m, int rtype, double alpha, double beta ) const |
||||
{ |
||||
int cn = channels(); |
||||
if( rtype < 0 ) |
||||
rtype = type(); |
||||
rtype = CV_MAKETYPE(rtype, cn); |
||||
|
||||
CV_Assert( hdr ); |
||||
m.create( dims(), hdr->size, rtype ); |
||||
m = Scalar(beta); |
||||
|
||||
SparseMatConstIterator from = begin(); |
||||
size_t N = nzcount(); |
||||
|
||||
if( alpha == 1 && beta == 0 ) |
||||
{ |
||||
ConvertData cvtfunc = getConvertElem(type(), rtype); |
||||
for( size_t i = 0; i < N; i++, ++from ) |
||||
{ |
||||
const Node* n = from.node(); |
||||
uchar* to = m.ptr(n->idx); |
||||
cvtfunc( from.ptr, to, cn ); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype); |
||||
for( size_t i = 0; i < N; i++, ++from ) |
||||
{ |
||||
const Node* n = from.node(); |
||||
uchar* to = m.ptr(n->idx); |
||||
cvtfunc( from.ptr, to, cn, alpha, beta ); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void SparseMat::clear() |
||||
{ |
||||
if( hdr ) |
||||
hdr->clear(); |
||||
} |
||||
|
||||
uchar* SparseMat::ptr(int i0, bool createMissing, size_t* hashval) |
||||
{ |
||||
CV_Assert( hdr && hdr->dims == 1 ); |
||||
size_t h = hashval ? *hashval : hash(i0); |
||||
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx]; |
||||
uchar* pool = &hdr->pool[0]; |
||||
while( nidx != 0 ) |
||||
{ |
||||
Node* elem = (Node*)(pool + nidx); |
||||
if( elem->hashval == h && elem->idx[0] == i0 ) |
||||
return &value<uchar>(elem); |
||||
nidx = elem->next; |
||||
} |
||||
|
||||
if( createMissing ) |
||||
{ |
||||
int idx[] = { i0 }; |
||||
return newNode( idx, h ); |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
uchar* SparseMat::ptr(int i0, int i1, bool createMissing, size_t* hashval) |
||||
{ |
||||
CV_Assert( hdr && hdr->dims == 2 ); |
||||
size_t h = hashval ? *hashval : hash(i0, i1); |
||||
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx]; |
||||
uchar* pool = &hdr->pool[0]; |
||||
while( nidx != 0 ) |
||||
{ |
||||
Node* elem = (Node*)(pool + nidx); |
||||
if( elem->hashval == h && elem->idx[0] == i0 && elem->idx[1] == i1 ) |
||||
return &value<uchar>(elem); |
||||
nidx = elem->next; |
||||
} |
||||
|
||||
if( createMissing ) |
||||
{ |
||||
int idx[] = { i0, i1 }; |
||||
return newNode( idx, h ); |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
uchar* SparseMat::ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval) |
||||
{ |
||||
CV_Assert( hdr && hdr->dims == 3 ); |
||||
size_t h = hashval ? *hashval : hash(i0, i1, i2); |
||||
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx]; |
||||
uchar* pool = &hdr->pool[0]; |
||||
while( nidx != 0 ) |
||||
{ |
||||
Node* elem = (Node*)(pool + nidx); |
||||
if( elem->hashval == h && elem->idx[0] == i0 && |
||||
elem->idx[1] == i1 && elem->idx[2] == i2 ) |
||||
return &value<uchar>(elem); |
||||
nidx = elem->next; |
||||
} |
||||
|
||||
if( createMissing ) |
||||
{ |
||||
int idx[] = { i0, i1, i2 }; |
||||
return newNode( idx, h ); |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
uchar* SparseMat::ptr(const int* idx, bool createMissing, size_t* hashval) |
||||
{ |
||||
CV_Assert( hdr ); |
||||
int i, d = hdr->dims; |
||||
size_t h = hashval ? *hashval : hash(idx); |
||||
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx]; |
||||
uchar* pool = &hdr->pool[0]; |
||||
while( nidx != 0 ) |
||||
{ |
||||
Node* elem = (Node*)(pool + nidx); |
||||
if( elem->hashval == h ) |
||||
{ |
||||
for( i = 0; i < d; i++ ) |
||||
if( elem->idx[i] != idx[i] ) |
||||
break; |
||||
if( i == d ) |
||||
return &value<uchar>(elem); |
||||
} |
||||
nidx = elem->next; |
||||
} |
||||
|
||||
return createMissing ? newNode(idx, h) : NULL; |
||||
} |
||||
|
||||
void SparseMat::erase(int i0, int i1, size_t* hashval) |
||||
{ |
||||
CV_Assert( hdr && hdr->dims == 2 ); |
||||
size_t h = hashval ? *hashval : hash(i0, i1); |
||||
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0; |
||||
uchar* pool = &hdr->pool[0]; |
||||
while( nidx != 0 ) |
||||
{ |
||||
Node* elem = (Node*)(pool + nidx); |
||||
if( elem->hashval == h && elem->idx[0] == i0 && elem->idx[1] == i1 ) |
||||
break; |
||||
previdx = nidx; |
||||
nidx = elem->next; |
||||
} |
||||
|
||||
if( nidx ) |
||||
removeNode(hidx, nidx, previdx); |
||||
} |
||||
|
||||
void SparseMat::erase(int i0, int i1, int i2, size_t* hashval) |
||||
{ |
||||
CV_Assert( hdr && hdr->dims == 3 ); |
||||
size_t h = hashval ? *hashval : hash(i0, i1, i2); |
||||
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0; |
||||
uchar* pool = &hdr->pool[0]; |
||||
while( nidx != 0 ) |
||||
{ |
||||
Node* elem = (Node*)(pool + nidx); |
||||
if( elem->hashval == h && elem->idx[0] == i0 && |
||||
elem->idx[1] == i1 && elem->idx[2] == i2 ) |
||||
break; |
||||
previdx = nidx; |
||||
nidx = elem->next; |
||||
} |
||||
|
||||
if( nidx ) |
||||
removeNode(hidx, nidx, previdx); |
||||
} |
||||
|
||||
void SparseMat::erase(const int* idx, size_t* hashval) |
||||
{ |
||||
CV_Assert( hdr ); |
||||
int i, d = hdr->dims; |
||||
size_t h = hashval ? *hashval : hash(idx); |
||||
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0; |
||||
uchar* pool = &hdr->pool[0]; |
||||
while( nidx != 0 ) |
||||
{ |
||||
Node* elem = (Node*)(pool + nidx); |
||||
if( elem->hashval == h ) |
||||
{ |
||||
for( i = 0; i < d; i++ ) |
||||
if( elem->idx[i] != idx[i] ) |
||||
break; |
||||
if( i == d ) |
||||
break; |
||||
} |
||||
previdx = nidx; |
||||
nidx = elem->next; |
||||
} |
||||
|
||||
if( nidx ) |
||||
removeNode(hidx, nidx, previdx); |
||||
} |
||||
|
||||
void SparseMat::resizeHashTab(size_t newsize) |
||||
{ |
||||
newsize = std::max(newsize, (size_t)8); |
||||
if((newsize & (newsize-1)) != 0) |
||||
newsize = (size_t)1 << cvCeil(std::log((double)newsize)/CV_LOG2); |
||||
|
||||
size_t hsize = hdr->hashtab.size(); |
||||
std::vector<size_t> _newh(newsize); |
||||
size_t* newh = &_newh[0]; |
||||
for( size_t i = 0; i < newsize; i++ ) |
||||
newh[i] = 0; |
||||
uchar* pool = &hdr->pool[0]; |
||||
for( size_t i = 0; i < hsize; i++ ) |
||||
{ |
||||
size_t nidx = hdr->hashtab[i]; |
||||
while( nidx ) |
||||
{ |
||||
Node* elem = (Node*)(pool + nidx); |
||||
size_t next = elem->next; |
||||
size_t newhidx = elem->hashval & (newsize - 1); |
||||
elem->next = newh[newhidx]; |
||||
newh[newhidx] = nidx; |
||||
nidx = next; |
||||
} |
||||
} |
||||
hdr->hashtab = _newh; |
||||
} |
||||
|
||||
uchar* SparseMat::newNode(const int* idx, size_t hashval) |
||||
{ |
||||
const int HASH_MAX_FILL_FACTOR=3; |
||||
assert(hdr); |
||||
size_t hsize = hdr->hashtab.size(); |
||||
if( ++hdr->nodeCount > hsize*HASH_MAX_FILL_FACTOR ) |
||||
{ |
||||
resizeHashTab(std::max(hsize*2, (size_t)8)); |
||||
hsize = hdr->hashtab.size(); |
||||
} |
||||
|
||||
if( !hdr->freeList ) |
||||
{ |
||||
size_t i, nsz = hdr->nodeSize, psize = hdr->pool.size(), |
||||
newpsize = std::max(psize*3/2, 8*nsz); |
||||
newpsize = (newpsize/nsz)*nsz; |
||||
hdr->pool.resize(newpsize); |
||||
uchar* pool = &hdr->pool[0]; |
||||
hdr->freeList = std::max(psize, nsz); |
||||
for( i = hdr->freeList; i < newpsize - nsz; i += nsz ) |
||||
((Node*)(pool + i))->next = i + nsz; |
||||
((Node*)(pool + i))->next = 0; |
||||
} |
||||
size_t nidx = hdr->freeList; |
||||
Node* elem = (Node*)&hdr->pool[nidx]; |
||||
hdr->freeList = elem->next; |
||||
elem->hashval = hashval; |
||||
size_t hidx = hashval & (hsize - 1); |
||||
elem->next = hdr->hashtab[hidx]; |
||||
hdr->hashtab[hidx] = nidx; |
||||
|
||||
int i, d = hdr->dims; |
||||
for( i = 0; i < d; i++ ) |
||||
elem->idx[i] = idx[i]; |
||||
size_t esz = elemSize(); |
||||
uchar* p = &value<uchar>(elem); |
||||
if( esz == sizeof(float) ) |
||||
*((float*)p) = 0.f; |
||||
else if( esz == sizeof(double) ) |
||||
*((double*)p) = 0.; |
||||
else |
||||
memset(p, 0, esz); |
||||
|
||||
return p; |
||||
} |
||||
|
||||
|
||||
void SparseMat::removeNode(size_t hidx, size_t nidx, size_t previdx) |
||||
{ |
||||
Node* n = node(nidx); |
||||
if( previdx ) |
||||
{ |
||||
Node* prev = node(previdx); |
||||
prev->next = n->next; |
||||
} |
||||
else |
||||
hdr->hashtab[hidx] = n->next; |
||||
n->next = hdr->freeList; |
||||
hdr->freeList = nidx; |
||||
--hdr->nodeCount; |
||||
} |
||||
|
||||
//
|
||||
// Operations
|
||||
//
|
||||
double norm( const SparseMat& src, int normType ) |
||||
{ |
||||
CV_INSTRUMENT_REGION() |
||||
|
||||
SparseMatConstIterator it = src.begin(); |
||||
|
||||
size_t i, N = src.nzcount(); |
||||
normType &= NORM_TYPE_MASK; |
||||
int type = src.type(); |
||||
double result = 0; |
||||
|
||||
CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 ); |
||||
|
||||
if( type == CV_32F ) |
||||
{ |
||||
if( normType == NORM_INF ) |
||||
for( i = 0; i < N; i++, ++it ) |
||||
{ |
||||
CV_Assert(it.ptr); |
||||
result = std::max(result, std::abs((double)it.value<float>())); |
||||
} |
||||
else if( normType == NORM_L1 ) |
||||
for( i = 0; i < N; i++, ++it ) |
||||
{ |
||||
CV_Assert(it.ptr); |
||||
result += std::abs(it.value<float>()); |
||||
} |
||||
else |
||||
for( i = 0; i < N; i++, ++it ) |
||||
{ |
||||
CV_Assert(it.ptr); |
||||
double v = it.value<float>(); |
||||
result += v*v; |
||||
} |
||||
} |
||||
else if( type == CV_64F ) |
||||
{ |
||||
if( normType == NORM_INF ) |
||||
for( i = 0; i < N; i++, ++it ) |
||||
{ |
||||
CV_Assert(it.ptr); |
||||
result = std::max(result, std::abs(it.value<double>())); |
||||
} |
||||
else if( normType == NORM_L1 ) |
||||
for( i = 0; i < N; i++, ++it ) |
||||
{ |
||||
CV_Assert(it.ptr); |
||||
result += std::abs(it.value<double>()); |
||||
} |
||||
else |
||||
for( i = 0; i < N; i++, ++it ) |
||||
{ |
||||
CV_Assert(it.ptr); |
||||
double v = it.value<double>(); |
||||
result += v*v; |
||||
} |
||||
} |
||||
else |
||||
CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" ); |
||||
|
||||
if( normType == NORM_L2 ) |
||||
result = std::sqrt(result); |
||||
return result; |
||||
} |
||||
|
||||
void minMaxLoc( const SparseMat& src, double* _minval, double* _maxval, int* _minidx, int* _maxidx ) |
||||
{ |
||||
CV_INSTRUMENT_REGION() |
||||
|
||||
SparseMatConstIterator it = src.begin(); |
||||
size_t i, N = src.nzcount(), d = src.hdr ? src.hdr->dims : 0; |
||||
int type = src.type(); |
||||
const int *minidx = 0, *maxidx = 0; |
||||
|
||||
if( type == CV_32F ) |
||||
{ |
||||
float minval = FLT_MAX, maxval = -FLT_MAX; |
||||
for( i = 0; i < N; i++, ++it ) |
||||
{ |
||||
CV_Assert(it.ptr); |
||||
float v = it.value<float>(); |
||||
if( v < minval ) |
||||
{ |
||||
minval = v; |
||||
minidx = it.node()->idx; |
||||
} |
||||
if( v > maxval ) |
||||
{ |
||||
maxval = v; |
||||
maxidx = it.node()->idx; |
||||
} |
||||
} |
||||
if( _minval ) |
||||
*_minval = minval; |
||||
if( _maxval ) |
||||
*_maxval = maxval; |
||||
} |
||||
else if( type == CV_64F ) |
||||
{ |
||||
double minval = DBL_MAX, maxval = -DBL_MAX; |
||||
for( i = 0; i < N; i++, ++it ) |
||||
{ |
||||
CV_Assert(it.ptr); |
||||
double v = it.value<double>(); |
||||
if( v < minval ) |
||||
{ |
||||
minval = v; |
||||
minidx = it.node()->idx; |
||||
} |
||||
if( v > maxval ) |
||||
{ |
||||
maxval = v; |
||||
maxidx = it.node()->idx; |
||||
} |
||||
} |
||||
if( _minval ) |
||||
*_minval = minval; |
||||
if( _maxval ) |
||||
*_maxval = maxval; |
||||
} |
||||
else |
||||
CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" ); |
||||
|
||||
if( _minidx && minidx ) |
||||
for( i = 0; i < d; i++ ) |
||||
_minidx[i] = minidx[i]; |
||||
if( _maxidx && maxidx ) |
||||
for( i = 0; i < d; i++ ) |
||||
_maxidx[i] = maxidx[i]; |
||||
} |
||||
|
||||
|
||||
void normalize( const SparseMat& src, SparseMat& dst, double a, int norm_type ) |
||||
{ |
||||
CV_INSTRUMENT_REGION() |
||||
|
||||
double scale = 1; |
||||
if( norm_type == CV_L2 || norm_type == CV_L1 || norm_type == CV_C ) |
||||
{ |
||||
scale = norm( src, norm_type ); |
||||
scale = scale > DBL_EPSILON ? a/scale : 0.; |
||||
} |
||||
else |
||||
CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" ); |
||||
|
||||
src.convertTo( dst, -1, scale ); |
||||
} |
||||
|
||||
} // cv::
|
||||
|
||||
//
|
||||
// C-API glue
|
||||
//
|
||||
CvSparseMat* cvCreateSparseMat(const cv::SparseMat& sm) |
||||
{ |
||||
if( !sm.hdr || sm.hdr->dims > (int)cv::SparseMat::MAX_DIM) |
||||
return 0; |
||||
|
||||
CvSparseMat* m = cvCreateSparseMat(sm.hdr->dims, sm.hdr->size, sm.type()); |
||||
|
||||
cv::SparseMatConstIterator from = sm.begin(); |
||||
size_t i, N = sm.nzcount(), esz = sm.elemSize(); |
||||
|
||||
for( i = 0; i < N; i++, ++from ) |
||||
{ |
||||
const cv::SparseMat::Node* n = from.node(); |
||||
uchar* to = cvPtrND(m, n->idx, 0, -2, 0); |
||||
cv::copyElem(from.ptr, to, esz); |
||||
} |
||||
return m; |
||||
} |
||||
|
||||
void CvSparseMat::copyToSparseMat(cv::SparseMat& m) const |
||||
{ |
||||
m.create( dims, &size[0], type ); |
||||
|
||||
CvSparseMatIterator it; |
||||
CvSparseNode* n = cvInitSparseMatIterator(this, &it); |
||||
size_t esz = m.elemSize(); |
||||
|
||||
for( ; n != 0; n = cvGetNextSparseNode(&it) ) |
||||
{ |
||||
const int* idx = CV_NODE_IDX(this, n); |
||||
uchar* to = m.newNode(idx, m.hash(idx)); |
||||
cv::copyElem((const uchar*)CV_NODE_VAL(this, n), to, esz); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue