From: Vadim Pisarevsky Date: Mon, 18 Oct 2010 08:51:46 +0000 (+0000) Subject: added Mat::push_back, pop_back and related operations; enabled reading/writing/creati... X-Git-Tag: accepted/tizen/6.0/unified/20201030.111113~8586 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=02885b8b498687e9f2815a8221b7909e077192cd;p=platform%2Fupstream%2Fopencv.git added Mat::push_back, pop_back and related operations; enabled reading/writing/creating/copying matrices with zero dimensions. --- diff --git a/modules/core/include/opencv2/core/core.hpp b/modules/core/include/opencv2/core/core.hpp index 59b319b..b969100 100644 --- a/modules/core/include/opencv2/core/core.hpp +++ b/modules/core/include/opencv2/core/core.hpp @@ -94,6 +94,7 @@ class CV_EXPORTS VectorArg; class CV_EXPORTS MatArg; class CV_EXPORTS MatConstIterator; +template class CV_EXPORTS Mat_; template class CV_EXPORTS MatIterator_; template class CV_EXPORTS MatConstIterator_; template class CV_EXPORTS MatCommaInitializer_; @@ -1600,7 +1601,22 @@ public: void deallocate(); //! internal use function; properly re-allocates _size, _step arrays void copySize(const Mat& m); - + + //! reserves enough space to fit sz hyper-planes + void reserve(size_t sz); + //! resizes matrix to the specified number of hyper-planes + void resize(size_t sz); + //! resizes matrix to the specified number of hyper-planes; initializes the newly added elements + void resize(size_t sz, const Scalar& s); + //! internal function + void push_back_(const void* elem); + //! adds element to the end of 1d matrix (or possibly multiple elements when _Tp=Mat) + template void push_back(const _Tp& elem); + template void push_back(const Mat_<_Tp>& elem); + void push_back(const Mat& m); + //! removes several hyper-planes from bottom of the matrix + void pop_back(size_t nelems); + //! locates matrix header within a parent matrix. See below void locateROI( Size& wholeSize, Point& ofs ) const; //! moves/resizes the current matrix ROI inside the parent matrix. @@ -1626,6 +1642,10 @@ public: // (i.e. when there are no gaps between successive rows). // similar to CV_IS_MAT_CONT(cvmat->type) bool isContinuous() const; + + //! returns true if the matrix is a submatrix of another matrix + bool isSubmatrix() const; + //! returns element size in bytes, // similar to CV_ELEM_SIZE(cvmat->type) size_t elemSize() const; @@ -1707,7 +1727,7 @@ public: template MatConstIterator_<_Tp> begin() const; template MatConstIterator_<_Tp> end() const; - enum { MAGIC_VAL=0x42FF0000, AUTO_STEP=0, CONTINUOUS_FLAG=CV_MAT_CONT_FLAG }; + enum { MAGIC_VAL=0x42FF0000, AUTO_STEP=0, CONTINUOUS_FLAG=CV_MAT_CONT_FLAG, SUBMATRIX_FLAG=CV_SUBMAT_FLAG }; /*! includes several bit-fields: - the magic signature @@ -1730,6 +1750,8 @@ public: //! helper fields used in locateROI and adjustROI uchar* datastart; uchar* dataend; + uchar* datalimit; + //! custom allocator ArrayAllocator* allocator; @@ -2252,13 +2274,13 @@ CV_EXPORTS void fillConvexPoly(Mat& img, CV_CARRAY(npts) const Point* pts, int n int shift=0); //! fills an area bounded by one or more polygons -CV_EXPORTS void fillPoly(Mat& img, CV_CARRAY(ncontours) const Point** pts, +CV_EXPORTS void fillPoly(Mat& img, CV_CARRAY(ncontours.npts) const Point** pts, CV_CARRAY(ncontours) const int* npts, int ncontours, const Scalar& color, int lineType=8, int shift=0, Point offset=Point() ); //! draws one or more polygonal curves -CV_EXPORTS void polylines(Mat& img, CV_CARRAY(ncontours) const Point** pts, CV_CARRAY(ncontours) const int* npts, +CV_EXPORTS void polylines(Mat& img, CV_CARRAY(ncontours.npts) const Point** pts, CV_CARRAY(ncontours) const int* npts, int ncontours, bool isClosed, const Scalar& color, int thickness=1, int lineType=8, int shift=0 ); diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index c034215..e53761f 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -57,20 +57,20 @@ namespace cv inline Mat::Mat() : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) + datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows) { } inline Mat::Mat(int _rows, int _cols, int _type) : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) + datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows) { create(_rows, _cols, _type); } inline Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s) : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) + datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows) { create(_rows, _cols, _type); *this = _s; @@ -78,14 +78,14 @@ inline Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s) inline Mat::Mat(Size _sz, int _type) : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) + datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows) { create( _sz.height, _sz.width, _type ); } inline Mat::Mat(Size _sz, int _type, const Scalar& _s) : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) + datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows) { create(_sz.height, _sz.width, _type); *this = _s; @@ -93,14 +93,14 @@ inline Mat::Mat(Size _sz, int _type, const Scalar& _s) inline Mat::Mat(int _dims, const int* _sz, int _type) : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) + datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows) { create(_dims, _sz, _type); } inline Mat::Mat(int _dims, const int* _sz, int _type, const Scalar& _s) : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) + datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows) { create(_dims, _sz, _type); *this = _s; @@ -109,7 +109,7 @@ inline Mat::Mat(int _dims, const int* _sz, int _type, const Scalar& _s) inline Mat::Mat(const Mat& m) : flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), data(m.data), refcount(m.refcount), datastart(m.datastart), dataend(m.dataend), - allocator(m.allocator), size(&rows) + datalimit(m.datalimit), allocator(m.allocator), size(&rows) { if( refcount ) CV_XADD(refcount, 1); @@ -126,10 +126,10 @@ inline Mat::Mat(const Mat& m) inline Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step) : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_rows), cols(_cols), - data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend((uchar*)_data), - allocator(0), size(&rows) + data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend(0), + datalimit(0), allocator(0), size(&rows) { - size_t minstep = cols*elemSize(); + size_t esz = CV_ELEM_SIZE(_type), minstep = cols*esz; if( _step == AUTO_STEP ) { _step = minstep; @@ -141,16 +141,17 @@ inline Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step) CV_DbgAssert( _step >= minstep ); flags |= _step == minstep ? CONTINUOUS_FLAG : 0; } - step[0] = _step; step[1] = elemSize(); - dataend += _step*(rows-1) + minstep; + step[0] = _step; step[1] = esz; + datalimit = datastart + _step*rows; + dataend = datalimit - _step + minstep; } inline Mat::Mat(Size _sz, int _type, void* _data, size_t _step) : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_sz.height), cols(_sz.width), - data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend((uchar*)_data), - allocator(0), size(&rows) + data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend(0), + datalimit(0), allocator(0), size(&rows) { - size_t minstep = cols*elemSize(); + size_t esz = CV_ELEM_SIZE(_type), minstep = cols*esz; if( _step == AUTO_STEP ) { _step = minstep; @@ -162,23 +163,25 @@ inline Mat::Mat(Size _sz, int _type, void* _data, size_t _step) CV_DbgAssert( _step >= minstep ); flags |= _step == minstep ? CONTINUOUS_FLAG : 0; } - step[0] = _step; step[1] = elemSize(); - dataend += _step*(rows-1) + minstep; + step[0] = _step; step[1] = esz; + datalimit = datastart + _step*rows; + dataend = datalimit - _step + minstep; } inline Mat::Mat(const CvMat* m, bool copyData) : flags(MAGIC_VAL + (m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG))), dims(2), rows(m->rows), cols(m->cols), data(m->data.ptr), refcount(0), - datastart(m->data.ptr), dataend(m->data.ptr), + datastart(0), dataend(0), allocator(0), size(&rows) { if( !copyData ) { - size_t esz = elemSize(), minstep = cols*esz, _step = m->step; + size_t esz = CV_ELEM_SIZE(m->type), minstep = cols*esz, _step = m->step; if( _step == 0 ) _step = minstep; - dataend += _step*(rows-1) + minstep; + datalimit = datastart + _step*rows; + dataend = datalimit - _step + minstep; step[0] = _step; step[1] = esz; } else @@ -199,7 +202,7 @@ template inline Mat::Mat(const vector<_Tp>& vec, bool copyData) { step[0] = step[1] = sizeof(_Tp); data = datastart = (uchar*)&vec[0]; - dataend = datastart + rows*step[0]; + datalimit = dataend = datastart + rows*step[0]; } else Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this); @@ -215,7 +218,7 @@ template inline Mat::Mat(const Vec<_Tp, n>& vec, bool copyD { step[0] = step[1] = sizeof(_Tp); data = datastart = (uchar*)vec.val; - dataend = datastart + rows*step[0]; + datalimit = dataend = datastart + rows*step[0]; } else Mat(n, 1, DataType<_Tp>::type, (void*)vec.val).copyTo(*this); @@ -232,7 +235,7 @@ template inline Mat::Mat(const Matx<_Tp,m,n>& M, boo step[0] = cols*sizeof(_Tp); step[1] = sizeof(_Tp); data = datastart = (uchar*)M.val; - dataend = datastart + rows*step[0]; + datalimit = dataend = datastart + rows*step[0]; } else Mat(m, n, DataType<_Tp>::type, (uchar*)M.val).copyTo(*this); @@ -248,7 +251,7 @@ template inline Mat::Mat(const Point_<_Tp>& pt, bool copyData) { step[0] = step[1] = sizeof(_Tp); data = datastart = (uchar*)&pt.x; - dataend = datastart + rows*step[0]; + datalimit = dataend = datastart + rows*step[0]; } else { @@ -268,7 +271,7 @@ template inline Mat::Mat(const Point3_<_Tp>& pt, bool copyData) { step[0] = step[1] = sizeof(_Tp); data = datastart = (uchar*)&pt.x; - dataend = datastart + rows*step[0]; + datalimit = dataend = datastart + rows*step[0]; } else { @@ -314,7 +317,9 @@ inline Mat& Mat::operator = (const Mat& m) else copySize(m); data = m.data; - datastart = m.datastart; dataend = m.dataend; + datastart = m.datastart; + dataend = m.dataend; + datalimit = m.datalimit; refcount = m.refcount; allocator = m.allocator; } @@ -375,8 +380,8 @@ inline void Mat::release() { if( refcount && CV_XADD(refcount, -1) == 1 ) deallocate(); - data = datastart = dataend = 0; - rows = cols = 0; + data = datastart = dataend = datalimit = 0; + size.p[0] = 0; refcount = 0; } @@ -403,13 +408,14 @@ inline Mat::operator CvMat() const } inline bool Mat::isContinuous() const { return (flags & CONTINUOUS_FLAG) != 0; } -inline size_t Mat::elemSize() const { return CV_ELEM_SIZE(flags); } +inline bool Mat::isSubmatrix() const { return (flags & SUBMATRIX_FLAG) != 0; } +inline size_t Mat::elemSize() const { return step.p[dims-1]; } inline size_t Mat::elemSize1() const { return CV_ELEM_SIZE1(flags); } inline int Mat::type() const { return CV_MAT_TYPE(flags); } inline int Mat::depth() const { return CV_MAT_DEPTH(flags); } inline int Mat::channels() const { return CV_MAT_CN(flags); } inline size_t Mat::step1(int i) const { return step.p[i]/elemSize1(); } -inline bool Mat::empty() const { return data == 0; } +inline bool Mat::empty() const { return data == 0 || size.p[0] == 0; } inline size_t Mat::total() const { if( dims <= 2 ) @@ -581,7 +587,7 @@ template inline MatIterator_<_Tp> Mat::end() template inline Mat::operator vector<_Tp>() const { - if( !data ) + if( empty() ) return vector<_Tp>(); CV_Assert( dims >= 1 && DataType<_Tp>::channels == channels()); vector<_Tp> v(total()); @@ -611,10 +617,34 @@ template inline Mat::operator Matx<_Tp, m, n>() cons Matx<_Tp, m, n> mtx; Mat tmp(rows, cols, DataType<_Tp>::type, mtx.val); convertTo(tmp, tmp.type()); return mtx; -} +} + +template inline void Mat::push_back(const _Tp& elem) +{ + CV_Assert(DataType<_Tp>::type == type() && cols == 1 + /* && dims == 2 (cols == 1 implies dims == 2) */); + uchar* tmp = dataend + step[0]; + if( !isSubmatrix() && isContinuous() && tmp <= datalimit ) + { + *(_Tp*)(data + (size.p[0]++)*step.p[0]) = elem; + dataend = tmp; + } + else + push_back_(&elem); +} + +template inline void Mat::push_back(const Mat_<_Tp>& m) +{ + push_back((const Mat&)m); +} + inline Mat::MSize::MSize(int* _p) : p(_p) {} -inline Size Mat::MSize::operator()() const { return Size(p[1], p[0]); } +inline Size Mat::MSize::operator()() const +{ + CV_DbgAssert(p[-1] <= 2); + return Size(p[1], p[0]); +} inline int Mat::MSize::operator[](int i) const { return p[i]; } inline int& Mat::MSize::operator[](int i) { return p[i]; } inline Mat::MSize::operator const int*() const { return p; } @@ -642,8 +672,17 @@ inline Mat::MStep::MStep() { p = buf; p[0] = p[1] = 0; } inline Mat::MStep::MStep(size_t s) { p = buf; p[0] = s; p[1] = 0; } inline size_t Mat::MStep::operator[](int i) const { return p[i]; } inline size_t& Mat::MStep::operator[](int i) { return p[i]; } -inline Mat::MStep::operator size_t() const { return p[0]; } -inline Mat::MStep& Mat::MStep::operator = (size_t s) { p[0] = s; return *this; } +inline Mat::MStep::operator size_t() const +{ + CV_DbgAssert( p == buf ); + return buf[0]; +} +inline Mat::MStep& Mat::MStep::operator = (size_t s) +{ + CV_DbgAssert( p == buf ); + buf[0] = s; + return *this; +} static inline Mat cvarrToMatND(const CvArr* arr, bool copyData=false, int coiMode=0) { diff --git a/modules/core/include/opencv2/core/operations.hpp b/modules/core/include/opencv2/core/operations.hpp index 8e0b5aa..8341022 100644 --- a/modules/core/include/opencv2/core/operations.hpp +++ b/modules/core/include/opencv2/core/operations.hpp @@ -2692,7 +2692,6 @@ operator << ( FileStorage& fs, const vector<_Tp>& vec ) } CV_EXPORTS void write( FileStorage& fs, const string& name, const Mat& value ); -CV_EXPORTS void write( FileStorage& fs, const string& name, const MatND& value ); CV_EXPORTS void write( FileStorage& fs, const string& name, const SparseMat& value ); template static inline FileStorage& operator << (FileStorage& fs, const _Tp& value) diff --git a/modules/core/include/opencv2/core/types_c.h b/modules/core/include/opencv2/core/types_c.h index 7e7d761..986cdab 100644 --- a/modules/core/include/opencv2/core/types_c.h +++ b/modules/core/include/opencv2/core/types_c.h @@ -601,9 +601,9 @@ IplConvKernelFP; #define CV_MAT_CONT_FLAG (1 << CV_MAT_CONT_FLAG_SHIFT) #define CV_IS_MAT_CONT(flags) ((flags) & CV_MAT_CONT_FLAG) #define CV_IS_CONT_MAT CV_IS_MAT_CONT -#define CV_MAT_TEMP_FLAG_SHIFT 15 -#define CV_MAT_TEMP_FLAG (1 << CV_MAT_TEMP_FLAG_SHIFT) -#define CV_IS_TEMP_MAT(flags) ((flags) & CV_MAT_TEMP_FLAG) +#define CV_SUBMAT_FLAG_SHIFT 15 +#define CV_SUBMAT_FLAG (1 << CV_SUBMAT_FLAG_SHIFT) +#define CV_IS_SUBMAT(flags) ((flags) & CV_MAT_SUBMAT_FLAG) #define CV_MAGIC_MASK 0xFFFF0000 #define CV_MAT_MAGIC_VAL 0x42420000 @@ -653,6 +653,11 @@ CvMat; (((const CvMat*)(mat))->type & CV_MAGIC_MASK) == CV_MAT_MAGIC_VAL && \ ((const CvMat*)(mat))->cols > 0 && ((const CvMat*)(mat))->rows > 0) +#define CV_IS_MAT_HDR_Z(mat) \ + ((mat) != NULL && \ + (((const CvMat*)(mat))->type & CV_MAGIC_MASK) == CV_MAT_MAGIC_VAL && \ + ((const CvMat*)(mat))->cols >= 0 && ((const CvMat*)(mat))->rows >= 0) + #define CV_IS_MAT(mat) \ (CV_IS_MAT_HDR(mat) && ((const CvMat*)(mat))->data.ptr != NULL) diff --git a/modules/core/src/array.cpp b/modules/core/src/array.cpp index 7778084..d78bfe2 100644 --- a/modules/core/src/array.cpp +++ b/modules/core/src/array.cpp @@ -109,7 +109,7 @@ cvCreateMatHeader( int rows, int cols, int type ) { type = CV_MAT_TYPE(type); - if( rows <= 0 || cols <= 0 ) + if( rows < 0 || cols <= 0 ) CV_Error( CV_StsBadSize, "Non-positive width or height" ); int min_step = CV_ELEM_SIZE(type)*cols; @@ -142,7 +142,7 @@ cvInitMatHeader( CvMat* arr, int rows, int cols, if( (unsigned)CV_MAT_DEPTH(type) > CV_DEPTH_MAX ) CV_Error( CV_BadNumChannels, "" ); - if( rows <= 0 || cols <= 0 ) + if( rows < 0 || cols <= 0 ) CV_Error( CV_StsBadSize, "Non-positive cols or rows" ); type = CV_MAT_TYPE( type ); @@ -175,12 +175,6 @@ cvInitMatHeader( CvMat* arr, int rows, int cols, } -#undef CV_IS_MAT_HDR_Z -#define CV_IS_MAT_HDR_Z(mat) \ - ((mat) != NULL && \ - (((const CvMat*)(mat))->type & CV_MAGIC_MASK) == CV_MAT_MAGIC_VAL && \ - ((const CvMat*)(mat))->cols >= 0 && ((const CvMat*)(mat))->rows >= 0) - // Deallocates the CvMat structure and underlying data CV_IMPL void cvReleaseMat( CvMat** array ) @@ -248,7 +242,7 @@ cvInitMatNDHeader( CvMatND* mat, int dims, const int* sizes, for( int i = dims - 1; i >= 0; i-- ) { - if( sizes[i] <= 0 ) + if( sizes[i] < 0 ) CV_Error( CV_StsBadSize, "one of dimesion sizes is non-positive" ); mat->dim[i].size = sizes[i]; if( step > INT_MAX ) @@ -795,12 +789,15 @@ icvDeleteNode( CvSparseMat* mat, const int* idx, unsigned* precalc_hashval ) CV_IMPL void cvCreateData( CvArr* arr ) { - if( CV_IS_MAT_HDR( arr )) + if( CV_IS_MAT_HDR_Z( arr )) { size_t step, total_size; CvMat* mat = (CvMat*)arr; step = mat->step; + if( mat->rows == 0 || mat->cols == 0 ) + return; + if( mat->data.ptr != 0 ) CV_Error( CV_StsError, "Data is already allocated" ); @@ -849,6 +846,9 @@ cvCreateData( CvArr* arr ) CvMatND* mat = (CvMatND*)arr; int i; size_t total_size = CV_ELEM_SIZE(mat->type); + + if( mat->dim[0].size == 0 ) + return; if( mat->data.ptr != 0 ) CV_Error( CV_StsError, "Data is already allocated" ); @@ -1207,7 +1207,7 @@ cvGetSize( const CvArr* arr ) { CvSize size = { 0, 0 }; - if( CV_IS_MAT_HDR( arr )) + if( CV_IS_MAT_HDR_Z( arr )) { CvMat *mat = (CvMat*)arr; diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index 9119866..84950cd 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -166,38 +166,45 @@ static SetMaskFunc setMaskFuncTab[] = /* dst = src */ void Mat::copyTo( Mat& dst ) const { - if( data == dst.data ) + if( data == dst.data && data != 0 ) return; if( dims > 2 ) { dst.create( dims, size, type() ); - const Mat* arrays[] = { this, &dst, 0 }; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - CV_DbgAssert(it.planes[0].isContinuous() && - it.planes[1].isContinuous()); - size_t planeSize = it.planes[0].elemSize()*it.planes[0].rows*it.planes[0].cols; - - for( int i = 0; i < it.nplanes; i++, ++it ) - memcpy(it.planes[1].data, it.planes[0].data, planeSize); + if( total() != 0 ) + { + const Mat* arrays[] = { this, &dst, 0 }; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + CV_DbgAssert(it.planes[0].isContinuous() && + it.planes[1].isContinuous()); + size_t planeSize = it.planes[0].elemSize()*it.planes[0].rows*it.planes[0].cols; + + for( int i = 0; i < it.nplanes; i++, ++it ) + memcpy(it.planes[1].data, it.planes[0].data, planeSize); + } return; } dst.create( rows, cols, type() ); Size sz = size(); - const uchar* sptr = data; - uchar* dptr = dst.data; - - sz.width *= (int)elemSize(); - if( isContinuous() && dst.isContinuous() ) + + if( rows > 0 && cols > 0 ) { - sz.width *= sz.height; - sz.height = 1; - } + const uchar* sptr = data; + uchar* dptr = dst.data; - for( ; sz.height--; sptr += step, dptr += dst.step ) - memcpy( dptr, sptr, sz.width ); + size_t width = sz.width*elemSize(); + if( isContinuous() && dst.isContinuous() ) + { + width *= sz.height; + sz.height = 1; + } + + for( ; sz.height--; sptr += step, dptr += dst.step ) + memcpy( dptr, sptr, width ); + } } void Mat::copyTo( Mat& dst, const Mat& mask ) const diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 781a060..80113e9 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -94,12 +94,12 @@ static inline void setSize( Mat& m, int _dims, const int* _sz, if( !_sz ) return; - size_t esz = m.elemSize(), total = esz; + size_t esz = CV_ELEM_SIZE(m.flags), total = esz; int i; for( i = _dims-1; i >= 0; i-- ) { int s = _sz[i]; - CV_Assert( s > 0 ); + CV_Assert( s >= (i == 0 ? 0 : 1) ); m.size.p[i] = s; if( _steps ) @@ -121,11 +121,10 @@ static inline void setSize( Mat& m, int _dims, const int* _sz, m.step[1] = esz; } } - -static void finalizeHdr(Mat& m) + +static void updateContinuityFlag(Mat& m) { int i, j; - for( i = 0; i < m.dims; i++ ) { if( m.size[i] > 1 ) @@ -137,19 +136,33 @@ static void finalizeHdr(Mat& m) if( m.step[j]*m.size[j] < m.step[j-1] ) break; } - m.flags &= ~Mat::CONTINUOUS_FLAG; - int64 t = (int64)(m.step[0]/m.elemSize())*m.size[0]; + + int64 t = (int64)(m.step[0]/CV_ELEM_SIZE(m.flags))*m.size[0]; if( j <= i && t == (int)t ) m.flags |= Mat::CONTINUOUS_FLAG; + else + m.flags &= ~Mat::CONTINUOUS_FLAG; +} +static void finalizeHdr(Mat& m) +{ + updateContinuityFlag(m); if( m.dims > 2 ) m.rows = m.cols = -1; if( m.data ) { - m.dataend = m.data; - for( i = 0; i < m.dims; i++ ) - m.dataend += (m.size[i] - 1)*m.step[i]; + m.datalimit = m.datastart + m.size[0]*m.step[0]; + if( m.size[0] > 0 ) + { + m.dataend = m.data; + for( int i = 0; i < m.dims; i++ ) + m.dataend += (m.size[i] - 1)*m.step[i]; + } + else + m.dataend = m.datalimit; } + else + m.dataend = m.datalimit = 0; } @@ -176,17 +189,20 @@ void Mat::create(int d, const int* _sizes, int _type) flags = (_type & CV_MAT_TYPE_MASK) | MAGIC_VAL; setSize(*this, d, _sizes, 0, allocator == 0); - if( !allocator ) - { - size_t total = alignSize(step.p[0]*size.p[0], (int)sizeof(*refcount)); - data = datastart = (uchar*)fastMalloc(total + (int)sizeof(*refcount)); - refcount = (int*)(data + total); - *refcount = 1; - } - else + if( size.p[0] > 0 ) { - allocator->allocate(dims, size, _type, refcount, datastart, data, step.p); - CV_Assert( step[dims-1] == elemSize() ); + if( !allocator ) + { + size_t total = alignSize(step.p[0]*size.p[0], (int)sizeof(*refcount)); + data = datastart = (uchar*)fastMalloc(total + (int)sizeof(*refcount)); + refcount = (int*)(data + total); + *refcount = 1; + } + else + { + allocator->allocate(dims, size, _type, refcount, datastart, data, step.p); + CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) ); + } } finalizeHdr(*this); @@ -216,7 +232,7 @@ void Mat::deallocate() Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange) : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) + datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows) { CV_Assert( m.dims >= 2 ); if( m.dims > 2 ) @@ -231,19 +247,21 @@ Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange) } *this = m; - if( rowRange != Range::all() ) + if( rowRange != Range::all() && rowRange != Range(0,rows) ) { CV_Assert( 0 <= rowRange.start && rowRange.start <= rowRange.end && rowRange.end <= m.rows ); rows = rowRange.size(); data += step*rowRange.start; + flags |= SUBMATRIX_FLAG; } - if( colRange != Range::all() ) + if( colRange != Range::all() && colRange != Range(0,cols) ) { CV_Assert( 0 <= colRange.start && colRange.start <= colRange.end && colRange.end <= m.cols ); cols = colRange.size(); data += colRange.start*elemSize(); flags &= cols < m.cols ? ~CONTINUOUS_FLAG : -1; + flags |= SUBMATRIX_FLAG; } if( rows == 1 ) @@ -262,18 +280,21 @@ Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange) Mat::Mat(const Mat& m, const Rect& roi) : flags(m.flags), dims(2), rows(roi.height), cols(roi.width), data(m.data + roi.y*m.step[0]), refcount(m.refcount), - datastart(m.datastart), dataend(m.dataend), allocator(m.allocator), size(&rows) + datastart(m.datastart), dataend(m.dataend), datalimit(m.datalimit), + allocator(m.allocator), size(&rows) { CV_Assert( m.dims <= 2 ); flags &= roi.width < m.cols ? ~CONTINUOUS_FLAG : -1; flags |= roi.height == 1 ? CONTINUOUS_FLAG : 0; - size_t esz = elemSize(); + size_t esz = CV_ELEM_SIZE(flags); data += roi.x*esz; CV_Assert( 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows ); if( refcount ) CV_XADD(refcount, 1); + if( roi.width < m.cols || roi.height < m.rows ) + flags |= SUBMATRIX_FLAG; step[0] = m.step[0]; step[1] = esz; @@ -286,9 +307,10 @@ Mat::Mat(const Mat& m, const Rect& roi) Mat::Mat(int _dims, const int* _sizes, int _type, void* _data, const size_t* _steps) - : flags(MAGIC_VAL|CV_MAT_TYPE(_type)), dims(0), rows(0), cols(0), - data((uchar*)_data), refcount(0), - datastart((uchar*)_data), dataend((uchar*)_data), allocator(0), size(&rows) + : flags(MAGIC_VAL|CV_MAT_TYPE(_type)), dims(0), + rows(0), cols(0), data((uchar*)_data), refcount(0), + datastart((uchar*)_data), dataend((uchar*)_data), datalimit((uchar*)_data), + allocator(0), size(&rows) { setSize(*this, _dims, _sizes, _steps, true); finalizeHdr(*this); @@ -297,7 +319,7 @@ Mat::Mat(int _dims, const int* _sizes, int _type, void* _data, const size_t* _st Mat::Mat(const Mat& m, const Range* ranges) : flags(m.flags), dims(0), rows(0), cols(0), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) + datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows) { int i, d = m.dims; @@ -311,21 +333,21 @@ Mat::Mat(const Mat& m, const Range* ranges) for( i = 0; i < d; i++ ) { Range r = ranges[i]; - if( r != Range::all() ) + if( r != Range::all() && r != Range(0, size.p[i])) { - size[i] = r.end - r.start; - data += r.start*step[i]; + size.p[i] = r.end - r.start; + data += r.start*step.p[i]; + flags |= SUBMATRIX_FLAG; } } - - finalizeHdr(*this); + updateContinuityFlag(*this); } Mat::Mat(const CvMatND* m, bool copyData) : flags(MAGIC_VAL|CV_MAT_TYPE(m->type)), dims(0), rows(0), cols(0), data((uchar*)m->data.ptr), refcount(0), - datastart((uchar*)m->data.ptr), dataend((uchar*)m->data.ptr), allocator(0), + datastart((uchar*)m->data.ptr), allocator(0), size(&rows) { int _sizes[CV_MAX_DIM]; @@ -376,6 +398,10 @@ Mat Mat::diag(int d) const m.flags &= ~CONTINUOUS_FLAG; else m.flags |= CONTINUOUS_FLAG; + + if( size() != Size(1,1) ) + m.flags |= SUBMATRIX_FLAG; + return m; } @@ -396,7 +422,7 @@ Mat::Mat(const IplImage* img, bool copyData) flags = MAGIC_VAL + CV_MAKETYPE(depth, img->nChannels); rows = img->height; cols = img->width; datastart = data = (uchar*)img->imageData; - esz = elemSize(); + esz = CV_ELEM_SIZE(flags); } else { @@ -404,13 +430,14 @@ Mat::Mat(const IplImage* img, bool copyData) bool selectedPlane = img->roi->coi && img->dataOrder == IPL_DATA_ORDER_PLANE; flags = MAGIC_VAL + CV_MAKETYPE(depth, selectedPlane ? 1 : img->nChannels); rows = img->roi->height; cols = img->roi->width; - esz = elemSize(); + esz = CV_ELEM_SIZE(flags); data = datastart = (uchar*)img->imageData + (selectedPlane ? (img->roi->coi - 1)*step*img->height : 0) + img->roi->yOffset*step[0] + img->roi->xOffset*esz; } - dataend = datastart + step*(rows-1) + esz*cols; - flags |= (cols*esz == step || rows == 1 ? CONTINUOUS_FLAG : 0); + datalimit = datastart + step.p[0]*rows; + dataend = datastart + step.p[0]*(rows-1) + esz*cols; + flags |= (cols*esz == step.p[0] || rows == 1 ? CONTINUOUS_FLAG : 0); step[1] = esz; if( copyData ) @@ -438,7 +465,132 @@ Mat::operator IplImage() const cvSetData(&img, data, (int)step[0]); return img; } + + +void Mat::pop_back(size_t nelems) +{ + CV_Assert( nelems <= (size_t)size.p[0] ); + + if( isSubmatrix() ) + *this = rowRange(0, size.p[0] - (int)nelems); + else + { + size.p[0] -= (int)nelems; + dataend -= nelems*step.p[0]; + /*if( size.p[0] <= 1 ) + { + if( dims <= 2 ) + flags |= CONTINUOUS_FLAG; + else + updateContinuityFlag(*this); + }*/ + } +} + + +void Mat::push_back_(const void* elem) +{ + int r = size.p[0]; + if( isSubmatrix() || dataend + step.p[0] > datalimit ) + reserve( std::max(r + 1, (r*3+1)/2) ); + + size_t esz = elemSize(); + memcpy(data + r*step.p[0], elem, esz); + size.p[0] = r + 1; + dataend += step.p[0]; + if( esz < step.p[0] ) + flags &= ~CONTINUOUS_FLAG; +} + +void Mat::reserve(size_t nelems) +{ + const size_t MIN_SIZE = 64; + + CV_Assert( (int)nelems >= 0 ); + if( !isSubmatrix() && data + step.p[0]*nelems <= datalimit ) + return; + + int r = size.p[0]; + size.p[0] = std::max((int)nelems, 1); + size_t newsize = total()*elemSize(); + + if( newsize < MIN_SIZE ) + size.p[0] = (int)((MIN_SIZE + newsize - 1)*nelems/newsize); + + Mat m(dims, size.p, type()); + size.p[0] = r; + if( r > 0 ) + { + Mat mpart = m.rowRange(0, r); + copyTo(mpart); + } + *this = m; + size.p[0] = r; + dataend = data + step.p[0]*r; +} + + +void Mat::resize(size_t nelems) +{ + int saveRows = size.p[0]; + CV_Assert( (int)nelems >= 0 ); + + if( isSubmatrix() || data + step.p[0]*nelems > datalimit ) + reserve(nelems); + + size.p[0] = (int)nelems; + dataend += (size.p[0] - saveRows)*step.p[0]; + + //updateContinuityFlag(*this); +} + + +void Mat::resize(size_t nelems, const Scalar& s) +{ + int saveRows = size.p[0]; + resize(nelems); + + if( size.p[0] > saveRows ) + { + Mat part = rowRange(saveRows, size.p[0]); + part = s; + } +} + +void Mat::push_back(const Mat& elems) +{ + int r = size.p[0], delta = elems.size.p[0]; + if( delta == 0 ) + return; + if( this != &elems ) + { + size.p[0] = elems.size.p[0]; + bool eq = size == elems.size; + size.p[0] = r; + if( !eq ) + CV_Error(CV_StsUnmatchedSizes, ""); + if( type() != elems.type() ) + CV_Error(CV_StsUnmatchedFormats, ""); + } + + if( isSubmatrix() || dataend + step.p[0]*delta > datalimit ) + reserve( std::max(r + delta, (r*3+1)/2) ); + + size.p[0] += delta; + dataend += step.p[0]*delta; + + //updateContinuityFlag(*this); + + if( isContinuous() && elems.isContinuous() ) + memcpy(data + r*step.p[0], elems.data, elems.total()*elems.elemSize()); + else + { + Mat part = rowRange(r, r + delta); + elems.copyTo(part); + } +} + Mat cvarrToMat(const CvArr* arr, bool copyData, bool allowND, int coiMode) diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 0e09624..4bf4dff 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -3328,7 +3328,7 @@ cvGetFileNodeName( const CvFileNode* file_node ) static int icvIsMat( const void* ptr ) { - return CV_IS_MAT_HDR(ptr); + return CV_IS_MAT_HDR_Z(ptr); } static void @@ -3340,7 +3340,7 @@ icvWriteMat( CvFileStorage* fs, const char* name, CvSize size; int y; - assert( CV_IS_MAT(mat) ); + assert( CV_IS_MAT_HDR_Z(mat) ); cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_MAT ); cvWriteInt( fs, "rows", mat->rows ); @@ -3349,14 +3349,17 @@ icvWriteMat( CvFileStorage* fs, const char* name, cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW ); size = cvGetSize(mat); - if( CV_IS_MAT_CONT(mat->type) ) + if( size.height > 0 && size.width > 0 && mat->data.ptr ) { - size.width *= size.height; - size.height = 1; - } + if( CV_IS_MAT_CONT(mat->type) ) + { + size.width *= size.height; + size.height = 1; + } - for( y = 0; y < size.height; y++ ) - cvWriteRawData( fs, mat->data.ptr + y*mat->step, size.width, dt ); + for( y = 0; y < size.height; y++ ) + cvWriteRawData( fs, mat->data.ptr + y*mat->step, size.width, dt ); + } cvEndWriteStruct( fs ); cvEndWriteStruct( fs ); } @@ -3379,11 +3382,11 @@ icvReadMat( CvFileStorage* fs, CvFileNode* node ) CvFileNode* data; int rows, cols, elem_type; - rows = cvReadIntByName( fs, node, "rows", 0 ); - cols = cvReadIntByName( fs, node, "cols", 0 ); + rows = cvReadIntByName( fs, node, "rows", -1 ); + cols = cvReadIntByName( fs, node, "cols", -1 ); dt = cvReadStringByName( fs, node, "dt", 0 ); - if( rows == 0 || cols == 0 || dt == 0 ) + if( rows < 0 || cols < 0 || dt < 0 ) CV_Error( CV_StsError, "Some of essential matrix attributes are absent" ); elem_type = icvDecodeSimpleFormat( dt ); @@ -3391,13 +3394,19 @@ icvReadMat( CvFileStorage* fs, CvFileNode* node ) data = cvGetFileNodeByName( fs, node, "data" ); if( !data ) CV_Error( CV_StsError, "The matrix data is not found in file storage" ); - - if( icvFileNodeSeqLen( data ) != rows*cols*CV_MAT_CN(elem_type) ) + + int nelems = icvFileNodeSeqLen( data ); + if( nelems > 0 && nelems != rows*cols*CV_MAT_CN(elem_type) ) CV_Error( CV_StsUnmatchedSizes, - "The matrix size does not match to the number of stored elements" ); - - mat = cvCreateMat( rows, cols, elem_type ); - cvReadRawData( fs, data, mat->data.ptr, dt ); + "The matrix size does not match to the number of stored elements" ); + + if( nelems > 0 ) + { + mat = cvCreateMat( rows, cols, elem_type ); + cvReadRawData( fs, data, mat->data.ptr, dt ); + } + else + mat = cvCreateMatHeader( rows, cols, elem_type ); ptr = mat; return ptr; @@ -3409,7 +3418,7 @@ icvReadMat( CvFileStorage* fs, CvFileNode* node ) static int icvIsMatND( const void* ptr ) { - return CV_IS_MATND(ptr); + return CV_IS_MATND_HDR(ptr); } @@ -3417,13 +3426,13 @@ static void icvWriteMatND( CvFileStorage* fs, const char* name, const void* struct_ptr, CvAttrList /*attr*/ ) { - void* mat = (void*)struct_ptr; + CvMatND* mat = (CvMatND*)struct_ptr; CvMatND stub; CvNArrayIterator iterator; int dims, sizes[CV_MAX_DIM]; char dt[16]; - assert( CV_IS_MATND(mat) ); + assert( CV_IS_MATND_HDR(mat) ); cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_MATND ); dims = cvGetDims( mat, sizes ); @@ -3433,11 +3442,14 @@ icvWriteMatND( CvFileStorage* fs, const char* name, cvWriteString( fs, "dt", icvEncodeFormat( cvGetElemType(mat), dt ), 0 ); cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW ); - cvInitNArrayIterator( 1, &mat, 0, &stub, &iterator ); + if( mat->dim[0].size > 0 && mat->data.ptr ) + { + cvInitNArrayIterator( 1, (CvArr**)&mat, 0, &stub, &iterator ); - do - cvWriteRawData( fs, iterator.ptr[0], iterator.size.width, dt ); - while( cvNextNArraySlice( &iterator )); + do + cvWriteRawData( fs, iterator.ptr[0], iterator.size.width, dt ); + while( cvNextNArraySlice( &iterator )); + } cvEndWriteStruct( fs ); cvEndWriteStruct( fs ); } @@ -3472,16 +3484,25 @@ icvReadMatND( CvFileStorage* fs, CvFileNode* node ) data = cvGetFileNodeByName( fs, node, "data" ); if( !data ) CV_Error( CV_StsError, "The matrix data is not found in file storage" ); - + + + for( total_size = CV_MAT_CN(elem_type), i = 0; i < dims; i++ ) total_size *= sizes[i]; - - if( icvFileNodeSeqLen( data ) != total_size ) + + int nelems = icvFileNodeSeqLen( data ); + + if( nelems > 0 && nelems != total_size ) CV_Error( CV_StsUnmatchedSizes, - "The matrix size does not match to the number of stored elements" ); - - mat = cvCreateMatND( dims, sizes, elem_type ); - cvReadRawData( fs, data, mat->data.ptr, dt ); + "The matrix size does not match to the number of stored elements" ); + + if( nelems > 0 ) + { + mat = cvCreateMatND( dims, sizes, elem_type ); + cvReadRawData( fs, data, mat->data.ptr, dt ); + } + else + mat = cvCreateMatNDHeader( dims, sizes, elem_type ); ptr = mat; return ptr; @@ -5304,12 +5325,12 @@ void read( const FileNode& node, Mat& mat, const Mat& default_mat ) return; } void* obj = cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node); - if(CV_IS_MAT(obj)) + if(CV_IS_MAT_HDR_Z(obj)) { Mat((const CvMat*)obj).copyTo(mat); cvReleaseMat((CvMat**)&obj); } - else if(CV_IS_MATND(obj)) + else if(CV_IS_MATND_HDR(obj)) { Mat((const CvMatND*)obj).copyTo(mat); cvReleaseMatND((CvMatND**)&obj);