From 541441e85b6b38b2660aee26fb3bceebaec78c50 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Tue, 12 Oct 2010 12:31:40 +0000 Subject: [PATCH] united cv::Mat and cv::MatND --- modules/core/include/opencv2/core/core.hpp | 1075 +++++------ modules/core/include/opencv2/core/mat.hpp | 1615 ++++++----------- .../core/include/opencv2/core/operations.hpp | 1 - modules/core/include/opencv2/core/types_c.h | 5 + modules/core/src/arithm.cpp | 286 ++- modules/core/src/convert.cpp | 111 +- modules/core/src/copy.cpp | 56 +- modules/core/src/mathfuncs.cpp | 109 +- modules/core/src/matmul.cpp | 14 +- modules/core/src/matrix.cpp | 1569 ++++++---------- modules/core/src/persistence.cpp | 49 +- modules/core/src/rand.cpp | 23 +- modules/core/src/stat.cpp | 274 ++- 13 files changed, 2428 insertions(+), 2759 deletions(-) diff --git a/modules/core/include/opencv2/core/core.hpp b/modules/core/include/opencv2/core/core.hpp index 0103fc573f..b65a018152 100644 --- a/modules/core/include/opencv2/core/core.hpp +++ b/modules/core/include/opencv2/core/core.hpp @@ -85,9 +85,14 @@ typedef std::string String; typedef std::basic_string WString; class Mat; -class MatND; +class SparseMat; +typedef Mat MatND; + class CV_EXPORTS MatExpr; class CV_EXPORTS MatOp_Base; +class CV_EXPORTS VectorArg; +class CV_EXPORTS MatArg; +class CV_EXPORTS MatConstIterator; template class CV_EXPORTS MatIterator_; template class CV_EXPORTS MatConstIterator_; @@ -1228,7 +1233,7 @@ public: protected: _Tp* obj; //< the object pointer. - int* refcount; //< the associated reference counter + int* refcount; //< the associated bbbbbbbbbbbbbbbbbb reference counter }; //////////////////////////////// Mat //////////////////////////////// @@ -1238,11 +1243,26 @@ enum { MAGIC_MASK=0xFFFF0000, TYPE_MASK=0x00000FFF, DEPTH_MASK=7 }; static inline size_t getElemSize(int type) { return CV_ELEM_SIZE(type); } /*! - The matrix class. + Custom array allocator + +*/ +class CV_EXPORTS ArrayAllocator +{ +public: + ArrayAllocator() {} + virtual ~ArrayAllocator() {} + virtual void allocate(int dims, const int* sizes, int type, int*& refcount, + uchar*& datastart, uchar*& data, size_t* step) = 0; + virtual void deallocate(int* refcount, uchar* datastart, uchar* data) = 0; +}; + +/*! + The n-dimensional matrix class. - The class represents a 2D numerical array that can act as a matrix, image, optical flow map etc. - It is very similar to CvMat type from earlier versions of OpenCV, and similarly to CvMat, - the matrix can be multi-channel. It also fully supports ROI mechanism. + The class represents an n-dimensional dense numerical array that can act as + a matrix, image, optical flow map, 3-focal tensor etc. + It is very similar to CvMat and CvMatND types from earlier versions of OpenCV, + and similarly to those types, the matrix can be multi-channel. It also fully supports ROI mechanism. There are many different ways to create cv::Mat object. Here are the some popular ones:
    @@ -1453,23 +1473,33 @@ class CV_EXPORTS Mat public: //! default constructor Mat(); - //! constructs matrix of the specified size and type + //! constructs 2D matrix of the specified size and type // (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.) Mat(int _rows, int _cols, int _type); Mat(Size _size, int _type); - //! constucts matrix and fills it with the specified value _s. + //! constucts 2D matrix and fills it with the specified value _s. Mat(int _rows, int _cols, int _type, const Scalar& _s); Mat(Size _size, int _type, const Scalar& _s); + + //! constructs n-dimensional matrix + Mat(int _ndims, const int* _sizes, int _type); + Mat(int _ndims, const int* _sizes, int _type, const Scalar& _s); + //! copy constructor Mat(const Mat& m); //! constructor for matrix headers pointing to user-allocated data Mat(int _rows, int _cols, int _type, void* _data, size_t _step=AUTO_STEP); Mat(Size _size, int _type, void* _data, size_t _step=AUTO_STEP); + Mat(int _ndims, const int* _sizes, int _type, void* _data, const size_t* _steps=0); + //! creates a matrix header for a part of the bigger matrix - Mat(const Mat& m, const Range& rowRange, const Range& colRange); + Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all()); Mat(const Mat& m, const Rect& roi); + Mat(const Mat& m, const Range* ranges); //! converts old-style CvMat to the new matrix; the data is not copied by default Mat(const CvMat* m, bool copyData=false); + //! converts old-style CvMatND to the new matrix; the data is not copied by default + Mat(const CvMatND* m, bool copyData=false); //! converts old-style IplImage to the new matrix; the data is not copied by default Mat(const IplImage* img, bool copyData=false); //! builds matrix from std::vector with or without copying the data @@ -1481,9 +1511,9 @@ public: template explicit Mat(const Matx<_Tp, m, n>& mtx, bool copyData=true); //! builds matrix from a 2D point - template explicit Mat(const Point_<_Tp>& pt); + template explicit Mat(const Point_<_Tp>& pt, bool copyData=true); //! builds matrix from a 3D point - template explicit Mat(const Point3_<_Tp>& pt); + template explicit Mat(const Point3_<_Tp>& pt, bool copyData=true); //! builds matrix from comma initializer template explicit Mat(const MatCommaInitializer_<_Tp>& commaInitializer); //! destructor - calls release() @@ -1529,6 +1559,7 @@ public: //! creates alternative matrix header for the same data, with different // number of channels and/or different number of rows. see cvReshape. Mat reshape(int _cn, int _rows=0) const; + Mat reshape(int _cn, int _newndims, const int* _newsz) const; //! matrix transposition by means of matrix expressions MatExpr t() const; @@ -1546,8 +1577,10 @@ public: //! Matlab-style matrix initialization static MatExpr zeros(int rows, int cols, int type); static MatExpr zeros(Size size, int type); + static MatExpr zeros(int ndims, const int* sz, int type); static MatExpr ones(int rows, int cols, int type); static MatExpr ones(Size size, int type); + static MatExpr ones(int ndims, const int* sz, int type); static MatExpr eye(int rows, int cols, int type); static MatExpr eye(Size size, int type); @@ -1555,11 +1588,18 @@ public: // previous data is unreferenced if needed. void create(int _rows, int _cols, int _type); void create(Size _size, int _type); + void create(int _ndims, const int* _sizes, int _type); + //! increases the reference counter; use with care to avoid memleaks void addref(); //! decreases reference counter; - // deallocate the data when reference counter reaches 0. + // deallocates the data when reference counter reaches 0. void release(); + + //! deallocates the matrix data + void deallocate(); + //! internal use function; properly re-allocates _size, _step arrays + void copySize(const Mat& m); //! locates matrix header within a parent matrix. See below void locateROI( Size& wholeSize, Point& ofs ) const; @@ -1569,9 +1609,12 @@ public: // (this is a generalized form of row, rowRange etc.) Mat operator()( Range rowRange, Range colRange ) const; Mat operator()( const Rect& roi ) const; + Mat operator()( const Range* ranges ) const; //! converts header to CvMat; no data is copied operator CvMat() const; + //! converts header to CvMatND; no data is copied + operator CvMatND() const; //! converts header to IplImage; no data is copied operator IplImage() const; @@ -1595,30 +1638,67 @@ public: //! returns element type, similar to CV_MAT_CN(cvmat->type) int channels() const; //! returns step/elemSize1() - size_t step1() const; - //! returns matrix size: - // width == number of columns, height == number of rows - Size size() const; + size_t step1(int i=0) const; //! returns true if matrix data is NULL bool empty() const; + //! returns the total number of matrix elements + size_t total() const; - //! returns pointer to y-th row - uchar* ptr(int y=0); - const uchar* ptr(int y=0) const; + //! returns pointer to i0-th submatrix along the dimension #0 + uchar* ptr(int i0=0); + const uchar* ptr(int i0=0) const; + + //! returns pointer to (i0,i1) submatrix along the dimensions #0 and #1 + uchar* ptr(int i0, int i1); + const uchar* ptr(int i0, int i1) const; + + //! returns pointer to (i0,i1,i3) submatrix along the dimensions #0, #1, #2 + uchar* ptr(int i0, int i1, int i2); + const uchar* ptr(int i0, int i1, int i2) const; + + //! returns pointer to the matrix element + uchar* ptr(const int* idx); + //! returns read-only pointer to the matrix element + const uchar* ptr(const int* idx) const; + + template uchar* ptr(const Vec& idx); + template const uchar* ptr(const Vec& idx) const; //! template version of the above method - template _Tp* ptr(int y=0); - template const _Tp* ptr(int y=0) const; + template _Tp* ptr(int i0=0); + template const _Tp* ptr(int i0=0) const; - //! template methods for read-write or read-only element access. - // note that _Tp must match the actual matrix type - - // the functions do not do any on-fly type conversion - template _Tp& at(int y, int x); + template _Tp* ptr(int i0, int i1); + template const _Tp* ptr(int i0, int i1) const; + + template _Tp* ptr(int i0, int i1, int i2); + template const _Tp* ptr(int i0, int i1, int i2) const; + + template _Tp* ptr(const int* idx); + template const _Tp* ptr(const int* idx) const; + + template _Tp* ptr(const Vec& idx); + template const _Tp* ptr(const Vec& idx) const; + + //! the same as above, with the pointer dereferencing + template _Tp& at(int i0=0); + template const _Tp& at(int i0=0) const; + + template _Tp& at(int i0, int i1); + template const _Tp& at(int i0, int i1) const; + + template _Tp& at(int i0, int i1, int i2); + template const _Tp& at(int i0, int i1, int i2) const; + + template _Tp& at(const int* idx); + template const _Tp& at(const int* idx) const; + + template _Tp& at(const Vec& idx); + template const _Tp& at(const Vec& idx) const; + + //! special versions for 2D arrays (especially convenient for referencing image pixels) template _Tp& at(Point pt); - template const _Tp& at(int y, int x) const; template const _Tp& at(Point pt) const; - template _Tp& at(int i); - template const _Tp& at(int i) const; //! template methods for iteration over matrix elements. // the iterators take care of skipping gaps in the end of rows (if any) @@ -1636,10 +1716,10 @@ public: - number of channels */ int flags; - //! the number of rows and columns + //! the matrix dimensionality + int dims; + //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions int rows, cols; - //! a distance between successive rows in bytes; includes the gap if any - size_t step; //! pointer to the data uchar* data; @@ -1650,6 +1730,39 @@ public: //! helper fields used in locateROI and adjustROI uchar* datastart; uchar* dataend; + //! custom allocator + ArrayAllocator* allocator; + + struct CV_EXPORTS MSize + { + MSize(int* _p); + Size operator()() const; + int operator[](int i) const; + int& operator[](int i); + operator const int*() const; + bool operator == (const MSize& sz) const; + bool operator != (const MSize& sz) const; + + int* p; + }; + + struct CV_EXPORTS MStep + { + MStep(); + MStep(size_t s); + size_t operator[](int i) const; + size_t& operator[](int i); + operator size_t() const; + MStep& operator = (size_t s); + + size_t* p; + size_t buf[2]; + protected: + MStep& operator = (const MStep&); + }; + + MSize size; + MStep step; }; @@ -1686,7 +1799,6 @@ public: //! returns uniformly distributed double-precision floating-point random number from [a,b) range double uniform(double a, double b); void fill( Mat& mat, int distType, const Scalar& a, const Scalar& b ); - void fill( MatND& mat, int distType, const Scalar& a, const Scalar& b ); //! returns Gaussian random variate with mean zero. double gaussian(double sigma); @@ -1720,205 +1832,214 @@ public: double epsilon; // the desired accuracy }; +//! swaps two matrices +CV_EXPORTS void swap(Mat& a, Mat& b); + //! converts array (CvMat or IplImage) to cv::Mat -CV_EXPORTS Mat cvarrToMat(const CvArr* arr, bool copyData, - bool allowND, int coiMode); +CV_EXPORTS Mat cvarrToMat(const CvArr* arr, bool copyData=false, + bool allowND=true, int coiMode=0); //! extracts Channel of Interest from CvMat or IplImage and makes cv::Mat out of it. -CV_EXPORTS void extractImageCOI(const CvArr* arr, Mat& coiimg, int coi=-1); +CV_EXPORTS void extractImageCOI(const CvArr* arr, CV_OUT Mat& coiimg, int coi=-1); //! inserts single-channel cv::Mat into a multi-channel CvMat or IplImage CV_EXPORTS void insertImageCOI(const Mat& coiimg, CvArr* arr, int coi=-1); -//! adds one matrix to another (c = a + b) -CV_EXPORTS void add(const Mat& a, const Mat& b, Mat& c, const Mat& mask); -//! subtracts one matrix from another (c = a - b) -CV_EXPORTS void subtract(const Mat& a, const Mat& b, Mat& c, const Mat& mask); -//! adds one matrix to another (c = a + b) -CV_EXPORTS void add(const Mat& a, const Mat& b, Mat& c); -//! subtracts one matrix from another (c = a - b) -CV_EXPORTS void subtract(const Mat& a, const Mat& b, Mat& c); -//! adds scalar to a matrix (c = a + s) -CV_EXPORTS void add(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat()); -//! subtracts scalar from a matrix (c = a - s) -CV_EXPORTS void subtract(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat()); -//! subtracts matrix from scalar (c = s - a) -CV_EXPORTS void subtract(const Scalar& s, const Mat& a, Mat& c, const Mat& mask=Mat()); +//! adds one matrix to another (dst = src1 + src2) +CV_EXPORTS void add(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, const Mat& mask); +//! subtracts one matrix from another (dst = src1 - src2) +CV_EXPORTS void subtract(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, const Mat& mask); +//! adds one matrix to another (dst = src1 + src2) +CV_EXPORTS void add(const Mat& src1, const Mat& src2, CV_OUT Mat& dst); +//! subtracts one matrix from another (dst = src1 - src2) +CV_EXPORTS void subtract(const Mat& src1, const Mat& src2, CV_OUT Mat& dst); +//! adds scalar to a matrix (dst = src1 + src2) +CV_EXPORTS void add(const Mat& src1, const Scalar& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); +//! subtracts scalar from a matrix (dst = src1 - src2) +CV_EXPORTS void subtract(const Mat& src1, const Scalar& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); +//! subtracts matrix from scalar (dst = src1 - src2) +CV_EXPORTS void subtract(const Scalar& src1, const Mat& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); -//! computes element-wise weighted product of the two arrays (c = scale*a*b) -CV_EXPORTS void multiply(const Mat& a, const Mat& b, Mat& c, double scale=1); -//! computes element-wise weighted quotient of the two arrays (c = scale*a/b) -CV_EXPORTS void divide(const Mat& a, const Mat& b, Mat& c, double scale=1); -//! computes element-wise weighted reciprocal of an array (c = scale/b) -CV_EXPORTS void divide(double scale, const Mat& b, Mat& c); +//! computes element-wise weighted product of the two arrays (dst = scale*src1*src2) +CV_EXPORTS void multiply(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, double scale=1); +//! computes element-wise weighted quotient of the two arrays (dst = scale*src1/src2) +CV_EXPORTS void divide(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, double scale=1); +//! computes element-wise weighted reciprocal of an array (dst = scale/src2) +CV_EXPORTS void divide(double scale, const Mat& src2, CV_OUT Mat& dst); -//! adds scaled array to another one (c = a*alpha + b) -CV_EXPORTS void scaleAdd(const Mat& a, double alpha, const Mat& b, Mat& c); -//! computes weighted sum of two arrays (c=alpha*a + beta*b + gamma) -CV_EXPORTS void addWeighted(const Mat& a, double alpha, const Mat& b, - double beta, double gamma, Mat& c); -//! scales array elements, computes absolute values and converts the results to 8-bit unsigned integers: c(i)=saturate_castabs(a(i)*alpha+beta) -CV_EXPORTS void convertScaleAbs(const Mat& a, Mat& c, double alpha=1, double beta=0); -//! transforms 8-bit unsigned integers using lookup table: b(i)=lut(a(i)) -CV_EXPORTS void LUT(const Mat& a, const Mat& lut, Mat& b); +//! adds scaled array to another one (dst = alpha*src1 + src2) +CV_EXPORTS void scaleAdd(const Mat& src1, double alpha, const Mat& src2, CV_OUT Mat& dst); +//! computes weighted sum of two arrays (dst = alpha*src1 + beta*src2 + gamma) +CV_EXPORTS void addWeighted(const Mat& src1, double alpha, const Mat& src2, + double beta, double gamma, CV_OUT Mat& dst); +//! scales array elements, computes absolute values and converts the results to 8-bit unsigned integers: dst(i)=saturate_castabs(src(i)*alpha+beta) +CV_EXPORTS void convertScaleAbs(const Mat& src, CV_OUT Mat& dst, double alpha=1, double beta=0); +//! transforms 8-bit unsigned integers using lookup table: dst(i)=lut(src(i)) +CV_EXPORTS void LUT(const Mat& src, const Mat& lut, CV_OUT Mat& dst); //! computes sum of array elements -CV_EXPORTS Scalar sum(const Mat& m); +CV_EXPORTS Scalar sum(const Mat& src); //! computes the number of nonzero array elements -CV_EXPORTS int countNonZero( const Mat& m ); +CV_EXPORTS int countNonZero( const Mat& src ); //! computes mean value of array elements -CV_EXPORTS Scalar mean(const Mat& m); +CV_EXPORTS Scalar mean(const Mat& src); //! computes mean value of selected array elements -CV_EXPORTS Scalar mean(const Mat& m, const Mat& mask); +CV_EXPORTS Scalar mean(const Mat& src, const Mat& mask); //! computes mean value and standard deviation of all or selected array elements -CV_EXPORTS void meanStdDev(const Mat& m, Scalar& mean, Scalar& stddev, const Mat& mask=Mat()); +CV_EXPORTS void meanStdDev(const Mat& src, CV_OUT Scalar& mean, CV_OUT Scalar& stddev, const Mat& mask=Mat()); //! computes norm of array -CV_EXPORTS double norm(const Mat& a, int normType=NORM_L2); +CV_EXPORTS double norm(const Mat& src, int normType=NORM_L2); //! computes norm of the difference between two arrays -CV_EXPORTS double norm(const Mat& a, const Mat& b, int normType=NORM_L2); +CV_EXPORTS double norm(const Mat& src1, const Mat& src2, int normType=NORM_L2); //! computes norm of the selected array part -CV_EXPORTS double norm(const Mat& a, int normType, const Mat& mask); +CV_EXPORTS double norm(const Mat& src, int normType, const Mat& mask); //! computes norm of selected part of the difference between two arrays -CV_EXPORTS double norm(const Mat& a, const Mat& b, +CV_EXPORTS double norm(const Mat& src1, const Mat& src2, int normType, const Mat& mask); //! scales and shifts array elements so that either the specified norm (alpha) or the minimum (alpha) and maximum (beta) array values get the specified values -CV_EXPORTS void normalize( const Mat& a, Mat& b, double alpha=1, double beta=0, - int norm_type=NORM_L2, int rtype=-1, const Mat& mask=Mat()); +CV_EXPORTS void normalize( const Mat& src, CV_OUT Mat& dst, double alpha=1, double beta=0, + int norm_type=NORM_L2, int rtype=-1, const Mat& mask=Mat()); //! finds global minimum and maximum array elements and returns their values and their locations -CV_EXPORTS void minMaxLoc(const Mat& a, double* minVal, - double* maxVal=0, Point* minLoc=0, - Point* maxLoc=0, const Mat& mask=Mat()); +CV_EXPORTS void minMaxLoc(const Mat& src, CV_OUT double* minVal, + CV_OUT double* maxVal=0, CV_OUT Point* minLoc=0, + CV_OUT Point* maxLoc=0, const Mat& mask=Mat()); +CV_EXPORTS void minMaxIdx(const Mat& src, double* minVal, + double* maxVal, + CV_OUT CV_CARRAY(src.dims) int* minIdx=0, + CV_OUT CV_CARRAY(src.dims) int* maxIdx=0, + const Mat& mask=Mat()); + //! transforms 2D matrix to 1D row or column vector by taking sum, minimum, maximum or mean value over all the rows -CV_EXPORTS void reduce(const Mat& m, Mat& dst, int dim, int rtype, int dtype=-1); +CV_EXPORTS void reduce(const Mat& src, CV_OUT Mat& dst, int dim, int rtype, int dtype=-1); //! makes multi-channel array out of several single-channel arrays -CV_EXPORTS void merge(const Mat* mv, size_t count, Mat& dst); +CV_EXPORTS void merge(CV_CARRAY(count) const Mat* mv, size_t count, CV_OUT Mat& dst); //! copies each plane of a multi-channel array to a dedicated array -CV_EXPORTS void split(const Mat& m, Mat* mvbegin); +CV_EXPORTS void split(const Mat& src, CV_OUT CV_CARRAY(src.channels()) Mat* mvbegin); //! copies selected channels from the input arrays to the selected channels of the output arrays -CV_EXPORTS void mixChannels(const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, - const int* fromTo, size_t npairs); +CV_EXPORTS void mixChannels(CV_CARRAY(nsrcs) const Mat* src, size_t nsrcs, CV_CARRAY(ndsts) Mat* dst, size_t ndsts, + CV_CARRAY(npairs*2) const int* fromTo, size_t npairs); //! reverses the order of the rows, columns or both in a matrix -CV_EXPORTS void flip(const Mat& a, Mat& b, int flipCode); +CV_EXPORTS void flip(const Mat& src, CV_OUT Mat& dst, int flipCode); //! replicates the input matrix the specified number of times in the horizontal and/or vertical direction -CV_EXPORTS void repeat(const Mat& a, int ny, int nx, Mat& b); +CV_EXPORTS void repeat(const Mat& src, int ny, int nx, CV_OUT Mat& dst); static inline Mat repeat(const Mat& src, int ny, int nx) { if( nx == 1 && ny == 1 ) return src; Mat dst; repeat(src, ny, nx, dst); return dst; } -//! computes bitwise conjunction of the two arrays (c = a & b) -CV_EXPORTS void bitwise_and(const Mat& a, const Mat& b, Mat& c, const Mat& mask=Mat()); -//! computes bitwise disjunction of the two arrays (c = a | b) -CV_EXPORTS void bitwise_or(const Mat& a, const Mat& b, Mat& c, const Mat& mask=Mat()); -//! computes bitwise exclusive-or of the two arrays (c = a ^ b) -CV_EXPORTS void bitwise_xor(const Mat& a, const Mat& b, Mat& c, const Mat& mask=Mat()); -//! computes bitwise conjunction of an array and scalar (c = a & s) -CV_EXPORTS void bitwise_and(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat()); -//! computes bitwise disjunction of an array and scalar (c = a | s) -CV_EXPORTS void bitwise_or(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat()); -//! computes bitwise exclusive-or of an array and scalar (c = a ^ s) -CV_EXPORTS void bitwise_xor(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat()); -//! inverts each bit of a (c = ~a) -CV_EXPORTS void bitwise_not(const Mat& a, Mat& c); -//! computes element-wise absolute difference of two arrays (c = abs(a - b)) -CV_EXPORTS void absdiff(const Mat& a, const Mat& b, Mat& c); -//! computes element-wise absolute difference of array and scalar (c = abs(a - s)) -CV_EXPORTS void absdiff(const Mat& a, const Scalar& s, Mat& c); +//! computes bitwise conjunction of the two arrays (dst = src1 & src2) +CV_EXPORTS void bitwise_and(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); +//! computes bitwise disjunction of the two arrays (dst = src1 | src2) +CV_EXPORTS void bitwise_or(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); +//! computes bitwise exclusive-or of the two arrays (dst = src1 ^ src2) +CV_EXPORTS void bitwise_xor(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); +//! computes bitwise conjunction of an array and scalar (dst = src1 & src2) +CV_EXPORTS void bitwise_and(const Mat& src1, const Scalar& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); +//! computes bitwise disjunction of an array and scalar (dst = src1 | src2) +CV_EXPORTS void bitwise_or(const Mat& src1, const Scalar& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); +//! computes bitwise exclusive-or of an array and scalar (dst = src1 ^ src2) +CV_EXPORTS void bitwise_xor(const Mat& src1, const Scalar& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); +//! inverts each bit of array (dst = ~src) +CV_EXPORTS void bitwise_not(const Mat& src, CV_OUT Mat& dst); +//! computes element-wise absolute difference of two arrays (dst = abs(src1 - src2)) +CV_EXPORTS void absdiff(const Mat& src1, const Mat& src2, CV_OUT Mat& dst); +//! computes element-wise absolute difference of array and scalar (dst = abs(src1 - src2)) +CV_EXPORTS void absdiff(const Mat& src1, const Scalar& src2, CV_OUT Mat& dst); //! set mask elements for those array elements which are within the element-specific bounding box (dst = lowerb <= src && src < upperb) CV_EXPORTS void inRange(const Mat& src, const Mat& lowerb, - const Mat& upperb, Mat& dst); + const Mat& upperb, CV_OUT Mat& dst); //! set mask elements for those array elements which are within the fixed bounding box (dst = lowerb <= src && src < upperb) CV_EXPORTS void inRange(const Mat& src, const Scalar& lowerb, - const Scalar& upperb, Mat& dst); -//! compares elements of two arrays (c = a b) -CV_EXPORTS void compare(const Mat& a, const Mat& b, Mat& c, int cmpop); -//! compares elements of array with scalar (c = a s) -CV_EXPORTS void compare(const Mat& a, double s, Mat& c, int cmpop); -//! computes per-element minimum of two arrays (c = min(a, b)) -CV_EXPORTS void min(const Mat& a, const Mat& b, Mat& c); -//! computes per-element minimum of array and scalar (c = min(a, alpha)) -CV_EXPORTS void min(const Mat& a, double alpha, Mat& c); -//! computes per-element maximum of two arrays (c = max(a, b)) -CV_EXPORTS void max(const Mat& a, const Mat& b, Mat& c); -//! computes per-element maximum of array and scalar (c = max(a, alpha)) -CV_EXPORTS void max(const Mat& a, double alpha, Mat& c); + const Scalar& upperb, CV_OUT Mat& dst); +//! compares elements of two arrays (dst = src1 src2) +CV_EXPORTS void compare(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, int cmpop); +//! compares elements of array with scalar (dst = src1 src2) +CV_EXPORTS void compare(const Mat& src1, double s, CV_OUT Mat& dst, int cmpop); +//! computes per-element minimum of two arrays (dst = min(src1, src2)) +CV_EXPORTS void min(const Mat& src1, const Mat& src2, CV_OUT Mat& dst); +//! computes per-element minimum of array and scalar (dst = min(src1, src2)) +CV_EXPORTS void min(const Mat& src1, double src2, CV_OUT Mat& dst); +//! computes per-element maximum of two arrays (dst = max(src1, src2)) +CV_EXPORTS void max(const Mat& src1, const Mat& src2, CV_OUT Mat& dst); +//! computes per-element maximum of array and scalar (dst = max(src1, src2)) +CV_EXPORTS void max(const Mat& src1, double src2, CV_OUT Mat& dst); -//! computes square root of each matrix element (b = a**0.5) -CV_EXPORTS void sqrt(const Mat& a, Mat& b); +//! computes square root of each matrix element (dst = src**0.5) +CV_EXPORTS void sqrt(const Mat& src, CV_OUT Mat& dst); //! raises the input matrix elements to the specified power (b = a**power) -CV_EXPORTS void pow(const Mat& a, double power, Mat& b); -//! computes exponent of each matrix element (b = e**a) -CV_EXPORTS void exp(const Mat& a, Mat& b); -//! computes natural logarithm of absolute value of each matrix element: b = log(abs(a)) -CV_EXPORTS void log(const Mat& a, Mat& b); +CV_EXPORTS void pow(const Mat& src, double power, CV_OUT Mat& dst); +//! computes exponent of each matrix element (dst = e**src) +CV_EXPORTS void exp(const Mat& src, CV_OUT Mat& dst); +//! computes natural logarithm of absolute value of each matrix element: dst = log(abs(src)) +CV_EXPORTS void log(const Mat& src, CV_OUT Mat& dst); //! computes cube root of the argument CV_EXPORTS float cubeRoot(float val); //! computes the angle in degrees (0..360) of the vector (x,y) CV_EXPORTS float fastAtan2(float y, float x); //! converts polar coordinates to Cartesian CV_EXPORTS void polarToCart(const Mat& magnitude, const Mat& angle, - Mat& x, Mat& y, bool angleInDegrees=false); + CV_OUT Mat& x, CV_OUT Mat& y, bool angleInDegrees=false); //! converts Cartesian coordinates to polar CV_EXPORTS void cartToPolar(const Mat& x, const Mat& y, - Mat& magnitude, Mat& angle, + CV_OUT Mat& magnitude, CV_OUT Mat& angle, bool angleInDegrees=false); //! computes angle (angle(i)) of each (x(i), y(i)) vector -CV_EXPORTS void phase(const Mat& x, const Mat& y, Mat& angle, +CV_EXPORTS void phase(const Mat& x, const Mat& y, CV_OUT Mat& angle, bool angleInDegrees=false); //! computes magnitude (magnitude(i)) of each (x(i), y(i)) vector -CV_EXPORTS void magnitude(const Mat& x, const Mat& y, Mat& magnitude); +CV_EXPORTS void magnitude(const Mat& x, const Mat& y, CV_OUT Mat& magnitude); //! checks that each matrix element is within the specified range. -CV_EXPORTS bool checkRange(const Mat& a, bool quiet=true, Point* pt=0, +CV_EXPORTS bool checkRange(const Mat& a, bool quiet=true, CV_OUT Point* pt=0, double minVal=-DBL_MAX, double maxVal=DBL_MAX); //! implements generalized matrix product algorithm GEMM from BLAS -CV_EXPORTS void gemm(const Mat& a, const Mat& b, double alpha, - const Mat& c, double gamma, Mat& d, int flags=0); +CV_EXPORTS void gemm(const Mat& src1, const Mat& src2, double alpha, + const Mat& src3, double gamma, CV_OUT Mat& dst, int flags=0); //! multiplies matrix by its transposition from the left or from the right -CV_EXPORTS void mulTransposed( const Mat& a, Mat& c, bool aTa, +CV_EXPORTS void mulTransposed( const Mat& src, CV_OUT Mat& dst, bool aTa, const Mat& delta=Mat(), double scale=1, int rtype=-1 ); //! transposes the matrix -CV_EXPORTS void transpose(const Mat& a, Mat& b); +CV_EXPORTS void transpose(const Mat& src, CV_OUT Mat& dst); //! performs affine transformation of each element of multi-channel input matrix -CV_EXPORTS void transform(const Mat& src, Mat& dst, const Mat& m ); +CV_EXPORTS void transform(const Mat& src, CV_OUT Mat& dst, const Mat& m ); //! performs perspective transformation of each element of multi-channel input matrix -CV_EXPORTS void perspectiveTransform(const Mat& src, Mat& dst, const Mat& m ); +CV_EXPORTS void perspectiveTransform(const Mat& src, CV_OUT Mat& dst, const Mat& m ); //! extends the symmetrical matrix from the lower half or from the upper half -CV_EXPORTS void completeSymm(Mat& a, bool lowerToUpper=false); +CV_EXPORTS void completeSymm(Mat& mtx, bool lowerToUpper=false); //! initializes scaled identity matrix -CV_EXPORTS void setIdentity(Mat& c, const Scalar& s=Scalar(1)); +CV_EXPORTS void setIdentity(Mat& mtx, const Scalar& s=Scalar(1)); //! computes determinant of a square matrix -CV_EXPORTS double determinant(const Mat& m); +CV_EXPORTS double determinant(const Mat& mtx); //! computes trace of a matrix -CV_EXPORTS Scalar trace(const Mat& m); +CV_EXPORTS Scalar trace(const Mat& mtx); //! computes inverse or pseudo-inverse matrix -CV_EXPORTS double invert(const Mat& a, Mat& c, int flags=DECOMP_LU); +CV_EXPORTS double invert(const Mat& src, CV_OUT Mat& dst, int flags=DECOMP_LU); //! solves linear system or a least-square problem -CV_EXPORTS bool solve(const Mat& a, const Mat& b, Mat& x, int flags=DECOMP_LU); +CV_EXPORTS bool solve(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, int flags=DECOMP_LU); //! sorts independently each matrix row or each matrix column -CV_EXPORTS void sort(const Mat& a, Mat& b, int flags); +CV_EXPORTS void sort(const Mat& src, CV_OUT Mat& dst, int flags); //! sorts independently each matrix row or each matrix column -CV_EXPORTS void sortIdx(const Mat& a, Mat& b, int flags); +CV_EXPORTS void sortIdx(const Mat& src, CV_OUT Mat& dst, int flags); //! finds real roots of a cubic polynomial -CV_EXPORTS int solveCubic(const Mat& coeffs, Mat& roots); +CV_EXPORTS int solveCubic(const Mat& coeffs, CV_OUT Mat& roots); //! finds real and complex roots of a polynomial -CV_EXPORTS double solvePoly(const Mat& coeffs, Mat& roots, int maxIters=300); +CV_EXPORTS double solvePoly(const Mat& coeffs, CV_OUT Mat& roots, int maxIters=300); //! finds eigenvalues of a symmetric matrix -CV_EXPORTS bool eigen(const Mat& a, Mat& eigenvalues, int lowindex=-1, +CV_EXPORTS bool eigen(const Mat& src, CV_OUT Mat& eigenvalues, int lowindex=-1, int highindex=-1); //! finds eigenvalues and eigenvectors of a symmetric matrix -CV_EXPORTS bool eigen(const Mat& a, Mat& eigenvalues, Mat& eigenvectors, +CV_EXPORTS bool eigen(const Mat& src, CV_OUT Mat& eigenvalues, CV_OUT Mat& eigenvectors, int lowindex=-1, int highindex=-1); //! computes covariation matrix of a set of samples -CV_EXPORTS void calcCovarMatrix( const Mat* samples, int nsamples, - Mat& covar, Mat& mean, +CV_EXPORTS void calcCovarMatrix( CV_CARRAY(nsamples) const Mat* samples, int nsamples, + CV_OUT Mat& covar, CV_OUT Mat& mean, int flags, int ctype=CV_64F); //! computes covariation matrix of a set of samples -CV_EXPORTS void calcCovarMatrix( const Mat& samples, Mat& covar, Mat& mean, +CV_EXPORTS void calcCovarMatrix( const Mat& samples, CV_OUT Mat& covar, CV_OUT Mat& mean, int flags, int ctype=CV_64F); /*! @@ -1987,11 +2108,11 @@ public: //! projects vector from the original space to the principal components subspace Mat project(const Mat& vec) const; //! projects vector from the original space to the principal components subspace - void project(const Mat& vec, Mat& result) const; + void project(const Mat& vec, CV_OUT Mat& result) const; //! reconstructs the original vector from the projection Mat backProject(const Mat& vec) const; //! reconstructs the original vector from the projection - void backProject(const Mat& vec, Mat& result) const; + void backProject(const Mat& vec, CV_OUT Mat& result) const; Mat eigenvectors; //!< eigenvectors of the covariation matrix Mat eigenvalues; //!< eigenvalues of the covariation matrix @@ -2018,17 +2139,17 @@ public: //! the default constructor SVD(); //! the constructor that performs SVD - SVD( const Mat& m, int flags=0 ); + SVD( const Mat& src, int flags=0 ); //! the operator that performs SVD. The previously allocated SVD::u, SVD::w are SVD::vt are released. - SVD& operator ()( const Mat& m, int flags=0 ); + SVD& operator ()( const Mat& src, int flags=0 ); //! decomposes matrix and stores the results to user-provided matrices - static void compute( const Mat& m, Mat& w, Mat& u, Mat& vt, int flags=0 ); + static void compute( const Mat& src, CV_OUT Mat& w, CV_OUT Mat& u, CV_OUT Mat& vt, int flags=0 ); //! computes singular values of a matrix - static void compute( const Mat& m, Mat& w, int flags=0 ); + static void compute( const Mat& src, CV_OUT Mat& w, int flags=0 ); //! performs back substitution static void backSubst( const Mat& w, const Mat& u, const Mat& vt, - const Mat& rhs, Mat& dst ); + const Mat& rhs, CV_OUT Mat& dst ); template static void compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w, Matx<_Tp, m, nm>& u, Matx<_Tp, n, nm>& vt ); @@ -2038,9 +2159,9 @@ public: const Matx<_Tp, m, nm>& u, const Matx<_Tp, n, nm>& vt, const Matx<_Tp, m, nb>& rhs, Matx<_Tp, n, nb>& dst ); //! finds dst = arg min_{|dst|=1} |m*dst| - static void solveZ( const Mat& m, Mat& dst ); + static void solveZ( const Mat& src, CV_OUT Mat& dst ); //! performs back substitution, so that dst is the solution or pseudo-solution of m*dst = rhs, where m is the decomposed matrix - void backSubst( const Mat& rhs, Mat& dst ) const; + void backSubst( const Mat& rhs, CV_OUT Mat& dst ) const; Mat u, w, vt; }; @@ -2052,15 +2173,15 @@ static inline double Mahalonobis(const Mat& v1, const Mat& v2, const Mat& icovar { return Mahalanobis(v1, v2, icovar); } //! performs forward or inverse 1D or 2D Discrete Fourier Transformation -CV_EXPORTS void dft(const Mat& src, Mat& dst, int flags=0, int nonzeroRows=0); +CV_EXPORTS void dft(const Mat& src, CV_OUT Mat& dst, int flags=0, int nonzeroRows=0); //! performs inverse 1D or 2D Discrete Fourier Transformation -CV_EXPORTS void idft(const Mat& src, Mat& dst, int flags=0, int nonzeroRows=0); +CV_EXPORTS void idft(const Mat& src, CV_OUT Mat& dst, int flags=0, int nonzeroRows=0); //! performs forward or inverse 1D or 2D Discrete Cosine Transformation -CV_EXPORTS void dct(const Mat& src, Mat& dst, int flags=0); +CV_EXPORTS void dct(const Mat& src, CV_OUT Mat& dst, int flags=0); //! performs inverse 1D or 2D Discrete Cosine Transformation -CV_EXPORTS void idct(const Mat& src, Mat& dst, int flags=0); +CV_EXPORTS void idct(const Mat& src, CV_OUT Mat& dst, int flags=0); //! computes element-wise product of the two Fourier spectrums. The second spectrum can optionally be conjugated before the multiplication -CV_EXPORTS void mulSpectrums(const Mat& a, const Mat& b, Mat& c, +CV_EXPORTS void mulSpectrums(const Mat& a, const Mat& b, CV_OUT Mat& c, int flags, bool conjB=false); //! computes the minimal vector size vecsize1 >= vecsize so that the dft() of the vector of length vecsize1 can be computed efficiently CV_EXPORTS int getOptimalDFTSize(int vecsize); @@ -2075,9 +2196,9 @@ enum KMEANS_USE_INITIAL_LABELS=1 // Uses the user-provided labels for K-Means initialization }; //! clusters the input data using k-Means algorithm -CV_EXPORTS double kmeans( const Mat& data, int K, Mat& bestLabels, +CV_EXPORTS double kmeans( const Mat& data, int K, CV_OUT Mat& bestLabels, TermCriteria criteria, int attempts, - int flags, Mat* centers ); + int flags, CV_OUT Mat* centers=0 ); //! returns the thread-local Random number generator CV_EXPORTS RNG& theRNG(); @@ -2086,11 +2207,11 @@ CV_EXPORTS RNG& theRNG(); template static inline _Tp randu() { return (_Tp)theRNG(); } //! fills array with uniformly-distributed random numbers from the range [low, high) -static inline void randu(Mat& dst, const Scalar& low, const Scalar& high) +static inline void randu(CV_OUT Mat& dst, const Scalar& low, const Scalar& high) { theRNG().fill(dst, RNG::UNIFORM, low, high); } //! fills array with normally-distributed random numbers with the specified mean and the standard deviation -static inline void randn(Mat& dst, const Scalar& mean, const Scalar& stddev) +static inline void randn(CV_OUT Mat& dst, const Scalar& mean, const Scalar& stddev) { theRNG().fill(dst, RNG::NORMAL, mean, stddev); } //! shuffles the input array elements @@ -2126,18 +2247,20 @@ CV_EXPORTS void ellipse(Mat& img, const RotatedRect& box, const Scalar& color, int thickness=1, int lineType=8); //! draws a filled convex polygon in the image -CV_EXPORTS void fillConvexPoly(Mat& img, const Point* pts, int npts, +CV_EXPORTS void fillConvexPoly(Mat& img, CV_CARRAY(npts) const Point* pts, int npts, const Scalar& color, int lineType=8, int shift=0); //! fills an area bounded by one or more polygons -CV_EXPORTS void fillPoly(Mat& img, const Point** pts, const int* npts, int ncontours, +CV_EXPORTS void fillPoly(Mat& img, CV_CARRAY(ncontours) 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, const Point** pts, const int* npts, int ncontours, bool isClosed, - const Scalar& color, int thickness=1, int lineType=8, int shift=0 ); +CV_EXPORTS void polylines(Mat& img, CV_CARRAY(ncontours) 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 ); //! clips the line segment by the rectangle Rect(0, 0, imgSize.width, imgSize.height) CV_EXPORTS bool clipLine(Size imgSize, Point& pt1, Point& pt2); @@ -2155,8 +2278,8 @@ class CV_EXPORTS LineIterator { public: //! intializes the iterator - LineIterator(const Mat& img, Point pt1, Point pt2, - int connectivity=8, bool leftToRight=false); + LineIterator( const Mat& img, Point pt1, Point pt2, + int connectivity=8, bool leftToRight=false ); //! returns pointer to the current pixel uchar* operator *(); //! prefix increment operator (++it). shifts iterator to the next pixel @@ -2176,7 +2299,7 @@ public: //! converts elliptic arc to a polygonal curve CV_EXPORTS void ellipse2Poly( Point center, Size axes, int angle, - int arcStart, int arcEnd, int delta, vector& pts ); + int arcStart, int arcEnd, int delta, CV_OUT vector& pts ); enum { @@ -2200,7 +2323,7 @@ CV_EXPORTS void putText( Mat& img, const string& text, Point org, //! returns bounding box of the text string CV_EXPORTS Size getTextSize(const string& text, int fontFace, double fontScale, int thickness, - int* baseLine); + CV_OUT int* baseLine); ///////////////////////////////// Mat_<_Tp> //////////////////////////////////// @@ -2267,22 +2390,30 @@ public: explicit Mat_(Size _size); //! constructor that sets each matrix element to specified value Mat_(Size _size, const _Tp& value); + //! n-dim array constructor + Mat_(int _ndims, const int* _sizes); + //! n-dim array constructor that sets each matrix element to specified value + Mat_(int _ndims, const int* _sizes, const _Tp& value); //! copy/conversion contructor. If m is of different type, it's converted Mat_(const Mat& m); //! copy constructor Mat_(const Mat_& m); //! constructs a matrix on top of user-allocated data. step is in bytes(!!!), regardless of the type Mat_(int _rows, int _cols, _Tp* _data, size_t _step=AUTO_STEP); + //! constructs n-dim matrix on top of user-allocated data. steps are in bytes(!!!), regardless of the type + Mat_(int _ndims, const int* _sizes, _Tp* _data, const size_t* _steps=0); //! selects a submatrix - Mat_(const Mat_& m, const Range& rowRange, const Range& colRange); + Mat_(const Mat_& m, const Range& rowRange, const Range& colRange=Range::all()); //! selects a submatrix Mat_(const Mat_& m, const Rect& roi); + //! selects a submatrix, n-dim version + Mat_(const Mat_& m, const Range* ranges); //! makes a matrix out of Vec, std::vector, Point_ or Point3_. The matrix will have a single column explicit Mat_(const vector<_Tp>& vec, bool copyData=false); template explicit Mat_(const Vec<_Tp, n>& vec, bool copyData=true); template explicit Mat_(const Matx<_Tp, m, n>& mtx, bool copyData=true); - explicit Mat_(const Point_<_Tp>& pt); - explicit Mat_(const Point3_<_Tp>& pt); + explicit Mat_(const Point_<_Tp>& pt, bool copyData=true); + explicit Mat_(const Point3_<_Tp>& pt, bool copyData=true); explicit Mat_(const MatCommaInitializer_<_Tp>& commaInitializer); Mat_& operator = (const Mat& m); @@ -2300,6 +2431,8 @@ public: void create(int _rows, int _cols); //! equivalent to Mat::create(_size, DataType<_Tp>::type) void create(Size _size); + //! equivalent to Mat::create(_ndims, _sizes, DatType<_Tp>::type) + void create(int _ndims, const int* _sizes); //! cross-product Mat_ cross(const Mat_& m) const; //! to support complex matrix expressions @@ -2318,15 +2451,17 @@ public: int type() const; int depth() const; int channels() const; - size_t step1() const; + size_t step1(int i=0) const; //! returns step()/sizeof(_Tp) - size_t stepT() const; + size_t stepT(int i=0) const; //! overridden forms of Mat::zeros() etc. Data type is omitted, of course static MatExpr zeros(int rows, int cols); static MatExpr zeros(Size size); + static MatExpr zeros(int _ndims, const int* _sizes); static MatExpr ones(int rows, int cols); static MatExpr ones(Size size); + static MatExpr ones(int _ndims, const int* _sizes); static MatExpr eye(int rows, int cols); static MatExpr eye(Size size); @@ -2335,17 +2470,37 @@ public: Mat_& adjustROI( int dtop, int dbottom, int dleft, int dright ); Mat_ operator()( const Range& rowRange, const Range& colRange ) const; Mat_ operator()( const Rect& roi ) const; + Mat_ operator()( const Range* ranges ) const; //! more convenient forms of row and element access operators _Tp* operator [](int y); const _Tp* operator [](int y) const; - _Tp& operator ()(int row, int col); - const _Tp& operator ()(int row, int col) const; + //! returns reference to the specified element + _Tp& operator ()(const int* idx); + //! returns read-only reference to the specified element + const _Tp& operator ()(const int* idx) const; + + //! returns reference to the specified element + template _Tp& operator ()(const Vec& idx); + //! returns read-only reference to the specified element + template const _Tp& operator ()(const Vec& idx) const; + + //! returns reference to the specified element (1D case) + _Tp& operator ()(int idx0); + //! returns read-only reference to the specified element (1D case) + const _Tp& operator ()(int idx0) const; + //! returns reference to the specified element (2D case) + _Tp& operator ()(int idx0, int idx1); + //! returns read-only reference to the specified element (2D case) + const _Tp& operator ()(int idx0, int idx1) const; + //! returns reference to the specified element (3D case) + _Tp& operator ()(int idx0, int idx1, int idx2); + //! returns read-only reference to the specified element (3D case) + const _Tp& operator ()(int idx0, int idx1, int idx2) const; + _Tp& operator ()(Point pt); const _Tp& operator ()(Point pt) const; - _Tp& operator ()(int i); - const _Tp& operator ()(int i) const; //! conversion to vector. operator vector<_Tp>() const; @@ -2387,16 +2542,72 @@ typedef Mat_ Mat4d; //////////// Iterators & Comma initializers ////////////////// +class CV_EXPORTS MatConstIterator +{ +public: + typedef uchar* value_type; + typedef ptrdiff_t difference_type; + typedef const uchar** pointer; + typedef uchar* reference; + typedef std::random_access_iterator_tag iterator_category; + + //! default constructor + MatConstIterator(); + //! constructor that sets the iterator to the beginning of the matrix + MatConstIterator(const Mat* _m); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator(const Mat* _m, int _row, int _col=0); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator(const Mat* _m, Point _pt); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator(const Mat* _m, const int* _idx); + //! copy constructor + MatConstIterator(const MatConstIterator& it); + + //! copy operator + MatConstIterator& operator = (const MatConstIterator& it); + //! returns the current matrix element + uchar* operator *() const; + //! returns the i-th matrix element, relative to the current + uchar* operator [](ptrdiff_t i) const; + + //! shifts the iterator forward by the specified number of elements + MatConstIterator& operator += (ptrdiff_t ofs); + //! shifts the iterator backward by the specified number of elements + MatConstIterator& operator -= (ptrdiff_t ofs); + //! decrements the iterator + MatConstIterator& operator --(); + //! decrements the iterator + MatConstIterator operator --(int); + //! increments the iterator + MatConstIterator& operator ++(); + //! increments the iterator + MatConstIterator operator ++(int); + //! returns the current iterator position + Point pos() const; + //! returns the current iterator position + void pos(int* _idx) const; + ptrdiff_t lpos() const; + void seek(ptrdiff_t ofs, bool relative=false); + void seek(const int* _idx, bool relative=false); + + const Mat* m; + size_t elemSize; + uchar* ptr; + uchar* sliceStart; + uchar* sliceEnd; +}; + /*! Matrix read-only iterator - */ + */ template -class CV_EXPORTS MatConstIterator_ +class CV_EXPORTS MatConstIterator_ : public MatConstIterator { public: typedef _Tp value_type; - typedef int difference_type; + typedef ptrdiff_t difference_type; typedef const _Tp* pointer; typedef const _Tp& reference; typedef std::random_access_iterator_tag iterator_category; @@ -2409,6 +2620,8 @@ public: MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col=0); //! constructor that sets the iterator to the specified element of the matrix MatConstIterator_(const Mat_<_Tp>* _m, Point _pt); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator_(const Mat_<_Tp>* _m, const int* _idx); //! copy constructor MatConstIterator_(const MatConstIterator_& it); @@ -2417,12 +2630,12 @@ public: //! returns the current matrix element _Tp operator *() const; //! returns the i-th matrix element, relative to the current - _Tp operator [](int i) const; + _Tp operator [](ptrdiff_t i) const; //! shifts the iterator forward by the specified number of elements - MatConstIterator_& operator += (int ofs); + MatConstIterator_& operator += (ptrdiff_t ofs); //! shifts the iterator backward by the specified number of elements - MatConstIterator_& operator -= (int ofs); + MatConstIterator_& operator -= (ptrdiff_t ofs); //! decrements the iterator MatConstIterator_& operator --(); //! decrements the iterator @@ -2433,10 +2646,6 @@ public: MatConstIterator_ operator ++(int); //! returns the current iterator position Point pos() const; - - const Mat_<_Tp>* m; - _Tp* ptr; - _Tp* sliceEnd; }; @@ -2460,6 +2669,8 @@ public: MatIterator_(Mat_<_Tp>* _m, int _row, int _col=0); //! constructor that sets the iterator to the specified element of the matrix MatIterator_(const Mat_<_Tp>* _m, Point _pt); + //! constructor that sets the iterator to the specified element of the matrix + MatIterator_(const Mat_<_Tp>* _m, const int* _idx); //! copy constructor MatIterator_(const MatIterator_& it); //! copy operator @@ -2468,12 +2679,12 @@ public: //! returns the current matrix element _Tp& operator *() const; //! returns the i-th matrix element, relative to the current - _Tp& operator [](int i) const; + _Tp& operator [](ptrdiff_t i) const; //! shifts the iterator forward by the specified number of elements - MatIterator_& operator += (int ofs); + MatIterator_& operator += (ptrdiff_t ofs); //! shifts the iterator backward by the specified number of elements - MatIterator_& operator -= (int ofs); + MatIterator_& operator -= (ptrdiff_t ofs); //! decrements the iterator MatIterator_& operator --(); //! decrements the iterator @@ -2598,190 +2809,10 @@ protected: /////////////////////////// multi-dimensional dense matrix ////////////////////////// -class MatND; -class SparseMat; - -/*! - n-Dimensional Dense Matrix Class. - - The class cv::MatND describes n-dimensional dense numerical single-channel or multi-channel array. - This is a convenient representation for multi-dimensional histograms - (when they are not very sparse, otherwise cv::SparseMat will do better), - voxel volumes, stacked motion fields etc. The data layout of matrix M is defined by the array of M.step[], - so that the address of element (i_0,...,i_{M.dims-1}), where 0 <= i_k < M.size[k] is computed as: - - addr(M_{i_0,...,i_{M.dims-1}}) = M.data + M.step[0]*i_0 + M.step[1]*i_1 + ... + M.step[M.dims-1]*i_{M.dims-1} - - which is more general form of the respective formula for cv::Mat, wherein size[0] ~ rows, - size[1] ~ cols, step[0] was simply called step, and step[1] was not stored at all but computed as Mat::elemSize(). - - In other aspects cv::MatND is also very similar to cv::Mat, with the following limitations and differences: -
      -
    • much less operations are implemented for cv::MatND -
    • currently, algebraic expressions with cv::MatND's are not supported -
    • the cv::MatND iterator is completely different from cv::Mat_ and cv::SparseMat_ iterators. - The latter are per-element iterators, while the former is per-slice iterator, see below. -
    - - Here is how you can use cv::MatND to compute NxNxN histogram of color 8bpp image - (i.e. each channel value ranges from 0..255 and we quantize it to 0..N-1): - - \code - void computeColorHist(const Mat& image, MatND& hist, int N) - { - const int histSize[] = {N, N, N}; - - // make sure that the histogram has proper size and type - hist.create(3, histSize, CV_32F); - - // and clear it - hist = Scalar(0); - - // the loop below assumes that the image - // is 8-bit 3-channel, so let's check it. - CV_Assert(image.type() == CV_8UC3); - MatConstIterator_ it = image.begin(), - it_end = image.end(); - for( ; it != it_end; ++it ) - { - const Vec3b& pix = *it; - - // we could have incremented the cells by 1.f/(image.rows*image.cols) - // instead of 1.f to make the histogram normalized. - hist.at(pix[0]*N/256, pix[1]*N/256, pix[2]*N/256) += 1.f; - } - } - \endcode -*/ -class CV_EXPORTS MatND -{ -public: - //! default constructor - MatND(); - //! constructs array with specific size and data type - MatND(int _ndims, const int* _sizes, int _type); - //! constructs array and fills it with the specified value - MatND(int _ndims, const int* _sizes, int _type, const Scalar& _s); - //! copy constructor. only the header is copied. - MatND(const MatND& m); - //! sub-array selection. only the header is copied - MatND(const MatND& m, const Range* ranges); - //! converts 2D matrix to ND matrix - explicit MatND(const Mat& m); - //! converts old-style nd array to MatND; optionally, copies the data - MatND(const CvMatND* m, bool copyData=false); - //! destructor - ~MatND(); - //! the copy operator - MatND& operator = (const MatND& m); - - //! helper method for matrix expressions - void assignTo( MatND& m, int type ) const; - - //! creates a complete copy of the matrix (all the data is copied) - MatND clone() const; - //! sub-array selection; only the header is copied - MatND operator()(const Range* ranges) const; - - //! copies the data to another matrix. Calls m.create(this->size(), this->type()) prior to copying the data - void copyTo( MatND& m ) const; - //! copies only the selected elements to another matrix. - void copyTo( MatND& m, const MatND& mask ) const; - //! converts data to the specified data type. Calls m.create(this->size(), rtype) prior to the conversion - void convertTo( MatND& m, int rtype, double alpha=1, double beta=0 ) const; - - //! assigns "s" to each array element. - MatND& operator = (const Scalar& s); - //! assigns "s" to the selected elements of array (or to all the elements if mask==MatND()) - MatND& setTo(const Scalar& s, const MatND& mask=MatND()); - //! modifies geometry of array without copying the data - MatND reshape(int _newcn, int _newndims=0, const int* _newsz=0) const; - - //! allocates a new buffer for the data unless the current one already has the specified size and type. - void create(int _ndims, const int* _sizes, int _type); - //! manually increment reference counter (use with care !!!) - void addref(); - //! decrements the reference counter. Dealloctes the data when the reference counter reaches zero. - void release(); - - //! converts the matrix to 2D Mat without copying the data - operator Mat() const; - //! converts the matrix to CvMatND without copying the data - operator CvMatND() const; - //! returns true if the array data is stored continuously - bool isContinuous() const; - //! returns size of each element in bytes - size_t elemSize() const; - //! returns size of each element channel in bytes - size_t elemSize1() const; - //! returns OpenCV data type id (CV_8UC1, ... CV_64FC4,...) - int type() const; - //! returns depth (CV_8U ... CV_64F) - int depth() const; - //! returns the number of channels - int channels() const; - //! returns step()/elemSize1() - size_t step1(int i) const; - - //! returns pointer to the element of 1D matrix - uchar* ptr(int i0); - //! returns read-only pointer to the element of 1D matrix - const uchar* ptr(int i0) const; - //! returns pointer to the element of 2D matrix - uchar* ptr(int i0, int i1); - //! returns read-only pointer to the element of 2D matrix - const uchar* ptr(int i0, int i1) const; - //! returns pointer to the element of 3D matrix - uchar* ptr(int i0, int i1, int i2); - //! returns read-only pointer to the element of 3D matrix - const uchar* ptr(int i0, int i1, int i2) const; - //! returns pointer to the element of nD matrix - uchar* ptr(const int* idx); - //! returns read-only pointer to the element of nD matrix - const uchar* ptr(const int* idx) const; - - //! returns reference to the element of 1D matrix - template _Tp& at(int i0); - //! returns read-only reference to the element of 1D matrix - template const _Tp& at(int i0) const; - //! returns reference to the element of 2D matrix - template _Tp& at(int i0, int i1); - //! returns read-only reference to the element of 2D matrix - template const _Tp& at(int i0, int i1) const; - //! returns reference to the element of 3D matrix - template _Tp& at(int i0, int i1, int i2); - //! returns read-only reference to the element of 3D matrix - template const _Tp& at(int i0, int i1, int i2) const; - //! returns reference to the element of nD matrix - template _Tp& at(const int* idx); - //! returns read-only reference to the element of nD matrix - template const _Tp& at(const int* idx) const; - - enum { MAGIC_VAL=0x42FE0000, AUTO_STEP=-1, - CONTINUOUS_FLAG=CV_MAT_CONT_FLAG, MAX_DIM=CV_MAX_DIM }; - - // combines data type, continuity flag, signature (magic value) - int flags; - // the array dimensionality - int dims; - - // data reference counter - int* refcount; - // pointer to the data - uchar* data; - // and its actual beginning and end - uchar* datastart; - uchar* dataend; - - // step and size for each dimension, MAX_DIM at max - int size[MAX_DIM]; - size_t step[MAX_DIM]; -}; - /*! n-Dimensional Dense Matrix Iterator Class. - The class cv::NAryMatNDIterator is used for iterating over one or more n-dimensional dense arrays (cv::MatND's). + The class cv::NAryMatNDIterator is used for iterating over one or more n-dimensional dense arrays (cv::Mat's). The iterator is completely different from cv::Mat_ and cv::SparseMat_ iterators. It iterates through the slices (or planes), not the elements, where "slice" is a continuous part of the arrays. @@ -2789,27 +2820,29 @@ public: Here is the example on how the iterator can be used to normalize 3D histogram: \code - void normalizeColorHist(MatND& hist) + void normalizeColorHist(Mat& hist) { #if 1 // intialize iterator (the style is different from STL). // after initialization the iterator will contain // the number of slices or planes // the iterator will go through - MatNDIterator it(hist); + Mat* arrays[] = { &hist, 0 }; + Mat planes[1]; + NAryMatIterator it(arrays, planes); double s = 0; // iterate through the matrix. on each iteration // it.planes[i] (of type Mat) will be set to the current plane of // i-th n-dim matrix passed to the iterator constructor. for(int p = 0; p < it.nplanes; p++, ++it) s += sum(it.planes[0])[0]; - it = MatNDIterator(hist); + it = NAryMatIterator(hist); s = 1./s; for(int p = 0; p < it.nplanes; p++, ++it) it.planes[0] *= s; #elif 1 // this is a shorter implementation of the above - // using built-in operations on MatND + // using built-in operations on Mat double s = sum(hist)[0]; hist.convertTo(hist, hist.type(), 1./s, 0); #else @@ -2826,147 +2859,35 @@ public: Then, during the iteration it.planes[0], it.planes[1], ... will be the slices of the corresponding matrices */ -class CV_EXPORTS NAryMatNDIterator +class CV_EXPORTS NAryMatIterator { public: //! the default constructor - NAryMatNDIterator(); + NAryMatIterator(); //! the full constructor taking arbitrary number of n-dim matrices - NAryMatNDIterator(const MatND* arrays, size_t count); - //! another form of the constructor taking pointers to the headers - NAryMatNDIterator(const MatND** arrays, size_t count); - //! the full constructor for iteration through a single n-dim matrix - NAryMatNDIterator(const MatND& m0); - //! the full constructor for iteration through 2 n-dim matrices - NAryMatNDIterator(const MatND& m0, const MatND& m1); - //! the full constructor for iteration through 3 n-dim matrices - NAryMatNDIterator(const MatND& m0, const MatND& m1, const MatND& m2); - //! the full constructor for iteration through 4 n-dim matrices - NAryMatNDIterator(const MatND& m0, const MatND& m1, const MatND& m2, const MatND& m3); - //! the full constructor for iteration through 5 n-dim matrices - NAryMatNDIterator(const MatND& m0, const MatND& m1, const MatND& m2, - const MatND& m3, const MatND& m4); - //! the full constructor for iteration through 6 n-dim matrices - NAryMatNDIterator(const MatND& m0, const MatND& m1, const MatND& m2, - const MatND& m3, const MatND& m4, const MatND& m5); + NAryMatIterator(const Mat** arrays, Mat* planes, int narrays=-1); //! the separate iterator initialization method - void init(const MatND** arrays, size_t count); + void init(const Mat** arrays, Mat* planes, int narrays=-1); //! proceeds to the next plane of every iterated matrix - NAryMatNDIterator& operator ++(); + NAryMatIterator& operator ++(); //! proceeds to the next plane of every iterated matrix (postfix increment operator) - NAryMatNDIterator operator ++(int); - - //! the iterated arrays - vector arrays; - //! the current planes - vector planes; + NAryMatIterator operator ++(int); + //! the iterated arrays + const Mat** arrays; + //! the current planes + Mat* planes; + //! the number of arrays + int narrays; + //! the number of planes in each array int nplanes; protected: int iterdepth, idx; }; - -//! adds one n-dim array to another -CV_EXPORTS void add(const MatND& a, const MatND& b, MatND& c, const MatND& mask); -//! subtracts one n-dim array from another -CV_EXPORTS void subtract(const MatND& a, const MatND& b, MatND& c, const MatND& mask); -//! adds one n-dim array to another -CV_EXPORTS void add(const MatND& a, const MatND& b, MatND& c); -//! subtracts one n-dim array from another -CV_EXPORTS void subtract(const MatND& a, const MatND& b, MatND& c); -//! adds scalar to n-dim array -CV_EXPORTS void add(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND()); -//! subtracts scalar from n-dim array -CV_EXPORTS void subtract(const Scalar& s, const MatND& a, MatND& c, const MatND& mask=MatND()); -//! computes element-wise weighted product of the two n-dim arrays (c = scale*a*b) -CV_EXPORTS void multiply(const MatND& a, const MatND& b, MatND& c, double scale=1); -//! computes element-wise weighted quotient of the two n-dim arrays (c = scale*a/b) -CV_EXPORTS void divide(const MatND& a, const MatND& b, MatND& c, double scale=1); -//! computes element-wise weighted reciprocal of n-dim array (c = scale/b) -CV_EXPORTS void divide(double scale, const MatND& b, MatND& c); -//! adds weighted n-dim array to another (c = a*alpha + b) -CV_EXPORTS void scaleAdd(const MatND& a, double alpha, const MatND& b, MatND& c); -//! computes weighted sum of 2 n-dim arrays (c = a*alpha + b*beta + gamma) -CV_EXPORTS void addWeighted(const MatND& a, double alpha, const MatND& b, - double beta, double gamma, MatND& c); -//! computes the sum of n-dim array elements -CV_EXPORTS Scalar sum(const MatND& m); -//! computes the number of non-zero elements of n-dim array -CV_EXPORTS int countNonZero( const MatND& m ); -//! computes mean value of n-dim array elements -CV_EXPORTS Scalar mean(const MatND& m); -//! computes mean value of selected elements of n-dim array -CV_EXPORTS Scalar mean(const MatND& m, const MatND& mask); -//! computes the mean and the standard deviation of n-dim array -CV_EXPORTS void meanStdDev(const MatND& m, Scalar& mean, Scalar& stddev, const MatND& mask=MatND()); -//! computes norm of n-dim array -CV_EXPORTS double norm(const MatND& a, int normType=NORM_L2, const MatND& mask=MatND()); -//! computes norm of the difference between 2 n-dim arrays -CV_EXPORTS double norm(const MatND& a, const MatND& b, - int normType=NORM_L2, const MatND& mask=MatND()); -//! scales and shifts array elements so that either the specified norm (alpha) or the minimum (alpha) and maximum (beta) array values get the specified values -CV_EXPORTS void normalize( const MatND& a, MatND& b, double alpha=1, double beta=0, - int norm_type=NORM_L2, int rtype=-1, const MatND& mask=MatND()); -//! finds global minimum and maximum array elements and returns their values and their locations -CV_EXPORTS void minMaxLoc(const MatND& a, double* minVal, - double* maxVal, int* minIdx=0, int* maxIdx=0, - const MatND& mask=MatND()); -//! makes multi-channel n-dim array out of several single-channel n-dim arrays -CV_EXPORTS void merge(const MatND* mvbegin, size_t count, MatND& dst); -//! copies each plane of a multi-channel n-dim array to a dedicated array -CV_EXPORTS void split(const MatND& m, MatND* mv); -//! copies selected channels from the input arrays to the selected channels of the output arrays -CV_EXPORTS void mixChannels(const MatND* src, int nsrcs, MatND* dst, int ndsts, - const int* fromTo, size_t npairs); -//! computes bitwise conjunction of the two n-dim arrays (c = a & b) -CV_EXPORTS void bitwise_and(const MatND& a, const MatND& b, MatND& c, const MatND& mask=MatND()); -//! computes bitwise disjunction of the two n-dim arrays (c = a | b) -CV_EXPORTS void bitwise_or(const MatND& a, const MatND& b, MatND& c, const MatND& mask=MatND()); -//! computes bitwise exclusive-or of the two n-dim arrays (c = a ^ b) -CV_EXPORTS void bitwise_xor(const MatND& a, const MatND& b, MatND& c, const MatND& mask=MatND()); -//! computes bitwise conjunction of n-dim array and scalar (c = a & s) -CV_EXPORTS void bitwise_and(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND()); -//! computes bitwise disjunction of n-dim array and scalar (c = a | s) -CV_EXPORTS void bitwise_or(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND()); -//! computes bitwise exclusive-or of n-dim array and scalar (c = a ^ s) -CV_EXPORTS void bitwise_xor(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND()); -//! inverts each bit of each n-dim array element (c = ~a) -CV_EXPORTS void bitwise_not(const MatND& a, MatND& c); -//! computes element-wise absolute difference of two n-dim arrays (c = abs(a - b)) -CV_EXPORTS void absdiff(const MatND& a, const MatND& b, MatND& c); -//! computes element-wise absolute difference of n-dim array and scalar (c = abs(a - s)) -CV_EXPORTS void absdiff(const MatND& a, const Scalar& s, MatND& c); -//! set mask elements for those n-dim array elements which are within the element-specific bounding box (dst = lowerb <= src && src < upperb) -CV_EXPORTS void inRange(const MatND& src, const MatND& lowerb, - const MatND& upperb, MatND& dst); -//! set mask elements for those n-dim array elements which are within the fixed bounding box (dst = lowerb <= src && src < upperb) -CV_EXPORTS void inRange(const MatND& src, const Scalar& lowerb, - const Scalar& upperb, MatND& dst); -//! compares elements of two arrays (c = a b) -CV_EXPORTS void compare(const MatND& a, const MatND& b, MatND& c, int cmpop); -//! compares elements of two arrays (c = a b) -CV_EXPORTS void compare(const MatND& a, double s, MatND& c, int cmpop); -//! computes per-element minimum of two n-dim arrays (c = min(a, b)) -CV_EXPORTS void min(const MatND& a, const MatND& b, MatND& c); -//! computes per-element minimum of n-dim array and scalar (c = min(a, s)) -CV_EXPORTS void min(const MatND& a, double alpha, MatND& c); -//! computes per-element maximum of two n-dim arrays (c = max(a, s)) -CV_EXPORTS void max(const MatND& a, const MatND& b, MatND& c); -//! computes per-element maximum of n-dim array and scalar (c = min(a, s)) -CV_EXPORTS void max(const MatND& a, double alpha, MatND& c); -//! computes square root of each element of n-dim array (b = a**0.5) -CV_EXPORTS void sqrt(const MatND& a, MatND& b); -//! raises each n-dim array element to the specific power (b = a**power) -CV_EXPORTS void pow(const MatND& a, double power, MatND& b); -//! computes exponent of each n-dim array element (b = e**a) -CV_EXPORTS void exp(const MatND& a, MatND& b); -//! computes natural logarithm of absolute value of each n-dim array element (b = log(abs(a))) -CV_EXPORTS void log(const MatND& a, MatND& b); -//! checks that each matrix element is within the specified range. -CV_EXPORTS bool checkRange(const MatND& a, bool quiet=true, int* idx=0, - double minVal=-DBL_MAX, double maxVal=DBL_MAX); +//typedef NAryMatIterator NAryMatNDIterator; + typedef void (*ConvertData)(const void* from, void* to, int cn); typedef void (*ConvertScaleData)(const void* from, void* to, int cn, double alpha, double beta); @@ -2975,110 +2896,7 @@ CV_EXPORTS ConvertData getConvertElem(int fromType, int toType); //! returns the function for converting pixels from one data type to another with the optional scaling CV_EXPORTS ConvertScaleData getConvertScaleElem(int fromType, int toType); -/*! - Template n-dimensional dense matrix class derived from cv::MatND - - The class relates to cv::MatND almost like cv::Mat_ relates to cv::Mat - it provides - a bit more convenient element access operations and adds no extra members - or virtual methods to the base class, thus references/pointers to cv::MatND_ and cv::MatND - can be easily converted one to another, e.g. - - \code - void computeColorHist(const Mat& image, MatND& hist, int N) - { - const int histSize[] = {N, N, N}; - - // make sure that the histogram has proper size and type - hist.create(3, histSize, CV_32F); - - // and clear it - hist = Scalar(0); - - // the loop below assumes that the image - // is 8-bit 3-channel, so let's check it. - CV_Assert(image.type() == CV_8UC3); - MatConstIterator_ it = image.begin(), - it_end = image.end(); - MatND_& hist_ = (MatND_&)hist; - - for( ; it != it_end; ++it ) - { - const Vec3b& pix = *it; - hist_(pix[0]*N/256, pix[1]*N/256, pix[2]*N/256) += 1.f; - } - } - \endcode -*/ -template class CV_EXPORTS MatND_ : public MatND -{ -public: - typedef _Tp value_type; - typedef typename DataType<_Tp>::channel_type channel_type; - - //! the default constructor - MatND_(); - //! the full constructor, equivalent to MatND(dims, _sizes, DataType<_Tp>::type) - MatND_(int dims, const int* _sizes); - //! the full constructor that sets each matrix element to the specified value - MatND_(int dims, const int* _sizes, const _Tp& _s); - //! the copy constructor. If m.type() != DataType<_Tp>::type, all the data is converted - MatND_(const MatND& m); - //! the copy constructor. - MatND_(const MatND_& m); - //! constructor for the specified subarray. The data is not copied! - MatND_(const MatND_& m, const Range* ranges); - //! the conversion constructor - MatND_(const CvMatND* m, bool copyData=false); - //! the assignment operator. If m.type() != DataType<_Tp>::type, all the data is converted - MatND_& operator = (const MatND& m); - //! the assignment operator. No data is copied - MatND_& operator = (const MatND_& m); - //! the assignment operator. All the elements are set to the specified value - MatND_& operator = (const _Tp& s); - - //! equivalent to create(dims, _sizes, DataType<_Tp>::type) - void create(int dims, const int* _sizes); - //! conversion to another data type - template operator MatND_() const; - //! creates full copy of the matrix, including the data - MatND_ clone() const; - //! creates header for the specified submatrix. No data is copied - MatND_ operator()(const Range* ranges) const; - //! returns the element size in bytes - size_t elemSize() const; - //! returns the size of each element channel in bytes - size_t elemSize1() const; - //! returns DataType<_Tp>::type - int type() const; - //! returns DataType<_Tp>::depth - int depth() const; - //! returns DataType<_Tp>::channels - int channels() const; - //! returns step[i]/elemSize() - size_t stepT(int i) const; - //! returns step[i]/elemSize1() - size_t step1(int i) const; - - //! returns reference to the specified element - _Tp& operator ()(const int* idx); - //! returns read-only reference to the specified element - const _Tp& operator ()(const int* idx) const; - - //! returns reference to the specified element (1D case) - _Tp& operator ()(int idx0); - //! returns read-only reference to the specified element (1D case) - const _Tp& operator ()(int idx0) const; - //! returns reference to the specified element (2D case) - _Tp& operator ()(int idx0, int idx1); - //! returns read-only reference to the specified element (2D case) - const _Tp& operator ()(int idx0, int idx1) const; - //! returns reference to the specified element (3D case) - _Tp& operator ()(int idx0, int idx1, int idx2); - //! returns read-only reference to the specified element (3D case) - const _Tp& operator ()(int idx0, int idx1, int idx2) const; -}; - /////////////////////////// multi-dimensional sparse matrix ////////////////////////// class SparseMatIterator; @@ -3090,7 +2908,7 @@ template class SparseMatConstIterator_; Sparse matrix class. The class represents multi-dimensional sparse numerical arrays. Such a sparse array can store elements - of any type that cv::Mat and cv::MatND are able to store. "Sparse" means that only non-zero elements + of any type that cv::Mat is able to store. "Sparse" means that only non-zero elements are stored (though, as a result of some operations on a sparse matrix, some of its stored elements can actually become 0. It's user responsibility to detect such elements and delete them using cv::SparseMat::erase(). The non-zero elements are stored in a hash table that grows when it's filled enough, @@ -3112,7 +2930,7 @@ template class SparseMatConstIterator_; } \endcode -
  • Sparse matrix iterators. Like cv::Mat iterators and unlike cv::MatND iterators, the sparse matrix iterators are STL-style, +
  • Sparse matrix iterators. Like cv::Mat iterators and unlike cv::Mat iterators, the sparse matrix iterators are STL-style, that is, the iteration is done as following: \code // prints elements of a sparse floating-point matrix and the sum of elements. @@ -3216,9 +3034,7 @@ public: \param try1d if true and m is a single-column matrix (Nx1), then the sparse matrix will be 1-dimensional. */ - SparseMat(const Mat& m, bool try1d=false); - //! converts dense n-dim array to the sparse form - SparseMat(const MatND& m); + SparseMat(const Mat& m); //! converts old-style sparse matrix to the new-style. All the data is copied SparseMat(const CvSparseMat* m); //! the destructor @@ -3226,20 +3042,16 @@ public: //! assignment operator. This is O(1) operation, i.e. no data is copied SparseMat& operator = (const SparseMat& m); - //! equivalent to the corresponding constructor with try1d=false + //! equivalent to the corresponding constructor SparseMat& operator = (const Mat& m); - //! converts dense n-dim array to the sparse form - SparseMat& operator = (const MatND& m); //! creates full copy of the matrix SparseMat clone() const; //! copies all the data to the destination matrix. All the previous content of m is erased void copyTo( SparseMat& m ) const; - //! converts 1D or 2D sparse matrix to dense 2D matrix. If the sparse matrix is 1D, then the result will be a single-column matrix. + //! converts sparse matrix to dense matrix. void copyTo( Mat& m ) const; - //! converts sparse matrix to the dense form. The output matrix may require a lot of memory! - void copyTo( MatND& m ) const; //! multiplies all the matrix elements by the specified scale factor alpha and converts the results to the specified data type void convertTo( SparseMat& m, int rtype, double alpha=1 ) const; //! converts sparse matrix to dense n-dim matrix with optional type conversion and scaling. @@ -3249,13 +3061,6 @@ public: \param beta The optional delta added to the scaled values before the conversion */ void convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const; - //! converts sparse matrix to dense 2D matrix with optional type conversion and scaling. - /*! - \param rtype The output matrix data type. When it is =-1, the output array will have the same data type as (*this) - \param alpha The scale factor - \param beta The optional delta added to the scaled values before the conversion - */ - void convertTo( MatND& m, int rtype, double alpha=1, double beta=0 ) const; // not used now void assignTo( SparseMat& m, int type=-1 ) const; @@ -3551,20 +3356,16 @@ public: SparseMat_(const SparseMat& m); //! the copy constructor. This is O(1) operation - no data is copied SparseMat_(const SparseMat_& m); - //! converts dense 2D matrix to the sparse form + //! converts dense matrix to the sparse form SparseMat_(const Mat& m); - //! converts dense n-dim matrix to the sparse form - SparseMat_(const MatND& m); //! converts the old-style sparse matrix to the C++ class. All the elements are copied SparseMat_(const CvSparseMat* m); //! the assignment operator. If DataType<_Tp>.type != m.type(), the m elements are converted SparseMat_& operator = (const SparseMat& m); //! the assignment operator. This is O(1) operation - no data is copied SparseMat_& operator = (const SparseMat_& m); - //! converts dense 2D matrix to the sparse form + //! converts dense matrix to the sparse form SparseMat_& operator = (const Mat& m); - //! converts dense n-dim matrix to the sparse form - SparseMat_& operator = (const MatND& m); //! makes full copy of the matrix. All the elements are duplicated SparseMat_ clone() const; diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 40cf91f81e..c0342150bc 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -56,175 +56,150 @@ namespace cv //////////////////////////////// Mat //////////////////////////////// inline Mat::Mat() - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) {} + : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0), + datastart(0), dataend(0), allocator(0), size(&rows) +{ +} inline Mat::Mat(int _rows, int _cols, int _type) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) + : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0), + datastart(0), dataend(0), allocator(0), size(&rows) { - if( _rows > 0 && _cols > 0 ) - create( _rows, _cols, _type ); + create(_rows, _cols, _type); } inline Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), - datastart(0), dataend(0) + : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0), + datastart(0), dataend(0), allocator(0), size(&rows) { - if(_rows > 0 && _cols > 0) - { - create(_rows, _cols, _type); - *this = _s; - } + create(_rows, _cols, _type); + *this = _s; } -inline Mat::Mat(Size _size, int _type) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), - datastart(0), dataend(0) +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) { - if( _size.height > 0 && _size.width > 0 ) - create( _size.height, _size.width, _type ); + create( _sz.height, _sz.width, _type ); } -inline Mat::Mat(Size _size, int _type, const Scalar& _s) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), - datastart(0), dataend(0) +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) { - if( _size.height > 0 && _size.width > 0 ) - { - create( _size.height, _size.width, _type ); - *this = _s; - } + create(_sz.height, _sz.width, _type); + *this = _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) +{ + 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) +{ + create(_dims, _sz, _type); + *this = _s; } inline Mat::Mat(const Mat& m) - : flags(m.flags), rows(m.rows), cols(m.cols), step(m.step), data(m.data), - refcount(m.refcount), datastart(m.datastart), dataend(m.dataend) + : 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) { if( refcount ) CV_XADD(refcount, 1); + if( m.dims <= 2 ) + { + step[0] = m.step[0]; step[1] = m.step[1]; + } + else + { + dims = 0; + copySize(m); + } } inline Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step) - : flags(MAGIC_VAL + (_type & TYPE_MASK)), rows(_rows), cols(_cols), - step(_step), data((uchar*)_data), refcount(0), - datastart((uchar*)_data), dataend((uchar*)_data) + : 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) { size_t minstep = cols*elemSize(); - if( step == AUTO_STEP ) + if( _step == AUTO_STEP ) { - step = minstep; + _step = minstep; flags |= CONTINUOUS_FLAG; } else { - if( rows == 1 ) step = minstep; - CV_DbgAssert( step >= minstep ); - flags |= step == minstep ? CONTINUOUS_FLAG : 0; + if( rows == 1 ) _step = minstep; + CV_DbgAssert( _step >= minstep ); + flags |= _step == minstep ? CONTINUOUS_FLAG : 0; } - dataend += step*(rows-1) + minstep; + step[0] = _step; step[1] = elemSize(); + dataend += _step*(rows-1) + minstep; } -inline Mat::Mat(Size _size, int _type, void* _data, size_t _step) - : flags(MAGIC_VAL + (_type & TYPE_MASK)), rows(_size.height), cols(_size.width), - step(_step), data((uchar*)_data), refcount(0), - datastart((uchar*)_data), dataend((uchar*)_data) +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) { size_t minstep = cols*elemSize(); - if( step == AUTO_STEP ) + if( _step == AUTO_STEP ) { - step = minstep; + _step = minstep; flags |= CONTINUOUS_FLAG; } else { - if( rows == 1 ) step = minstep; - CV_DbgAssert( step >= minstep ); - flags |= step == minstep ? CONTINUOUS_FLAG : 0; + if( rows == 1 ) _step = minstep; + CV_DbgAssert( _step >= minstep ); + flags |= _step == minstep ? CONTINUOUS_FLAG : 0; } - dataend += step*(rows-1) + minstep; -} - -inline Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange) -{ - flags = m.flags; - step = m.step; refcount = m.refcount; - data = m.data; datastart = m.datastart; dataend = m.dataend; - - if( rowRange == Range::all() ) - rows = m.rows; - else - { - CV_Assert( 0 <= rowRange.start && rowRange.start <= rowRange.end && rowRange.end <= m.rows ); - rows = rowRange.size(); - data += step*rowRange.start; - } - - if( colRange == Range::all() ) - cols = m.cols; - else - { - 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; - } - - if( rows == 1 ) - flags |= CONTINUOUS_FLAG; - - if( refcount ) - CV_XADD(refcount, 1); - if( rows <= 0 || cols <= 0 ) - rows = cols = 0; -} - -inline Mat::Mat(const Mat& m, const Rect& roi) - : flags(m.flags), rows(roi.height), cols(roi.width), - step(m.step), data(m.data + roi.y*step), refcount(m.refcount), - datastart(m.datastart), dataend(m.dataend) -{ - flags &= roi.width < m.cols ? ~CONTINUOUS_FLAG : -1; - data += roi.x*elemSize(); - 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( rows <= 0 || cols <= 0 ) - rows = cols = 0; + step[0] = _step; step[1] = elemSize(); + dataend += _step*(rows-1) + minstep; } + inline Mat::Mat(const CvMat* m, bool copyData) : flags(MAGIC_VAL + (m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG))), - rows(m->rows), cols(m->cols), step(m->step), data(m->data.ptr), refcount(0), - datastart(m->data.ptr), dataend(m->data.ptr) + dims(2), rows(m->rows), cols(m->cols), data(m->data.ptr), refcount(0), + datastart(m->data.ptr), dataend(m->data.ptr), + allocator(0), size(&rows) { - if( step == 0 ) - step = cols*elemSize(); - size_t minstep = cols*elemSize(); - dataend += step*(rows-1) + minstep; - if( copyData ) + if( !copyData ) + { + size_t esz = elemSize(), minstep = cols*esz, _step = m->step; + if( _step == 0 ) + _step = minstep; + dataend += _step*(rows-1) + minstep; + step[0] = _step; step[1] = esz; + } + else { data = datastart = dataend = 0; Mat(m->rows, m->cols, m->type, m->data.ptr, m->step).copyTo(*this); } } -CV_EXPORTS Mat cvarrToMat(const CvArr* arr, bool copyData=false, - bool allowND=true, int coiMode=0); - template inline Mat::Mat(const vector<_Tp>& vec, bool copyData) : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - rows(0), cols(0), step(0), data(0), refcount(0), - datastart(0), dataend(0) + dims(2), rows((int)vec.size()), cols(1), data(0), refcount(0), + datastart(0), dataend(0), allocator(0), size(&rows) { if(vec.empty()) return; if( !copyData ) { - rows = (int)vec.size(); - cols = 1; - step = sizeof(_Tp); + step[0] = step[1] = sizeof(_Tp); data = datastart = (uchar*)&vec[0]; - dataend = datastart + rows*step; + dataend = datastart + rows*step[0]; } else Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this); @@ -233,66 +208,82 @@ template inline Mat::Mat(const vector<_Tp>& vec, bool copyData) template inline Mat::Mat(const Vec<_Tp, n>& vec, bool copyData) : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - rows(0), cols(0), step(0), data(0), refcount(0), - datastart(0), dataend(0) + dims(2), rows(n), cols(1), data(0), refcount(0), + datastart(0), dataend(0), allocator(0), size(&rows) { if( !copyData ) { - rows = n; - cols = 1; - step = sizeof(_Tp); + step[0] = step[1] = sizeof(_Tp); data = datastart = (uchar*)vec.val; - dataend = datastart + rows*step; + dataend = datastart + rows*step[0]; } else - Mat(n, 1, DataType<_Tp>::type, vec.val).copyTo(*this); + Mat(n, 1, DataType<_Tp>::type, (void*)vec.val).copyTo(*this); } template inline Mat::Mat(const Matx<_Tp,m,n>& M, bool copyData) : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - rows(0), cols(0), step(0), data(0), refcount(0), - datastart(0), dataend(0) + dims(2), rows(m), cols(n), data(0), refcount(0), + datastart(0), dataend(0), allocator(0), size(&rows) { if( !copyData ) { - rows = m; - cols = n; - step = n*sizeof(_Tp); + step[0] = cols*sizeof(_Tp); + step[1] = sizeof(_Tp); data = datastart = (uchar*)M.val; - dataend = datastart + rows*step; + dataend = datastart + rows*step[0]; } else Mat(m, n, DataType<_Tp>::type, (uchar*)M.val).copyTo(*this); } -template inline Mat::Mat(const Point_<_Tp>& pt) +template inline Mat::Mat(const Point_<_Tp>& pt, bool copyData) : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - rows(0), cols(0), step(0), data(0), refcount(0), - datastart(0), dataend(0) + dims(2), rows(2), cols(1), data(0), refcount(0), + datastart(0), dataend(0), allocator(0), size(&rows) { - create(2, 1, DataType<_Tp>::type); - ((_Tp*)data)[0] = pt.x; - ((_Tp*)data)[1] = pt.y; + if( !copyData ) + { + step[0] = step[1] = sizeof(_Tp); + data = datastart = (uchar*)&pt.x; + dataend = datastart + rows*step[0]; + } + else + { + create(2, 1, DataType<_Tp>::type); + ((_Tp*)data)[0] = pt.x; + ((_Tp*)data)[1] = pt.y; + } } -template inline Mat::Mat(const Point3_<_Tp>& pt) +template inline Mat::Mat(const Point3_<_Tp>& pt, bool copyData) : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - rows(0), cols(0), step(0), data(0), refcount(0), - datastart(0), dataend(0) + dims(2), rows(3), cols(1), data(0), refcount(0), + datastart(0), dataend(0), allocator(0), size(&rows) { - create(3, 1, DataType<_Tp>::type); - ((_Tp*)data)[0] = pt.x; - ((_Tp*)data)[1] = pt.y; - ((_Tp*)data)[2] = pt.z; + if( !copyData ) + { + step[0] = step[1] = sizeof(_Tp); + data = datastart = (uchar*)&pt.x; + dataend = datastart + rows*step[0]; + } + else + { + create(3, 1, DataType<_Tp>::type); + ((_Tp*)data)[0] = pt.x; + ((_Tp*)data)[1] = pt.y; + ((_Tp*)data)[2] = pt.z; + } } + template inline Mat::Mat(const MatCommaInitializer_<_Tp>& commaInitializer) : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - rows(0), cols(0), step(0), data(0), refcount(0), - datastart(0), dataend(0) + dims(0), rows(0), cols(0), data(0), refcount(0), + datastart(0), dataend(0), allocator(0), size(&rows) { *this = *commaInitializer; } @@ -300,6 +291,8 @@ template inline Mat::Mat(const MatCommaInitializer_<_Tp>& commaIni inline Mat::~Mat() { release(); + if( step.p != step.buf ) + fastFree(step.p); } inline Mat& Mat::operator = (const Mat& m) @@ -310,10 +303,20 @@ inline Mat& Mat::operator = (const Mat& m) CV_XADD(m.refcount, 1); release(); flags = m.flags; - rows = m.rows; cols = m.cols; - step = m.step; data = m.data; + if( dims <= 2 && m.dims <= 2 ) + { + dims = m.dims; + rows = m.rows; + cols = m.cols; + step[0] = m.step[0]; + step[1] = m.step[1]; + } + else + copySize(m); + data = m.data; datastart = m.datastart; dataend = m.dataend; refcount = m.refcount; + allocator = m.allocator; } return *this; } @@ -329,33 +332,6 @@ inline Mat Mat::colRange(int startcol, int endcol) const inline Mat Mat::colRange(const Range& r) const { return Mat(*this, Range::all(), r); } -inline Mat Mat::diag(int d) const -{ - Mat m = *this; - size_t esz = elemSize(); - int len; - - if( d >= 0 ) - { - len = std::min(cols - d, rows); - m.data += esz*d; - } - else - { - len = std::min(rows + d, cols); - m.data -= step*d; - } - CV_DbgAssert( len > 0 ); - m.rows = len; - m.cols = 1; - m.step += esz; - if( m.rows > 1 ) - m.flags &= ~CONTINUOUS_FLAG; - else - m.flags |= CONTINUOUS_FLAG; - return m; -} - inline Mat Mat::diag(const Mat& d) { Mat m(d.rows, d.rows, d.type(), Scalar(0)), md = m.diag(); @@ -381,32 +357,15 @@ inline void Mat::assignTo( Mat& m, int type ) const inline void Mat::create(int _rows, int _cols, int _type) { _type &= TYPE_MASK; - if( rows == _rows && cols == _cols && type() == _type && data ) + if( dims <= 2 && rows == _rows && cols == _cols && type() == _type && data ) return; - if( data ) - release(); - CV_DbgAssert( _rows >= 0 && _cols >= 0 ); - if( _rows > 0 && _cols > 0 ) - { - flags = MAGIC_VAL + CONTINUOUS_FLAG + _type; - rows = _rows; - cols = _cols; - step = elemSize()*cols; - int64 _nettosize = (int64)step*rows; - size_t nettosize = (size_t)_nettosize; - if( _nettosize != (int64)nettosize ) - CV_Error(CV_StsNoMem, "Too big buffer is allocated"); - size_t datasize = alignSize(nettosize, (int)sizeof(*refcount)); - datastart = data = (uchar*)fastMalloc(datasize + sizeof(*refcount)); - dataend = data + nettosize; - refcount = (int*)(data + datasize); - *refcount = 1; - } + int sz[] = {_rows, _cols}; + create(2, sz, _type); } -inline void Mat::create(Size _size, int _type) +inline void Mat::create(Size _sz, int _type) { - create(_size.height, _size.width, _type); + create(_sz.height, _sz.width, _type); } inline void Mat::addref() @@ -415,60 +374,30 @@ inline void Mat::addref() inline void Mat::release() { if( refcount && CV_XADD(refcount, -1) == 1 ) - fastFree(datastart); + deallocate(); data = datastart = dataend = 0; - step = rows = cols = 0; + rows = cols = 0; refcount = 0; } -inline void Mat::locateROI( Size& wholeSize, Point& ofs ) const -{ - size_t esz = elemSize(), minstep; - ptrdiff_t delta1 = data - datastart, delta2 = dataend - datastart; - CV_DbgAssert( step > 0 ); - if( delta1 == 0 ) - ofs.x = ofs.y = 0; - else - { - ofs.y = (int)(delta1/step); - ofs.x = (int)((delta1 - step*ofs.y)/esz); - CV_DbgAssert( data == datastart + ofs.y*step + ofs.x*esz ); - } - minstep = (ofs.x + cols)*esz; - wholeSize.height = (int)((delta2 - minstep)/step + 1); - wholeSize.height = std::max(wholeSize.height, ofs.y + rows); - wholeSize.width = (int)((delta2 - step*(wholeSize.height-1))/esz); - wholeSize.width = std::max(wholeSize.width, ofs.x + cols); -} - -inline Mat& Mat::adjustROI( int dtop, int dbottom, int dleft, int dright ) -{ - Size wholeSize; Point ofs; - size_t esz = elemSize(); - locateROI( wholeSize, ofs ); - int row1 = std::max(ofs.y - dtop, 0), row2 = std::min(ofs.y + rows + dbottom, wholeSize.height); - int col1 = std::max(ofs.x - dleft, 0), col2 = std::min(ofs.x + cols + dright, wholeSize.width); - data += (row1 - ofs.y)*step + (col1 - ofs.x)*esz; - rows = row2 - row1; cols = col2 - col1; - if( esz*cols == step || rows == 1 ) - flags |= CONTINUOUS_FLAG; - else - flags &= ~CONTINUOUS_FLAG; - return *this; -} - inline Mat Mat::operator()( Range rowRange, Range colRange ) const { return Mat(*this, rowRange, colRange); } - + inline Mat Mat::operator()( const Rect& roi ) const { return Mat(*this, roi); } +inline Mat Mat::operator()(const Range* ranges) const +{ + return Mat(*this, ranges); +} + inline Mat::operator CvMat() const { - CvMat m = cvMat(rows, cols, type(), data); - m.step = (int)step; + CV_DbgAssert(dims <= 2); + CvMat m = cvMat(rows, dims == 1 ? 1 : cols, type(), data); + m.step = (int)step[0]; m.type = (m.type & ~CONTINUOUS_FLAG) | (flags & CONTINUOUS_FLAG); return m; } @@ -479,93 +408,148 @@ 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() const { return step/elemSize1(); } -inline Size Mat::size() const { return Size(cols, rows); } +inline size_t Mat::step1(int i) const { return step.p[i]/elemSize1(); } inline bool Mat::empty() const { return data == 0; } +inline size_t Mat::total() const +{ + if( dims <= 2 ) + return rows*cols; + size_t p = 1; + for( int i = 0; i < dims; i++ ) + p *= size[i]; + return p; +} inline uchar* Mat::ptr(int y) { - CV_DbgAssert( (unsigned)y < (unsigned)rows ); - return data + step*y; + CV_DbgAssert( data && dims >= 1 && (unsigned)y < (unsigned)size.p[0] ); + return data + step.p[0]*y; } inline const uchar* Mat::ptr(int y) const { - CV_DbgAssert( (unsigned)y < (unsigned)rows ); - return data + step*y; + CV_DbgAssert( data && dims >= 1 && (unsigned)y < (unsigned)size.p[0] ); + return data + step.p[0]*y; } template inline _Tp* Mat::ptr(int y) { - CV_DbgAssert( (unsigned)y < (unsigned)rows ); - return (_Tp*)(data + step*y); + CV_DbgAssert( data && dims >= 1 && (unsigned)y < (unsigned)size.p[0] ); + return (_Tp*)(data + step.p[0]*y); } template inline const _Tp* Mat::ptr(int y) const { - CV_DbgAssert( (unsigned)y < (unsigned)rows ); - return (const _Tp*)(data + step*y); + CV_DbgAssert( dims >= 1 && data && (unsigned)y < (unsigned)size.p[0] ); + return (const _Tp*)(data + step.p[0]*y); } -template inline _Tp& Mat::at(int y, int x) -{ - CV_DbgAssert( (unsigned)y < (unsigned)rows && - (unsigned)(x*DataType<_Tp>::channels) < (unsigned)(cols*channels()) && - CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); - return ((_Tp*)(data + step*y))[x]; -} - -template inline const _Tp& Mat::at(int y, int x) const -{ - CV_DbgAssert( (unsigned)y < (unsigned)rows && - (unsigned)(x*DataType<_Tp>::channels) < (unsigned)(cols*channels()) && - CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); - return ((const _Tp*)(data + step*y))[x]; -} - -template inline _Tp& Mat::at(int i) -{ - CV_DbgAssert( CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1() ); - if( cols == 1 ) +inline uchar* Mat::ptr(int i0, int i1) +{ + CV_DbgAssert( dims >= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] ); + return data + i0*step.p[0] + i1*step.p[1]; +} + +inline const uchar* Mat::ptr(int i0, int i1) const +{ + CV_DbgAssert( dims >= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] ); + return data + i0*step.p[0] + i1*step.p[1]; +} + +inline uchar* Mat::ptr(int i0, int i1, int i2) +{ + CV_DbgAssert( dims >= 3 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + (unsigned)i2 < (unsigned)size.p[2] ); + return data + i0*step.p[0] + i1*step.p[1] + i2*step.p[2]; +} + +inline const uchar* Mat::ptr(int i0, int i1, int i2) const +{ + CV_DbgAssert( dims >= 3 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + (unsigned)i2 < (unsigned)size.p[2] ); + return data + i0*step.p[0] + i1*step.p[1] + i2*step.p[2]; +} + +inline uchar* Mat::ptr(const int* idx) +{ + int i, d = dims; + uchar* p = data; + CV_DbgAssert( d >= 1 && p ); + for( i = 0; i < d; i++ ) { - CV_DbgAssert( (unsigned)i < (unsigned)rows ); - return *(_Tp*)(data + step*i); + CV_DbgAssert( (unsigned)idx[i] < (unsigned)size.p[i] ); + p += idx[i]*step.p[i]; } - - CV_DbgAssert( rows == 1 && (unsigned)(i*DataType<_Tp>::channels) < (unsigned)(cols*channels()) ); - return ((_Tp*)data)[i]; + return p; } -template inline const _Tp& Mat::at(int i) const +inline const uchar* Mat::ptr(const int* idx) const { - CV_DbgAssert( CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1() ); - - if( cols == 1 ) + int i, d = dims; + uchar* p = data; + CV_DbgAssert( d >= 1 && p ); + for( i = 0; i < d; i++ ) { - CV_DbgAssert( (unsigned)i < (unsigned)rows ); - return *(_Tp*)(data + step*i); + CV_DbgAssert( (unsigned)idx[i] < (unsigned)size.p[i] ); + p += idx[i]*step.p[i]; } + return p; +} - CV_DbgAssert( rows == 1 && (unsigned)(i*DataType<_Tp>::channels) < (unsigned)(cols*channels()) ); - return ((_Tp*)data)[i]; +template inline _Tp& Mat::at(int i0, int i1) +{ + CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && + CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); + return ((_Tp*)(data + step.p[0]*i0))[i1]; +} + +template inline const _Tp& Mat::at(int i0, int i1) const +{ + CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && + CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); + return ((const _Tp*)(data + step.p[0]*i0))[i1]; } template inline _Tp& Mat::at(Point pt) { - CV_DbgAssert( (unsigned)pt.y < (unsigned)rows && - (unsigned)(pt.x*DataType<_Tp>::channels) < (unsigned)(cols*channels()) && + CV_DbgAssert( dims <= 2 && data && (unsigned)pt.y < (unsigned)size.p[0] && + (unsigned)(pt.x*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); - return ((_Tp*)(data + step*pt.y))[pt.x]; + return ((_Tp*)(data + step.p[0]*pt.y))[pt.x]; } template inline const _Tp& Mat::at(Point pt) const { - CV_DbgAssert( (unsigned)pt.y < (unsigned)rows && - (unsigned)(pt.x*DataType<_Tp>::channels) < (unsigned)(cols*channels()) && + CV_DbgAssert( dims <= 2 && data && (unsigned)pt.y < (unsigned)size.p[0] && + (unsigned)(pt.x*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); - return ((const _Tp*)(data + step*pt.y))[pt.x]; + return ((const _Tp*)(data + step.p[0]*pt.y))[pt.x]; } + +template inline _Tp& Mat::at(int i0) +{ return *(_Tp*)ptr(i0); } +template inline const _Tp& Mat::at(int i0) const +{ return *(const _Tp*)ptr(i0); } +template inline _Tp& Mat::at(int i0, int i1, int i2) +{ return *(_Tp*)ptr(i0, i1, i2); } +template inline const _Tp& Mat::at(int i0, int i1, int i2) const +{ return *(const _Tp*)ptr(i0, i1, i2); } +template inline _Tp& Mat::at(const int* idx) +{ return *(_Tp*)ptr(idx); } +template inline const _Tp& Mat::at(const int* idx) const +{ return *(const _Tp*)ptr(idx); } + template inline MatConstIterator_<_Tp> Mat::begin() const { @@ -577,7 +561,7 @@ template inline MatConstIterator_<_Tp> Mat::end() const { CV_DbgAssert( elemSize() == sizeof(_Tp) ); MatConstIterator_<_Tp> it((const Mat_<_Tp>*)this); - it.ptr = it.sliceEnd = (_Tp*)(data + step*(rows-1)) + cols; + it += total(); return it; } @@ -591,36 +575,25 @@ template inline MatIterator_<_Tp> Mat::end() { CV_DbgAssert( elemSize() == sizeof(_Tp) ); MatIterator_<_Tp> it((Mat_<_Tp>*)this); - it.ptr = it.sliceEnd = (_Tp*)(data + step*(rows-1)) + cols; + it += total(); return it; } - -static inline void swap( Mat& a, Mat& b ) -{ - std::swap( a.flags, b.flags ); - std::swap( a.rows, b.rows ); std::swap( a.cols, b.cols ); - std::swap( a.step, b.step ); std::swap( a.data, b.data ); - std::swap( a.datastart, b.datastart ); - std::swap( a.dataend, b.dataend ); - std::swap( a.refcount, b.refcount ); -} - + template inline Mat::operator vector<_Tp>() const { - CV_Assert( (rows == 1 || cols == 1) && channels() == DataType<_Tp>::channels ); - - int n = rows + cols - 1; - if( isContinuous() && type() == DataType<_Tp>::type ) - return vector<_Tp>((_Tp*)data,(_Tp*)data + n); - vector<_Tp> v(n); Mat tmp(rows, cols, DataType<_Tp>::type, &v[0]); - convertTo(tmp, tmp.type()); + if( !data ) + return vector<_Tp>(); + CV_Assert( dims >= 1 && DataType<_Tp>::channels == channels()); + vector<_Tp> v(total()); + Mat temp(dims, size.p, type(), &v[0]); + convertTo(temp, DataType<_Tp>::type); return v; } template inline Mat::operator Vec<_Tp, n>() const { - CV_Assert( (rows == 1 || cols == 1) && rows + cols - 1 == n && - channels() == DataType<_Tp>::channels ); + CV_Assert( data && dims <= 2 && (rows == 1 || cols == 1) && + rows + cols - 1 == n && channels() == 1 ); if( isContinuous() && type() == DataType<_Tp>::type ) return Vec<_Tp, n>((_Tp*)data); @@ -631,8 +604,7 @@ template inline Mat::operator Vec<_Tp, n>() const template inline Mat::operator Matx<_Tp, m, n>() const { - CV_Assert( rows == m && cols == n && - channels() == DataType<_Tp>::channels ); + CV_Assert( data && dims <= 2 && rows == m && cols == n && channels() == 1 ); if( isContinuous() && type() == DataType<_Tp>::type ) return Matx<_Tp, m, n>((_Tp*)data); @@ -640,6 +612,43 @@ template inline Mat::operator Matx<_Tp, m, n>() cons convertTo(tmp, tmp.type()); return mtx; } + +inline Mat::MSize::MSize(int* _p) : p(_p) {} +inline Size Mat::MSize::operator()() const { 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; } + +inline bool Mat::MSize::operator == (const MSize& sz) const +{ + int d = p[-1], dsz = sz.p[-1]; + if( d != dsz ) + return false; + if( d == 2 ) + return p[0] == sz.p[0] && p[1] == sz.p[1]; + + for( int i = 0; i < d; i++ ) + if( p[i] != sz.p[i] ) + return false; + return true; +} + +inline bool Mat::MSize::operator != (const MSize& sz) const +{ + return !(*this == sz); +} + +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; } + +static inline Mat cvarrToMatND(const CvArr* arr, bool copyData=false, int coiMode=0) +{ + return cvarrToMat(arr, copyData, true, coiMode); +} inline SVD::SVD() {} inline SVD::SVD( const Mat& m, int flags ) { operator ()(m, flags); } @@ -680,28 +689,38 @@ SVD::backSubst( const Matx<_Tp, nm, 1>& w, const Matx<_Tp, m, nm>& u, ///////////////////////////////// Mat_<_Tp> //////////////////////////////////// -template inline Mat_<_Tp>::Mat_() : - Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; } +template inline Mat_<_Tp>::Mat_() + : Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; } -template inline Mat_<_Tp>::Mat_(int _rows, int _cols) : - Mat(_rows, _cols, DataType<_Tp>::type) {} +template inline Mat_<_Tp>::Mat_(int _rows, int _cols) + : Mat(_rows, _cols, DataType<_Tp>::type) {} -template inline Mat_<_Tp>::Mat_(int _rows, int _cols, const _Tp& value) : - Mat(_rows, _cols, DataType<_Tp>::type) { *this = value; } +template inline Mat_<_Tp>::Mat_(int _rows, int _cols, const _Tp& value) + : Mat(_rows, _cols, DataType<_Tp>::type) { *this = value; } -template inline Mat_<_Tp>::Mat_(Size _size) : - Mat(_size.height, _size.width, DataType<_Tp>::type) {} +template inline Mat_<_Tp>::Mat_(Size _sz) + : Mat(_sz.height, _sz.width, DataType<_Tp>::type) {} -template inline Mat_<_Tp>::Mat_(Size _size, const _Tp& value) : - Mat(_size.height, _size.width, DataType<_Tp>::type) { *this = value; } +template inline Mat_<_Tp>::Mat_(Size _sz, const _Tp& value) + : Mat(_sz.height, _sz.width, DataType<_Tp>::type) { *this = value; } -template inline Mat_<_Tp>::Mat_(const Mat& m) : Mat() -{ flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; *this = m; } +template inline Mat_<_Tp>::Mat_(int _dims, const int* _sz) + : Mat(_dims, _sz, DataType<_Tp>::type) {} + +template inline Mat_<_Tp>::Mat_(int _dims, const int* _sz, const _Tp& _s) + : Mat(_dims, _sz, DataType<_Tp>::type, Scalar(_s)) {} + +template inline Mat_<_Tp>::Mat_(const Mat_<_Tp>& m, const Range* ranges) + : Mat(m, ranges) {} + +template inline Mat_<_Tp>::Mat_(const Mat& m) + : Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; *this = m; } -template inline Mat_<_Tp>::Mat_(const Mat_& m) : Mat(m) {} +template inline Mat_<_Tp>::Mat_(const Mat_& m) + : Mat(m) {} -template inline Mat_<_Tp>::Mat_(int _rows, int _cols, _Tp* _data, size_t _step) - : Mat(_rows, _cols, DataType<_Tp>::type, _data, _step) {} +template inline Mat_<_Tp>::Mat_(int _rows, int _cols, _Tp* _data, size_t steps) + : Mat(_rows, _cols, DataType<_Tp>::type, _data, steps) {} template inline Mat_<_Tp>::Mat_(const Mat_& m, const Range& rowRange, const Range& colRange) : Mat(m, rowRange, colRange) {} @@ -711,42 +730,23 @@ template inline Mat_<_Tp>::Mat_(const Mat_& m, const Rect& roi) template template inline Mat_<_Tp>::Mat_(const Vec<_Tp, n>& vec, bool copyData) - : Mat(vec, copyData) -{ -} + : Mat(vec, copyData) {} template template inline Mat_<_Tp>::Mat_(const Matx<_Tp,m,n>& M, bool copyData) - : Mat(M, copyData) -{ -} + : Mat(M, copyData) {} -template inline Mat_<_Tp>::Mat_(const Point_<_Tp>& pt) - : Mat(2, 1, DataType<_Tp>::type) -{ - ((_Tp*)data)[0] = pt.x; - ((_Tp*)data)[1] = pt.y; -} +template inline Mat_<_Tp>::Mat_(const Point_<_Tp>& pt, bool copyData) + : Mat(pt, copyData) {} - -template inline Mat_<_Tp>::Mat_(const Point3_<_Tp>& pt) - : Mat(3, 1, DataType<_Tp>::type) -{ - ((_Tp*)data)[0] = pt.x; - ((_Tp*)data)[1] = pt.y; - ((_Tp*)data)[2] = pt.z; -} - +template inline Mat_<_Tp>::Mat_(const Point3_<_Tp>& pt, bool copyData) + : Mat(pt, copyData) {} template inline Mat_<_Tp>::Mat_(const MatCommaInitializer_<_Tp>& commaInitializer) -: Mat(commaInitializer) -{ -} - + : Mat(commaInitializer) {} template inline Mat_<_Tp>::Mat_(const vector<_Tp>& vec, bool copyData) - : Mat(vec, copyData) -{} + : Mat(vec, copyData) {} template inline Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat& m) { @@ -757,7 +757,7 @@ template inline Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat& m) } if( DataType<_Tp>::depth == m.depth() ) { - return (*this = m.reshape(DataType<_Tp>::channels)); + return (*this = m.reshape(DataType<_Tp>::channels, m.dims, 0)); } CV_DbgAssert(DataType<_Tp>::channels == m.channels()); m.convertTo(*this, type()); @@ -783,11 +783,17 @@ template inline void Mat_<_Tp>::create(int _rows, int _cols) Mat::create(_rows, _cols, DataType<_Tp>::type); } -template inline void Mat_<_Tp>::create(Size _size) +template inline void Mat_<_Tp>::create(Size _sz) { - Mat::create(_size, DataType<_Tp>::type); + Mat::create(_sz, DataType<_Tp>::type); } +template inline void Mat_<_Tp>::create(int _dims, const int* _sz) +{ + Mat::create(_dims, _sz, DataType<_Tp>::type); +} + + template inline Mat_<_Tp> Mat_<_Tp>::cross(const Mat_& m) const { return Mat_<_Tp>(Mat::cross(m)); } @@ -829,8 +835,8 @@ template inline int Mat_<_Tp>::channels() const CV_DbgAssert( Mat::channels() == DataType<_Tp>::channels ); return DataType<_Tp>::channels; } -template inline size_t Mat_<_Tp>::stepT() const { return step/elemSize(); } -template inline size_t Mat_<_Tp>::step1() const { return step/elemSize1(); } +template inline size_t Mat_<_Tp>::stepT(int i) const { return step.p[i]/elemSize(); } +template inline size_t Mat_<_Tp>::step1(int i) const { return step.p[i]/elemSize1(); } template inline Mat_<_Tp> Mat_<_Tp>::reshape(int _rows) const { return Mat_<_Tp>(Mat::reshape(0,_rows)); } @@ -844,53 +850,81 @@ template inline Mat_<_Tp> Mat_<_Tp>::operator()( const Range& rowR template inline Mat_<_Tp> Mat_<_Tp>::operator()( const Rect& roi ) const { return Mat_<_Tp>(*this, roi); } +template inline Mat_<_Tp> Mat_<_Tp>::operator()( const Range* ranges ) const +{ return Mat_<_Tp>(*this, ranges); } + template inline _Tp* Mat_<_Tp>::operator [](int y) { return (_Tp*)ptr(y); } template inline const _Tp* Mat_<_Tp>::operator [](int y) const { return (const _Tp*)ptr(y); } -template inline _Tp& Mat_<_Tp>::operator ()(int row, int col) +template inline _Tp& Mat_<_Tp>::operator ()(int i0, int i1) { - CV_DbgAssert( (unsigned)row < (unsigned)rows && - (unsigned)col < (unsigned)cols && - type() == DataType<_Tp>::type ); - return ((_Tp*)(data + step*row))[col]; + CV_DbgAssert( dims <= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + type() == DataType<_Tp>::type ); + return ((_Tp*)(data + step.p[0]*i0))[i1]; } -template inline const _Tp& Mat_<_Tp>::operator ()(int row, int col) const +template inline const _Tp& Mat_<_Tp>::operator ()(int i0, int i1) const { - CV_DbgAssert( (unsigned)row < (unsigned)rows && - (unsigned)col < (unsigned)cols && - type() == DataType<_Tp>::type ); - return ((const _Tp*)(data + step*row))[col]; + CV_DbgAssert( dims <= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + type() == DataType<_Tp>::type ); + return ((const _Tp*)(data + step.p[0]*i0))[i1]; } -template inline _Tp& Mat_<_Tp>::operator ()(int i) -{ - return at<_Tp>(i); -} - -template inline const _Tp& Mat_<_Tp>::operator ()(int i) const -{ - return at<_Tp>(i); -} - template inline _Tp& Mat_<_Tp>::operator ()(Point pt) { - CV_DbgAssert( (unsigned)pt.y < (unsigned)rows && - (unsigned)pt.x < (unsigned)cols && - type() == DataType<_Tp>::type ); - return ((_Tp*)(data + step*pt.y))[pt.x]; + CV_DbgAssert( dims <= 2 && data && + (unsigned)pt.y < (unsigned)size.p[0] && + (unsigned)pt.x < (unsigned)size.p[1] && + type() == DataType<_Tp>::type ); + return ((_Tp*)(data + step.p[0]*pt.y))[pt.x]; } template inline const _Tp& Mat_<_Tp>::operator ()(Point pt) const { - CV_DbgAssert( (unsigned)pt.y < (unsigned)rows && - (unsigned)pt.x < (unsigned)cols && + CV_DbgAssert( dims <= 2 && data && + (unsigned)pt.y < (unsigned)size.p[0] && + (unsigned)pt.x < (unsigned)size.p[1] && type() == DataType<_Tp>::type ); - return ((const _Tp*)(data + step*pt.y))[pt.x]; + return ((const _Tp*)(data + step.p[0]*pt.y))[pt.x]; } +template inline _Tp& Mat_<_Tp>::operator ()(const int* idx) +{ + return Mat::at<_Tp>(idx); +} + +template inline const _Tp& Mat_<_Tp>::operator ()(const int* idx) const +{ + return Mat::at<_Tp>(idx); +} + +template inline _Tp& Mat_<_Tp>::operator ()(int i0) +{ + return this->at<_Tp>(i0); +} + +template inline const _Tp& Mat_<_Tp>::operator ()(int i0) const +{ + return this->at<_Tp>(i0); +} + +template inline _Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2) +{ + return this->at<_Tp>(i0, i1, i2); +} + +template inline const _Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2) const +{ + return this->at<_Tp>(i0, i1, i2); +} + + template inline Mat_<_Tp>::operator vector<_Tp>() const { return this->Mat::operator vector<_Tp>(); @@ -905,7 +939,6 @@ template template inline Mat_<_Tp>::operator Matx<_T { return this->Mat::operator Matx<_Tp, m, n>(); } - template inline void process( const Mat_& m1, Mat_& m2, Op op ) @@ -1405,9 +1438,6 @@ operator ^= (const Mat_<_Tp>& a, const Scalar& s) static inline void merge(const vector& mv, Mat& dst) { merge(&mv[0], mv.size(), dst); } - -template void merge(const Mat_<_Tp>* mvbegin, size_t count, Mat& dst) -{ merge( (const Mat*)mvbegin, count, dst ); } static inline void split(const Mat& m, vector& mv) { @@ -1459,147 +1489,171 @@ template inline MatExpr Mat_<_Tp>::eye(Size sz) //////////// Iterators & Comma initializers ////////////////// -template inline MatConstIterator_<_Tp>::MatConstIterator_() - : m(0), ptr(0), sliceEnd(0) {} +inline MatConstIterator::MatConstIterator() + : m(0), elemSize(0), ptr(0), sliceStart(0), sliceEnd(0) {} -template inline MatConstIterator_<_Tp>::MatConstIterator_(const Mat_<_Tp>* _m) : m(_m) +inline MatConstIterator::MatConstIterator(const Mat* _m) + : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) { - if( !_m ) - ptr = sliceEnd = 0; - else + if( m && m->isContinuous() ) { - ptr = (_Tp*)_m->data; - sliceEnd = ptr + (_m->isContinuous() ? _m->rows*_m->cols : _m->cols); + sliceStart = m->data; + sliceEnd = sliceStart + m->total()*elemSize; } + seek((const int*)0); } +inline MatConstIterator::MatConstIterator(const Mat* _m, int _row, int _col) + : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) +{ + CV_Assert(m && m->dims <= 2); + if( m->isContinuous() ) + { + sliceStart = m->data; + sliceEnd = sliceStart + m->total()*elemSize; + } + int idx[]={_row, _col}; + seek(idx); +} + +inline MatConstIterator::MatConstIterator(const Mat* _m, Point _pt) + : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) +{ + CV_Assert(m && m->dims <= 2); + if( m->isContinuous() ) + { + sliceStart = m->data; + sliceEnd = sliceStart + m->total()*elemSize; + } + int idx[]={_pt.y, _pt.x}; + seek(idx); +} + +inline MatConstIterator::MatConstIterator(const MatConstIterator& it) + : m(it.m), elemSize(it.elemSize), ptr(it.ptr), sliceStart(it.sliceStart), sliceEnd(it.sliceEnd) +{} + +inline MatConstIterator& MatConstIterator::operator = (const MatConstIterator& it ) +{ + m = it.m; elemSize = it.elemSize; ptr = it.ptr; + sliceStart = it.sliceStart; sliceEnd = it.sliceEnd; + return *this; +} + +inline uchar* MatConstIterator::operator *() const { return ptr; } + +inline MatConstIterator& MatConstIterator::operator += (ptrdiff_t ofs) +{ + if( !m || ofs == 0 ) + return *this; + ptrdiff_t ofsb = ofs*elemSize; + ptr += ofsb; + if( ptr < sliceStart || sliceEnd <= ptr ) + { + ptr -= ofsb; + seek(ofs, true); + } + return *this; +} + +inline MatConstIterator& MatConstIterator::operator -= (ptrdiff_t ofs) +{ return (*this += -ofs); } + +inline MatConstIterator& MatConstIterator::operator --() +{ + if( m && (ptr -= elemSize) < sliceStart ) + { + ptr += elemSize; + seek(-1, true); + } + return *this; +} + +inline MatConstIterator MatConstIterator::operator --(int) +{ + MatConstIterator b = *this; + *this += -1; + return b; +} + +inline MatConstIterator& MatConstIterator::operator ++() +{ + if( m && (ptr += elemSize) >= sliceEnd ) + { + ptr -= elemSize; + seek(1, true); + } + return *this; +} + +inline MatConstIterator MatConstIterator::operator ++(int) +{ + MatConstIterator b = *this; + *this += 1; + return b; +} + +template inline MatConstIterator_<_Tp>::MatConstIterator_() {} + +template inline MatConstIterator_<_Tp>::MatConstIterator_(const Mat_<_Tp>* _m) + : MatConstIterator(_m) {} + template inline MatConstIterator_<_Tp>:: - MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col) : m(_m) -{ - if( !_m ) - ptr = sliceEnd = 0; - else - { - CV_DbgAssert( (unsigned)_row < _m->rows && (unsigned)_col < _m->cols ); - ptr = (_Tp*)(_m->data + _m->step*_row); - sliceEnd = _m->isContinuous() ? (_Tp*)_m->data + _m->rows*_m->cols : ptr + _m->cols; - ptr += _col; - } -} + MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col) + : MatConstIterator(_m, _row, _col) {} template inline MatConstIterator_<_Tp>:: - MatConstIterator_(const Mat_<_Tp>* _m, Point _pt) : m(_m) -{ - if( !_m ) - ptr = sliceEnd = 0; - else - { - CV_DbgAssert( (unsigned)_pt.y < (unsigned)_m->rows && (unsigned)_pt.x < (unsigned)_m->cols ); - ptr = (_Tp*)(_m->data + _m->step*_pt.y); - sliceEnd = _m->isContinuous() ? (_Tp*)_m->data + _m->rows*_m->cols : ptr + _m->cols; - ptr += _pt.x; - } -} + MatConstIterator_(const Mat_<_Tp>* _m, Point _pt) + : MatConstIterator(_m, _pt) {} template inline MatConstIterator_<_Tp>:: MatConstIterator_(const MatConstIterator_& it) - : m(it.m), ptr(it.ptr), sliceEnd(it.sliceEnd) {} + : MatConstIterator(it) {} template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator = (const MatConstIterator_& it ) { - m = it.m; ptr = it.ptr; sliceEnd = it.sliceEnd; + MatConstIterator::operator = (it); return *this; } template inline _Tp MatConstIterator_<_Tp>::operator *() const { return *ptr; } -template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator += (int ofs) +template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator += (ptrdiff_t ofs) { - if( !m || ofs == 0 ) - return *this; - ptr += ofs; - if( m->isContinuous() ) - { - if( ptr > sliceEnd ) - ptr = sliceEnd; - else if( ptr < (_Tp*)m->data ) - ptr = (_Tp*)m->data; - } - else if( ptr >= sliceEnd || ptr < sliceEnd - m->cols ) - { - ptr -= ofs; - Point pt = pos(); - int cols = m->cols; - ofs += pt.y*cols + pt.x; - if( ofs >= cols*m->rows ) - { - ptr = sliceEnd = (_Tp*)(m->data + m->step*(m->rows-1)) + cols; - return *this; - } - else if( ofs < 0 ) - ofs = 0; - pt.y = ofs/cols; - pt.x = ofs - pt.y*cols; - ptr = (_Tp*)(m->data + m->step*pt.y); - sliceEnd = ptr + cols; - ptr += pt.x; - } + MatConstIterator::operator += (ofs); return *this; } -template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator -= (int ofs) +template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator -= (ptrdiff_t ofs) { return (*this += -ofs); } template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator --() -{ return (*this += -1); } +{ + MatConstIterator::operator --(); + return *this; +} template inline MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator --(int) { MatConstIterator_ b = *this; - *this += -1; + MatConstIterator::operator --(); return b; } template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator ++() { - if( m && ++ptr >= sliceEnd ) - { - --ptr; - *this += 1; - } + MatConstIterator::operator ++(); return *this; } template inline MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator ++(int) { MatConstIterator_ b = *this; - if( m && ++ptr >= sliceEnd ) - { - --ptr; - *this += 1; - } + MatConstIterator::operator ++(); return b; } -template inline Point MatConstIterator_<_Tp>::pos() const -{ - if( !m ) - return Point(); - if( m->isContinuous() ) - { - ptrdiff_t ofs = ptr - (_Tp*)m->data; - int y = (int)(ofs / m->cols), x = (int)(ofs - (ptrdiff_t)y*m->cols); - return Point(x, y); - } - else - { - ptrdiff_t ofs = (uchar*)ptr - m->data; - int y = (int)(ofs / m->step), x = (int)((ofs - y*m->step)/sizeof(_Tp)); - return Point(x, y); - } -} - template inline MatIterator_<_Tp>::MatIterator_() : MatConstIterator_<_Tp>() {} template inline MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m) @@ -1610,133 +1664,141 @@ template inline MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m, int template inline MatIterator_<_Tp>::MatIterator_(const Mat_<_Tp>* _m, Point _pt) : MatConstIterator_<_Tp>(_m, _pt) {} - + +template inline MatIterator_<_Tp>::MatIterator_(const Mat_<_Tp>* _m, const int* _idx) + : MatConstIterator_<_Tp>(_m, _idx) {} + template inline MatIterator_<_Tp>::MatIterator_(const MatIterator_& it) : MatConstIterator_<_Tp>(it) {} template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator = (const MatIterator_<_Tp>& it ) { - this->m = it.m; this->ptr = it.ptr; this->sliceEnd = it.sliceEnd; + MatConstIterator::operator = (it); return *this; } -template inline _Tp& MatIterator_<_Tp>::operator *() const { return *(this->ptr); } +template inline _Tp& MatIterator_<_Tp>::operator *() const { return *(_Tp*)(this->ptr); } -template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator += (int ofs) +template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator += (ptrdiff_t ofs) { - MatConstIterator_<_Tp>::operator += (ofs); + MatConstIterator::operator += (ofs); return *this; } -template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator -= (int ofs) +template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator -= (ptrdiff_t ofs) { - MatConstIterator_<_Tp>::operator += (-ofs); + MatConstIterator::operator += (-ofs); return *this; } template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator --() { - MatConstIterator_<_Tp>::operator += (-1); + MatConstIterator::operator --(); return *this; } template inline MatIterator_<_Tp> MatIterator_<_Tp>::operator --(int) { MatIterator_ b = *this; - MatConstIterator_<_Tp>::operator += (-1); + MatConstIterator::operator --(); return b; } template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator ++() { - if( this->m && ++this->ptr >= this->sliceEnd ) - { - --this->ptr; - MatConstIterator_<_Tp>::operator += (1); - } + MatConstIterator::operator ++(); return *this; } template inline MatIterator_<_Tp> MatIterator_<_Tp>::operator ++(int) { MatIterator_ b = *this; - if( this->m && ++this->ptr >= this->sliceEnd ) - { - --this->ptr; - MatConstIterator_<_Tp>::operator += (1); - } + MatConstIterator::operator ++(); return b; } +static inline bool +operator == (const MatConstIterator& a, const MatConstIterator& b) +{ return a.m == b.m && a.ptr == b.ptr; } + +template static inline bool +operator != (const MatConstIterator& a, const MatConstIterator& b) +{ return !(a == b); } + template static inline bool operator == (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) { return a.m == b.m && a.ptr == b.ptr; } template static inline bool operator != (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) -{ return !(a == b); } +{ return a.m != b.m || a.ptr != b.ptr; } template static inline bool -operator < (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) +operator == (const MatIterator_<_Tp>& a, const MatIterator_<_Tp>& b) +{ return a.m == b.m && a.ptr == b.ptr; } + +template static inline bool +operator != (const MatIterator_<_Tp>& a, const MatIterator_<_Tp>& b) +{ return a.m != b.m || a.ptr != b.ptr; } + +static inline bool +operator < (const MatConstIterator& a, const MatConstIterator& b) { return a.ptr < b.ptr; } -template static inline bool -operator > (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) +static inline bool +operator > (const MatConstIterator& a, const MatConstIterator& b) { return a.ptr > b.ptr; } - -template static inline bool -operator <= (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) + +static inline bool +operator <= (const MatConstIterator& a, const MatConstIterator& b) { return a.ptr <= b.ptr; } -template static inline bool -operator >= (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) +static inline bool +operator >= (const MatConstIterator& a, const MatConstIterator& b) { return a.ptr >= b.ptr; } -template static inline int -operator - (const MatConstIterator_<_Tp>& b, const MatConstIterator_<_Tp>& a) -{ - if( a.m != b.m ) - return INT_MAX; - if( a.sliceEnd == b.sliceEnd ) - return b.ptr - a.ptr; - { - Point ap = a.pos(), bp = b.pos(); - if( bp.y > ap.y ) - return (bp.y - ap.y - 1)*a.m->cols + (a.m->cols - ap.x) + bp.x; - if( bp.y < ap.y ) - return -((ap.y - bp.y - 1)*a.m->cols + (a.m->cols - bp.x) + ap.x); - return bp.x - ap.x; - } -} +CV_EXPORTS ptrdiff_t operator - (const MatConstIterator& b, const MatConstIterator& a); + +static inline MatConstIterator operator + (const MatConstIterator& a, ptrdiff_t ofs) +{ MatConstIterator b = a; return b += ofs; } + +static inline MatConstIterator operator + (ptrdiff_t ofs, const MatConstIterator& a) +{ MatConstIterator b = a; return b += ofs; } + +static inline MatConstIterator operator - (const MatConstIterator& a, ptrdiff_t ofs) +{ MatConstIterator b = a; return b += -ofs; } + +template static inline MatConstIterator_<_Tp> +operator + (const MatConstIterator_<_Tp>& a, ptrdiff_t ofs) +{ return (MatConstIterator_<_Tp>&)((const MatConstIterator&)a + ofs); } template static inline MatConstIterator_<_Tp> -operator + (const MatConstIterator_<_Tp>& a, int ofs) -{ MatConstIterator_<_Tp> b = a; return b += ofs; } - +operator + (ptrdiff_t ofs, const MatConstIterator_<_Tp>& a) +{ return (MatConstIterator_<_Tp>&)((const MatConstIterator&)a + ofs); } + template static inline MatConstIterator_<_Tp> -operator + (int ofs, const MatConstIterator_<_Tp>& a) -{ MatConstIterator_<_Tp> b = a; return b += ofs; } +operator - (const MatConstIterator_<_Tp>& a, ptrdiff_t ofs) +{ return (MatConstIterator_<_Tp>&)((const MatConstIterator&)a - ofs); } -template static inline MatConstIterator_<_Tp> -operator - (const MatConstIterator_<_Tp>& a, int ofs) -{ MatConstIterator_<_Tp> b = a; return b += -ofs; } - -template inline _Tp MatConstIterator_<_Tp>::operator [](int i) const +inline uchar* MatConstIterator::operator [](ptrdiff_t i) const { return *(*this + i); } + +template inline _Tp MatConstIterator_<_Tp>::operator [](ptrdiff_t i) const +{ return *(_Tp*)MatConstIterator::operator [](i); } template static inline MatIterator_<_Tp> -operator + (const MatIterator_<_Tp>& a, int ofs) -{ MatIterator_<_Tp> b = a; return b += ofs; } +operator + (const MatIterator_<_Tp>& a, ptrdiff_t ofs) +{ return (MatIterator_<_Tp>&)((const MatConstIterator&)a + ofs); } template static inline MatIterator_<_Tp> -operator + (int ofs, const MatIterator_<_Tp>& a) -{ MatIterator_<_Tp> b = a; return b += ofs; } +operator + (ptrdiff_t ofs, const MatIterator_<_Tp>& a) +{ return (MatIterator_<_Tp>&)((const MatConstIterator&)a + ofs); } template static inline MatIterator_<_Tp> -operator - (const MatIterator_<_Tp>& a, int ofs) -{ MatIterator_<_Tp> b = a; return b += -ofs; } - -template inline _Tp& MatIterator_<_Tp>::operator [](int i) const +operator - (const MatIterator_<_Tp>& a, ptrdiff_t ofs) +{ return (MatIterator_<_Tp>&)((const MatConstIterator&)a - ofs); } + +template inline _Tp& MatIterator_<_Tp>::operator [](ptrdiff_t i) const { return *(*this + i); } template inline MatConstIterator_<_Tp> Mat_<_Tp>::begin() const @@ -1756,21 +1818,21 @@ template inline MatCommaInitializer_<_Tp>::MatCommaInitializer_(Ma template template inline MatCommaInitializer_<_Tp>& MatCommaInitializer_<_Tp>::operator , (T2 v) { - CV_DbgAssert( this->it < this->it.m->end() ); + CV_DbgAssert( this->it < ((const Mat_<_Tp>*)this->it.m)->end() ); *this->it = _Tp(v); ++this->it; return *this; } template inline Mat_<_Tp> MatCommaInitializer_<_Tp>::operator *() const { - CV_DbgAssert( this->it == this->it.m->end() ); - return *this->it.m; + CV_DbgAssert( this->it == ((const Mat_<_Tp>*)this->it.m)->end() ); + return Mat_<_Tp>(*this->it.m); } template inline MatCommaInitializer_<_Tp>::operator Mat_<_Tp>() const { - CV_DbgAssert( this->it == this->it.m->end() ); - return *this->it.m; + CV_DbgAssert( this->it == ((const Mat_<_Tp>*)this->it.m)->end() ); + return Mat_<_Tp>(*this->it.m); } template inline void @@ -1786,460 +1848,6 @@ operator << (const Mat_<_Tp>& m, T2 val) return (commaInitializer, val); } -//////////////////////////////// MatND //////////////////////////////// - -inline MatND::MatND() - : flags(MAGIC_VAL), dims(0), refcount(0), data(0), datastart(0), dataend(0) -{ -} - -inline MatND::MatND(int _dims, const int* _sizes, int _type) - : flags(MAGIC_VAL), dims(0), refcount(0), data(0), datastart(0), dataend(0) -{ - create(_dims, _sizes, _type); -} - -inline MatND::MatND(int _dims, const int* _sizes, int _type, const Scalar& _s) - : flags(MAGIC_VAL), dims(0), refcount(0), data(0), datastart(0), dataend(0) -{ - create(_dims, _sizes, _type); - *this = _s; -} - -inline MatND::MatND(const MatND& m) - : flags(m.flags), dims(m.dims), refcount(m.refcount), - data(m.data), datastart(m.datastart), dataend(m.dataend) -{ - int i, d = dims; - for( i = 0; i < d; i++ ) - { - size[i] = m.size[i]; - step[i] = m.step[i]; - } - if( refcount ) - CV_XADD(refcount, 1); -} - -inline MatND::MatND(const Mat& m) - : flags(m.flags), dims(2), refcount(m.refcount), - data(m.data), datastart(m.datastart), dataend(m.dataend) -{ - size[0] = m.rows; size[1] = m.cols; - step[0] = m.step; step[1] = m.elemSize(); - if( refcount ) - CV_XADD(refcount, 1); -} - -static inline MatND cvarrToMatND(const CvArr* arr, bool copyData=false, int coiMode=0) -{ - if( CV_IS_MAT(arr) || CV_IS_IMAGE(arr)) - return MatND(cvarrToMat(arr, copyData, true, coiMode)); - else if( CV_IS_MATND(arr) ) - return MatND((const CvMatND*)arr, copyData); - return MatND(); -} - -inline MatND::MatND(const CvMatND* m, bool copyData) - : flags(MAGIC_VAL|(m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG))), - dims(m->dims), refcount(0), data(m->data.ptr) -{ - int i, d = dims; - for( i = 0; i < d; i++ ) - { - size[i] = m->dim[i].size; - step[i] = m->dim[i].step; - } - datastart = data; - dataend = datastart + size[0]*step[0]; - if( copyData ) - { - MatND temp(*this); - temp.copyTo(*this); - } -} - -inline MatND::~MatND() { release(); } - -inline MatND& MatND::operator = (const MatND& m) -{ - if( this != &m ) - { - if( m.refcount ) - CV_XADD(m.refcount, 1); - release(); - flags = m.flags; - dims = m.dims; - data = m.data; - datastart = m.datastart; - dataend = m.dataend; - refcount = m.refcount; - int i, d = dims; - for( i = 0; i < d; i++ ) - { - size[i] = m.size[i]; - step[i] = m.step[i]; - } - } - return *this; -} - -inline MatND MatND::clone() const -{ - MatND temp; - this->copyTo(temp); - return temp; -} - -inline MatND MatND::operator()(const Range* ranges) const -{ - return MatND(*this, ranges); -} - -inline void MatND::assignTo( MatND& m, int type ) const -{ - if( type < 0 ) - m = *this; - else - convertTo(m, type); -} - -inline void MatND::addref() -{ - if( refcount ) CV_XADD(refcount, 1); -} - -inline void MatND::release() -{ - if( refcount && CV_XADD(refcount, -1) == 1 ) - fastFree(datastart); - dims = 0; - data = datastart = dataend = 0; - refcount = 0; -} - -inline bool MatND::isContinuous() const { return (flags & CONTINUOUS_FLAG) != 0; } -inline size_t MatND::elemSize() const { return getElemSize(flags); } -inline size_t MatND::elemSize1() const { return CV_ELEM_SIZE1(flags); } -inline int MatND::type() const { return CV_MAT_TYPE(flags); } -inline int MatND::depth() const { return CV_MAT_DEPTH(flags); } -inline int MatND::channels() const { return CV_MAT_CN(flags); } - -inline size_t MatND::step1(int i) const -{ CV_DbgAssert((unsigned)i < (unsigned)dims); return step[i]/elemSize1(); } - -inline uchar* MatND::ptr(int i0) -{ - CV_DbgAssert( dims == 1 && data && - (unsigned)i0 < (unsigned)size[0] ); - return data + i0*step[0]; -} - -inline const uchar* MatND::ptr(int i0) const -{ - CV_DbgAssert( dims == 1 && data && - (unsigned)i0 < (unsigned)size[0] ); - return data + i0*step[0]; -} - -inline uchar* MatND::ptr(int i0, int i1) -{ - CV_DbgAssert( dims == 2 && data && - (unsigned)i0 < (unsigned)size[0] && - (unsigned)i1 < (unsigned)size[1] ); - return data + i0*step[0] + i1*step[1]; -} - -inline const uchar* MatND::ptr(int i0, int i1) const -{ - CV_DbgAssert( dims == 2 && data && - (unsigned)i0 < (unsigned)size[0] && - (unsigned)i1 < (unsigned)size[1] ); - return data + i0*step[0] + i1*step[1]; -} - -inline uchar* MatND::ptr(int i0, int i1, int i2) -{ - CV_DbgAssert( dims == 3 && data && - (unsigned)i0 < (unsigned)size[0] && - (unsigned)i1 < (unsigned)size[1] && - (unsigned)i2 < (unsigned)size[2] ); - return data + i0*step[0] + i1*step[1] + i2*step[2]; -} - -inline const uchar* MatND::ptr(int i0, int i1, int i2) const -{ - CV_DbgAssert( dims == 3 && data && - (unsigned)i0 < (unsigned)size[0] && - (unsigned)i1 < (unsigned)size[1] && - (unsigned)i2 < (unsigned)size[2] ); - return data + i0*step[0] + i1*step[1] + i2*step[2]; -} - -inline uchar* MatND::ptr(const int* idx) -{ - int i, d = dims; - uchar* p = data; - CV_DbgAssert( data ); - for( i = 0; i < d; i++ ) - { - CV_DbgAssert( (unsigned)idx[i] < (unsigned)size[i] ); - p += idx[i]*step[i]; - } - return p; -} - -inline const uchar* MatND::ptr(const int* idx) const -{ - int i, d = dims; - uchar* p = data; - CV_DbgAssert( data ); - for( i = 0; i < d; i++ ) - { - CV_DbgAssert( (unsigned)idx[i] < (unsigned)size[i] ); - p += idx[i]*step[i]; - } - return p; -} - -template inline _Tp& MatND::at(int i0) -{ return *(_Tp*)ptr(i0); } -template inline const _Tp& MatND::at(int i0) const -{ return *(const _Tp*)ptr(i0); } -template inline _Tp& MatND::at(int i0, int i1) -{ return *(_Tp*)ptr(i0, i1); } -template inline const _Tp& MatND::at(int i0, int i1) const -{ return *(const _Tp*)ptr(i0, i1); } -template inline _Tp& MatND::at(int i0, int i1, int i2) -{ return *(_Tp*)ptr(i0, i1, i2); } -template inline const _Tp& MatND::at(int i0, int i1, int i2) const -{ return *(const _Tp*)ptr(i0, i1, i2); } -template inline _Tp& MatND::at(const int* idx) -{ return *(_Tp*)ptr(idx); } -template inline const _Tp& MatND::at(const int* idx) const -{ return *(const _Tp*)ptr(idx); } - -inline NAryMatNDIterator::NAryMatNDIterator() -{ -} - -inline void subtract(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND()) -{ - add(a, -s, c, mask); -} - - -template inline MatND_<_Tp>::MatND_() -{ - flags = MAGIC_VAL | DataType<_Tp>::type; -} - -template inline MatND_<_Tp>::MatND_(int _dims, const int* _sizes) -: MatND(_dims, _sizes, DataType<_Tp>::type) -{ -} - -template inline MatND_<_Tp>::MatND_(int _dims, const int* _sizes, const _Tp& _s) -: MatND(_dims, _sizes, DataType<_Tp>::type, Scalar(_s)) -{ -} - -template inline MatND_<_Tp>::MatND_(const MatND& m) -{ - if( m.type() == DataType<_Tp>::type ) - *this = (const MatND_<_Tp>&)m; - else - m.convertTo(this, DataType<_Tp>::type); -} - -template inline MatND_<_Tp>::MatND_(const MatND_<_Tp>& m) : MatND(m) -{ -} - -template inline MatND_<_Tp>::MatND_(const MatND_<_Tp>& m, const Range* ranges) -: MatND(m, ranges) -{ -} - -template inline MatND_<_Tp>::MatND_(const CvMatND* m, bool copyData) -{ - *this = MatND(m, copyData || CV_MAT_TYPE(m->type) != DataType<_Tp>::type); -} - -template inline MatND_<_Tp>& MatND_<_Tp>::operator = (const MatND& m) -{ - if( DataType<_Tp>::type == m.type() ) - { - Mat::operator = (m); - return *this; - } - if( DataType<_Tp>::depth == m.depth() ) - { - return (*this = m.reshape(DataType<_Tp>::channels)); - } - CV_DbgAssert(DataType<_Tp>::channels == m.channels()); - m.convertTo(*this, DataType<_Tp>::type); - return *this; -} - -template inline MatND_<_Tp>& MatND_<_Tp>::operator = (const MatND_<_Tp>& m) -{ - return ((MatND&)*this = m); -} - -template inline MatND_<_Tp>& MatND_<_Tp>::operator = (const _Tp& s) -{ - return (MatND&)*this = Scalar(s); -} - -template inline void MatND_<_Tp>::create(int _dims, const int* _sizes) -{ - MatND::create(_dims, _sizes, DataType<_Tp>::type); -} - -template template inline MatND_<_Tp>::operator MatND_<_Tp2>() const -{ - return MatND_<_Tp2>((const MatND&)*this); -} - -template inline MatND_<_Tp> MatND_<_Tp>::clone() const -{ - MatND_<_Tp> temp; - this->copyTo(temp); - return temp; -} - -template inline MatND_<_Tp> -MatND_<_Tp>::operator()(const Range* ranges) const -{ return MatND_<_Tp>(*this, ranges); } - -template inline size_t MatND_<_Tp>::elemSize() const -{ return CV_ELEM_SIZE(DataType<_Tp>::type); } - -template inline size_t MatND_<_Tp>::elemSize1() const -{ return CV_ELEM_SIZE1(DataType<_Tp>::type); } - -template inline int MatND_<_Tp>::type() const -{ return DataType<_Tp>::type; } - -template inline int MatND_<_Tp>::depth() const -{ return DataType<_Tp>::depth; } - -template inline int MatND_<_Tp>::channels() const -{ return DataType<_Tp>::channels; } - -template inline size_t MatND_<_Tp>::stepT(int i) const -{ - CV_DbgAssert( (unsigned)i < (unsigned)dims ); - return step[i]/elemSize(); -} - -template inline size_t MatND_<_Tp>::step1(int i) const -{ - CV_DbgAssert( (unsigned)i < (unsigned)dims ); - return step[i]/elemSize1(); -} - -template inline _Tp& MatND_<_Tp>::operator ()(const int* idx) -{ - uchar* ptr = data; - int i, d = dims; - for( i = 0; i < d; i++ ) - { - int ii = idx[i]; - CV_DbgAssert( (unsigned)ii < (unsigned)size[i] ); - ptr += ii*step[i]; - } - return *(_Tp*)ptr; -} - -template inline const _Tp& MatND_<_Tp>::operator ()(const int* idx) const -{ - const uchar* ptr = data; - int i, d = dims; - for( i = 0; i < d; i++ ) - { - int ii = idx[i]; - CV_DbgAssert( (unsigned)ii < (unsigned)size[i] ); - ptr += ii*step[i]; - } - return *(const _Tp*)ptr; -} - -template inline _Tp& MatND_<_Tp>::operator ()(int i0) -{ - CV_DbgAssert( dims == 1 && - (unsigned)i0 < (unsigned)size[0] ); - - return *(_Tp*)(data + i0*step[0]); -} - -template inline const _Tp& MatND_<_Tp>::operator ()(int i0) const -{ - CV_DbgAssert( dims == 1 && - (unsigned)i0 < (unsigned)size[0] ); - - return *(const _Tp*)(data + i0*step[0]); -} - - -template inline _Tp& MatND_<_Tp>::operator ()(int i0, int i1) -{ - CV_DbgAssert( dims == 2 && - (unsigned)i0 < (unsigned)size[0] && - (unsigned)i1 < (unsigned)size[1] ); - - return *(_Tp*)(data + i0*step[0] + i1*step[1]); -} - -template inline const _Tp& MatND_<_Tp>::operator ()(int i0, int i1) const -{ - CV_DbgAssert( dims == 2 && - (unsigned)i0 < (unsigned)size[0] && - (unsigned)i1 < (unsigned)size[1] ); - - return *(const _Tp*)(data + i0*step[0] + i1*step[1]); -} - - -template inline _Tp& MatND_<_Tp>::operator ()(int i0, int i1, int i2) -{ - CV_DbgAssert( dims == 3 && - (unsigned)i0 < (unsigned)size[0] && - (unsigned)i1 < (unsigned)size[1] && - (unsigned)i2 < (unsigned)size[2] ); - - return *(_Tp*)(data + i0*step[0] + i1*step[1] + i2*step[2]); -} - -template inline const _Tp& MatND_<_Tp>::operator ()(int i0, int i1, int i2) const -{ - CV_DbgAssert( dims == 3 && - (unsigned)i0 < (unsigned)size[0] && - (unsigned)i1 < (unsigned)size[1] && - (unsigned)i2 < (unsigned)size[2] ); - - return *(const _Tp*)(data + i0*step[0] + i1*step[1] + i2*step[2]); -} - - -static inline void merge(const vector& mv, MatND& dst) -{ - merge(&mv[0], mv.size(), dst); -} - -static inline void split(const MatND& m, vector& mv) -{ - mv.resize(m.channels()); - if(m.channels() > 0) - split(m, &mv[0]); -} - -static inline void mixChannels(const vector& src, vector& dst, - const int* fromTo, int npairs) -{ - mixChannels(&src[0], (int)src.size(), &dst[0], (int)dst.size(), fromTo, npairs); -} - //////////////////////////////// SparseMat //////////////////////////////// inline SparseMat::SparseMat() @@ -2280,9 +1888,6 @@ inline SparseMat& SparseMat::operator = (const SparseMat& m) inline SparseMat& SparseMat::operator = (const Mat& m) { return (*this = SparseMat(m)); } -inline SparseMat& SparseMat::operator = (const MatND& m) -{ return (*this = SparseMat(m)); } - inline SparseMat SparseMat::clone() const { SparseMat temp; @@ -2583,12 +2188,6 @@ template inline SparseMat_<_Tp>::SparseMat_(const Mat& m) *this = sm; } -template inline SparseMat_<_Tp>::SparseMat_(const MatND& m) -{ - SparseMat sm(m); - *this = sm; -} - template inline SparseMat_<_Tp>::SparseMat_(const CvSparseMat* m) { SparseMat sm(m); @@ -2621,10 +2220,6 @@ template inline SparseMat_<_Tp>& SparseMat_<_Tp>::operator = (const Mat& m) { return (*this = SparseMat(m)); } -template inline SparseMat_<_Tp>& -SparseMat_<_Tp>::operator = (const MatND& m) -{ return (*this = SparseMat(m)); } - template inline SparseMat_<_Tp> SparseMat_<_Tp>::clone() const { diff --git a/modules/core/include/opencv2/core/operations.hpp b/modules/core/include/opencv2/core/operations.hpp index ef530fef07..8e0b5aa07b 100644 --- a/modules/core/include/opencv2/core/operations.hpp +++ b/modules/core/include/opencv2/core/operations.hpp @@ -2794,7 +2794,6 @@ static inline void read(const FileNode& node, string& value, const string& defau } CV_EXPORTS void read(const FileNode& node, Mat& mat, const Mat& default_mat=Mat() ); -CV_EXPORTS void read(const FileNode& node, MatND& mat, const MatND& default_mat=MatND() ); CV_EXPORTS void read(const FileNode& node, SparseMat& mat, const SparseMat& default_mat=SparseMat() ); inline FileNode::operator int() const diff --git a/modules/core/include/opencv2/core/types_c.h b/modules/core/include/opencv2/core/types_c.h index 121f39c0be..ed3b3bc8c5 100644 --- a/modules/core/include/opencv2/core/types_c.h +++ b/modules/core/include/opencv2/core/types_c.h @@ -157,6 +157,11 @@ typedef unsigned short ushort; typedef signed char schar; +/* special informative macros for wrapper generators */ +#define CV_OUT +#define CV_CARRAY(counter) +#define CV_METHOD + /* CvArr* is used to pass arbitrary * array-like data structures * into functions where the particular diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index a40bc3bc73..03054860e6 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -399,11 +399,57 @@ bitwiseSOp_( const Mat& srcmat, Mat& dstmat, const Scalar& _scalar ) } } + +static void +binaryOp( const Mat& src1, const Mat& src2, Mat& dst, BinaryFunc func, int dsttype=-1 ) +{ + if( dsttype == -1 ) + dsttype = src1.type(); + CV_Assert( src1.type() == src2.type() && func != 0 ); + + if( src1.dims > 2 || src2.dims > 2 ) + { + dst.create(src1.dims, src1.size, dsttype); + const Mat* arrays[] = { &src1, &src2, &dst, 0 }; + Mat planes[3]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func(it.planes[0], it.planes[1], it.planes[2]); + return; + } + + CV_Assert( src1.size() == src2.size() ); + dst.create( src1.size(), dsttype ); + func( src1, src2, dst ); +} + + static void binaryMaskOp( const Mat& src1, const Mat& src2, Mat& dst, const Mat& mask, BinaryFunc func ) { - CV_Assert( src1.size() == src2.size() && src1.type() == src2.type() && func != 0 ); + CV_Assert( src1.type() == src2.type() && func != 0 ); + + if( src1.dims > 2 || src2.dims > 2 ) + { + dst.create(src1.dims, src1.size, src1.type()); + const Mat* arrays[] = { &src1, &src2, &dst, &mask, 0 }; + Mat planes[4]; + NAryMatIterator it(arrays, planes); + + if( !mask.data ) + for( int i = 0; i < it.nplanes; i++, ++it ) + func(it.planes[0], it.planes[1], it.planes[2]); + else + for( int i = 0; i < it.nplanes; i++, ++it ) + binaryMaskOp(it.planes[0], it.planes[1], + it.planes[2], it.planes[3], + func); + return; + } + + CV_Assert( src1.size() == src2.size() ); dst.create( src1.size(), src1.type() ); if( !mask.data ) @@ -436,6 +482,24 @@ binarySMaskOp( const Mat& src1, const Scalar& s, Mat& dst, const Mat& mask, BinarySFuncCn func ) { CV_Assert( func != 0 ); + + if( src1.dims > 2 ) + { + dst.create(src1.dims, src1.size, src1.type()); + const Mat* arrays[] = { &src1, &dst, &mask, 0 }; + Mat planes[3]; + NAryMatIterator it(arrays, planes); + + if( !mask.data ) + for( int i = 0; i < it.nplanes; i++, ++it ) + func(it.planes[0], it.planes[1], s); + else + for( int i = 0; i < it.nplanes; i++, ++it ) + binarySMaskOp(it.planes[0], s, it.planes[1], + it.planes[2], func); + return; + } + dst.create( src1.size(), src1.type() ); if( !mask.data ) @@ -499,6 +563,18 @@ void bitwise_xor(const Mat& a, const Scalar& s, Mat& c, const Mat& mask) void bitwise_not(const Mat& src, Mat& dst) { + if( src.dims > 2 ) + { + dst.create(src.dims, src.size, src.type()); + const Mat* arrays[] = { &src, &dst, 0 }; + Mat planes[4]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + bitwise_not(it.planes[0], it.planes[1]); + return; + } + const uchar* sptr = src.data; dst.create( src.size(), src.type() ); uchar* dptr = dst.data; @@ -564,21 +640,50 @@ static BinaryFunc subTab[] = binaryOpC1_,NoVec>, 0 }; - void add( const Mat& src1, const Mat& src2, Mat& dst ) { - Size size = src1.size(); int type = src1.type(); + int type = src1.type(); BinaryFunc func = addTab[CV_MAT_DEPTH(type)]; - CV_Assert( size == src2.size() && type == src2.type() && func != 0 ); + CV_Assert( type == src2.type() && func != 0 ); + + if( src1.dims > 2 || src2.dims > 2 ) + { + dst.create(src1.dims, src1.size, src1.type()); + const Mat* arrays[] = {&src1, &src2, &dst, 0}; + Mat planes[3]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func( it.planes[0], it.planes[1], it.planes[2] ); + return; + } + + Size size = src1.size(); + CV_Assert( size == src2.size() ); dst.create( size, type ); func(src1, src2, dst); } void subtract( const Mat& src1, const Mat& src2, Mat& dst ) { - Size size = src1.size(); int type = src1.type(); + int type = src1.type(); BinaryFunc func = subTab[CV_MAT_DEPTH(type)]; - CV_Assert( size == src2.size() && type == src2.type() && func != 0 ); + CV_Assert( type == src2.type() && func != 0 ); + + if( src1.dims > 2 || src2.dims > 2 ) + { + dst.create(src1.dims, src1.size, src1.type()); + const Mat* arrays[] = {&src1, &src2, &dst, 0}; + Mat planes[3]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func( it.planes[0], it.planes[1], it.planes[2] ); + return; + } + + Size size = src1.size(); + CV_Assert( size == src2.size() ); dst.create( size, type ); func(src1, src2, dst); } @@ -698,7 +803,21 @@ void multiply(const Mat& src1, const Mat& src2, Mat& dst, double scale) }; MulDivFunc func = tab[src1.depth()]; - CV_Assert( src1.size() == src2.size() && src1.type() == src2.type() && func != 0 ); + CV_Assert( src1.type() == src2.type() && func != 0 ); + + if( src1.dims > 2 || src2.dims > 2 ) + { + dst.create(src1.dims, src1.size, src1.type()); + const Mat* arrays[] = {&src1, &src2, &dst, 0}; + Mat planes[3]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func( it.planes[0], it.planes[1], it.planes[2], scale ); + return; + } + + CV_Assert( src1.size() == src2.size() ); dst.create( src1.size(), src1.type() ); func( src1, src2, dst, scale ); } @@ -764,6 +883,20 @@ void divide(const Mat& src1, const Mat& src2, Mat& dst, double scale) MulDivFunc func = tab[src1.depth()]; CV_Assert( src1.size() == src2.size() && src1.type() == src2.type() && func != 0 ); + + if( src1.dims > 2 || src2.dims > 2 ) + { + dst.create(src1.dims, src1.size, src1.type()); + const Mat* arrays[] = {&src1, &src2, &dst, 0}; + Mat planes[3]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func( it.planes[0], it.planes[1], it.planes[2], scale ); + return; + } + + CV_Assert( src1.size() == src2.size() ); dst.create( src1.size(), src1.type() ); func( src1, src2, dst, scale ); } @@ -827,6 +960,19 @@ void divide(double scale, const Mat& src, Mat& dst) RecipFunc func = tab[src.depth()]; CV_Assert( func != 0 ); + + if( src.dims > 2 ) + { + dst.create(src.dims, src.size, src.type()); + const Mat* arrays[] = {&src, &dst, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func( scale, it.planes[0], it.planes[1] ); + return; + } + dst.create( src.size(), src.type() ); func( scale, src, dst ); } @@ -983,7 +1129,21 @@ void addWeighted( const Mat& src1, double alpha, const Mat& src2, }; AddWeightedFunc func = tab[src1.depth()]; - CV_Assert( src1.size() == src2.size() && src1.type() == src2.type() && func != 0 ); + CV_Assert( src1.type() == src2.type() && func != 0 ); + + if( src1.dims > 2 || src2.dims > 2 ) + { + dst.create(src1.dims, src1.size, src1.type()); + const Mat* arrays[] = {&src1, &src2, &dst, 0}; + Mat planes[3]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func( it.planes[0], alpha, it.planes[1], beta, gamma, it.planes[2] ); + return; + } + + CV_Assert( src1.size() == src2.size() ); dst.create( src1.size(), src1.type() ); func( src1, alpha, src2, beta, gamma, dst ); } @@ -1024,10 +1184,7 @@ void absdiff( const Mat& src1, const Mat& src2, Mat& dst ) binaryOpC1_,NoVec>, 0 }; - dst.create(src1.size(), src1.type()); - BinaryFunc func = tab[src1.depth()]; - CV_Assert(src1.size() == src2.size() && src1.type() == src2.type() && func != 0); - func( src1, src2, dst ); + binaryOp(src1, src2, dst, tab[src1.depth()]); } @@ -1043,9 +1200,22 @@ void absdiff( const Mat& src1, const Scalar& s, Mat& dst ) binarySOpCn_ >, 0 }; - dst.create(src1.size(), src1.type()); BinarySFuncCn func = tab[src1.depth()]; CV_Assert(src1.channels() <= 4 && func != 0); + + if( src1.dims > 2 ) + { + dst.create(src1.dims, src1.size, src1.type()); + const Mat* arrays[] = {&src1, &dst, 0}; + Mat planes[3]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func( it.planes[0], it.planes[1], s ); + return; + } + + dst.create(src1.size(), src1.type()); func( src1, dst, s ); } @@ -1174,13 +1344,24 @@ void inRange(const Mat& src, const Mat& lowerb, inRange_ >, 0 }; - CV_Assert( src.size() == lowerb.size() && src.size() == upperb.size() && - src.type() == lowerb.type() && src.type() == upperb.type() && - src.channels() <= 4 ); + CV_Assert( src.type() == lowerb.type() && src.type() == upperb.type() && src.channels() <= 4 ); InRangeFunc func = tab[src.type()]; CV_Assert( func != 0 ); + if( src.dims > 2 || lowerb.dims > 2 || upperb.dims > 2 ) + { + dst.create(src.dims, src.size, CV_8U); + const Mat* arrays[] = {&src, &lowerb, &upperb, &dst, 0}; + Mat planes[4]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func( it.planes[0], it.planes[1], it.planes[2], it.planes[3] ); + return; + } + + CV_Assert( src.size() == lowerb.size() && src.size() == upperb.size() ); dst.create(src.size(), CV_8U); func( src, lowerb, upperb, dst ); } @@ -1223,6 +1404,18 @@ void inRange(const Mat& src, const Scalar& lowerb, InRangeSFunc func = tab[src.type()]; CV_Assert( func != 0 ); + + if( src.dims > 2 ) + { + dst.create(src.dims, src.size, CV_8U); + const Mat* arrays[] = {&src, &dst, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func( it.planes[0], lowerb, upperb, it.planes[1] ); + return; + } dst.create(src.size(), CV_8U); func( src, lowerb, upperb, dst ); @@ -1275,8 +1468,7 @@ void compare( const Mat& src1, const Mat& src2, Mat& dst, int cmpOp ) binaryOpC1_,NoVec>, 0}, }; - dst.create(src1.rows, src1.cols, CV_8U); - CV_Assert(src1.size() == src2.size() && src1.type() == src2.type() && src1.channels() == 1); + CV_Assert(src1.channels() == 1); int depth = src1.depth(); const Mat *psrc1 = &src1, *psrc2 = &src2; @@ -1306,8 +1498,7 @@ void compare( const Mat& src1, const Mat& src2, Mat& dst, int cmpOp ) } BinaryFunc func = tab[cmpOp == CMP_EQ][depth]; - CV_Assert( func != 0 ); - func( *psrc1, *psrc2, dst ); + binaryOp(*psrc1, *psrc2, dst, func, CV_8U); if( invflag ) bitwise_not(dst, dst); } @@ -1368,6 +1559,23 @@ void compare( const Mat& src1, double value, Mat& dst, int cmpOp ) BinarySFuncC1 func = tab[cmpOp == CMP_EQ ? 0 : cmpOp == CMP_GT ? 1 : 2][depth]; CV_Assert( func != 0 ); + + if( src1.dims > 2 ) + { + dst.create(src1.dims, src1.size, CV_8U); + const Mat* arrays[] = {&src1, &dst, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + { + func( it.planes[0], it.planes[1], value ); + if( invflag ) + bitwise_not(it.planes[2], it.planes[2]); + } + return; + } + func( src1, dst, value ); if( invflag ) bitwise_not(dst, dst); @@ -1405,11 +1613,7 @@ void min( const Mat& src1, const Mat& src2, Mat& dst ) binaryOpC1_,VMin32f>, binaryOpC1_,NoVec>, 0 }; - BinaryFunc func = tab[src1.depth()]; - CV_Assert(src1.size() == src2.size() && src1.type() == src2.type() && func != 0); - dst.create(src1.size(), src1.type()); - - return func( src1, src2, dst ); + binaryOp(src1, src2, dst, tab[src1.depth()]); } void max( const Mat& src1, const Mat& src2, Mat& dst ) @@ -1421,11 +1625,7 @@ void max( const Mat& src1, const Mat& src2, Mat& dst ) binaryOpC1_,VMax32f>, binaryOpC1_,NoVec>, 0 }; - BinaryFunc func = tab[src1.depth()]; - CV_Assert(src1.size() == src2.size() && src1.type() == src2.type() && func != 0); - dst.create(src1.size(), src1.type()); - - return func( src1, src2, dst ); + binaryOp(src1, src2, dst, tab[src1.depth()]); } void min( const Mat& src1, double value, Mat& dst ) @@ -1442,6 +1642,19 @@ void min( const Mat& src1, double value, Mat& dst ) BinarySFuncC1 func = tab[src1.depth()]; CV_Assert(func != 0); + + if( src1.dims > 2 ) + { + dst.create(src1.dims, src1.size, src1.type()); + const Mat* arrays[] = {&src1, &dst, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func( it.planes[0], it.planes[1], value ); + return; + } + dst.create(src1.size(), src1.type()); return func( src1, dst, value ); } @@ -1460,6 +1673,19 @@ void max( const Mat& src1, double value, Mat& dst ) BinarySFuncC1 func = tab[src1.depth()]; CV_Assert(func != 0); + + if( src1.dims > 2 ) + { + dst.create(src1.dims, src1.size, src1.type()); + const Mat* arrays[] = {&src1, &dst, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func( it.planes[0], it.planes[1], value ); + return; + } + dst.create(src1.size(), src1.type()); return func( src1, dst, value ); } diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index f8e0fd961d..05fcc1c03f 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -120,7 +120,6 @@ void split(const Mat& src, Mat* mv) }; int i, depth = src.depth(), cn = src.channels(); - Size size = src.size(); if( cn == 1 ) { @@ -129,17 +128,31 @@ void split(const Mat& src, Mat* mv) } for( i = 0; i < cn; i++ ) - mv[i].create(src.size(), depth); + mv[i].create(src.dims, src.size, depth); if( cn <= 4 ) { SplitFunc func = tab[(cn-2)*5 + (src.elemSize1()>>1)]; CV_Assert( func != 0 ); - func( src, mv ); + + if( src.dims > 2 ) + { + const Mat* arrays[5]; + Mat planes[5]; + arrays[0] = &src; + for( i = 0; i < cn; i++ ) + arrays[i+1] = &mv[i]; + NAryMatIterator it(arrays, planes, cn+1); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func( it.planes[0], &it.planes[1] ); + } + else + func( src, mv ); } else { - vector pairs(cn*2); + AutoBuffer pairs(cn*2); for( i = 0; i < cn; i++ ) { @@ -216,7 +229,7 @@ mergeC4_( const Mat* srcmat, Mat& dstmat ) typedef void (*MergeFunc)(const Mat* src, Mat& dst); -void merge(const Mat* mv, size_t n, Mat& dst) +void merge(const Mat* mv, size_t _n, Mat& dst) { static MergeFunc tab[] = { @@ -225,18 +238,15 @@ void merge(const Mat* mv, size_t n, Mat& dst) mergeC4_, mergeC4_, mergeC4_, 0, mergeC4_ }; - size_t i; - CV_Assert( mv && n > 0 ); + CV_Assert( mv && _n > 0 ); int depth = mv[0].depth(); bool allch1 = true; - int total = 0; + int i, total = 0, n = (int)_n; - Size size = mv[0].size(); - for( i = 0; i < n; i++ ) { - CV_Assert(mv[i].size() == size && mv[i].depth() == depth); + CV_Assert(mv[i].size == mv[0].size && mv[i].depth() == depth); allch1 = allch1 && mv[i].channels() == 1; total += mv[i].channels(); } @@ -249,17 +259,30 @@ void merge(const Mat* mv, size_t n, Mat& dst) return; } - dst.create(size, CV_MAKETYPE(depth, total)); + dst.create(mv[0].dims, mv[0].size, CV_MAKETYPE(depth, total)); if( allch1 && total <= 4 ) { MergeFunc func = tab[(total-2)*5 + (CV_ELEM_SIZE(depth)>>1)]; CV_Assert( func != 0 ); - func( mv, dst ); + if( mv[0].dims > 2 ) + { + const Mat* arrays[5]; + Mat planes[5]; + arrays[total] = &dst; + for( i = 0; i < total; i++ ) + arrays[i] = &mv[i]; + NAryMatIterator it(arrays, planes, total+1); + + for( i = 0; i < it.nplanes; i++, ++it ) + func( &it.planes[0], it.planes[total] ); + } + else + func( mv, dst ); } else { - vector pairs(total*2); + AutoBuffer pairs(total*2); int j, k, ni=0; for( i = 0, j = 0; i < n; i++, j += ni ) @@ -335,12 +358,28 @@ typedef void (*MixChannelsFunc)( const void** src, const int* sdelta0, void mixChannels( const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int* fromTo, size_t npairs ) { - size_t i, j; - if( npairs == 0 ) return; CV_Assert( src && nsrcs > 0 && dst && ndsts > 0 && fromTo && npairs > 0 ); - + + if( src[0].dims > 2 ) + { + size_t k, m = nsrcs, n = ndsts; + CV_Assert( n > 0 && m > 0 ); + AutoBuffer v(m + n); + AutoBuffer planes(m + n); + for( k = 0; k < m; k++ ) + v[k] = &src[k]; + for( k = 0; k < n; k++ ) + v[m + k] = &dst[k]; + NAryMatIterator it(v, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + mixChannels( &it.planes[0], m, &it.planes[m], n, fromTo, npairs ); + return; + } + + size_t i, j; int depth = dst[0].depth(), esz1 = (int)dst[0].elemSize1(); Size size = dst[0].size(); @@ -704,22 +743,46 @@ void Mat::convertTo(Mat& dst, int _type, double alpha, double beta) const Mat temp; const Mat* psrc = this; - if( sdepth != ddepth && psrc == &dst ) + if( sdepth != ddepth && data == dst.data ) psrc = &(temp = *this); - dst.create( size(), _type ); + CvtFunc func = 0; + CvtScaleFunc scaleFunc = 0; + if( noScale ) { - CvtFunc func = tab[sdepth][ddepth]; + func = tab[sdepth][ddepth]; CV_Assert( func != 0 ); - func( *psrc, dst ); } else { - CvtScaleFunc func = stab[sdepth][ddepth]; - CV_Assert( func != 0 ); - func( *psrc, dst, alpha, beta ); + scaleFunc = stab[sdepth][ddepth]; + CV_Assert( scaleFunc != 0 ); } + + if( dims <= 2 ) + { + dst.create( size(), _type ); + if( func ) + func( *psrc, dst ); + else + scaleFunc( *psrc, dst, alpha, beta ); + } + else + { + dst.create( dims, size, _type ); + const Mat* arrays[] = {psrc, &dst, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + { + if( func ) + func(it.planes[0], it.planes[1]); + else + scaleFunc(it.planes[0], it.planes[1], alpha, beta); + } + } } /****************************************************************************************\ diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index d22048cc7e..91198667d6 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -168,7 +168,22 @@ void Mat::copyTo( Mat& dst ) const { if( data == dst.data ) 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); + return; + } + dst.create( rows, cols, type() ); Size sz = size(); const uchar* sptr = data; @@ -192,6 +207,18 @@ void Mat::copyTo( Mat& dst, const Mat& mask ) const copyTo(dst); return; } + + if( dims > 2 ) + { + dst.create( dims, size, type() ); + const Mat* arrays[] = { this, &dst, &mask, 0 }; + Mat planes[3]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + it.planes[0].copyTo(it.planes[1], it.planes[2]); + return; + } uchar* data0 = dst.data; dst.create( size(), type() ); @@ -202,6 +229,17 @@ void Mat::copyTo( Mat& dst, const Mat& mask ) const Mat& Mat::operator = (const Scalar& s) { + if( dims > 2 ) + { + const Mat* arrays[] = { this, 0 }; + Mat planes[1]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + it.planes[0] = s; + return *this; + } + Size sz = size(); uchar* dst = data; @@ -256,7 +294,18 @@ Mat& Mat::setTo(const Scalar& s, const Mat& mask) CV_Assert( func != 0 ); double buf[4]; scalarToRawData(s, buf, type(), 0); - func(buf, *this, mask); + + if( dims > 2 ) + { + const Mat* arrays[] = { this, &mask, 0 }; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func(buf, it.planes[0], it.planes[1]); + } + else + func(buf, *this, mask); } return *this; } @@ -379,6 +428,7 @@ void flip( const Mat& src, Mat& dst, int flip_mode ) flipHoriz_ > // 32 }; + CV_Assert( src.dims <= 2 ); dst.create( src.size(), src.type() ); if( flip_mode == 0 ) @@ -405,6 +455,8 @@ void flip( const Mat& src, Mat& dst, int flip_mode ) void repeat(const Mat& src, int ny, int nx, Mat& dst) { + CV_Assert( src.dims <= 2 ); + dst.create(src.rows*ny, src.cols*nx, src.type()); Size ssize = src.size(), dsize = dst.size(); int esz = (int)src.elemSize(); diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index fad4040706..9c3d4d70ad 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -347,7 +347,19 @@ static CvStatus CV_STDCALL Sqrt_64f(const double* src, double* dst, int len) void magnitude( const Mat& X, const Mat& Y, Mat& Mag ) { - int type = X.type(), depth = X.depth(), cn = X.channels(); + if( X.dims > 2 ) + { + Mag.create(X.dims, X.size, X.type()); + const Mat* arrays[] = {&X, &Y, &Mag, 0}; + Mat planes[3]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + magnitude( it.planes[0], it.planes[1], it.planes[2] ); + return; + } + + int type = X.type(), depth = X.depth(), cn = X.channels(); CV_Assert( X.size() == Y.size() && type == Y.type() && (depth == CV_32F || depth == CV_64F)); Mag.create( X.size(), type ); @@ -377,6 +389,18 @@ void magnitude( const Mat& X, const Mat& Y, Mat& Mag ) void phase( const Mat& X, const Mat& Y, Mat& Angle, bool angleInDegrees ) { + if( X.dims > 2 ) + { + Angle.create(X.dims, X.size, X.type()); + const Mat* arrays[] = {&X, &Y, &Angle, 0}; + Mat planes[3]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + phase( it.planes[0], it.planes[1], it.planes[2], angleInDegrees ); + return; + } + float buf[2][MAX_BLOCK_SIZE]; int i, j, type = X.type(), depth = X.depth(), cn = X.channels(); @@ -422,6 +446,19 @@ void phase( const Mat& X, const Mat& Y, Mat& Angle, bool angleInDegrees ) void cartToPolar( const Mat& X, const Mat& Y, Mat& Mag, Mat& Angle, bool angleInDegrees ) { + if( X.dims > 2 ) + { + Mag.create(X.dims, X.size, X.type()); + Angle.create(X.dims, X.size, X.type()); + const Mat* arrays[] = {&X, &Y, &Mag, &Angle, 0}; + Mat planes[4]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + cartToPolar( it.planes[0], it.planes[1], it.planes[2], it.planes[2], angleInDegrees ); + return; + } + float buf[2][MAX_BLOCK_SIZE]; int i, j, type = X.type(), depth = X.depth(), cn = X.channels(); @@ -568,6 +605,19 @@ SinCos_32f( const float *angle,float *sinval, float* cosval, void polarToCart( const Mat& Mag, const Mat& Angle, Mat& X, Mat& Y, bool angleInDegrees ) { + if( Mag.dims > 2 ) + { + X.create(Mag.dims, Mag.size, Mag.type()); + Y.create(Mag.dims, Mag.size, Mag.type()); + const Mat* arrays[] = {&Mag, &Angle, &X, &Y, 0}; + Mat planes[4]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + polarToCart( it.planes[0], it.planes[1], it.planes[2], it.planes[2], angleInDegrees ); + return; + } + int i, j, type = Angle.type(), depth = Angle.depth(); Size size; @@ -1115,6 +1165,18 @@ static CvStatus CV_STDCALL Exp_64f( const double *_x, double *y, int n ) void exp( const Mat& src, Mat& dst ) { + if( src.dims > 2 ) + { + dst.create(src.dims, src.size, src.type()); + const Mat* arrays[] = {&src, &dst, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + exp( it.planes[0], it.planes[1] ); + return; + } + int depth = src.depth(); dst.create( src.size(), src.type() ); Size size = getContinuousSize( src, dst, src.channels() ); @@ -1756,6 +1818,18 @@ static CvStatus CV_STDCALL Log_64f( const double *x, double *y, int n ) void log( const Mat& src, Mat& dst ) { + if( src.dims > 2 ) + { + dst.create(src.dims, src.size, src.type()); + const Mat* arrays[] = {&src, &dst, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + log( it.planes[0], it.planes[1] ); + return; + } + int depth = src.depth(); dst.create( src.size(), src.type() ); Size size = getContinuousSize( src, dst, src.channels() ); @@ -1804,6 +1878,18 @@ typedef CvStatus (CV_STDCALL * IPowFunc)( const void* src, void* dst, int len, i void pow( const Mat& _src, double power, Mat& dst ) { + if( _src.dims > 2 ) + { + dst.create(_src.dims, _src.size, _src.type()); + const Mat* arrays[] = {&_src, &dst, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + pow( it.planes[0], power, it.planes[1] ); + return; + } + int ipower = cvRound( power ), i, j; bool is_ipower = 0; int depth = _src.depth(); @@ -1913,6 +1999,23 @@ void sqrt(const Mat& a, Mat& b) bool checkRange(const Mat& src, bool quiet, Point* pt, double minVal, double maxVal) { + if( src.dims > 2 ) + { + const Mat* arrays[] = {&src, 0}; + Mat planes[1]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + { + if( !checkRange( it.planes[0], quiet, pt, minVal, maxVal )) + { + // todo: set index properly + return false; + } + } + return true; + } + int depth = src.depth(); Point badPt(-1, -1); double badValue = 0; @@ -2263,6 +2366,7 @@ cvSolveCubic( const CvMat* coeffs, CvMat* roots ) int cv::solveCubic( const Mat& coeffs, Mat& roots ) { + CV_Assert( coeffs.dims <= 2 ); const int n = 3; if( ((roots.rows != 1 || roots.cols != n) && (roots.rows != n || roots.cols != 1)) || @@ -2289,7 +2393,8 @@ double cv::solvePoly( const Mat& coeffs0, Mat& roots0, int maxIters ) double maxDiff = 0; int iter, i, j, n; - CV_Assert( (coeffs0.cols == 1 || coeffs0.rows == 1) && + CV_Assert( coeffs0.dims <= 2 && + (coeffs0.cols == 1 || coeffs0.rows == 1) && (coeffs0.depth() == CV_32F || coeffs0.depth() == CV_64F) && coeffs0.channels() <= 2 ); n = coeffs0.cols + coeffs0.rows - 2; diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index 11e76af116..d94f715f89 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -989,7 +989,7 @@ void gemm( const Mat& matA, const Mat& matB, double alpha, GEMMStoreFunc storeFunc; Mat *matD = &D, tmat; const uchar* Cdata = C ? C->data : 0; - size_t Cstep = C ? C->step : 0; + size_t Cstep = C ? (size_t)C->step : 0; AutoBuffer buf; if( type == CV_32FC1 ) @@ -2058,6 +2058,18 @@ void perspectiveTransform( const Mat& src, Mat& dst, const Mat& _m ) void scaleAdd( const Mat& src1, double alpha, const Mat& src2, Mat& dst ) { + if( src1.dims > 2 || src2.dims > 2 ) + { + dst.create(src1.dims, src1.size, src1.type()); + const Mat* arrays[] = {&src1, &src2, &dst, 0}; + Mat planes[3]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + scaleAdd( it.planes[0], alpha, it.planes[1], it.planes[2] ); + return; + } + int type = src1.type(), depth = CV_MAT_DEPTH(type); CV_Assert( src1.size() == src2.size() && type == src2.type() ); dst.create( src1.size(), type ); diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 3a7acf4e5a..781a0604b4 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -48,14 +48,347 @@ namespace cv { +void swap( Mat& a, Mat& b ) +{ + int *ap = (int*)&a, *bp = (int*)&b; + size_t i, n = sizeof(Mat)/sizeof(ap[0]); + + for( i = 0; i < n; i++ ) + std::swap(ap[i], bp[i]); + + if( a.step.p == b.step.buf ) + { + a.step.p = a.step.buf; + a.size.p = &a.rows; + } + + if( b.step.p == a.step.buf ) + { + b.step.p = b.step.buf; + b.size.p = &b.rows; + } +} + + +static inline void setSize( Mat& m, int _dims, const int* _sz, + const size_t* _steps, bool autoSteps=false ) +{ + CV_Assert( 0 <= _dims && _dims <= CV_MAX_DIM ); + if( m.dims != _dims ) + { + if( m.step.p != m.step.buf ) + { + fastFree(m.step.p); + m.step.p = m.step.buf; + m.size.p = &m.rows; + } + if( _dims > 2 ) + { + m.step.p = (size_t*)fastMalloc(_dims*sizeof(m.step.p[0]) + (_dims+1)*sizeof(m.size.p[0])); + m.size.p = (int*)(m.step.p + _dims) + 1; + m.size.p[-1] = _dims; + } + } + + m.dims = _dims; + if( !_sz ) + return; + + size_t esz = m.elemSize(), total = esz; + int i; + for( i = _dims-1; i >= 0; i-- ) + { + int s = _sz[i]; + CV_Assert( s > 0 ); + m.size.p[i] = s; + + if( _steps ) + m.step.p[i] = i < _dims-1 ? _steps[i] : esz; + else if( autoSteps ) + { + m.step.p[i] = total; + int64 total1 = (int64)total*s; + if( (uint64)total1 != (size_t)total1 ) + CV_Error( CV_StsOutOfRange, "The total matrix size does not fit to \"size_t\" type" ); + total = (size_t)total1; + } + } + + if( _dims == 1 ) + { + m.dims = 2; + m.cols = 1; + m.step[1] = esz; + } +} + +static void finalizeHdr(Mat& m) +{ + int i, j; + + for( i = 0; i < m.dims; i++ ) + { + if( m.size[i] > 1 ) + break; + } + + for( j = m.dims-1; j > i; j-- ) + { + 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]; + if( j <= i && t == (int)t ) + m.flags |= Mat::CONTINUOUS_FLAG; + + 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]; + } +} + + +void Mat::create(int d, const int* _sizes, int _type) +{ + int i; + CV_Assert(0 <= d && _sizes && d <= CV_MAX_DIM && _sizes); + _type = CV_MAT_TYPE(_type); + + if( data && (d == dims || (d == 1 && dims <= 2)) && _type == type() ) + { + if( d == 2 && rows == _sizes[0] && cols == _sizes[1] ) + return; + for( i = 0; i < d; i++ ) + if( size[i] != _sizes[i] ) + break; + if( i == d && (d > 1 || size[1] == 1)) + return; + } + + release(); + if( d == 0 ) + return; + 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 + { + allocator->allocate(dims, size, _type, refcount, datastart, data, step.p); + CV_Assert( step[dims-1] == elemSize() ); + } + + finalizeHdr(*this); +} + +void Mat::copySize(const Mat& m) +{ + setSize(*this, m.dims, 0, 0); + for( int i = 0; i < dims; i++ ) + { + size[i] = m.size[i]; + step[i] = m.step[i]; + } +} + +void Mat::deallocate() +{ + if( allocator ) + allocator->deallocate(refcount, datastart, data); + else + { + CV_DbgAssert(refcount != 0); + fastFree(datastart); + } +} + + +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) +{ + CV_Assert( m.dims >= 2 ); + if( m.dims > 2 ) + { + AutoBuffer rs(m.dims); + rs[0] = rowRange; + rs[1] = colRange; + for( int i = 2; i < m.dims; i++ ) + rs[i] = Range::all(); + *this = m(rs); + return; + } + + *this = m; + if( rowRange != Range::all() ) + { + CV_Assert( 0 <= rowRange.start && rowRange.start <= rowRange.end && rowRange.end <= m.rows ); + rows = rowRange.size(); + data += step*rowRange.start; + } + + if( colRange != Range::all() ) + { + 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; + } + + if( rows == 1 ) + flags |= CONTINUOUS_FLAG; + + if( refcount ) + CV_XADD(refcount, 1); + if( rows <= 0 || cols <= 0 ) + { + release(); + rows = cols = 0; + } +} + + +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) +{ + CV_Assert( m.dims <= 2 ); + flags &= roi.width < m.cols ? ~CONTINUOUS_FLAG : -1; + flags |= roi.height == 1 ? CONTINUOUS_FLAG : 0; + + size_t esz = elemSize(); + 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); + + step[0] = m.step[0]; step[1] = esz; + + if( rows <= 0 || cols <= 0 ) + { + release(); + rows = cols = 0; + } +} + + +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) +{ + setSize(*this, _dims, _sizes, _steps, true); + finalizeHdr(*this); +} + + +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) +{ + int i, d = m.dims; + + CV_Assert(ranges); + for( i = 0; i < d; i++ ) + { + Range r = ranges[i]; + CV_Assert( r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]) ); + } + *this = m; + for( i = 0; i < d; i++ ) + { + Range r = ranges[i]; + if( r != Range::all() ) + { + size[i] = r.end - r.start; + data += r.start*step[i]; + } + } + + finalizeHdr(*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), + size(&rows) +{ + int _sizes[CV_MAX_DIM]; + size_t _steps[CV_MAX_DIM]; + + int i, d = m->dims; + for( i = 0; i < d; i++ ) + { + _sizes[i] = m->dim[i].size; + _steps[i] = m->dim[i].step; + } + + setSize(*this, d, _sizes, _steps); + finalizeHdr(*this); + + if( copyData ) + { + Mat temp(*this); + temp.copyTo(*this); + } +} + + +Mat Mat::diag(int d) const +{ + CV_Assert( dims <= 2 ); + Mat m = *this; + size_t esz = elemSize(); + int len; + + if( d >= 0 ) + { + len = std::min(cols - d, rows); + m.data += esz*d; + } + else + { + len = std::min(rows + d, cols); + m.data -= step[0]*d; + } + CV_DbgAssert( len > 0 ); + + m.size[0] = m.rows = len; + m.size[1] = m.cols = 1; + m.step[0] += (len > 1 ? esz : 0); + + if( m.rows > 1 ) + m.flags &= ~CONTINUOUS_FLAG; + else + m.flags |= CONTINUOUS_FLAG; + return m; +} + + Mat::Mat(const IplImage* img, bool copyData) + : flags(MAGIC_VAL), dims(2), rows(0), cols(0), + data(0), refcount(0), datastart(0), dataend(0), allocator(0), size(&rows) { CV_DbgAssert(CV_IS_IMAGE(img) && img->imageData != 0); int depth = IPL2CV_DEPTH(img->depth); size_t esz; - step = img->widthStep; - refcount = 0; + step[0] = img->widthStep; if(!img->roi) { @@ -74,10 +407,11 @@ Mat::Mat(const IplImage* img, bool copyData) esz = elemSize(); data = datastart = (uchar*)img->imageData + (selectedPlane ? (img->roi->coi - 1)*step*img->height : 0) + - img->roi->yOffset*step + img->roi->xOffset*esz; + 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); + step[1] = esz; if( copyData ) { @@ -98,9 +432,10 @@ Mat::Mat(const IplImage* img, bool copyData) Mat::operator IplImage() const { + CV_Assert( dims <= 2 ); IplImage img; cvInitImageHeader(&img, size(), cvIplDepth(flags), channels()); - cvSetData(&img, data, (int)step); + cvSetData(&img, data, (int)step[0]); return img; } @@ -108,16 +443,20 @@ Mat::operator IplImage() const Mat cvarrToMat(const CvArr* arr, bool copyData, bool allowND, int coiMode) { + if( !arr ) + return Mat(); if( CV_IS_MAT(arr) ) return Mat((const CvMat*)arr, copyData ); - else if( CV_IS_IMAGE(arr) ) + if( CV_IS_MATND(arr) ) + return Mat((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 Mat(iplimg, copyData); } - else if( CV_IS_SEQ(arr) ) + if( CV_IS_SEQ(arr) ) { CvSeq* seq = (CvSeq*)arr; CV_Assert(seq->total > 0 && CV_ELEM_SIZE(seq->flags) == seq->elem_size); @@ -127,20 +466,53 @@ Mat cvarrToMat(const CvArr* arr, bool copyData, cvCvtSeqToArray(seq, buf.data, CV_WHOLE_SEQ); return buf; } - else - { - CvMat hdr, *cvmat = cvGetMat( arr, &hdr, 0, allowND ? 1 : 0 ); - if( cvmat ) - return Mat(cvmat, copyData); - } + CV_Error(CV_StsBadArg, "Unknown array type"); return Mat(); } - +void Mat::locateROI( Size& wholeSize, Point& ofs ) const +{ + CV_Assert( dims <= 2 && step[0] > 0 ); + size_t esz = elemSize(), minstep; + ptrdiff_t delta1 = data - datastart, delta2 = dataend - datastart; + + if( delta1 == 0 ) + ofs.x = ofs.y = 0; + else + { + ofs.y = (int)(delta1/step[0]); + ofs.x = (int)((delta1 - step[0]*ofs.y)/esz); + CV_DbgAssert( data == datastart + ofs.y*step[0] + ofs.x*esz ); + } + minstep = (ofs.x + cols)*esz; + wholeSize.height = (int)((delta2 - minstep)/step[0] + 1); + wholeSize.height = std::max(wholeSize.height, ofs.y + rows); + wholeSize.width = (int)((delta2 - step*(wholeSize.height-1))/esz); + wholeSize.width = std::max(wholeSize.width, ofs.x + cols); +} + +Mat& Mat::adjustROI( int dtop, int dbottom, int dleft, int dright ) +{ + CV_Assert( dims <= 2 && step[0] > 0 ); + Size wholeSize; Point ofs; + size_t esz = elemSize(); + locateROI( wholeSize, ofs ); + int row1 = std::max(ofs.y - dtop, 0), row2 = std::min(ofs.y + rows + dbottom, wholeSize.height); + int col1 = std::max(ofs.x - dleft, 0), col2 = std::min(ofs.x + cols + dright, wholeSize.width); + data += (row1 - ofs.y)*step + (col1 - ofs.x)*esz; + rows = row2 - row1; cols = col2 - col1; + size.p[0] = rows; size.p[1] = cols; + if( esz*cols == step[0] || rows == 1 ) + flags |= CONTINUOUS_FLAG; + else + flags &= ~CONTINUOUS_FLAG; + return *this; +} + void extractImageCOI(const CvArr* arr, Mat& ch, int coi) { Mat mat = cvarrToMat(arr, false, true, 1); - ch.create(mat.size(), mat.depth()); + ch.create(mat.dims, mat.size, mat.depth()); if(coi < 0) CV_Assert( CV_IS_IMAGE(arr) && (coi = cvGetImageCOI((const IplImage*)arr)-1) >= 0 ); CV_Assert(0 <= coi && coi < mat.channels()); @@ -153,7 +525,7 @@ void insertImageCOI(const Mat& ch, CvArr* arr, int coi) Mat mat = cvarrToMat(arr, false, true, 1); if(coi < 0) CV_Assert( CV_IS_IMAGE(arr) && (coi = cvGetImageCOI((const IplImage*)arr)-1) >= 0 ); - CV_Assert(ch.size() == mat.size() && ch.depth() == mat.depth() && 0 <= coi && coi < mat.channels()); + 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 ); } @@ -161,6 +533,7 @@ void insertImageCOI(const Mat& ch, CvArr* arr, int coi) Mat Mat::reshape(int new_cn, int new_rows) const { + CV_Assert( dims <= 2 ); Mat hdr = *this; int cn = channels(); @@ -189,7 +562,7 @@ Mat Mat::reshape(int new_cn, int new_rows) const "is not divisible by the new number of rows" ); hdr.rows = new_rows; - hdr.step = total_width * elemSize1(); + hdr.step[0] = total_width * elemSize1(); } int new_width = total_width / new_cn; @@ -207,6 +580,7 @@ Mat Mat::reshape(int new_cn, int new_rows) const void setIdentity( Mat& m, const Scalar& s ) { + CV_Assert( m.dims <= 2 ); int i, j, rows = m.rows, cols = m.cols, type = m.type(); if( type == CV_32FC1 ) @@ -244,6 +618,7 @@ setIdentity( Mat& m, const Scalar& s ) Scalar trace( const Mat& m ) { + CV_Assert( m.dims <= 2 ); int i, type = m.type(); int nm = std::min(m.rows, m.cols); @@ -270,7 +645,6 @@ Scalar trace( const Mat& m ) return cv::sum(m.diag()); } - /****************************************************************************************\ * transpose * \****************************************************************************************/ @@ -355,7 +729,7 @@ void transpose( const Mat& src, Mat& dst ) }; size_t esz = src.elemSize(); - CV_Assert( esz <= (size_t)32 ); + CV_Assert( src.dims <= 2 && esz <= (size_t)32 ); if( dst.data == src.data && dst.cols == dst.rows ) { @@ -373,16 +747,18 @@ void transpose( const Mat& src, Mat& dst ) } -void completeSymm( Mat& matrix, bool LtoR ) +void completeSymm( Mat& m, bool LtoR ) { - int i, j, nrows = matrix.rows, type = matrix.type(); + CV_Assert( m.dims <= 2 ); + + int i, j, nrows = m.rows, type = m.type(); int j0 = 0, j1 = nrows; - CV_Assert( matrix.rows == matrix.cols ); + CV_Assert( m.rows == m.cols ); if( type == CV_32FC1 || type == CV_32SC1 ) { - int* data = (int*)matrix.data; - size_t step = matrix.step/sizeof(data[0]); + int* data = (int*)m.data; + size_t step = m.step/sizeof(data[0]); for( i = 0; i < nrows; i++ ) { if( !LtoR ) j1 = i; else j0 = i+1; @@ -392,8 +768,8 @@ void completeSymm( Mat& matrix, bool LtoR ) } else if( type == CV_64FC1 ) { - double* data = (double*)matrix.data; - size_t step = matrix.step/sizeof(data[0]); + double* data = (double*)m.data; + size_t step = m.step/sizeof(data[0]); for( i = 0; i < nrows; i++ ) { if( !LtoR ) j1 = i; else j0 = i+1; @@ -405,10 +781,11 @@ void completeSymm( Mat& matrix, bool LtoR ) CV_Error( CV_StsUnsupportedFormat, "" ); } + Mat Mat::cross(const Mat& m) const { int t = type(), d = CV_MAT_DEPTH(t); - CV_Assert( size() == m.size() && t == m.type() && + CV_Assert( dims <= 2 && m.dims <= 2 && size() == m.size() && t == m.type() && ((rows == 3 && cols == 1) || (cols*channels() == 3 && rows == 1))); Mat result(rows, cols, t); @@ -528,6 +905,7 @@ typedef void (*ReduceFunc)( const Mat& src, Mat& dst ); void reduce(const Mat& src, Mat& dst, int dim, int op, int dtype) { + CV_Assert( src.dims <= 2 ); int op0 = op; int stype = src.type(), sdepth = src.depth(); if( dtype < 0 ) @@ -757,7 +1135,7 @@ void sort( const Mat& src, Mat& dst, int flags ) sort_, sort_, sort_, 0 }; SortFunc func = tab[src.depth()]; - CV_Assert( src.channels() == 1 && func != 0 ); + CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 ); dst.create( src.size(), src.type() ); func( src, dst, flags ); } @@ -770,7 +1148,7 @@ void sortIdx( const Mat& src, Mat& dst, int flags ) sortIdx_, sortIdx_, sortIdx_, 0 }; SortFunc func = tab[src.depth()]; - CV_Assert( src.channels() == 1 && func != 0 ); + CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 ); if( dst.data == src.data ) dst.release(); dst.create( src.size(), CV_32S ); @@ -898,7 +1276,7 @@ double kmeans( const Mat& data, int K, Mat& best_labels, bool simd = checkHardwareSupport(CV_CPU_SSE); attempts = std::max(attempts, 1); - CV_Assert( type == CV_32F && K > 0 ); + CV_Assert( data.dims <= 2 && type == CV_32F && K > 0 ); Mat _labels; if( flags & CV_KMEANS_USE_INITIAL_LABELS ) @@ -1253,196 +1631,14 @@ cvKMeans2( const CvArr* _samples, int cluster_count, CvArr* _labels, namespace cv { -//////////////////////////////// MatND /////////////////////////////////// - -MatND::MatND(const MatND& m, const Range* ranges) - : flags(MAGIC_VAL), dims(0), refcount(0), data(0), datastart(0), dataend(0) -{ - int i, j, d = m.dims; - - CV_Assert(ranges); - for( i = 0; i < d; i++ ) - { - Range r = ranges[i]; - CV_Assert( r == Range::all() || - (0 <= r.start && r.start < r.end && r.end <= m.size[i]) ); - } - *this = m; - for( i = 0; i < d; i++ ) - { - Range r = ranges[i]; - if( r != Range::all() ) - { - size[i] = r.end - r.start; - data += r.start*step[i]; - } - } - - for( i = 0; i < d; i++ ) - { - if( size[i] != 1 ) - break; - } - - CV_Assert( step[d-1] == elemSize() ); - for( j = d-1; j > i; j-- ) - { - if( step[j]*size[j] < step[j-1] ) - break; - } - flags = (flags & ~CONTINUOUS_FLAG) | (j <= i ? CONTINUOUS_FLAG : 0); -} - -void MatND::create(int d, const int* _sizes, int _type) -{ - CV_Assert(d > 0 && _sizes); - int i; - _type = CV_MAT_TYPE(_type); - if( data && d == dims && _type == type() ) - { - for( i = 0; i < d; i++ ) - if( size[i] != _sizes[i] ) - break; - if( i == d ) - return; - } - - release(); - - flags = (_type & CV_MAT_TYPE_MASK) | MAGIC_VAL | CONTINUOUS_FLAG; - size_t total = elemSize(); - int64 total1; - - for( i = d-1; i >= 0; i-- ) - { - int sz = _sizes[i]; - size[i] = sz; - step[i] = total; - total1 = (int64)total*sz; - CV_Assert( sz > 0 ); - if( (uint64)total1 != (size_t)total1 ) - CV_Error( CV_StsOutOfRange, "The total matrix size does not fit to \"size_t\" type" ); - total = (size_t)total1; - } - total = alignSize(total, (int)sizeof(*refcount)); - data = datastart = (uchar*)fastMalloc(total + (int)sizeof(*refcount)); - dataend = datastart + step[0]*size[0]; - refcount = (int*)(data + total); - *refcount = 1; - dims = d; -} - -void MatND::copyTo( MatND& m ) const -{ - m.create( dims, size, type() ); - NAryMatNDIterator it(*this, m); - - for( int i = 0; i < it.nplanes; i++, ++it ) - it.planes[0].copyTo(it.planes[1]); -} - -void MatND::copyTo( MatND& m, const MatND& mask ) const -{ - m.create( dims, size, type() ); - NAryMatNDIterator it(*this, m, mask); - - for( int i = 0; i < it.nplanes; i++, ++it ) - it.planes[0].copyTo(it.planes[1], it.planes[2]); -} - -void MatND::convertTo( MatND& m, int rtype, double alpha, double beta ) const -{ - rtype = rtype < 0 ? type() : CV_MAKETYPE(CV_MAT_DEPTH(rtype), channels()); - m.create( dims, size, rtype ); - NAryMatNDIterator it(*this, m); - - for( int i = 0; i < it.nplanes; i++, ++it ) - it.planes[0].convertTo(it.planes[1], rtype, alpha, beta); -} - -MatND& MatND::operator = (const Scalar& s) -{ - NAryMatNDIterator it(*this); - for( int i = 0; i < it.nplanes; i++, ++it ) - it.planes[0] = s; - - return *this; -} - -MatND& MatND::setTo(const Scalar& s, const MatND& mask) -{ - NAryMatNDIterator it(*this, mask); - for( int i = 0; i < it.nplanes; i++, ++it ) - it.planes[0].setTo(s, it.planes[1]); - - return *this; -} - -MatND MatND::reshape(int, int, const int*) const +Mat Mat::reshape(int, int, const int*) const { CV_Error(CV_StsNotImplemented, ""); // TBD - return MatND(); + return Mat(); } -MatND::operator Mat() const -{ - int i, d = dims, d1, rows, cols; - size_t _step = Mat::AUTO_STEP; - - if( d <= 2 ) - { - rows = size[0]; - cols = d == 2 ? size[1] : 1; - if( d == 2 ) - _step = step[0]; - } - else - { - rows = 1; - cols = size[d-1]; - - for( d1 = 0; d1 < d; d1++ ) - if( size[d1] > 1 ) - break; - - for( i = d-1; i > d1; i-- ) - { - int64 cols1 = (int64)cols*size[i-1]; - if( cols1 != (int)cols1 || size[i]*step[i] != step[i-1] ) - break; - cols = (int)cols1; - } - - if( i > d1 ) - { - --i; - _step = step[i]; - rows = size[i]; - for( ; i > d1; i-- ) - { - int64 rows1 = (int64)rows*size[i-1]; - if( rows1 != (int)rows1 || size[i]*step[i] != step[i-1] ) - break; - rows = (int)rows1; - } - - if( i > d1 ) - CV_Error( CV_StsBadArg, - "The nD matrix can not be represented as 2D matrix due " - "to its layout in memory; you may use (Mat)the_matnd.clone() instead" ); - } - } - - Mat m(rows, cols, type(), data, _step); - m.datastart = datastart; - m.dataend = dataend; - m.refcount = refcount; - m.addref(); - return m; -} - -MatND::operator CvMatND() const +Mat::operator CvMatND() const { CvMatND mat; cvInitMatNDHeader( &mat, dims, size, type(), data ); @@ -1453,77 +1649,43 @@ MatND::operator CvMatND() const return mat; } -NAryMatNDIterator::NAryMatNDIterator(const MatND** _arrays, size_t count) +NAryMatIterator::NAryMatIterator() + : arrays(0), planes(0), narrays(0), nplanes(0), iterdepth(0), idx(0) { - init(_arrays, count); -} - -NAryMatNDIterator::NAryMatNDIterator(const MatND* _arrays, size_t count) -{ - AutoBuffer buf(count); - for( size_t i = 0; i < count; i++ ) - buf[i] = _arrays + i; - init(buf, count); -} - - -NAryMatNDIterator::NAryMatNDIterator(const MatND& m1) -{ - const MatND* mm[] = {&m1}; - init(mm, 1); -} - -NAryMatNDIterator::NAryMatNDIterator(const MatND& m1, const MatND& m2) -{ - const MatND* mm[] = {&m1, &m2}; - init(mm, 2); -} - -NAryMatNDIterator::NAryMatNDIterator(const MatND& m1, const MatND& m2, const MatND& m3) -{ - const MatND* mm[] = {&m1, &m2, &m3}; - init(mm, 3); -} - -NAryMatNDIterator::NAryMatNDIterator(const MatND& m1, const MatND& m2, - const MatND& m3, const MatND& m4) -{ - const MatND* mm[] = {&m1, &m2, &m3, &m4}; - init(mm, 4); } -NAryMatNDIterator::NAryMatNDIterator(const MatND& m1, const MatND& m2, - const MatND& m3, const MatND& m4, - const MatND& m5) +NAryMatIterator::NAryMatIterator(const Mat** _arrays, Mat* _planes, int _narrays) + : arrays(0), planes(0), narrays(0), nplanes(0), iterdepth(0), idx(0) { - const MatND* mm[] = {&m1, &m2, &m3, &m4, &m5}; - init(mm, 5); + init(_arrays, _planes, _narrays); } -NAryMatNDIterator::NAryMatNDIterator(const MatND& m1, const MatND& m2, - const MatND& m3, const MatND& m4, - const MatND& m5, const MatND& m6) +void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, int _narrays) { - const MatND* mm[] = {&m1, &m2, &m3, &m4, &m5, &m6}; - init(mm, 6); -} + CV_Assert( _arrays && _planes ); + int i, j, d1=0, i0 = -1, d = -1, total = 0; -void NAryMatNDIterator::init(const MatND** _arrays, size_t count) -{ - CV_Assert( _arrays && count > 0 ); - arrays.resize(count); - int i, j, d1=0, i0 = -1, d = -1, n = (int)count; + arrays = _arrays; + planes = _planes; + narrays = _narrays; + nplanes = 0; + + if( narrays < 0 ) + { + for( i = 0; _arrays[i] != 0; i++ ) + ; + narrays = i; + CV_Assert(narrays <= 1000); + } iterdepth = 0; - for( i = 0; i < n; i++ ) + for( i = 0; i < narrays; i++ ) { - if( !_arrays[i] || !_arrays[i]->data ) - { - arrays[i] = MatND(); + CV_Assert(arrays[i] != 0); + if( !arrays[i]->data ) continue; - } - const MatND& A = arrays[i] = *_arrays[i]; + const Mat& A = *arrays[i]; if( i0 < 0 ) { @@ -1531,17 +1693,13 @@ void NAryMatNDIterator::init(const MatND** _arrays, size_t count) d = A.dims; // find the first dimensionality which is different from 1; - // in any of the arrays the first "d1" steps do not affect the continuity + // 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.dims == d ); - for( j = 0; j < d; j++ ) - CV_Assert( A.size[j] == arrays[i0].size[j] ); - } + CV_Assert( A.size == arrays[i0]->size ); if( !A.isContinuous() ) { @@ -1553,53 +1711,53 @@ void NAryMatNDIterator::init(const MatND** _arrays, size_t count) } } - if( i0 < 0 ) - CV_Error( CV_StsBadArg, "All the input arrays are empty" ); - - int total = arrays[i0].size[d-1]; - for( j = d-1; j > iterdepth; j-- ) + if( i0 >= 0 ) { - int64 total1 = (int64)total*arrays[i0].size[j-1]; - if( total1 != (int)total1 ) - break; - total = (int)total1; + total = arrays[i0]->size[d-1]; + for( j = d-1; j > iterdepth; j-- ) + { + int64 total1 = (int64)total*arrays[i0]->size[j-1]; + if( total1 != (int)total1 ) + break; + total = (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 = nplanes = 0; - iterdepth = j; - if( iterdepth == d1 ) - iterdepth = 0; - - planes.resize(n); - for( i = 0; i < n; i++ ) + for( i = 0; i < narrays; i++ ) { - if( !arrays[i].data ) + if( !arrays[i]->data ) { planes[i] = Mat(); continue; } - planes[i] = Mat( 1, total, arrays[i].type(), arrays[i].data ); - planes[i].datastart = arrays[i].datastart; - planes[i].dataend = arrays[i].dataend; - planes[i].refcount = arrays[i].refcount; - planes[i].addref(); + planes[i] = Mat( 1, total, arrays[i]->type(), arrays[i]->data ); + planes[i].datastart = arrays[i]->datastart; + planes[i].dataend = arrays[i]->dataend; } idx = 0; - nplanes = 1; - for( j = iterdepth-1; j >= 0; j-- ) - nplanes *= arrays[i0].size[j]; } -NAryMatNDIterator& NAryMatNDIterator::operator ++() +NAryMatIterator& NAryMatIterator::operator ++() { if( idx >= nplanes-1 ) return *this; ++idx; - for( size_t i = 0; i < arrays.size(); i++ ) + for( int i = 0; i < narrays; i++ ) { - const MatND& A = arrays[i]; + const Mat& A = *arrays[i]; Mat& M = planes[i]; if( !A.data ) continue; @@ -1617,588 +1775,149 @@ NAryMatNDIterator& NAryMatNDIterator::operator ++() return *this; } -NAryMatNDIterator NAryMatNDIterator::operator ++(int) +NAryMatIterator NAryMatIterator::operator ++(int) { - NAryMatNDIterator it = *this; + NAryMatIterator it = *this; ++*this; return it; } -void add(const MatND& a, const MatND& b, MatND& c, const MatND& mask) +/////////////////////////////////////////////////////////////////////////// +// MatConstIterator // +/////////////////////////////////////////////////////////////////////////// + +Point MatConstIterator::pos() const { - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c, mask); - - for( int i = 0; i < it.nplanes; i++, ++it ) - add( it.planes[0], it.planes[1], it.planes[2], it.planes[3] ); -} - -void subtract(const MatND& a, const MatND& b, MatND& c, const MatND& mask) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c, mask); - - for( int i = 0; i < it.nplanes; i++, ++it ) - subtract( it.planes[0], it.planes[1], it.planes[2], it.planes[3] ); -} - -void add(const MatND& a, const MatND& b, MatND& c) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - add( it.planes[0], it.planes[1], it.planes[2] ); -} - - -void subtract(const MatND& a, const MatND& b, MatND& c) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - subtract( it.planes[0], it.planes[1], it.planes[2] ); -} - -void add(const MatND& a, const Scalar& s, MatND& c, const MatND& mask) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, c, mask); - - for( int i = 0; i < it.nplanes; i++, ++it ) - add( it.planes[0], s, it.planes[1], it.planes[2] ); -} - -void subtract(const Scalar& s, const MatND& a, MatND& c, const MatND& mask) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, c, mask); - - for( int i = 0; i < it.nplanes; i++, ++it ) - subtract( s, it.planes[0], it.planes[1], it.planes[2] ); -} - -void multiply(const MatND& a, const MatND& b, MatND& c, double scale) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - multiply( it.planes[0], it.planes[1], it.planes[2], scale ); -} - -void divide(const MatND& a, const MatND& b, MatND& c, double scale) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - divide( it.planes[0], it.planes[1], it.planes[2], scale ); -} - -void divide(double scale, const MatND& b, MatND& c) -{ - c.create(b.dims, b.size, b.type()); - NAryMatNDIterator it(b, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - divide( scale, it.planes[0], it.planes[1] ); -} - -void scaleAdd(const MatND& a, double alpha, const MatND& b, MatND& c) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - scaleAdd( it.planes[0], alpha, it.planes[1], it.planes[2] ); -} - -void addWeighted(const MatND& a, double alpha, const MatND& b, - double beta, double gamma, MatND& c) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - addWeighted( it.planes[0], alpha, it.planes[1], beta, gamma, it.planes[2] ); -} - -Scalar sum(const MatND& m) -{ - NAryMatNDIterator it(m); - Scalar s; - - for( int i = 0; i < it.nplanes; i++, ++it ) - s += sum(it.planes[0]); - return s; -} - -int countNonZero( const MatND& m ) -{ - NAryMatNDIterator it(m); - int nz = 0; - - for( int i = 0; i < it.nplanes; i++, ++it ) - nz += countNonZero(it.planes[0]); - return nz; -} - -Scalar mean(const MatND& m) -{ - NAryMatNDIterator it(m); - double total = 1; - for( int i = 0; i < m.dims; i++ ) - total *= m.size[i]; - return sum(m)*(1./total); -} - -Scalar mean(const MatND& m, const MatND& mask) -{ - if( !mask.data ) - return mean(m); - NAryMatNDIterator it(m, mask); - double total = 0; - Scalar s; - for( int i = 0; i < it.nplanes; i++, ++it ) - { - int n = countNonZero(it.planes[1]); - s += mean(it.planes[0], it.planes[1])*(double)n; - total += n; - } - return s *= 1./std::max(total, 1.); -} - -void meanStdDev(const MatND& m, Scalar& mean, Scalar& stddev, const MatND& mask) -{ - NAryMatNDIterator it(m, mask); - double total = 0; - Scalar s, sq; - int k, cn = m.channels(); - - for( int i = 0; i < it.nplanes; i++, ++it ) - { - Scalar _mean, _stddev; - meanStdDev(it.planes[0], _mean, _stddev, it.planes[1]); - double nz = mask.data ? countNonZero(it.planes[1]) : - (double)it.planes[0].rows*it.planes[0].cols; - for( k = 0; k < cn; k++ ) - { - s[k] += _mean[k]*nz; - sq[k] += (_stddev[k]*_stddev[k] + _mean[k]*_mean[k])*nz; - } - total += nz; - } - - mean = stddev = Scalar(); - total = 1./std::max(total, 1.); - for( k = 0; k < cn; k++ ) - { - mean[k] = s[k]*total; - stddev[k] = std::sqrt(std::max(sq[k]*total - mean[k]*mean[k], 0.)); - } -} - -double norm(const MatND& a, int normType, const MatND& mask) -{ - NAryMatNDIterator it(a, mask); - double total = 0; - - for( int i = 0; i < it.nplanes; i++, ++it ) - { - double n = norm(it.planes[0], normType, it.planes[1]); - if( normType == NORM_INF ) - total = std::max(total, n); - else if( normType == NORM_L1 ) - total += n; - else - total += n*n; - } - - return normType != NORM_L2 ? total : std::sqrt(total); -} - -double norm(const MatND& a, const MatND& b, - int normType, const MatND& mask) -{ - bool isRelative = (normType & NORM_RELATIVE) != 0; - normType &= 7; - - NAryMatNDIterator it(a, b, mask); - double num = 0, denom = 0; - - for( int i = 0; i < it.nplanes; i++, ++it ) - { - double n = norm(it.planes[0], it.planes[1], normType, it.planes[2]); - double d = !isRelative ? 0 : norm(it.planes[1], normType, it.planes[2]); - if( normType == NORM_INF ) - { - num = std::max(num, n); - denom = std::max(denom, d); - } - else if( normType == NORM_L1 ) - { - num += n; - denom += d; - } - else - { - num += n*n; - denom += d*d; - } - } - - if( normType == NORM_L2 ) - { - num = std::sqrt(num); - denom = std::sqrt(denom); - } - - return !isRelative ? num : num/std::max(denom,DBL_EPSILON); -} - -void normalize( const MatND& src, MatND& dst, double a, double b, - int norm_type, int rtype, const MatND& mask ) -{ - double scale = 1, shift = 0; - if( norm_type == CV_MINMAX ) - { - double smin = 0, smax = 0; - double dmin = std::min( a, b ), dmax = std::max( a, b ); - minMaxLoc( src, &smin, &smax, 0, 0, mask ); - scale = (dmax - dmin)*(smax - smin > DBL_EPSILON ? 1./(smax - smin) : 0); - shift = dmin - smin*scale; - } - else if( norm_type == CV_L2 || norm_type == CV_L1 || norm_type == CV_C ) - { - scale = norm( src, norm_type, mask ); - scale = scale > DBL_EPSILON ? a/scale : 0.; - shift = 0; - } - else - CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" ); + if( !m ) + return Point(); + CV_DbgAssert(m->dims <= 2); - if( !mask.data ) - src.convertTo( dst, rtype, scale, shift ); - else + ptrdiff_t ofs = ptr - m->data; + 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->data; + for( int i = 0; i < m->dims; i++ ) { - MatND temp; - src.convertTo( temp, rtype, scale, shift ); - temp.copyTo( dst, mask ); + size_t s = m->step[i], v = ofs/s; + ofs -= v*s; + _idx[i] = (int)v; } } -static void ofs2idx(const MatND& a, size_t ofs, int* idx) +ptrdiff_t MatConstIterator::lpos() const { - int i, d = a.dims; + if(!m) + return 0; + if( m->isContinuous() ) + return (ptr - sliceStart)/elemSize; + ptrdiff_t ofs = ptr - m->data; + 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++ ) { - idx[i] = (int)(ofs / a.step[i]); - ofs %= a.step[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; + } -void minMaxLoc(const MatND& a, double* minVal, - double* maxVal, int* minLoc, int* maxLoc, - const MatND& mask) -{ - NAryMatNDIterator it(a, mask); - double minval = DBL_MAX, maxval = -DBL_MAX; - size_t minofs = 0, maxofs = 0, esz = a.elemSize(); + int d = m->dims; + if( d == 2 ) + { + ptrdiff_t ofs0, y; + if( relative ) + { + ofs0 = ptr - m->data; + 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->data + y1*m->step[0]; + sliceEnd = sliceStart + (m->cols-1)*elemSize; + ptr = y < 0 ? sliceStart : y >= m->rows ? sliceEnd : + sliceStart + (ofs - y*m->cols)*elemSize; + return; + } - for( int i = 0; i < it.nplanes; i++, ++it ) + 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->data + v*elemSize; + sliceStart = m->data; + + for( int i = d-2; i >= 0; i-- ) { - double val0 = 0, val1 = 0; - Point pt0, pt1; - minMaxLoc( it.planes[0], &val0, &val1, &pt0, &pt1, it.planes[1] ); - if( val0 < minval ) - { - minval = val0; - minofs = (it.planes[0].data - a.data) + pt0.x*esz; - } - if( val1 > maxval ) - { - maxval = val1; - maxofs = (it.planes[0].data - a.data) + pt1.x*esz; - } + szi = m->size[i]; + t = ofs/szi; + v = (int)(ofs - t*szi); + ofs = t; + sliceStart += v*m->step[i]; } - - if( minVal ) - *minVal = minval; - if( maxVal ) - *maxVal = maxval; - if( minLoc ) - ofs2idx(a, minofs, minLoc); - if( maxLoc ) - ofs2idx(a, maxofs, maxLoc); + + sliceEnd = sliceStart + m->size[d-1]*elemSize; + if( ofs > 0 ) + ptr = sliceEnd; + else + ptr = sliceStart + (ptr - m->data); } - -void merge(const MatND* mv, size_t n, MatND& dst) + +void MatConstIterator::seek(const int* _idx, bool relative) { - size_t k; - CV_Assert( n > 0 ); - vector v(n + 1); - int total_cn = 0; - for( k = 0; k < n; k++ ) + int i, d = m->dims; + ptrdiff_t ofs = 0; + if( !_idx ) + ; + else if( d == 2 ) + ofs = _idx[0]*m->size[1] + _idx[1]; + else { - total_cn += mv[k].channels(); - v[k] = mv[k]; + for( i = 0; i < d; i++ ) + ofs = ofs*m->size[i] + _idx[i]; } - dst.create( mv[0].dims, mv[0].size, CV_MAKETYPE(mv[0].depth(), total_cn) ); - v[n] = dst; - NAryMatNDIterator it(&v[0], v.size()); - - for( int i = 0; i < it.nplanes; i++, ++it ) - merge( &it.planes[0], n, it.planes[n] ); + seek(ofs, relative); } -void split(const MatND& m, MatND* mv) +ptrdiff_t operator - (const MatConstIterator& b, const MatConstIterator& a) { - size_t k, n = m.channels(); - CV_Assert( n > 0 ); - vector v(n + 1); - for( k = 0; k < n; k++ ) - { - mv[k].create( m.dims, m.size, CV_MAKETYPE(m.depth(), 1) ); - v[k] = mv[k]; - } - v[n] = m; - NAryMatNDIterator it(&v[0], v.size()); - - for( int i = 0; i < it.nplanes; i++, ++it ) - split( it.planes[n], &it.planes[0] ); -} - -void mixChannels(const MatND* src, int nsrcs, MatND* dst, int ndsts, - const int* fromTo, size_t npairs) -{ - size_t k, m = nsrcs, n = ndsts; - CV_Assert( n > 0 && m > 0 ); - vector v(m + n); - for( k = 0; k < m; k++ ) - v[k] = src[k]; - for( k = 0; k < n; k++ ) - v[m + k] = dst[k]; - NAryMatNDIterator it(&v[0], v.size()); - - for( int i = 0; i < it.nplanes; i++, ++it ) - { - Mat* pptr = &it.planes[0]; - mixChannels( pptr, m, pptr + m, n, fromTo, npairs ); - } -} - -void bitwise_and(const MatND& a, const MatND& b, MatND& c, const MatND& mask) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c, mask); - - for( int i = 0; i < it.nplanes; i++, ++it ) - bitwise_and( it.planes[0], it.planes[1], it.planes[2], it.planes[3] ); -} - -void bitwise_or(const MatND& a, const MatND& b, MatND& c, const MatND& mask) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c, mask); - - for( int i = 0; i < it.nplanes; i++, ++it ) - bitwise_or( it.planes[0], it.planes[1], it.planes[2], it.planes[3] ); -} - -void bitwise_xor(const MatND& a, const MatND& b, MatND& c, const MatND& mask) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c, mask); - - for( int i = 0; i < it.nplanes; i++, ++it ) - bitwise_xor( it.planes[0], it.planes[1], it.planes[2], it.planes[3] ); -} - -void bitwise_and(const MatND& a, const Scalar& s, MatND& c, const MatND& mask) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, c, mask); - - for( int i = 0; i < it.nplanes; i++, ++it ) - bitwise_and( it.planes[0], s, it.planes[1], it.planes[2] ); -} - -void bitwise_or(const MatND& a, const Scalar& s, MatND& c, const MatND& mask) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, c, mask); - - for( int i = 0; i < it.nplanes; i++, ++it ) - bitwise_or( it.planes[0], s, it.planes[1], it.planes[2] ); -} - -void bitwise_xor(const MatND& a, const Scalar& s, MatND& c, const MatND& mask) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, c, mask); - - for( int i = 0; i < it.nplanes; i++, ++it ) - bitwise_xor( it.planes[0], s, it.planes[1], it.planes[2] ); -} - -void bitwise_not(const MatND& a, MatND& c) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - bitwise_not( it.planes[0], it.planes[1] ); -} - -void absdiff(const MatND& a, const MatND& b, MatND& c) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - absdiff( it.planes[0], it.planes[1], it.planes[2] ); -} - -void absdiff(const MatND& a, const Scalar& s, MatND& c) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - absdiff( it.planes[0], s, it.planes[1] ); -} - -void inRange(const MatND& src, const MatND& lowerb, - const MatND& upperb, MatND& dst) -{ - dst.create(src.dims, src.size, CV_8UC1); - NAryMatNDIterator it(src, lowerb, upperb, dst); - - for( int i = 0; i < it.nplanes; i++, ++it ) - inRange( it.planes[0], it.planes[1], it.planes[2], it.planes[3] ); -} - -void inRange(const MatND& src, const Scalar& lowerb, - const Scalar& upperb, MatND& dst) -{ - dst.create(src.dims, src.size, CV_8UC1); - NAryMatNDIterator it(src, dst); - - for( int i = 0; i < it.nplanes; i++, ++it ) - inRange( it.planes[0], lowerb, upperb, it.planes[1] ); -} - -void compare(const MatND& a, const MatND& b, MatND& c, int cmpop) -{ - c.create(a.dims, a.size, CV_8UC1); - NAryMatNDIterator it(a, b, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - compare( it.planes[0], it.planes[1], it.planes[2], cmpop ); -} - -void compare(const MatND& a, double s, MatND& c, int cmpop) -{ - c.create(a.dims, a.size, CV_8UC1); - NAryMatNDIterator it(a, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - compare( it.planes[0], s, it.planes[1], cmpop ); -} - -void min(const MatND& a, const MatND& b, MatND& c) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - min( it.planes[0], it.planes[1], it.planes[2] ); -} - -void min(const MatND& a, double alpha, MatND& c) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - min( it.planes[0], alpha, it.planes[1] ); -} - -void max(const MatND& a, const MatND& b, MatND& c) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - max( it.planes[0], it.planes[1], it.planes[2] ); -} - -void max(const MatND& a, double alpha, MatND& c) -{ - c.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, c); - - for( int i = 0; i < it.nplanes; i++, ++it ) - max( it.planes[0], alpha, it.planes[1] ); -} - -void sqrt(const MatND& a, MatND& b) -{ - b.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b); - - for( int i = 0; i < it.nplanes; i++, ++it ) - sqrt( it.planes[0], it.planes[1] ); -} - -void pow(const MatND& a, double power, MatND& b) -{ - b.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b); - - for( int i = 0; i < it.nplanes; i++, ++it ) - pow( it.planes[0], power, it.planes[1] ); -} - -void exp(const MatND& a, MatND& b) -{ - b.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b); - - for( int i = 0; i < it.nplanes; i++, ++it ) - exp( it.planes[0], it.planes[1] ); -} - -void log(const MatND& a, MatND& b) -{ - b.create(a.dims, a.size, a.type()); - NAryMatNDIterator it(a, b); - - for( int i = 0; i < it.nplanes; i++, ++it ) - log( it.planes[0], it.planes[1] ); -} - -bool checkRange(const MatND& a, bool quiet, int*, - double minVal, double maxVal) -{ - NAryMatNDIterator it(a); - - for( int i = 0; i < it.nplanes; i++, ++it ) - { - Point pt; - if( !checkRange( it.planes[0], quiet, &pt, minVal, maxVal )) - { - // todo: set index properly - return false; - } - } - return true; -} - + if( a.m != b.m ) + return INT_MAX; + if( a.sliceEnd == b.sliceEnd ) + return (b.ptr - a.ptr)/b.elemSize; + return b.lpos() - a.lpos(); +} + //////////////////////////////// SparseMat //////////////////////////////// template void @@ -2366,48 +2085,7 @@ void SparseMat::Hdr::clear() } -SparseMat::SparseMat(const Mat& m, bool try1d) -: flags(MAGIC_VAL), hdr(0) -{ - bool is1d = try1d && m.cols == 1; - - if( is1d ) - { - int i, M = m.rows; - const uchar* data = m.data; - size_t step = m.step, esz = m.elemSize(); - create( 1, &M, m.type() ); - for( i = 0; i < M; i++ ) - { - const uchar* from = data + step*i; - if( isZeroElem(from, esz) ) - continue; - uchar* to = newNode(&i, hash(i)); - copyElem(from, to, esz); - } - } - else - { - int i, j, size[] = {m.rows, m.cols}; - const uchar* data = m.data; - size_t step = m.step, esz = m.elemSize(); - create( 2, size, m.type() ); - for( i = 0; i < m.rows; i++ ) - { - for( j = 0; j < m.cols; j++ ) - { - const uchar* from = data + step*i + esz*j; - if( isZeroElem(from, esz) ) - continue; - int idx[] = {i, j}; - uchar* to = newNode(idx, hash(i, j)); - copyElem(from, to, esz); - } - } - } -} - -SparseMat::SparseMat(const MatND& m) +SparseMat::SparseMat(const Mat& m) : flags(MAGIC_VAL), hdr(0) { create( m.dims, m.size, m.type() ); @@ -2502,35 +2180,6 @@ void SparseMat::copyTo( SparseMat& m ) const } void SparseMat::copyTo( Mat& m ) const -{ - CV_Assert( hdr && hdr->dims <= 2 ); - m.create( hdr->size[0], hdr->dims == 2 ? hdr->size[1] : 1, type() ); - m = Scalar(0); - - SparseMatConstIterator from = begin(); - size_t i, N = nzcount(), esz = elemSize(); - - if( hdr->dims == 2 ) - { - for( i = 0; i < N; i++, ++from ) - { - const Node* n = from.node(); - uchar* to = m.data + m.step*n->idx[0] + esz*n->idx[1]; - copyElem( from.ptr, to, esz ); - } - } - else - { - for( i = 0; i < N; i++, ++from ) - { - const Node* n = from.node(); - uchar* to = m.data + esz*n->idx[0]; - copyElem( from.ptr, to, esz ); - } - } -} - -void SparseMat::copyTo( MatND& m ) const { CV_Assert( hdr ); m.create( dims(), hdr->size, type() ); @@ -2598,68 +2247,6 @@ void SparseMat::convertTo( Mat& m, int rtype, double alpha, double beta ) const rtype = type(); rtype = CV_MAKETYPE(rtype, cn); - CV_Assert( hdr && hdr->dims <= 2 ); - m.create( hdr->size[0], hdr->dims == 2 ? hdr->size[1] : 1, type() ); - m = Scalar(beta); - - SparseMatConstIterator from = begin(); - size_t i, N = nzcount(), esz = CV_ELEM_SIZE(rtype); - - if( alpha == 1 && beta == 0 ) - { - ConvertData cvtfunc = getConvertData(type(), rtype); - - if( hdr->dims == 2 ) - { - for( i = 0; i < N; i++, ++from ) - { - const Node* n = from.node(); - uchar* to = m.data + m.step*n->idx[0] + esz*n->idx[1]; - cvtfunc( from.ptr, to, cn ); - } - } - else - { - for( i = 0; i < N; i++, ++from ) - { - const Node* n = from.node(); - uchar* to = m.data + esz*n->idx[0]; - cvtfunc( from.ptr, to, cn ); - } - } - } - else - { - ConvertScaleData cvtfunc = getConvertScaleData(type(), rtype); - - if( hdr->dims == 2 ) - { - for( i = 0; i < N; i++, ++from ) - { - const Node* n = from.node(); - uchar* to = m.data + m.step*n->idx[0] + esz*n->idx[1]; - cvtfunc( from.ptr, to, cn, alpha, beta ); - } - } - else - { - for( i = 0; i < N; i++, ++from ) - { - const Node* n = from.node(); - uchar* to = m.data + esz*n->idx[0]; - cvtfunc( from.ptr, to, cn, alpha, beta ); - } - } - } -} - -void SparseMat::convertTo( MatND& 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); diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index f631c2d480..0e09624e80 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -5266,16 +5266,18 @@ void writeScalar(FileStorage& fs, const string& value ) void write( FileStorage& fs, const string& name, const Mat& value ) { - CvMat mat = value; - cvWrite( *fs, name.size() ? name.c_str() : 0, &mat ); + if( value.dims <= 2 ) + { + CvMat mat = value; + cvWrite( *fs, name.size() ? name.c_str() : 0, &mat ); + } + else + { + CvMatND mat = value; + cvWrite( *fs, name.size() ? name.c_str() : 0, &mat ); + } } -void write( FileStorage& fs, const string& name, const MatND& value ) -{ - CvMatND mat = value; - cvWrite( *fs, name.size() ? name.c_str() : 0, &mat ); -} - // TODO: the 4 functions below need to be implemented more efficiently void write( FileStorage& fs, const string& name, const SparseMat& value ) { @@ -5301,23 +5303,24 @@ void read( const FileNode& node, Mat& mat, const Mat& default_mat ) default_mat.copyTo(mat); return; } - Ptr m = (CvMat*)cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node); - CV_Assert(CV_IS_MAT(m)); - Mat(m).copyTo(mat); + void* obj = cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node); + if(CV_IS_MAT(obj)) + { + Mat((const CvMat*)obj).copyTo(mat); + cvReleaseMat((CvMat**)&obj); + } + else if(CV_IS_MATND(obj)) + { + Mat((const CvMatND*)obj).copyTo(mat); + cvReleaseMatND((CvMatND**)&obj); + } + else + { + cvRelease(&obj); + CV_Error(CV_StsBadArg, "Unknown array type"); + } } -void read( const FileNode& node, MatND& mat, const MatND& default_mat ) -{ - if( node.empty() ) - { - default_mat.copyTo(mat); - return; - } - Ptr m = (CvMatND*)cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node); - CV_Assert(CV_IS_MATND(m)); - MatND(m).copyTo(mat); -} - void read( const FileNode& node, SparseMat& mat, const SparseMat& default_mat ) { if( node.empty() ) diff --git a/modules/core/src/rand.cpp b/modules/core/src/rand.cpp index ff2774cf24..3088097489 100644 --- a/modules/core/src/rand.cpp +++ b/modules/core/src/rand.cpp @@ -482,7 +482,7 @@ void RNG::fill( Mat& mat, int disttype, const Scalar& param1, const Scalar& para Randn_, Randn_, 0} }; - + int depth = mat.depth(), channels = mat.channels(); double dparam[2][12]; float fparam[2][12]; @@ -588,15 +588,18 @@ void RNG::fill( Mat& mat, int disttype, const Scalar& param1, const Scalar& para } CV_Assert( func != 0); - func( mat, &state, param ); -} - -void RNG::fill( MatND& mat, int disttype, const Scalar& param1, const Scalar& param2 ) -{ - NAryMatNDIterator it(mat); - - for( int i = 0; i < it.nplanes; i++, ++it ) - fill( it.planes[0], disttype, param1, param2 ); + + if( mat.dims > 2 ) + { + const Mat* arrays[] = {&mat, 0}; + Mat planes[1]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + func( it.planes[0], &state, param ); + } + else + func( mat, &state, param ); } #ifdef WIN32 diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 6e52226b83..e4ce8348db 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -160,14 +160,23 @@ Scalar sum( const Mat& m ) sum_, Vec >, 0 }; - Size size = m.size(); - SumFunc func; - CV_Assert( m.channels() <= 4 ); - func = tab[m.type()]; + SumFunc func = tab[m.type()]; CV_Assert( func != 0 ); + if( m.dims > 2 ) + { + const Mat* arrays[] = {&m, 0}; + Mat planes[1]; + NAryMatIterator it(arrays, planes); + Scalar s; + + for( int i = 0; i < it.nplanes; i++, ++it ) + s += func(it.planes[0]); + return s; + } + return func(m); } @@ -208,6 +217,19 @@ int countNonZero( const Mat& m ) CountNonZeroFunc func = tab[m.depth()]; CV_Assert( m.channels() == 1 && func != 0 ); + + if( m.dims > 2 ) + { + const Mat* arrays[] = {&m, 0}; + Mat planes[1]; + NAryMatIterator it(arrays, planes); + int nz = 0; + + for( int i = 0; i < it.nplanes; i++, ++it ) + nz += func(it.planes[0]); + return nz; + } + return func(m); } @@ -275,7 +297,7 @@ typedef Scalar (*MeanMaskFunc)(const Mat& src, const Mat& mask); Scalar mean(const Mat& m) { - return sum(m)*(1./std::max(m.rows*m.cols, 1)); + return sum(m)*(1./m.total()); } Scalar mean( const Mat& m, const Mat& mask ) @@ -314,11 +336,28 @@ Scalar mean( const Mat& m, const Mat& mask ) if( !mask.data ) return mean(m); - CV_Assert( m.channels() <= 4 && m.size() == mask.size() && mask.type() == CV_8U ); + CV_Assert( m.channels() <= 4 && mask.type() == CV_8U ); MeanMaskFunc func = tab[m.type()]; CV_Assert( func != 0 ); - + + if( m.dims > 2 ) + { + const Mat* arrays[] = {&m, &mask, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + double total = 0; + Scalar s; + for( int i = 0; i < it.nplanes; i++, ++it ) + { + int n = countNonZero(it.planes[1]); + s += mean(it.planes[0], it.planes[1])*(double)n; + total += n; + } + return (s * 1./std::max(total, 1.)); + } + + CV_Assert( m.size() == mask.size() ); return func( m, mask ); } @@ -510,20 +549,57 @@ void meanStdDev( const Mat& m, Scalar& mean, Scalar& stddev, const Mat& mask ) meanStdDevMask_ >, 0 }; - CV_Assert( m.channels() <= 4 ); + CV_Assert( m.channels() <= 4 && (mask.empty() || mask.type() == CV_8U) ); - if( !mask.data ) + MeanStdDevFunc func = tab[m.type()]; + MeanStdDevMaskFunc mfunc = mtab[m.type()]; + CV_Assert( func != 0 || mfunc != 0 ); + + if( m.dims > 2 ) { - MeanStdDevFunc func = tab[m.type()]; - CV_Assert( func != 0 ); - func( m, mean, stddev ); + Scalar s, sq; + double total = 0; + + const Mat* arrays[] = {&m, &mask, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + int k, cn = m.channels(); + + for( int i = 0; i < it.nplanes; i++, ++it ) + { + Scalar _mean, _stddev; + double nz = (double)(mask.data ? countNonZero(it.planes[1]) : it.planes[0].rows*it.planes[0].cols); + + if( func ) + func(it.planes[0], _mean, _stddev); + else + mfunc(it.planes[0], it.planes[1], _mean, _stddev); + + total += nz; + for( k = 0; k < cn; k++ ) + { + s[k] += _mean[k]*nz; + sq[k] += (_stddev[k]*_stddev[k] + _mean[k]*_mean[k])*nz; + } + } + + mean = stddev = Scalar(); + total = 1./std::max(total, 1.); + for( k = 0; k < cn; k++ ) + { + mean[k] = s[k]*total; + stddev[k] = std::sqrt(std::max(sq[k]*total - mean[k]*mean[k], 0.)); + } + return; + } + + if( mask.data ) + { + CV_Assert( mask.size() == m.size() ); + mfunc( m, mask, mean, stddev ); } else - { - MeanStdDevMaskFunc func = mtab[m.type()]; - CV_Assert( mask.size() == m.size() && mask.type() == CV_8U && func != 0 ); - func( m, mask, mean, stddev ); - } + func( m, mean, stddev ); } @@ -630,6 +706,8 @@ typedef void (*MinMaxIndxMaskFunc)(const Mat&, const Mat&, void minMaxLoc( const Mat& img, double* minVal, double* maxVal, Point* minLoc, Point* maxLoc, const Mat& mask ) { + CV_Assert(img.dims <= 2); + static MinMaxIndxFunc tab[] = {minMaxIndx_, 0, minMaxIndx_, minMaxIndx_, minMaxIndx_, minMaxIndx_, minMaxIndx_, 0}; @@ -683,6 +761,64 @@ void minMaxLoc( const Mat& img, double* minVal, double* maxVal, } } +static void ofs2idx(const Mat& a, size_t ofs, int* idx) +{ + int i, d = a.dims; + for( i = 0; i < d; i++ ) + { + idx[i] = (int)(ofs / a.step[i]); + ofs %= a.step[i]; + } +} + +void minMaxIndx(const Mat& a, double* minVal, + double* maxVal, int* minIdx, int* maxIdx, + const Mat& mask) +{ + if( a.dims <= 2 ) + { + Point minLoc, maxLoc; + minMaxLoc(a, minVal, maxVal, &minLoc, &maxLoc, mask); + if( minIdx ) + minIdx[0] = minLoc.x, minIdx[1] = minLoc.y; + if( maxIdx ) + maxIdx[0] = maxLoc.x, maxIdx[1] = maxLoc.y; + return; + } + + const Mat* arrays[] = {&a, &mask, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + double minval = DBL_MAX, maxval = -DBL_MAX; + size_t minofs = 0, maxofs = 0, esz = a.elemSize(); + + for( int i = 0; i < it.nplanes; i++, ++it ) + { + double val0 = 0, val1 = 0; + Point pt0, pt1; + minMaxLoc( it.planes[0], &val0, &val1, &pt0, &pt1, it.planes[1] ); + if( val0 < minval ) + { + minval = val0; + minofs = (it.planes[0].data - a.data) + pt0.x*esz; + } + if( val1 > maxval ) + { + maxval = val1; + maxofs = (it.planes[0].data - a.data) + pt1.x*esz; + } + } + + if( minVal ) + *minVal = minval; + if( maxVal ) + *maxVal = maxval; + if( minIdx ) + ofs2idx(a, minofs, minIdx); + if( maxIdx ) + ofs2idx(a, maxofs, maxIdx); +} + /****************************************************************************************\ * norm * \****************************************************************************************/ @@ -1066,7 +1202,26 @@ double norm( const Mat& a, int normType ) CV_Assert(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2); NormFunc func = tab[normType >> 1][a.depth()]; CV_Assert(func != 0); - double r = func(a); + + double r = 0; + if( a.dims > 2 ) + { + const Mat* arrays[] = {&a, 0}; + Mat planes[1]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + { + double n = func(it.planes[0]); + if( normType == NORM_INF ) + r = std::max(r, n); + else + r += n; + } + } + else + r = func(a); + return normType == NORM_L2 ? std::sqrt(r) : r; } @@ -1111,10 +1266,32 @@ double norm( const Mat& a, int normType, const Mat& mask ) normType &= 7; CV_Assert((normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2) && - a.size() == mask.size() && mask.type() == CV_8U && a.channels() == 1); + mask.type() == CV_8U && a.channels() == 1); NormMaskFunc func = tab[normType >> 1][a.depth()]; CV_Assert(func != 0); - double r = func(a, mask); + + double r = 0; + if( a.dims > 2 ) + { + const Mat* arrays[] = {&a, &mask, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + { + double n = func(it.planes[0], it.planes[1]); + if( normType == NORM_INF ) + r = std::max(r, n); + else + r += n; + } + } + else + { + CV_Assert( a.size() == mask.size() ); + r = func(a, mask); + } + return normType == NORM_L2 ? std::sqrt(r) : r; } @@ -1154,15 +1331,35 @@ double norm( const Mat& a, const Mat& b, int normType ) } }; - CV_Assert( a.type() == b.type() && a.size() == b.size() ); - + CV_Assert( a.type() == b.type() ); bool isRelative = (normType & NORM_RELATIVE) != 0; normType &= 7; CV_Assert(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2); - NormDiffFunc func = tab[normType >> 1][a.depth()]; CV_Assert(func != 0); - double r = func( a, b ); + + double r = 0.; + if( a.dims > 2 ) + { + const Mat* arrays[] = {&a, &b, 0}; + Mat planes[2]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + { + double n = func(it.planes[0], it.planes[1]); + + if( normType == NORM_INF ) + r = std::max(r, n); + else + r += n; + } + } + else + { + CV_Assert( a.size() == b.size() ); + r = func( a, b ); + } if( normType == NORM_L2 ) r = std::sqrt(r); if( isRelative ) @@ -1208,16 +1405,37 @@ double norm( const Mat& a, const Mat& b, int normType, const Mat& mask ) if( !mask.data ) return norm(a, b, normType); - CV_Assert( a.type() == b.type() && a.size() == b.size() && - a.size() == mask.size() && mask.type() == CV_8U && a.channels() == 1); - + CV_Assert( a.type() == b.type() && mask.type() == CV_8U && a.channels() == 1); bool isRelative = (normType & NORM_RELATIVE) != 0; normType &= 7; CV_Assert(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2); NormDiffMaskFunc func = tab[normType >> 1][a.depth()]; CV_Assert(func != 0); - double r = func( a, b, mask ); + + double r = 0.; + if( a.dims > 2 ) + { + const Mat* arrays[] = {&a, &b, &mask, 0}; + Mat planes[3]; + NAryMatIterator it(arrays, planes); + + for( int i = 0; i < it.nplanes; i++, ++it ) + { + double n = func(it.planes[0], it.planes[1], it.planes[2]); + + if( normType == NORM_INF ) + r = std::max(r, n); + else + r += n; + } + } + else + { + CV_Assert( a.size() == b.size() && a.size() == mask.size() ); + r = func( a, b, mask ); + } + if( normType == NORM_L2 ) r = std::sqrt(r); if( isRelative )