united cv::Mat and cv::MatND
authorVadim Pisarevsky <no@email>
Tue, 12 Oct 2010 12:31:40 +0000 (12:31 +0000)
committerVadim Pisarevsky <no@email>
Tue, 12 Oct 2010 12:31:40 +0000 (12:31 +0000)
13 files changed:
modules/core/include/opencv2/core/core.hpp
modules/core/include/opencv2/core/mat.hpp
modules/core/include/opencv2/core/operations.hpp
modules/core/include/opencv2/core/types_c.h
modules/core/src/arithm.cpp
modules/core/src/convert.cpp
modules/core/src/copy.cpp
modules/core/src/mathfuncs.cpp
modules/core/src/matmul.cpp
modules/core/src/matrix.cpp
modules/core/src/persistence.cpp
modules/core/src/rand.cpp
modules/core/src/stat.cpp

index 0103fc573faa3aeb3cc90b91b70a274f7b061580..b65a018152f0463f269734fe981edd5d1c57f757 100644 (file)
@@ -85,9 +85,14 @@ typedef std::string String;
 typedef std::basic_string<wchar_t> 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<typename _Tp> class CV_EXPORTS MatIterator_;
 template<typename _Tp> 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:
    <ul>
@@ -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<typename _Tp, int m, int n> explicit Mat(const Matx<_Tp, m, n>& mtx,
                                                       bool copyData=true);
     //! builds matrix from a 2D point
-    template<typename _Tp> explicit Mat(const Point_<_Tp>& pt);
+    template<typename _Tp> explicit Mat(const Point_<_Tp>& pt, bool copyData=true);
     //! builds matrix from a 3D point
-    template<typename _Tp> explicit Mat(const Point3_<_Tp>& pt);
+    template<typename _Tp> explicit Mat(const Point3_<_Tp>& pt, bool copyData=true);
     //! builds matrix from comma initializer
     template<typename _Tp> 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<int n> uchar* ptr(const Vec<int, n>& idx);
+    template<int n> const uchar* ptr(const Vec<int, n>& idx) const;
 
     //! template version of the above method
-    template<typename _Tp> _Tp* ptr(int y=0);
-    template<typename _Tp> const _Tp* ptr(int y=0) const;
+    template<typename _Tp> _Tp* ptr(int i0=0);
+    template<typename _Tp> const _Tp* ptr(int i0=0) const;
+    
+    template<typename _Tp> _Tp* ptr(int i0, int i1);
+    template<typename _Tp> const _Tp* ptr(int i0, int i1) const;
+    
+    template<typename _Tp> _Tp* ptr(int i0, int i1, int i2);
+    template<typename _Tp> const _Tp* ptr(int i0, int i1, int i2) 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<typename _Tp> _Tp& at(int y, int x);
+    template<typename _Tp> _Tp* ptr(const int* idx);
+    template<typename _Tp> const _Tp* ptr(const int* idx) const;
+    
+    template<typename _Tp, int n> _Tp* ptr(const Vec<int, n>& idx);
+    template<typename _Tp, int n> const _Tp* ptr(const Vec<int, n>& idx) const;
+    
+    //! the same as above, with the pointer dereferencing
+    template<typename _Tp> _Tp& at(int i0=0);
+    template<typename _Tp> const _Tp& at(int i0=0) const;
+    
+    template<typename _Tp> _Tp& at(int i0, int i1);
+    template<typename _Tp> const _Tp& at(int i0, int i1) const;
+    
+    template<typename _Tp> _Tp& at(int i0, int i1, int i2);
+    template<typename _Tp> const _Tp& at(int i0, int i1, int i2) const;
+    
+    template<typename _Tp> _Tp& at(const int* idx);
+    template<typename _Tp> const _Tp& at(const int* idx) const;
+    
+    template<typename _Tp, int n> _Tp& at(const Vec<int, n>& idx);
+    template<typename _Tp, int n> const _Tp& at(const Vec<int, n>& idx) const;
+    
+    //! special versions for 2D arrays (especially convenient for referencing image pixels)
     template<typename _Tp> _Tp& at(Point pt);
-    template<typename _Tp> const _Tp& at(int y, int x) const;
     template<typename _Tp> const _Tp& at(Point pt) const;
-    template<typename _Tp> _Tp& at(int i);
-    template<typename _Tp> 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());
-
-//! 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);
-
-//! 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_cast<uchar>abs(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 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 (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 (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_cast<uchar>abs(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 <cmpop> b)
-CV_EXPORTS void compare(const Mat& a, const Mat& b, Mat& c, int cmpop);
-//! compares elements of array with scalar (c = a <cmpop> 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);
-
-//! computes square root of each matrix element (b = a**0.5)
-CV_EXPORTS void sqrt(const Mat& a, Mat& b);
+                        const Scalar& upperb, CV_OUT Mat& dst);
+//! compares elements of two arrays (dst = src1 <cmpop> 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 <cmpop> 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 (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<typename _Tp, int m, int n, int nm> 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<typename _Tp> 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<Point>& pts );
+                              int arcStart, int arcEnd, int delta, CV_OUT vector<Point>& 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<int n> explicit Mat_(const Vec<_Tp, n>& vec, bool copyData=true);
     template<int m, int n> 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<int n> _Tp& operator ()(const Vec<int, n>& idx);
+    //! returns read-only reference to the specified element
+    template<int n> const _Tp& operator ()(const Vec<int, n>& 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_<Vec4d> 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<typename _Tp>
-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:
- <ul>
- <li> much less operations are implemented for cv::MatND
- <li> currently, algebraic expressions with cv::MatND's are not supported
- <li> 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.
- </ul>
- 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_<Vec3b> it = image.begin<Vec3b>(),
-                              it_end = image.end<Vec3b>();    
-     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<float>(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<typename _Tp> _Tp& at(int i0);
-    //! returns read-only reference to the element of 1D matrix
-    template<typename _Tp> const _Tp& at(int i0) const;
-    //! returns reference to the element of 2D matrix
-    template<typename _Tp> _Tp& at(int i0, int i1);
-    //! returns read-only reference to the element of 2D matrix
-    template<typename _Tp> const _Tp& at(int i0, int i1) const;
-    //! returns reference to the element of 3D matrix
-    template<typename _Tp> _Tp& at(int i0, int i1, int i2);
-    //! returns read-only reference to the element of 3D matrix
-    template<typename _Tp> const _Tp& at(int i0, int i1, int i2) const;
-    //! returns reference to the element of nD matrix
-    template<typename _Tp> _Tp& at(const int* idx);
-    //! returns read-only reference to the element of nD matrix
-    template<typename _Tp> 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);
-    
+    NAryMatIterator operator ++(int);
+
     //! the iterated arrays
-    vector<MatND> arrays;
+    const Mat** arrays;
     //! the current planes
-    vector<Mat> 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 <cmpop> b)
-CV_EXPORTS void compare(const MatND& a, const MatND& b, MatND& c, int cmpop);
-//! compares elements of two arrays (c = a <cmpop> 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_<Vec3b> it = image.begin<Vec3b>(),
-                              it_end = image.end<Vec3b>();
-     MatND_<float>& hist_ = (MatND_<float>&)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<typename _Tp> 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<typename T2> operator MatND_<T2>() 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<typename _Tp> 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<typename _Tp> class SparseMatConstIterator_;
  }
  \endcode
  
- <li>Sparse matrix iterators. Like cv::Mat iterators and unlike cv::MatND iterators, the sparse matrix iterators are STL-style,
+ <li>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;
index 40cf91f81e4f954293f24f5318eea4c2a64ee359..c0342150bcdfe0b5b7588e1ba83c90f4ef41d63f 100644 (file)
@@ -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);
-}
-
-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)
-{
-    size_t minstep = cols*elemSize();
-    if( step == AUTO_STEP )
+    if( m.dims <= 2 )
     {
-        step = minstep;
-        flags |= CONTINUOUS_FLAG;
+        step[0] = m.step[0]; step[1] = m.step[1];
     }
     else
     {
-        if( rows == 1 ) step = minstep;
-        CV_DbgAssert( step >= minstep );
-        flags |= step == minstep ? CONTINUOUS_FLAG : 0;
+        dims = 0;
+        copySize(m);
     }
-    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(int _rows, int _cols, int _type, void* _data, size_t _step)
+    : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_rows), cols(_cols),
+    data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend((uchar*)_data),
+    allocator(0), size(&rows)
 {
     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(const Mat& m, const Range& rowRange, const Range& colRange)
+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)
 {
-    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
+    size_t minstep = cols*elemSize();
+    if( _step == AUTO_STEP )
     {
-        CV_Assert( 0 <= rowRange.start && rowRange.start <= rowRange.end && rowRange.end <= m.rows );
-        rows = rowRange.size();
-        data += step*rowRange.start;
+        _step = minstep;
+        flags |= CONTINUOUS_FLAG;
     }
-
-    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 ) _step = minstep;
+        CV_DbgAssert( _step >= minstep );
+        flags |= _step == minstep ? CONTINUOUS_FLAG : 0;
     }
-
-    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<typename _Tp> 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<typename _Tp> inline Mat::Mat(const vector<_Tp>& vec, bool copyData)
     
 template<typename _Tp, int n> 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<typename _Tp, int m, int n> 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<typename _Tp> inline Mat::Mat(const Point_<_Tp>& pt)
+template<typename _Tp> 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<typename _Tp> inline Mat::Mat(const Point3_<_Tp>& pt)
+template<typename _Tp> 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<typename _Tp> 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<typename _Tp> 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<typename _Tp> 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<typename _Tp> 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<typename _Tp> inline _Tp& Mat::at(int y, int x)
+    
+inline uchar* Mat::ptr(int i0, int i1)
 {
-    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];
+    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];
 }
 
-template<typename _Tp> inline const _Tp& Mat::at(int y, int x) const
+inline const uchar* Mat::ptr(int i0, int i1) 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];
+    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];
 }
 
-template<typename _Tp> inline _Tp& Mat::at(int i)
+inline uchar* Mat::ptr(int i0, int i1, int i2)
 {
-    CV_DbgAssert( CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1() );
-    
-    if( cols == 1 )
+    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<typename _Tp> 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<typename _Tp> 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<typename _Tp> 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<typename _Tp> 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<typename _Tp> 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<typename _Tp> inline _Tp& Mat::at(int i0)
+{ return *(_Tp*)ptr(i0); }
+template<typename _Tp> inline const _Tp& Mat::at(int i0) const
+{ return *(const _Tp*)ptr(i0); }
+template<typename _Tp> inline _Tp& Mat::at(int i0, int i1, int i2)
+{ return *(_Tp*)ptr(i0, i1, i2); }
+template<typename _Tp> inline const _Tp& Mat::at(int i0, int i1, int i2) const
+{ return *(const _Tp*)ptr(i0, i1, i2); }
+template<typename _Tp> inline _Tp& Mat::at(const int* idx)
+{ return *(_Tp*)ptr(idx); }
+template<typename _Tp> inline const _Tp& Mat::at(const int* idx) const
+{ return *(const _Tp*)ptr(idx); }
+    
     
 template<typename _Tp> inline MatConstIterator_<_Tp> Mat::begin() const
 {
@@ -577,7 +561,7 @@ template<typename _Tp> 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<typename _Tp> 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<typename _Tp> 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<typename _Tp, int n> 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<typename _Tp, int n> inline Mat::operator Vec<_Tp, n>() const
     
 template<typename _Tp, int m, int n> 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<typename _Tp, int m, int n> 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<typename _Tp> inline Mat_<_Tp>::Mat_() :
-    Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; }
+template<typename _Tp> inline Mat_<_Tp>::Mat_()
+    Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; }
     
-template<typename _Tp> inline Mat_<_Tp>::Mat_(int _rows, int _cols) :
-    Mat(_rows, _cols, DataType<_Tp>::type) {}
+template<typename _Tp> inline Mat_<_Tp>::Mat_(int _rows, int _cols)
+    Mat(_rows, _cols, DataType<_Tp>::type) {}
 
-template<typename _Tp> inline Mat_<_Tp>::Mat_(int _rows, int _cols, const _Tp& value) :
-    Mat(_rows, _cols, DataType<_Tp>::type) { *this = value; }
+template<typename _Tp> inline Mat_<_Tp>::Mat_(int _rows, int _cols, const _Tp& value)
+    Mat(_rows, _cols, DataType<_Tp>::type) { *this = value; }
 
-template<typename _Tp> inline Mat_<_Tp>::Mat_(Size _size) :
-    Mat(_size.height, _size.width, DataType<_Tp>::type) {}
+template<typename _Tp> inline Mat_<_Tp>::Mat_(Size _sz)
+    : Mat(_sz.height, _sz.width, DataType<_Tp>::type) {}
+    
+template<typename _Tp> inline Mat_<_Tp>::Mat_(Size _sz, const _Tp& value)
+    : Mat(_sz.height, _sz.width, DataType<_Tp>::type) { *this = value; }
+    
+template<typename _Tp> inline Mat_<_Tp>::Mat_(int _dims, const int* _sz)
+    : Mat(_dims, _sz, DataType<_Tp>::type) {}
     
-template<typename _Tp> inline Mat_<_Tp>::Mat_(Size _size, const _Tp& value) :
-    Mat(_size.height, _size.width, DataType<_Tp>::type) { *this = value; }
+template<typename _Tp> inline Mat_<_Tp>::Mat_(int _dims, const int* _sz, const _Tp& _s)
+    : Mat(_dims, _sz, DataType<_Tp>::type, Scalar(_s)) {}
     
-template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat& m) : Mat()
-{ flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; *this = m; }
+template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat_<_Tp>& m, const Range* ranges)
+    : Mat(m, ranges) {}
+    
+template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat& m)
+    : Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; *this = m; }
 
-template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat_& m) : Mat(m) {}
+template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat_& m)
+    : Mat(m) {}
 
-template<typename _Tp> inline Mat_<_Tp>::Mat_(int _rows, int _cols, _Tp* _data, size_t _step)
-    : Mat(_rows, _cols, DataType<_Tp>::type, _data, _step) {}
+template<typename _Tp> inline Mat_<_Tp>::Mat_(int _rows, int _cols, _Tp* _data, size_t steps)
+    : Mat(_rows, _cols, DataType<_Tp>::type, _data, steps) {}
 
 template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat_& m, const Range& rowRange, const Range& colRange)
     : Mat(m, rowRange, colRange) {}
@@ -711,42 +730,23 @@ template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat_& m, const Rect& roi)
 
 template<typename _Tp> template<int n> inline
     Mat_<_Tp>::Mat_(const Vec<_Tp, n>& vec, bool copyData)
-    : Mat(vec, copyData)
-{
-}
+    : Mat(vec, copyData) {}
 
 template<typename _Tp> template<int m, int n> inline
     Mat_<_Tp>::Mat_(const Matx<_Tp,m,n>& M, bool copyData)
-    : Mat(M, copyData)
-{
-}    
+    : Mat(M, copyData) {}    
     
-template<typename _Tp> 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<typename _Tp> inline Mat_<_Tp>::Mat_(const Point_<_Tp>& pt, bool copyData)
+    : Mat(pt, copyData) {}
 
-template<typename _Tp> 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<typename _Tp> inline Mat_<_Tp>::Mat_(const Point3_<_Tp>& pt, bool copyData)
+    : Mat(pt, copyData) {}
 
 template<typename _Tp> inline Mat_<_Tp>::Mat_(const MatCommaInitializer_<_Tp>& commaInitializer)
-: Mat(commaInitializer)
-{
-}
-    
+    : Mat(commaInitializer) {}
     
 template<typename _Tp> inline Mat_<_Tp>::Mat_(const vector<_Tp>& vec, bool copyData)
-    : Mat(vec, copyData)
-{}
+    : Mat(vec, copyData) {}
 
 template<typename _Tp> inline Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat& m)
 {
@@ -757,7 +757,7 @@ template<typename _Tp> 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<typename _Tp> inline void Mat_<_Tp>::create(int _rows, int _cols)
     Mat::create(_rows, _cols, DataType<_Tp>::type);
 }
 
-template<typename _Tp> inline void Mat_<_Tp>::create(Size _size)
+template<typename _Tp> inline void Mat_<_Tp>::create(Size _sz)
 {
-    Mat::create(_size, DataType<_Tp>::type);
+    Mat::create(_sz, DataType<_Tp>::type);
 }
 
+template<typename _Tp> inline void Mat_<_Tp>::create(int _dims, const int* _sz)
+{
+    Mat::create(_dims, _sz, DataType<_Tp>::type);
+}    
+    
+    
 template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::cross(const Mat_& m) const
 { return Mat_<_Tp>(Mat::cross(m)); }
 
@@ -829,8 +835,8 @@ template<typename _Tp> inline int Mat_<_Tp>::channels() const
     CV_DbgAssert( Mat::channels() == DataType<_Tp>::channels );
     return DataType<_Tp>::channels;
 }
-template<typename _Tp> inline size_t Mat_<_Tp>::stepT() const { return step/elemSize(); }
-template<typename _Tp> inline size_t Mat_<_Tp>::step1() const { return step/elemSize1(); }
+template<typename _Tp> inline size_t Mat_<_Tp>::stepT(int i) const { return step.p[i]/elemSize(); }
+template<typename _Tp> inline size_t Mat_<_Tp>::step1(int i) const { return step.p[i]/elemSize1(); }
 
 template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::reshape(int _rows) const
 { return Mat_<_Tp>(Mat::reshape(0,_rows)); }
@@ -844,53 +850,81 @@ template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::operator()( const Range& rowR
 template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::operator()( const Rect& roi ) const
 { return Mat_<_Tp>(*this, roi); }
 
+template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::operator()( const Range* ranges ) const
+{ return Mat_<_Tp>(*this, ranges); }    
+    
 template<typename _Tp> inline _Tp* Mat_<_Tp>::operator [](int y)
 { return (_Tp*)ptr(y); }
 template<typename _Tp> inline const _Tp* Mat_<_Tp>::operator [](int y) const
 { return (const _Tp*)ptr(y); }
 
-template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(int row, int col)
+template<typename _Tp> 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<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(int i0, int i1) const
+{
+    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<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(Point pt)
+{
+    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<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(int row, int col) const
+template<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(Point pt) const
 {
-    CV_DbgAssert( (unsigned)row < (unsigned)rows &&
-                 (unsigned)col < (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*row))[col];
+    return ((const _Tp*)(data + step.p[0]*pt.y))[pt.x];
 }
 
-template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(int i)
+template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(const int* idx)
 {
-    return at<_Tp>(i);
+    return Mat::at<_Tp>(idx);
 }
-    
-template<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(int i) const
+
+template<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(const int* idx) const
 {
-    return at<_Tp>(i);
+    return Mat::at<_Tp>(idx);
 }
-    
-template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(Point pt)
+
+template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(int i0)
 {
-    CV_DbgAssert( (unsigned)pt.y < (unsigned)rows &&
-                 (unsigned)pt.x < (unsigned)cols &&
-                 type() == DataType<_Tp>::type );
-    return ((_Tp*)(data + step*pt.y))[pt.x];
+    return this->at<_Tp>(i0);
 }
 
-template<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(Point pt) const
+template<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(int i0) const
 {
-    CV_DbgAssert( (unsigned)pt.y < (unsigned)rows &&
-                  (unsigned)pt.x < (unsigned)cols &&
-                 type() == DataType<_Tp>::type );
-    return ((const _Tp*)(data + step*pt.y))[pt.x];
+    return this->at<_Tp>(i0);
+}    
+
+template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2)
+{
+    return this->at<_Tp>(i0, i1, i2);
 }
 
+template<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2) const
+{
+    return this->at<_Tp>(i0, i1, i2);
+}    
+    
+    
 template<typename _Tp> inline Mat_<_Tp>::operator vector<_Tp>() const
 {
     return this->Mat::operator vector<_Tp>();
@@ -905,7 +939,6 @@ template<typename _Tp> template<int m, int n> inline Mat_<_Tp>::operator Matx<_T
 {
     return this->Mat::operator Matx<_Tp, m, n>();
 }    
-
     
 template<typename T1, typename T2, typename Op> inline void
 process( const Mat_<T1>& m1, Mat_<T2>& m2, Op op )
@@ -1405,9 +1438,6 @@ operator ^= (const Mat_<_Tp>& a, const Scalar& s)
 
 static inline void merge(const vector<Mat>& mv, Mat& dst)
 { merge(&mv[0], mv.size(), dst); }
-    
-template<typename _Tp> 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<Mat>& mv)
 {
@@ -1459,284 +1489,316 @@ template<typename _Tp> inline MatExpr Mat_<_Tp>::eye(Size sz)
     
 //////////// Iterators & Comma initializers //////////////////
 
-template<typename _Tp> inline MatConstIterator_<_Tp>::MatConstIterator_()
-    : m(0), ptr(0), sliceEnd(0) {}
+inline MatConstIterator::MatConstIterator()
+    : m(0), elemSize(0), ptr(0), sliceStart(0), sliceEnd(0) {}
 
-template<typename _Tp> 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);
 }
 
-template<typename _Tp> inline MatConstIterator_<_Tp>::
-    MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col) : m(_m)
+inline MatConstIterator::MatConstIterator(const Mat* _m, int _row, int _col)
+    : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0)
 {
-    if( !_m )
-        ptr = sliceEnd = 0;
-    else
+    CV_Assert(m && m->dims <= 2);
+    if( m->isContinuous() )
     {
-        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;
+        sliceStart = m->data;
+        sliceEnd = sliceStart + m->total()*elemSize;
     }
+    int idx[]={_row, _col};
+    seek(idx);
 }
 
-template<typename _Tp> inline MatConstIterator_<_Tp>::
-    MatConstIterator_(const Mat_<_Tp>* _m, Point _pt) : m(_m)
+inline MatConstIterator::MatConstIterator(const Mat* _m, Point _pt)
+    : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0)
 {
-    if( !_m )
-        ptr = sliceEnd = 0;
-    else
+    CV_Assert(m && m->dims <= 2);
+    if( m->isContinuous() )
     {
-        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;
+        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)
+{}
 
-template<typename _Tp> inline MatConstIterator_<_Tp>::
-    MatConstIterator_(const MatConstIterator_& it)
-    : m(it.m), ptr(it.ptr), sliceEnd(it.sliceEnd) {}
-
-template<typename _Tp> inline MatConstIterator_<_Tp>&
-    MatConstIterator_<_Tp>::operator = (const MatConstIterator_& it )
+inline MatConstIterator& MatConstIterator::operator = (const MatConstIterator& it )
 {
-    m = it.m; ptr = it.ptr; sliceEnd = it.sliceEnd;
+    m = it.m; elemSize = it.elemSize; ptr = it.ptr;
+    sliceStart = it.sliceStart; sliceEnd = it.sliceEnd;
     return *this;
 }
 
-template<typename _Tp> inline _Tp MatConstIterator_<_Tp>::operator *() const { return *ptr; }
-
-template<typename _Tp> inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator += (int ofs)
+inline uchar* MatConstIterator::operator *() const { return ptr; }
+    
+inline MatConstIterator& MatConstIterator::operator += (ptrdiff_t ofs)
 {
     if( !m || ofs == 0 )
         return *this;
-    ptr += ofs;
-    if( m->isContinuous() )
+    ptrdiff_t ofsb = ofs*elemSize;
+    ptr += ofsb;
+    if( ptr < sliceStart || sliceEnd <= ptr )
     {
-        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;
+        ptr -= ofsb;
+        seek(ofs, true);
     }
     return *this;
 }
 
-template<typename _Tp> inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator -= (int ofs)
+inline MatConstIterator& MatConstIterator::operator -= (ptrdiff_t ofs)
 { return (*this += -ofs); }
 
-template<typename _Tp> inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator --()
-{ return (*this += -1); }
+inline MatConstIterator& MatConstIterator::operator --()
+{
+    if( m && (ptr -= elemSize) < sliceStart )
+    {
+        ptr += elemSize;
+        seek(-1, true); 
+    }
+    return *this;
+}
 
-template<typename _Tp> inline MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator --(int)
+inline MatConstIterator MatConstIterator::operator --(int)
 {
-    MatConstIterator_ b = *this;
+    MatConstIterator b = *this;
     *this += -1;
     return b;
 }
 
-template<typename _Tp> inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator ++()
+inline MatConstIterator& MatConstIterator::operator ++()
 {
-    if( m && ++ptr >= sliceEnd )
+    if( m && (ptr += elemSize) >= sliceEnd )
     {
-        --ptr;
-        *this += 1;
+        ptr -= elemSize;
+        seek(1, true); 
     }
     return *this;
 }
 
-template<typename _Tp> inline MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator ++(int)
+inline MatConstIterator MatConstIterator::operator ++(int)
 {
-    MatConstIterator_ b = *this;
-    if( m && ++ptr >= sliceEnd )
-    {
-        --ptr;
-        *this += 1;
-    }
+    MatConstIterator b = *this;
+    *this += 1;
     return b;
 }
 
-template<typename _Tp> 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<typename _Tp> inline MatIterator_<_Tp>::MatIterator_() : MatConstIterator_<_Tp>() {}
+template<typename _Tp> inline MatConstIterator_<_Tp>::MatConstIterator_() {}
 
-template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m)
-    : MatConstIterator_<_Tp>(_m) {}
+template<typename _Tp> inline MatConstIterator_<_Tp>::MatConstIterator_(const Mat_<_Tp>* _m)
+    : MatConstIterator(_m) {}
 
-template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m, int _row, int _col)
-    : MatConstIterator_<_Tp>(_m, _row, _col) {}
+template<typename _Tp> inline MatConstIterator_<_Tp>::
+    MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col)
+    : MatConstIterator(_m, _row, _col) {}
 
-template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_(const Mat_<_Tp>* _m, Point _pt)
-    : MatConstIterator_<_Tp>(_m, _pt) {}
+template<typename _Tp> inline MatConstIterator_<_Tp>::
+    MatConstIterator_(const Mat_<_Tp>* _m, Point _pt)
+    : MatConstIterator(_m, _pt) {}
 
-template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_(const MatIterator_& it)
-    : MatConstIterator_<_Tp>(it) {}
+template<typename _Tp> inline MatConstIterator_<_Tp>::
+    MatConstIterator_(const MatConstIterator_& it)
+    : MatConstIterator(it) {}
 
-template<typename _Tp> inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator = (const MatIterator_<_Tp>& it )
+template<typename _Tp> inline MatConstIterator_<_Tp>&
+    MatConstIterator_<_Tp>::operator = (const MatConstIterator_& it )
 {
-    this->m = it.m; this->ptr = it.ptr; this->sliceEnd = it.sliceEnd;
+    MatConstIterator::operator = (it);
     return *this;
 }
 
-template<typename _Tp> inline _Tp& MatIterator_<_Tp>::operator *() const { return *(this->ptr); }
+template<typename _Tp> inline _Tp MatConstIterator_<_Tp>::operator *() const { return *ptr; }
 
-template<typename _Tp> inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator += (int ofs)
+template<typename _Tp> inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator += (ptrdiff_t ofs)
 {
-    MatConstIterator_<_Tp>::operator += (ofs);
+    MatConstIterator::operator += (ofs);
     return *this;
 }
 
-template<typename _Tp> inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator -= (int ofs)
-{
-    MatConstIterator_<_Tp>::operator += (-ofs);
+template<typename _Tp> inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator -= (ptrdiff_t ofs)
+{ return (*this += -ofs); }
+
+template<typename _Tp> inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator --()
+{
+    MatConstIterator::operator --();
+    return *this;
+}
+
+template<typename _Tp> inline MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator --(int)
+{
+    MatConstIterator_ b = *this;
+    MatConstIterator::operator --();
+    return b;
+}
+
+template<typename _Tp> inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator ++()
+{
+    MatConstIterator::operator ++();
+    return *this;
+}
+
+template<typename _Tp> inline MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator ++(int)
+{
+    MatConstIterator_ b = *this;
+    MatConstIterator::operator ++();
+    return b;
+}
+
+template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_() : MatConstIterator_<_Tp>() {}
+
+template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m)
+    : MatConstIterator_<_Tp>(_m) {}
+
+template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m, int _row, int _col)
+    : MatConstIterator_<_Tp>(_m, _row, _col) {}
+
+template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_(const Mat_<_Tp>* _m, Point _pt)
+    : MatConstIterator_<_Tp>(_m, _pt) {}
+    
+template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_(const Mat_<_Tp>* _m, const int* _idx)
+    : MatConstIterator_<_Tp>(_m, _idx) {}
+    
+template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_(const MatIterator_& it)
+    : MatConstIterator_<_Tp>(it) {}
+
+template<typename _Tp> inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator = (const MatIterator_<_Tp>& it )
+{
+    MatConstIterator::operator = (it);
+    return *this;
+}
+
+template<typename _Tp> inline _Tp& MatIterator_<_Tp>::operator *() const { return *(_Tp*)(this->ptr); }
+
+template<typename _Tp> inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator += (ptrdiff_t ofs)
+{
+    MatConstIterator::operator += (ofs);
+    return *this;
+}
+
+template<typename _Tp> inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator -= (ptrdiff_t ofs)
+{
+    MatConstIterator::operator += (-ofs);
     return *this;
 }
 
 template<typename _Tp> inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator --()
 {
-    MatConstIterator_<_Tp>::operator += (-1);
+    MatConstIterator::operator --();
     return *this;
 }
 
 template<typename _Tp> inline MatIterator_<_Tp> MatIterator_<_Tp>::operator --(int)
 {
     MatIterator_ b = *this;
-    MatConstIterator_<_Tp>::operator += (-1);
+    MatConstIterator::operator --();
     return b;
 }
 
 template<typename _Tp> inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator ++()
 {
-    if( this->m && ++this->ptr >= this->sliceEnd )
-    {
-        --this->ptr;
-        MatConstIterator_<_Tp>::operator += (1);
-    }
+    MatConstIterator::operator ++();
     return *this;
 }
 
 template<typename _Tp> 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<typename _Tp> static inline bool
+operator != (const MatConstIterator& a, const MatConstIterator& b)
+{ return !(a == b); }
+
 template<typename _Tp> static inline bool
 operator == (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b)
 { return a.m == b.m && a.ptr == b.ptr; }
 
 template<typename _Tp> 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<typename _Tp> static inline bool
-operator < (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b)
-{ return a.ptr < b.ptr; }
+operator == (const MatIterator_<_Tp>& a, const MatIterator_<_Tp>& b)
+{ return a.m == b.m && a.ptr == b.ptr; }
 
 template<typename _Tp> static inline bool
-operator > (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b)
-{ return a.ptr > b.ptr; }
+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<typename _Tp> 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; }
+    
+static inline bool
+operator <= (const MatConstIterator& a, const MatConstIterator& b)
 { return a.ptr <= b.ptr; }
 
-template<typename _Tp> 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<typename _Tp> 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);
 
-template<typename _Tp> static inline MatConstIterator_<_Tp>
-operator + (const MatConstIterator_<_Tp>& a, int ofs)
-{ MatConstIterator_<_Tp> b = a; return b += ofs; }
+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<typename _Tp> 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<typename _Tp> 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<typename _Tp> static inline MatConstIterator_<_Tp>
+operator - (const MatConstIterator_<_Tp>& a, ptrdiff_t ofs)
+{ return (MatConstIterator_<_Tp>&)((const MatConstIterator&)a - ofs); }
 
-template<typename _Tp> inline _Tp MatConstIterator_<_Tp>::operator [](int i) const
+inline uchar* MatConstIterator::operator [](ptrdiff_t i) const
 { return *(*this + i); }
+    
+template<typename _Tp> inline _Tp MatConstIterator_<_Tp>::operator [](ptrdiff_t i) const
+{ return *(_Tp*)MatConstIterator::operator [](i); }
 
 template<typename _Tp> 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<typename _Tp> 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<typename _Tp> static inline MatIterator_<_Tp>
-operator - (const MatIterator_<_Tp>& a, int ofs)
-{ MatIterator_<_Tp> b = a; return b += -ofs; }
-
-template<typename _Tp> inline _Tp& MatIterator_<_Tp>::operator [](int i) const
+operator - (const MatIterator_<_Tp>& a, ptrdiff_t ofs)
+{ return (MatIterator_<_Tp>&)((const MatConstIterator&)a - ofs); }
+    
+template<typename _Tp> inline _Tp& MatIterator_<_Tp>::operator [](ptrdiff_t i) const
 { return *(*this + i); }
 
 template<typename _Tp> inline MatConstIterator_<_Tp> Mat_<_Tp>::begin() const
@@ -1756,21 +1818,21 @@ template<typename _Tp> inline MatCommaInitializer_<_Tp>::MatCommaInitializer_(Ma
 template<typename _Tp> template<typename T2> 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<typename _Tp> 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<typename _Tp> 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<typename _Tp> 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<typename _Tp> inline _Tp& MatND::at(int i0)
-{ return *(_Tp*)ptr(i0); }
-template<typename _Tp> inline const _Tp& MatND::at(int i0) const
-{ return *(const _Tp*)ptr(i0); }
-template<typename _Tp> inline _Tp& MatND::at(int i0, int i1)
-{ return *(_Tp*)ptr(i0, i1); }
-template<typename _Tp> inline const _Tp& MatND::at(int i0, int i1) const
-{ return *(const _Tp*)ptr(i0, i1); }
-template<typename _Tp> inline _Tp& MatND::at(int i0, int i1, int i2)
-{ return *(_Tp*)ptr(i0, i1, i2); }
-template<typename _Tp> inline const _Tp& MatND::at(int i0, int i1, int i2) const
-{ return *(const _Tp*)ptr(i0, i1, i2); }
-template<typename _Tp> inline _Tp& MatND::at(const int* idx)
-{ return *(_Tp*)ptr(idx); }
-template<typename _Tp> 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<typename _Tp> inline MatND_<_Tp>::MatND_()
-{
-    flags = MAGIC_VAL | DataType<_Tp>::type;
-}
-
-template<typename _Tp> inline MatND_<_Tp>::MatND_(int _dims, const int* _sizes)
-: MatND(_dims, _sizes, DataType<_Tp>::type)
-{
-}
-
-template<typename _Tp> inline MatND_<_Tp>::MatND_(int _dims, const int* _sizes, const _Tp& _s)
-: MatND(_dims, _sizes, DataType<_Tp>::type, Scalar(_s))
-{
-}
-
-template<typename _Tp> 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<typename _Tp> inline MatND_<_Tp>::MatND_(const MatND_<_Tp>& m) : MatND(m)
-{
-}
-
-template<typename _Tp> inline MatND_<_Tp>::MatND_(const MatND_<_Tp>& m, const Range* ranges)
-: MatND(m, ranges)
-{
-}
-
-template<typename _Tp> inline MatND_<_Tp>::MatND_(const CvMatND* m, bool copyData)
-{
-    *this = MatND(m, copyData || CV_MAT_TYPE(m->type) != DataType<_Tp>::type);
-}
-
-template<typename _Tp> 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<typename _Tp> inline MatND_<_Tp>& MatND_<_Tp>::operator = (const MatND_<_Tp>& m)
-{
-    return ((MatND&)*this = m);
-}
-
-template<typename _Tp> inline MatND_<_Tp>& MatND_<_Tp>::operator = (const _Tp& s)
-{
-    return (MatND&)*this = Scalar(s);
-}
-
-template<typename _Tp> inline void MatND_<_Tp>::create(int _dims, const int* _sizes)
-{
-    MatND::create(_dims, _sizes, DataType<_Tp>::type);
-}
-
-template<typename _Tp> template<typename _Tp2> inline MatND_<_Tp>::operator MatND_<_Tp2>() const
-{
-    return MatND_<_Tp2>((const MatND&)*this);
-}
-
-template<typename _Tp> inline MatND_<_Tp> MatND_<_Tp>::clone() const
-{
-    MatND_<_Tp> temp;
-    this->copyTo(temp);
-    return temp;
-}
-
-template<typename _Tp> inline MatND_<_Tp>
-MatND_<_Tp>::operator()(const Range* ranges) const
-{ return MatND_<_Tp>(*this, ranges); }
-
-template<typename _Tp> inline size_t MatND_<_Tp>::elemSize() const
-{ return CV_ELEM_SIZE(DataType<_Tp>::type); }
-
-template<typename _Tp> inline size_t MatND_<_Tp>::elemSize1() const
-{ return CV_ELEM_SIZE1(DataType<_Tp>::type); }
-
-template<typename _Tp> inline int MatND_<_Tp>::type() const
-{ return DataType<_Tp>::type; }
-
-template<typename _Tp> inline int MatND_<_Tp>::depth() const
-{ return DataType<_Tp>::depth; }
-
-template<typename _Tp> inline int MatND_<_Tp>::channels() const
-{ return DataType<_Tp>::channels; }
-
-template<typename _Tp> inline size_t MatND_<_Tp>::stepT(int i) const
-{
-    CV_DbgAssert( (unsigned)i < (unsigned)dims );
-    return step[i]/elemSize();
-}
-
-template<typename _Tp> inline size_t MatND_<_Tp>::step1(int i) const
-{
-    CV_DbgAssert( (unsigned)i < (unsigned)dims );
-    return step[i]/elemSize1();
-}
-
-template<typename _Tp> 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<typename _Tp> 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<typename _Tp> inline _Tp& MatND_<_Tp>::operator ()(int i0)
-{
-    CV_DbgAssert( dims == 1 &&
-                 (unsigned)i0 < (unsigned)size[0] );
-    
-    return *(_Tp*)(data + i0*step[0]);
-}
-
-template<typename _Tp> 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<typename _Tp> 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<typename _Tp> 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<typename _Tp> 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<typename _Tp> 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<MatND>& mv, MatND& dst)
-{
-    merge(&mv[0], mv.size(), dst);
-}
-    
-static inline void split(const MatND& m, vector<MatND>& mv)
-{
-    mv.resize(m.channels());
-    if(m.channels() > 0)
-        split(m, &mv[0]);
-}
-
-static inline void mixChannels(const vector<MatND>& src, vector<MatND>& 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<typename _Tp> inline SparseMat_<_Tp>::SparseMat_(const Mat& m)
     *this = sm;
 }
 
-template<typename _Tp> inline SparseMat_<_Tp>::SparseMat_(const MatND& m)
-{
-    SparseMat sm(m);
-    *this = sm;
-}
-
 template<typename _Tp> inline SparseMat_<_Tp>::SparseMat_(const CvSparseMat* m)
 {
     SparseMat sm(m);
@@ -2621,10 +2220,6 @@ template<typename _Tp> inline SparseMat_<_Tp>&
 SparseMat_<_Tp>::operator = (const Mat& m)
 { return (*this = SparseMat(m)); }
 
-template<typename _Tp> inline SparseMat_<_Tp>&
-SparseMat_<_Tp>::operator = (const MatND& m)
-{ return (*this = SparseMat(m)); }
-
 template<typename _Tp> inline SparseMat_<_Tp>
 SparseMat_<_Tp>::clone() const
 {
index ef530fef070139b550ab88e4742a8faf61054485..8e0b5aa07b717c2e0f2083e454e54af4613b11ca 100644 (file)
@@ -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
index 121f39c0be9edf035b79a95027166c2a4b0ac73f..ed3b3bc8c5be4ac255c2497c944c69d6824e61f4 100644 (file)
@@ -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
index a40bc3bc73f1db9f02c5acd8dd51bce40c7bc7fd..03054860e60f71154935c54ad3b4120bc50b4609 100644 (file)
@@ -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_<OpSub<double>,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_<OpAbsDiff<double>,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_<OpAbsDiffS<double> >, 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_<InRangeC4<double, double> >, 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_<CmpEQ<double>,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_<MinOp<float>,VMin32f>, binaryOpC1_<MinOp<double>,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_<MaxOp<float>,VMax32f>, binaryOpC1_<MaxOp<double>,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 );
 }
index f8e0fd961d81589b2440de4527e53601ec9e82eb..05fcc1c03fa90601471a32ad7a4cdcc4fcb92f46 100644 (file)
@@ -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<int> pairs(cn*2);
+        AutoBuffer<int> 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_<uchar>, mergeC4_<ushort>, mergeC4_<int>, 0, mergeC4_<int64>
     };
 
-    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<int> pairs(total*2);
+        AutoBuffer<int> 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<const Mat*> v(m + n);
+        AutoBuffer<Mat> 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);
+        }
+    }    
 }
 
 /****************************************************************************************\
index d22048cc7eda6707329ffbbc4c0c257f651f05d2..91198667d6eaf3b41956f2e3ff153dcb388f35c7 100644 (file)
@@ -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_<Vec<int64,4> > // 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();
index fad404070618f912b426af86a778b7bc4301acbe..9c3d4d70adb2854dfbc0ba862d5ddb3f1f551f86 100644 (file)
@@ -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;
index 11e76af1160777772be4d83fedb58438e01b11d5..d94f715f897e3b64e94be760aaacf897a511af98 100644 (file)
@@ -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<uchar> 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 );
index 3a7acf4e5a7d2ae2c8e0d905b2146757381cb684..781a0604b496e46809b8faccd8b748b77806dcf8 100644 (file)
 
 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<Range> 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;
     }
+    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
     {
-        CvMat hdr, *cvmat = cvGetMat( arr, &hdr, 0, allowND ? 1 : 0 );
-        if( cvmat )
-            return Mat(cvmat, copyData);
+        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 );
     }
-    return Mat();
+    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_<int>, sort_<float>, sort_<double>, 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_<int>, sortIdx_<float>, sortIdx_<double>, 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,353 +1631,133 @@ 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)
+Mat Mat::reshape(int, int, const int*) const
 {
-    int i, j, d = m.dims;
+    CV_Error(CV_StsNotImplemented, "");
+    // TBD
+    return Mat();
+}
 
-    CV_Assert(ranges);
+Mat::operator CvMatND() const
+{
+    CvMatND mat;
+    cvInitMatNDHeader( &mat, dims, size, type(), data );
+    int i, d = dims;
     for( i = 0; i < d; i++ )
+        mat.dim[i].step = (int)step[i];
+    mat.type |= flags & CONTINUOUS_FLAG;
+    return mat;
+}
+
+NAryMatIterator::NAryMatIterator()
+    : arrays(0), planes(0), narrays(0), nplanes(0), iterdepth(0), idx(0)
+{
+}
+    
+NAryMatIterator::NAryMatIterator(const Mat** _arrays, Mat* _planes, int _narrays)
+    : arrays(0), planes(0), narrays(0), nplanes(0), iterdepth(0), idx(0)
+{
+    init(_arrays, _planes, _narrays);
+}
+    
+void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, int _narrays)
+{
+    CV_Assert( _arrays && _planes );
+    int i, j, d1=0, i0 = -1, d = -1, total = 0;
+    
+    arrays = _arrays;
+    planes = _planes;
+    narrays = _narrays;
+    nplanes = 0;
+    
+    if( narrays < 0 )
     {
-        Range r = ranges[i];
-        CV_Assert( r == Range::all() ||
-            (0 <= r.start && r.start < r.end && r.end <= m.size[i]) );
+        for( i = 0; _arrays[i] != 0; i++ )
+            ;
+        narrays = i;
+        CV_Assert(narrays <= 1000);
     }
-    *this = m;
-    for( i = 0; i < d; i++ )
+
+    iterdepth = 0;
+
+    for( i = 0; i < narrays; i++ )
     {
-        Range r = ranges[i];
-        if( r != Range::all() )
+        CV_Assert(arrays[i] != 0);
+        if( !arrays[i]->data )
+            continue;
+        const Mat& A = *arrays[i];
+        
+        if( i0 < 0 )
         {
-            size[i] = r.end - r.start;
-            data += r.start*step[i];
+            i0 = i;
+            d = A.dims;
+            
+            // find the first dimensionality which is different from 1;
+            // in any of the arrays the first "d1" step do not affect the continuity
+            for( d1 = 0; d1 < d; d1++ )
+                if( A.size[d1] > 1 )
+                    break;
+        }
+        else
+            CV_Assert( A.size == arrays[i0]->size );
+
+        if( !A.isContinuous() )
+        {
+            CV_Assert( A.step[d-1] == A.elemSize() );
+            for( j = d-1; j > d1; j-- )
+                if( A.step[j]*A.size[j] < A.step[j-1] )
+                    break;
+            iterdepth = std::max(iterdepth, j);
         }
     }
-    
-    for( i = 0; i < d; i++ )
+
+    if( i0 >= 0 )
     {
-        if( size[i] != 1 )
-            break;
+        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;
 
-    CV_Assert( step[d-1] == elemSize() );
-    for( j = d-1; j > i; j-- )
+    for( i = 0; i < narrays; i++ )
     {
-        if( step[j]*size[j] < step[j-1] )
-            break;
+        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;
     }
-    flags = (flags & ~CONTINUOUS_FLAG) | (j <= i ? CONTINUOUS_FLAG : 0);
+
+    idx = 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
-{
-    CV_Error(CV_StsNotImplemented, "");
-    // TBD
-    return MatND();
-}
-
-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
-{
-    CvMatND mat;
-    cvInitMatNDHeader( &mat, dims, size, type(), data );
-    int i, d = dims;
-    for( i = 0; i < d; i++ )
-        mat.dim[i].step = (int)step[i];
-    mat.type |= flags & CONTINUOUS_FLAG;
-    return mat;
-}
-
-NAryMatNDIterator::NAryMatNDIterator(const MatND** _arrays, size_t count)
-{
-    init(_arrays, count);
-}
-
-NAryMatNDIterator::NAryMatNDIterator(const MatND* _arrays, size_t count)
-{
-    AutoBuffer<const MatND*, 32> 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)
-{
-    const MatND* mm[] = {&m1, &m2, &m3, &m4, &m5};
-    init(mm, 5);
-}
-    
-NAryMatNDIterator::NAryMatNDIterator(const MatND& m1, const MatND& m2,
-                                     const MatND& m3, const MatND& m4,
-                                     const MatND& m5, const MatND& m6)
-{
-    const MatND* mm[] = {&m1, &m2, &m3, &m4, &m5, &m6};
-    init(mm, 6);
-}    
-    
-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;
-
-    iterdepth = 0;
-
-    for( i = 0; i < n; i++ )
-    {
-        if( !_arrays[i] || !_arrays[i]->data )
-        {
-            arrays[i] = MatND();
-            continue;
-        }
-        const MatND& A = arrays[i] = *_arrays[i];
-        
-        if( i0 < 0 )
-        {
-            i0 = i;
-            d = A.dims;
-            
-            // find the first dimensionality which is different from 1;
-            // in any of the arrays the first "d1" steps 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] );
-        }
-
-        if( !A.isContinuous() )
-        {
-            CV_Assert( A.step[d-1] == A.elemSize() );
-            for( j = d-1; j > d1; j-- )
-                if( A.step[j]*A.size[j] < A.step[j-1] )
-                    break;
-            iterdepth = std::max(iterdepth, j);
-        }
-    }
-
-    if( i0 < 0 )
-        CV_Error( CV_StsBadArg, "All the input arrays are empty" );
-
-    int 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;
-
-    planes.resize(n);
-    for( i = 0; i < n; i++ )
-    {
-        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();
-    }
-
-    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)
-{
-    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] ); 
-}
+///////////////////////////////////////////////////////////////////////////
+//                              MatConstIterator                         //
+///////////////////////////////////////////////////////////////////////////
 
-void subtract(const Scalar& s, const MatND& a, MatND& c, const MatND& mask)
+Point MatConstIterator::pos() const
 {
-    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);
+    if( !m )
+        return Point();
+    CV_DbgAssert(m->dims <= 2);
+    
+    ptrdiff_t ofs = ptr - m->data;
+    int y = (int)(ofs/m->step[0]);
+    return Point((int)((ofs - y*m->step[0])/elemSize), y);
 }
 
-Scalar mean(const MatND& m, const MatND& mask)
+void MatConstIterator::pos(int* _idx) const
 {
-    if( !mask.data )
-        return mean(m);
-    NAryMatNDIterator it(m, mask);
-    double total = 0;
-    Scalar s;
-    for( int i = 0; i < it.nplanes; i++, ++it )
+    CV_Assert(m != 0 && _idx);
+    ptrdiff_t ofs = ptr - m->data;
+    for( int i = 0; i < m->dims; i++ )
     {
-        int n = countNonZero(it.planes[1]);
-        s += mean(it.planes[0], it.planes[1])*(double)n;
-        total += n;
+        size_t s = m->step[i], v = ofs/s;
+        ofs -= v*s;
+        _idx[i] = (int)v;
     }
-    return s *= 1./std::max(total, 1.);
 }
 
-void meanStdDev(const MatND& m, Scalar& mean, Scalar& stddev, const MatND& mask)
+ptrdiff_t MatConstIterator::lpos() const
 {
-    NAryMatNDIterator it(m, mask);
-    double total = 0;
-    Scalar s, sq;
-    int k, cn = m.channels();
-
-    for( int i = 0; i < it.nplanes; i++, ++it )
+    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 )
     {
-        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;
+        ptrdiff_t y = ofs/m->step[0];
+        return y*m->cols + (ofs - y*m->step[0])/elemSize;
     }
-
-    mean = stddev = Scalar();
-    total = 1./std::max(total, 1.);
-    for( k = 0; k < cn; k++ )
+    ptrdiff_t result = 0;
+    for( i = 0; i < d; i++ )
     {
-        mean[k] = s[k]*total;
-        stddev[k] = std::sqrt(std::max(sq[k]*total - mean[k]*mean[k], 0.));
+        size_t s = m->step[i], v = ofs/s;
+        ofs -= v*s;
+        result = result*m->size[i] + v;
     }
+    return result;
 }
-
-double norm(const MatND& a, int normType, const MatND& mask)
+    
+void MatConstIterator::seek(ptrdiff_t ofs, bool relative)
 {
-    NAryMatNDIterator it(a, mask);
-    double total = 0;
-
-    for( int i = 0; i < it.nplanes; i++, ++it )
+    if( m->isContinuous() )
     {
-        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;
+        ptr = (relative ? ptr : sliceStart) + ofs*elemSize;
+        if( ptr < sliceStart )
+            ptr = sliceStart;
+        else if( ptr > sliceEnd )
+            ptr = sliceEnd;
+        return;
     }
-
-    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 )
+    
+    int d = m->dims;
+    if( d == 2 )
     {
-        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 )
+        ptrdiff_t ofs0, y;
+        if( relative )
         {
-            num = std::max(num, n);
-            denom = std::max(denom, d);
+            ofs0 = ptr - m->data;
+            y = ofs0/m->step[0];
+            ofs += y*m->cols + (ofs0 - y*m->step[0])/elemSize;
         }
-        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;
+        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;
     }
-    else
-        CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" );
     
-    if( !mask.data )
-        src.convertTo( dst, rtype, scale, shift );
-    else
-    {
-        MatND temp;
-        src.convertTo( temp, rtype, scale, shift );
-        temp.copyTo( dst, mask );
-    }
-}
-
-static void ofs2idx(const MatND& 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];
-    }
-}
+    if( relative )
+        ofs += lpos();
     
+    if( ofs < 0 )
+        ofs = 0;
     
-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 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 = 0; i < it.nplanes; i++, ++it )
+    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);
-}
-
-void merge(const MatND* mv, size_t n, MatND& dst)
-{
-    size_t k;
-    CV_Assert( n > 0 );
-    vector<MatND> v(n + 1);
-    int total_cn = 0;
-    for( k = 0; k < n; k++ )
-    {
-        total_cn += mv[k].channels();
-        v[k] = mv[k];
-    }
-    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] );
-}
-
-void split(const MatND& m, MatND* mv)
-{
-    size_t k, n = m.channels();
-    CV_Assert( n > 0 );
-    vector<MatND> 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] );
+    
+    sliceEnd = sliceStart + m->size[d-1]*elemSize;
+    if( ofs > 0 )
+        ptr = sliceEnd;
+    else
+        ptr = sliceStart + (ptr - m->data);
 }
-
-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<MatND> 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 )
+    
+void MatConstIterator::seek(const int* _idx, bool relative)
+{
+    int i, d = m->dims;
+    ptrdiff_t ofs = 0;
+    if( !_idx )
+        ;
+    else if( d == 2 )
+        ofs = _idx[0]*m->size[1] + _idx[1];
+    else
     {
-        Mat* pptr = &it.planes[0];
-        mixChannels( pptr, m, pptr + m, n, fromTo, npairs );
+        for( i = 0; i < d; i++ )
+            ofs = ofs*m->size[i] + _idx[i];
     }
+    seek(ofs, relative);
 }
 
-void bitwise_and(const MatND& a, const MatND& b, MatND& c, const MatND& mask)
+ptrdiff_t operator - (const MatConstIterator& b, const MatConstIterator& a)
 {
-    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<typename T1, typename T2> 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);
index f631c2d4804c983e39a9c911ef90973843f12aac..0e09624e80476e9fbc6a6b333eb83562786937f0 100644 (file)
@@ -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<CvMat> m = (CvMat*)cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node);
-    CV_Assert(CV_IS_MAT(m));
-    Mat(m).copyTo(mat);
-}
-    
-void read( const FileNode& node, MatND& mat, const MatND& default_mat )
-{
-    if( node.empty() )
+    void* obj = cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node);
+    if(CV_IS_MAT(obj))
     {
-        default_mat.copyTo(mat);
-        return;
+        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");
     }
-    Ptr<CvMatND> 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() )
index ff2774cf242a54655f8c6784db5ac620919d2a9b..3088097489502698a84a1718921520778f7f87dc 100644 (file)
@@ -482,7 +482,7 @@ void RNG::fill( Mat& mat, int disttype, const Scalar& param1, const Scalar& para
         Randn_<float,float>,
         Randn_<double,double>, 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
index 6e52226b83aa65b27c2ace117bad4d190a8f4669..e4ce8348dbdff2f1761d8039ade5dad09356fdfa 100644 (file)
@@ -160,14 +160,23 @@ Scalar sum( const Mat& m )
         sum_<Vec<double, 4>, Vec<double, 4> >, 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_<SqrC4<double, double> >, 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;
     }
-    else
+    
+    if( mask.data )
     {
-        MeanStdDevMaskFunc func = mtab[m.type()];
-        CV_Assert( mask.size() == m.size() && mask.type() == CV_8U && func != 0 );
-        func( m, mask, mean, stddev );
+        CV_Assert( mask.size() == m.size() ); 
+        mfunc( m, mask, mean, stddev );
     }
+    else
+        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_<uchar>, 0, minMaxIndx_<ushort>, minMaxIndx_<short>,
         minMaxIndx_<int>, minMaxIndx_<float>, minMaxIndx_<double>, 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 )