X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=modules%2Fcore%2Finclude%2Fopencv2%2Fcore%2Fmat.hpp;h=cc589a06758f4f20308d69152b14a04a7cad93ec;hb=ba5f343c382610ca3f12a3637d0a0f29579c965f;hp=8a3167a032e0beaee2b27de432883118cce324df;hpb=05e0b3b7e6bf24f1f245ad9a54f1ce71c8784ff7;p=profile%2Fivi%2Fopencv.git diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 8a3167a..cc589a0 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -7,11 +7,12 @@ // copy or use the software. // // -// License Agreement +// License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -40,1139 +41,2178 @@ // //M*/ -#ifndef __OPENCV_CORE_MATRIX_OPERATIONS_HPP__ -#define __OPENCV_CORE_MATRIX_OPERATIONS_HPP__ +#ifndef __OPENCV_CORE_MAT_HPP__ +#define __OPENCV_CORE_MAT_HPP__ -#ifndef SKIP_INCLUDES -#include -#include -#endif // SKIP_INCLUDES +#ifndef __cplusplus +# error mat.hpp header must be compiled as C++ +#endif + +#include "opencv2/core/matx.hpp" +#include "opencv2/core/types.hpp" -#ifdef __cplusplus +#include "opencv2/core/bufferpool.hpp" namespace cv { -//////////////////////////////// Mat //////////////////////////////// - -inline void Mat::initEmpty() -{ - flags = MAGIC_VAL; - dims = rows = cols = 0; - data = datastart = dataend = datalimit = 0; - refcount = 0; - allocator = 0; -} - -inline Mat::Mat() : size(&rows) -{ - initEmpty(); -} +enum { ACCESS_READ=1<<24, ACCESS_WRITE=1<<25, + ACCESS_RW=3<<24, ACCESS_MASK=ACCESS_RW, ACCESS_FAST=1<<26 }; -inline Mat::Mat(int _rows, int _cols, int _type) : size(&rows) -{ - initEmpty(); - create(_rows, _cols, _type); -} +class CV_EXPORTS _OutputArray; -inline Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s) : size(&rows) -{ - initEmpty(); - create(_rows, _cols, _type); - *this = _s; -} +//////////////////////// Input/Output Array Arguments ///////////////////////////////// -inline Mat::Mat(Size _sz, int _type) : size(&rows) +/*! + Proxy datatype for passing Mat's and vector<>'s as input parameters + */ +class CV_EXPORTS _InputArray { - initEmpty(); - create( _sz.height, _sz.width, _type ); -} +public: + enum { + KIND_SHIFT = 16, + FIXED_TYPE = 0x8000 << KIND_SHIFT, + FIXED_SIZE = 0x4000 << KIND_SHIFT, + KIND_MASK = 31 << KIND_SHIFT, + + NONE = 0 << KIND_SHIFT, + MAT = 1 << KIND_SHIFT, + MATX = 2 << KIND_SHIFT, + STD_VECTOR = 3 << KIND_SHIFT, + STD_VECTOR_VECTOR = 4 << KIND_SHIFT, + STD_VECTOR_MAT = 5 << KIND_SHIFT, + EXPR = 6 << KIND_SHIFT, + OPENGL_BUFFER = 7 << KIND_SHIFT, + CUDA_MEM = 8 << KIND_SHIFT, + GPU_MAT = 9 << KIND_SHIFT, + UMAT =10 << KIND_SHIFT, + STD_VECTOR_UMAT =11 << KIND_SHIFT + }; + + _InputArray(); + _InputArray(int _flags, void* _obj); + _InputArray(const Mat& m); + _InputArray(const MatExpr& expr); + _InputArray(const std::vector& vec); + template _InputArray(const Mat_<_Tp>& m); + template _InputArray(const std::vector<_Tp>& vec); + template _InputArray(const std::vector >& vec); + template _InputArray(const std::vector >& vec); + template _InputArray(const _Tp* vec, int n); + template _InputArray(const Matx<_Tp, m, n>& matx); + _InputArray(const double& val); + _InputArray(const cuda::GpuMat& d_mat); + _InputArray(const ogl::Buffer& buf); + _InputArray(const cuda::CudaMem& cuda_mem); + template _InputArray(const cudev::GpuMat_<_Tp>& m); + _InputArray(const UMat& um); + _InputArray(const std::vector& umv); + + virtual Mat getMat(int idx=-1) const; + virtual UMat getUMat(int idx=-1) const; + virtual void getMatVector(std::vector& mv) const; + virtual void getUMatVector(std::vector& umv) const; + virtual cuda::GpuMat getGpuMat() const; + virtual ogl::Buffer getOGlBuffer() const; + void* getObj() const; + + virtual int kind() const; + virtual int dims(int i=-1) const; + virtual int cols(int i=-1) const; + virtual int rows(int i=-1) const; + virtual Size size(int i=-1) const; + virtual int sizend(int* sz, int i=-1) const; + virtual bool sameSize(const _InputArray& arr) const; + virtual size_t total(int i=-1) const; + virtual int type(int i=-1) const; + virtual int depth(int i=-1) const; + virtual int channels(int i=-1) const; + virtual bool isContinuous(int i=-1) const; + virtual bool isSubmatrix(int i=-1) const; + virtual bool empty() const; + virtual void copyTo(const _OutputArray& arr) const; + virtual void copyTo(const _OutputArray& arr, const _InputArray & mask) const; + virtual size_t offset(int i=-1) const; + virtual size_t step(int i=-1) const; + bool isMat() const; + bool isUMat() const; + bool isMatVector() const; + bool isUMatVector() const; + bool isMatx() const; + + virtual ~_InputArray(); + +protected: + int flags; + void* obj; + Size sz; -inline Mat::Mat(Size _sz, int _type, const Scalar& _s) : size(&rows) -{ - initEmpty(); - create(_sz.height, _sz.width, _type); - *this = _s; -} + void init(int _flags, const void* _obj); + void init(int _flags, const void* _obj, Size _sz); +}; -inline Mat::Mat(int _dims, const int* _sz, int _type) : size(&rows) -{ - initEmpty(); - create(_dims, _sz, _type); -} -inline Mat::Mat(int _dims, const int* _sz, int _type, const Scalar& _s) : size(&rows) -{ - initEmpty(); - create(_dims, _sz, _type); - *this = _s; -} - -inline Mat::Mat(const Mat& m) - : flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), data(m.data), - refcount(m.refcount), datastart(m.datastart), dataend(m.dataend), - datalimit(m.datalimit), allocator(m.allocator), size(&rows) -{ - if( refcount ) - CV_XADD(refcount, 1); - if( m.dims <= 2 ) - { - step[0] = m.step[0]; step[1] = m.step[1]; - } - else - { - dims = 0; - copySize(m); - } -} - -inline Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step) - : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_rows), cols(_cols), - data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend(0), - datalimit(0), allocator(0), size(&rows) +/*! + Proxy datatype for passing Mat's and vector<>'s as input parameters + */ +class CV_EXPORTS _OutputArray : public _InputArray { - size_t esz = CV_ELEM_SIZE(_type), minstep = cols*esz; - if( _step == AUTO_STEP ) - { - _step = minstep; - flags |= CONTINUOUS_FLAG; - } - else - { - if( rows == 1 ) _step = minstep; - CV_DbgAssert( _step >= minstep ); - flags |= _step == minstep ? CONTINUOUS_FLAG : 0; - } - step[0] = _step; step[1] = esz; - datalimit = datastart + _step*rows; - dataend = datalimit - _step + minstep; -} - -inline Mat::Mat(Size _sz, int _type, void* _data, size_t _step) - : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_sz.height), cols(_sz.width), - data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend(0), - datalimit(0), allocator(0), size(&rows) -{ - size_t esz = CV_ELEM_SIZE(_type), minstep = cols*esz; - if( _step == AUTO_STEP ) - { - _step = minstep; - flags |= CONTINUOUS_FLAG; - } - else - { - if( rows == 1 ) _step = minstep; - CV_DbgAssert( _step >= minstep ); - flags |= _step == minstep ? CONTINUOUS_FLAG : 0; - } - step[0] = _step; step[1] = esz; - datalimit = datastart + _step*rows; - dataend = datalimit - _step + minstep; -} - - -template inline Mat::Mat(const vector<_Tp>& vec, bool copyData) - : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - 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 ) - { - step[0] = step[1] = sizeof(_Tp); - data = datastart = (uchar*)&vec[0]; - datalimit = dataend = datastart + rows*step[0]; - } - else - Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this); -} - - -template inline Mat::Mat(const Vec<_Tp, n>& vec, bool copyData) - : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - dims(2), rows(n), cols(1), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) -{ - if( !copyData ) - { - step[0] = step[1] = sizeof(_Tp); - data = datastart = (uchar*)vec.val; - datalimit = dataend = datastart + rows*step[0]; - } - else - Mat(n, 1, DataType<_Tp>::type, (void*)vec.val).copyTo(*this); -} - - -template inline Mat::Mat(const Matx<_Tp,m,n>& M, bool copyData) - : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - dims(2), rows(m), cols(n), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) -{ - if( !copyData ) - { - step[0] = cols*sizeof(_Tp); - step[1] = sizeof(_Tp); - data = datastart = (uchar*)M.val; - datalimit = dataend = datastart + rows*step[0]; - } - else - Mat(m, n, DataType<_Tp>::type, (uchar*)M.val).copyTo(*this); -} - - -template inline Mat::Mat(const Point_<_Tp>& pt, bool copyData) - : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - dims(2), rows(2), cols(1), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) -{ - if( !copyData ) - { - step[0] = step[1] = sizeof(_Tp); - data = datastart = (uchar*)&pt.x; - datalimit = dataend = datastart + rows*step[0]; - } - else +public: + enum { - create(2, 1, DataType<_Tp>::type); - ((_Tp*)data)[0] = pt.x; - ((_Tp*)data)[1] = pt.y; - } -} + DEPTH_MASK_8U = 1 << CV_8U, + DEPTH_MASK_8S = 1 << CV_8S, + DEPTH_MASK_16U = 1 << CV_16U, + DEPTH_MASK_16S = 1 << CV_16S, + DEPTH_MASK_32S = 1 << CV_32S, + DEPTH_MASK_32F = 1 << CV_32F, + DEPTH_MASK_64F = 1 << CV_64F, + DEPTH_MASK_ALL = (DEPTH_MASK_64F<<1)-1, + DEPTH_MASK_ALL_BUT_8S = DEPTH_MASK_ALL & ~DEPTH_MASK_8S, + DEPTH_MASK_FLT = DEPTH_MASK_32F + DEPTH_MASK_64F + }; + + _OutputArray(); + _OutputArray(int _flags, void* _obj); + _OutputArray(Mat& m); + _OutputArray(std::vector& vec); + _OutputArray(cuda::GpuMat& d_mat); + _OutputArray(ogl::Buffer& buf); + _OutputArray(cuda::CudaMem& cuda_mem); + template _OutputArray(cudev::GpuMat_<_Tp>& m); + template _OutputArray(std::vector<_Tp>& vec); + template _OutputArray(std::vector >& vec); + template _OutputArray(std::vector >& vec); + template _OutputArray(Mat_<_Tp>& m); + template _OutputArray(_Tp* vec, int n); + template _OutputArray(Matx<_Tp, m, n>& matx); + _OutputArray(UMat& m); + _OutputArray(std::vector& vec); + + _OutputArray(const Mat& m); + _OutputArray(const std::vector& vec); + _OutputArray(const cuda::GpuMat& d_mat); + _OutputArray(const ogl::Buffer& buf); + _OutputArray(const cuda::CudaMem& cuda_mem); + template _OutputArray(const cudev::GpuMat_<_Tp>& m); + template _OutputArray(const std::vector<_Tp>& vec); + template _OutputArray(const std::vector >& vec); + template _OutputArray(const std::vector >& vec); + template _OutputArray(const Mat_<_Tp>& m); + template _OutputArray(const _Tp* vec, int n); + template _OutputArray(const Matx<_Tp, m, n>& matx); + _OutputArray(const UMat& m); + _OutputArray(const std::vector& vec); + + virtual bool fixedSize() const; + virtual bool fixedType() const; + virtual bool needed() const; + virtual Mat& getMatRef(int i=-1) const; + virtual UMat& getUMatRef(int i=-1) const; + virtual cuda::GpuMat& getGpuMatRef() const; + virtual ogl::Buffer& getOGlBufferRef() const; + virtual cuda::CudaMem& getCudaMemRef() const; + virtual void create(Size sz, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; + virtual void create(int rows, int cols, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; + virtual void create(int dims, const int* size, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; + virtual void createSameSize(const _InputArray& arr, int mtype) const; + virtual void release() const; + virtual void clear() const; + virtual void setTo(const _InputArray& value, const _InputArray & mask = _InputArray()) const; + + void assign(const UMat& u) const; + void assign(const Mat& m) const; +}; -template inline Mat::Mat(const Point3_<_Tp>& pt, bool copyData) - : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - dims(2), rows(3), cols(1), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) -{ - if( !copyData ) - { - step[0] = step[1] = sizeof(_Tp); - data = datastart = (uchar*)&pt.x; - datalimit = dataend = datastart + rows*step[0]; - } - else - { - create(3, 1, DataType<_Tp>::type); - ((_Tp*)data)[0] = pt.x; - ((_Tp*)data)[1] = pt.y; - ((_Tp*)data)[2] = pt.z; - } -} - - -template inline Mat::Mat(const MatCommaInitializer_<_Tp>& commaInitializer) - : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), - dims(0), rows(0), cols(0), data(0), refcount(0), - datastart(0), dataend(0), allocator(0), size(&rows) +class CV_EXPORTS _InputOutputArray : public _OutputArray { - *this = *commaInitializer; -} +public: + _InputOutputArray(); + _InputOutputArray(int _flags, void* _obj); + _InputOutputArray(Mat& m); + _InputOutputArray(std::vector& vec); + _InputOutputArray(cuda::GpuMat& d_mat); + _InputOutputArray(ogl::Buffer& buf); + _InputOutputArray(cuda::CudaMem& cuda_mem); + template _InputOutputArray(cudev::GpuMat_<_Tp>& m); + template _InputOutputArray(std::vector<_Tp>& vec); + template _InputOutputArray(std::vector >& vec); + template _InputOutputArray(std::vector >& vec); + template _InputOutputArray(Mat_<_Tp>& m); + template _InputOutputArray(_Tp* vec, int n); + template _InputOutputArray(Matx<_Tp, m, n>& matx); + _InputOutputArray(UMat& m); + _InputOutputArray(std::vector& vec); + + _InputOutputArray(const Mat& m); + _InputOutputArray(const std::vector& vec); + _InputOutputArray(const cuda::GpuMat& d_mat); + _InputOutputArray(const ogl::Buffer& buf); + _InputOutputArray(const cuda::CudaMem& cuda_mem); + template _InputOutputArray(const cudev::GpuMat_<_Tp>& m); + template _InputOutputArray(const std::vector<_Tp>& vec); + template _InputOutputArray(const std::vector >& vec); + template _InputOutputArray(const std::vector >& vec); + template _InputOutputArray(const Mat_<_Tp>& m); + template _InputOutputArray(const _Tp* vec, int n); + template _InputOutputArray(const Matx<_Tp, m, n>& matx); + _InputOutputArray(const UMat& m); + _InputOutputArray(const std::vector& vec); +}; -inline Mat::~Mat() -{ - release(); - if( step.p != step.buf ) - fastFree(step.p); -} +typedef const _InputArray& InputArray; +typedef InputArray InputArrayOfArrays; +typedef const _OutputArray& OutputArray; +typedef OutputArray OutputArrayOfArrays; +typedef const _InputOutputArray& InputOutputArray; +typedef InputOutputArray InputOutputArrayOfArrays; -inline Mat& Mat::operator = (const Mat& m) -{ - if( this != &m ) - { - if( m.refcount ) - CV_XADD(m.refcount, 1); - release(); - flags = m.flags; - 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; - datalimit = m.datalimit; - refcount = m.refcount; - allocator = m.allocator; - } - return *this; -} - -inline Mat Mat::row(int y) const { return Mat(*this, Range(y, y+1), Range::all()); } -inline Mat Mat::col(int x) const { return Mat(*this, Range::all(), Range(x, x+1)); } -inline Mat Mat::rowRange(int startrow, int endrow) const - { return Mat(*this, Range(startrow, endrow), Range::all()); } -inline Mat Mat::rowRange(const Range& r) const - { return Mat(*this, r, Range::all()); } -inline Mat Mat::colRange(int startcol, int endcol) const - { return Mat(*this, Range::all(), Range(startcol, endcol)); } -inline Mat Mat::colRange(const Range& r) const - { return Mat(*this, Range::all(), r); } - -inline Mat Mat::diag(const Mat& d) -{ - CV_Assert( d.cols == 1 || d.rows == 1 ); - int len = d.rows + d.cols - 1; - Mat m(len, len, d.type(), Scalar(0)), md = m.diag(); - if( d.cols == 1 ) - d.copyTo(md); - else - transpose(d, md); - return m; -} - -inline Mat Mat::clone() const -{ - Mat m; - copyTo(m); - return m; -} +CV_EXPORTS InputOutputArray noArray(); -inline void Mat::assignTo( Mat& m, int _type ) const -{ - if( _type < 0 ) - m = *this; - else - convertTo(m, _type); -} +/////////////////////////////////// MatAllocator ////////////////////////////////////// -inline void Mat::create(int _rows, int _cols, int _type) +//! Usage flags for allocator +enum UMatUsageFlags { - _type &= TYPE_MASK; - if( dims <= 2 && rows == _rows && cols == _cols && type() == _type && data ) - return; - int sz[] = {_rows, _cols}; - create(2, sz, _type); -} - -inline void Mat::create(Size _sz, int _type) -{ - create(_sz.height, _sz.width, _type); -} + USAGE_DEFAULT = 0, -inline void Mat::addref() -{ if( refcount ) CV_XADD(refcount, 1); } + // default allocation policy is platform and usage specific + USAGE_ALLOCATE_HOST_MEMORY = 1 << 0, + USAGE_ALLOCATE_DEVICE_MEMORY = 1 << 1, -inline void Mat::release() -{ - if( refcount && CV_XADD(refcount, -1) == 1 ) - deallocate(); - data = datastart = dataend = datalimit = 0; - size.p[0] = 0; - refcount = 0; -} - -inline Mat Mat::operator()( Range _rowRange, Range _colRange ) const -{ - return Mat(*this, _rowRange, _colRange); -} + __UMAT_USAGE_FLAGS_32BIT = 0x7fffffff // Binary compatibility hint +}; -inline Mat Mat::operator()( const Rect& roi ) const -{ return Mat(*this, roi); } +struct CV_EXPORTS UMatData; -inline Mat Mat::operator()(const Range* ranges) const -{ - return Mat(*this, ranges); -} +/*! + Custom array allocator -inline Mat::operator CvMat() const -{ - 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; -} - -inline bool Mat::isContinuous() const { return (flags & CONTINUOUS_FLAG) != 0; } -inline bool Mat::isSubmatrix() const { return (flags & SUBMATRIX_FLAG) != 0; } -inline size_t Mat::elemSize() const { return dims > 0 ? step.p[dims-1] : 0; } -inline size_t Mat::elemSize1() const { return CV_ELEM_SIZE1(flags); } -inline int Mat::type() const { return CV_MAT_TYPE(flags); } -inline int Mat::depth() const { return CV_MAT_DEPTH(flags); } -inline int Mat::channels() const { return CV_MAT_CN(flags); } -inline size_t Mat::step1(int i) const { return step.p[i]/elemSize1(); } -inline bool Mat::empty() const { return data == 0 || total() == 0; } -inline size_t Mat::total() const +*/ +class CV_EXPORTS MatAllocator { - if( dims <= 2 ) - return (size_t)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( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) ); - return data + step.p[0]*y; -} +public: + MatAllocator() {} + virtual ~MatAllocator() {} + + // let's comment it off for now to detect and fix all the uses of allocator + //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; + virtual UMatData* allocate(int dims, const int* sizes, int type, + void* data, size_t* step, int flags, UMatUsageFlags usageFlags) const = 0; + virtual bool allocate(UMatData* data, int accessflags, UMatUsageFlags usageFlags) const = 0; + virtual void deallocate(UMatData* data) const = 0; + virtual void map(UMatData* data, int accessflags) const; + virtual void unmap(UMatData* data) const; + virtual void download(UMatData* data, void* dst, int dims, const size_t sz[], + const size_t srcofs[], const size_t srcstep[], + const size_t dststep[]) const; + virtual void upload(UMatData* data, const void* src, int dims, const size_t sz[], + const size_t dstofs[], const size_t dststep[], + const size_t srcstep[]) const; + virtual void copy(UMatData* srcdata, UMatData* dstdata, int dims, const size_t sz[], + const size_t srcofs[], const size_t srcstep[], + const size_t dstofs[], const size_t dststep[], bool sync) const; + + // default implementation returns DummyBufferPoolController + virtual BufferPoolController* getBufferPoolController() const; +}; -inline const uchar* Mat::ptr(int y) const -{ - CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) ); - return data + step.p[0]*y; -} -template inline _Tp* Mat::ptr(int y) -{ - CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) ); - return (_Tp*)(data + step.p[0]*y); -} +//////////////////////////////// MatCommaInitializer ////////////////////////////////// -template inline const _Tp* Mat::ptr(int y) const -{ - CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) ); - return (const _Tp*)(data + step.p[0]*y); -} +/*! + Comma-separated Matrix Initializer + The class instances are usually not created explicitly. + Instead, they are created on "matrix << firstValue" operator. -inline uchar* Mat::ptr(int i0, int i1) -{ - CV_DbgAssert( dims >= 2 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] ); - return data + i0*step.p[0] + i1*step.p[1]; -} + The sample below initializes 2x2 rotation matrix: -inline const uchar* Mat::ptr(int i0, int i1) const + \code + double angle = 30, a = cos(angle*CV_PI/180), b = sin(angle*CV_PI/180); + Mat R = (Mat_(2,2) << a, -b, b, a); + \endcode +*/ +template class MatCommaInitializer_ { - 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]; -} +public: + //! the constructor, created by "matrix << firstValue" operator, where matrix is cv::Mat + MatCommaInitializer_(Mat_<_Tp>* _m); + //! the operator that takes the next value and put it to the matrix + template MatCommaInitializer_<_Tp>& operator , (T2 v); + //! another form of conversion operator + operator Mat_<_Tp>() const; +protected: + MatIterator_<_Tp> it; +}; -template inline _Tp* Mat::ptr(int i0, int i1) -{ - CV_DbgAssert( dims >= 2 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] ); - return (_Tp*)(data + i0*step.p[0] + i1*step.p[1]); -} -template inline const _Tp* Mat::ptr(int i0, int i1) const -{ - CV_DbgAssert( dims >= 2 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] ); - return (const _Tp*)(data + i0*step.p[0] + i1*step.p[1]); -} +/////////////////////////////////////// Mat /////////////////////////////////////////// + +// note that umatdata might be allocated together +// with the matrix data, not as a separate object. +// therefore, it does not have constructor or destructor; +// it should be explicitly initialized using init(). +struct CV_EXPORTS UMatData +{ + enum { COPY_ON_MAP=1, HOST_COPY_OBSOLETE=2, + DEVICE_COPY_OBSOLETE=4, TEMP_UMAT=8, TEMP_COPIED_UMAT=24, + USER_ALLOCATED=32, DEVICE_MEM_MAPPED=64}; + UMatData(const MatAllocator* allocator); + ~UMatData(); + + // provide atomic access to the structure + void lock(); + void unlock(); + + bool hostCopyObsolete() const; + bool deviceCopyObsolete() const; + bool deviceMemMapped() const; + bool copyOnMap() const; + bool tempUMat() const; + bool tempCopiedUMat() const; + void markHostCopyObsolete(bool flag); + void markDeviceCopyObsolete(bool flag); + void markDeviceMemMapped(bool flag); + + const MatAllocator* prevAllocator; + const MatAllocator* currAllocator; + int urefcount; + int refcount; + uchar* data; + uchar* origdata; + size_t size, capacity; -inline uchar* Mat::ptr(int i0, int i1, int i2) -{ - CV_DbgAssert( dims >= 3 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] && - (unsigned)i2 < (unsigned)size.p[2] ); - return data + i0*step.p[0] + i1*step.p[1] + i2*step.p[2]; -} - -inline const uchar* Mat::ptr(int i0, int i1, int i2) const -{ - CV_DbgAssert( dims >= 3 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] && - (unsigned)i2 < (unsigned)size.p[2] ); - return data + i0*step.p[0] + i1*step.p[1] + i2*step.p[2]; -} - -template inline _Tp* Mat::ptr(int i0, int i1, int i2) -{ - CV_DbgAssert( dims >= 3 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] && - (unsigned)i2 < (unsigned)size.p[2] ); - return (_Tp*)(data + i0*step.p[0] + i1*step.p[1] + i2*step.p[2]); -} - -template inline const _Tp* 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 (const _Tp*)(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)idx[i] < (unsigned)size.p[i] ); - p += idx[i]*step.p[i]; - } - return p; -} + int flags; + void* handle; + void* userdata; + int allocatorFlags_; +}; -inline const uchar* Mat::ptr(const int* idx) const -{ - int i, d = dims; - uchar* p = data; - CV_DbgAssert( d >= 1 && p ); - for( i = 0; i < d; i++ ) - { - CV_DbgAssert( (unsigned)idx[i] < (unsigned)size.p[i] ); - p += idx[i]*step.p[i]; - } - return p; -} -template inline _Tp& Mat::at(int i0, int i1) +struct CV_EXPORTS UMatDataAutoLock { - 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]; -} + explicit UMatDataAutoLock(UMatData* u); + ~UMatDataAutoLock(); + UMatData* u; +}; -template inline const _Tp& Mat::at(int i0, int i1) const -{ - CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && - CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); - return ((const _Tp*)(data + step.p[0]*i0))[i1]; -} -template inline _Tp& Mat::at(Point pt) +struct CV_EXPORTS MatSize { - 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.p[0]*pt.y))[pt.x]; -} + explicit MatSize(int* _p); + Size operator()() const; + const int& operator[](int i) const; + int& operator[](int i); + operator const int*() const; + bool operator == (const MatSize& sz) const; + bool operator != (const MatSize& sz) const; -template inline const _Tp& Mat::at(Point pt) const -{ - 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.p[0]*pt.y))[pt.x]; -} + int* p; +}; -template inline _Tp& Mat::at(int i0) -{ - CV_DbgAssert( dims <= 2 && data && - (unsigned)i0 < (unsigned)(size.p[0]*size.p[1]) && - elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - if( isContinuous() || size.p[0] == 1 ) - return ((_Tp*)data)[i0]; - if( size.p[1] == 1 ) - return *(_Tp*)(data + step.p[0]*i0); - int i = i0/cols, j = i0 - i*cols; - return ((_Tp*)(data + step.p[0]*i))[j]; -} - -template inline const _Tp& Mat::at(int i0) const -{ - CV_DbgAssert( dims <= 2 && data && - (unsigned)i0 < (unsigned)(size.p[0]*size.p[1]) && - elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - if( isContinuous() || size.p[0] == 1 ) - return ((const _Tp*)data)[i0]; - if( size.p[1] == 1 ) - return *(const _Tp*)(data + step.p[0]*i0); - int i = i0/cols, j = i0 - i*cols; - return ((const _Tp*)(data + step.p[0]*i))[j]; -} - -template inline _Tp& Mat::at(int i0, int i1, int i2) -{ - CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - return *(_Tp*)ptr(i0, i1, i2); -} -template inline const _Tp& Mat::at(int i0, int i1, int i2) const -{ - CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - return *(const _Tp*)ptr(i0, i1, i2); -} -template inline _Tp& Mat::at(const int* idx) -{ - CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - return *(_Tp*)ptr(idx); -} -template inline const _Tp& Mat::at(const int* idx) const -{ - CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - return *(const _Tp*)ptr(idx); -} -template _Tp& Mat::at(const Vec& idx) -{ - CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - return *(_Tp*)ptr(idx.val); -} -template inline const _Tp& Mat::at(const Vec& idx) const +struct CV_EXPORTS MatStep { - CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); - return *(const _Tp*)ptr(idx.val); -} + MatStep(); + explicit MatStep(size_t s); + const size_t& operator[](int i) const; + size_t& operator[](int i); + operator size_t() const; + MatStep& operator = (size_t s); + size_t* p; + size_t buf[2]; +protected: + MatStep& operator = (const MatStep&); +}; -template inline MatConstIterator_<_Tp> Mat::begin() const -{ - CV_DbgAssert( elemSize() == sizeof(_Tp) ); - return MatConstIterator_<_Tp>((const Mat_<_Tp>*)this); -} - -template inline MatConstIterator_<_Tp> Mat::end() const + /*! + The n-dimensional matrix class. + + 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: +
    +
  • using cv::Mat::create(nrows, ncols, type) method or + the similar constructor cv::Mat::Mat(nrows, ncols, type[, fill_value]) constructor. + A new matrix of the specified size and specifed type will be allocated. + "type" has the same meaning as in cvCreateMat function, + e.g. CV_8UC1 means 8-bit single-channel matrix, CV_32FC2 means 2-channel (i.e. complex) + floating-point matrix etc: + + \code + // make 7x7 complex matrix filled with 1+3j. + cv::Mat M(7,7,CV_32FC2,Scalar(1,3)); + // and now turn M to 100x60 15-channel 8-bit matrix. + // The old content will be deallocated + M.create(100,60,CV_8UC(15)); + \endcode + + As noted in the introduction of this chapter, Mat::create() + will only allocate a new matrix when the current matrix dimensionality + or type are different from the specified. + +
  • by using a copy constructor or assignment operator, where on the right side it can + be a matrix or expression, see below. Again, as noted in the introduction, + matrix assignment is O(1) operation because it only copies the header + and increases the reference counter. cv::Mat::clone() method can be used to get a full + (a.k.a. deep) copy of the matrix when you need it. + +
  • by constructing a header for a part of another matrix. It can be a single row, single column, + several rows, several columns, rectangular region in the matrix (called a minor in algebra) or + a diagonal. Such operations are also O(1), because the new header will reference the same data. + You can actually modify a part of the matrix using this feature, e.g. + + \code + // add 5-th row, multiplied by 3 to the 3rd row + M.row(3) = M.row(3) + M.row(5)*3; + + // now copy 7-th column to the 1-st column + // M.col(1) = M.col(7); // this will not work + Mat M1 = M.col(1); + M.col(7).copyTo(M1); + + // create new 320x240 image + cv::Mat img(Size(320,240),CV_8UC3); + // select a roi + cv::Mat roi(img, Rect(10,10,100,100)); + // fill the ROI with (0,255,0) (which is green in RGB space); + // the original 320x240 image will be modified + roi = Scalar(0,255,0); + \endcode + + Thanks to the additional cv::Mat::datastart and cv::Mat::dataend members, it is possible to + compute the relative sub-matrix position in the main "container" matrix using cv::Mat::locateROI(): + + \code + Mat A = Mat::eye(10, 10, CV_32S); + // extracts A columns, 1 (inclusive) to 3 (exclusive). + Mat B = A(Range::all(), Range(1, 3)); + // extracts B rows, 5 (inclusive) to 9 (exclusive). + // that is, C ~ A(Range(5, 9), Range(1, 3)) + Mat C = B(Range(5, 9), Range::all()); + Size size; Point ofs; + C.locateROI(size, ofs); + // size will be (width=10,height=10) and the ofs will be (x=1, y=5) + \endcode + + As in the case of whole matrices, if you need a deep copy, use cv::Mat::clone() method + of the extracted sub-matrices. + +
  • by making a header for user-allocated-data. It can be useful for +
      +
    1. processing "foreign" data using OpenCV (e.g. when you implement + a DirectShow filter or a processing module for gstreamer etc.), e.g. + + \code + void process_video_frame(const unsigned char* pixels, + int width, int height, int step) + { + cv::Mat img(height, width, CV_8UC3, pixels, step); + cv::GaussianBlur(img, img, cv::Size(7,7), 1.5, 1.5); + } + \endcode + +
    2. for quick initialization of small matrices and/or super-fast element access + + \code + double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}}; + cv::Mat M = cv::Mat(3, 3, CV_64F, m).inv(); + \endcode +
    + + partial yet very common cases of this "user-allocated data" case are conversions + from CvMat and IplImage to cv::Mat. For this purpose there are special constructors + taking pointers to CvMat or IplImage and the optional + flag indicating whether to copy the data or not. + + Backward conversion from cv::Mat to CvMat or IplImage is provided via cast operators + cv::Mat::operator CvMat() an cv::Mat::operator IplImage(). + The operators do not copy the data. + + + \code + IplImage* img = cvLoadImage("greatwave.jpg", 1); + Mat mtx(img); // convert IplImage* -> cv::Mat + CvMat oldmat = mtx; // convert cv::Mat -> CvMat + CV_Assert(oldmat.cols == img->width && oldmat.rows == img->height && + oldmat.data.ptr == (uchar*)img->imageData && oldmat.step == img->widthStep); + \endcode + +
  • by using MATLAB-style matrix initializers, cv::Mat::zeros(), cv::Mat::ones(), cv::Mat::eye(), e.g.: + + \code + // create a double-precision identity martix and add it to M. + M += Mat::eye(M.rows, M.cols, CV_64F); + \endcode + +
  • by using comma-separated initializer: + + \code + // create 3x3 double-precision identity matrix + Mat M = (Mat_(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1); + \endcode + + here we first call constructor of cv::Mat_ class (that we describe further) with the proper matrix, + and then we just put "<<" operator followed by comma-separated values that can be constants, + variables, expressions etc. Also, note the extra parentheses that are needed to avoid compiler errors. + +
+ + Once matrix is created, it will be automatically managed by using reference-counting mechanism + (unless the matrix header is built on top of user-allocated data, + in which case you should handle the data by yourself). + The matrix data will be deallocated when no one points to it; + if you want to release the data pointed by a matrix header before the matrix destructor is called, + use cv::Mat::release(). + + The next important thing to learn about the matrix class is element access. Here is how the matrix is stored. + The elements are stored in row-major order (row by row). The cv::Mat::data member points to the first element of the first row, + cv::Mat::rows contains the number of matrix rows and cv::Mat::cols - the number of matrix columns. There is yet another member, + cv::Mat::step that is used to actually compute address of a matrix element. cv::Mat::step is needed because the matrix can be + a part of another matrix or because there can some padding space in the end of each row for a proper alignment. + + Given these parameters, address of the matrix element M_{ij} is computed as following: + + addr(M_{ij})=M.data + M.step*i + j*M.elemSize() + + if you know the matrix element type, e.g. it is float, then you can use cv::Mat::at() method: + + addr(M_{ij})=&M.at(i,j) + + (where & is used to convert the reference returned by cv::Mat::at() to a pointer). + if you need to process a whole row of matrix, the most efficient way is to get + the pointer to the row first, and then just use plain C operator []: + + \code + // compute sum of positive matrix elements + // (assuming that M is double-precision matrix) + double sum=0; + for(int i = 0; i < M.rows; i++) + { + const double* Mi = M.ptr(i); + for(int j = 0; j < M.cols; j++) + sum += std::max(Mi[j], 0.); + } + \endcode + + Some operations, like the above one, do not actually depend on the matrix shape, + they just process elements of a matrix one by one (or elements from multiple matrices + that are sitting in the same place, e.g. matrix addition). Such operations are called + element-wise and it makes sense to check whether all the input/output matrices are continuous, + i.e. have no gaps in the end of each row, and if yes, process them as a single long row: + + \code + // compute sum of positive matrix elements, optimized variant + double sum=0; + int cols = M.cols, rows = M.rows; + if(M.isContinuous()) + { + cols *= rows; + rows = 1; + } + for(int i = 0; i < rows; i++) + { + const double* Mi = M.ptr(i); + for(int j = 0; j < cols; j++) + sum += std::max(Mi[j], 0.); + } + \endcode + in the case of continuous matrix the outer loop body will be executed just once, + so the overhead will be smaller, which will be especially noticeable in the case of small matrices. + + Finally, there are STL-style iterators that are smart enough to skip gaps between successive rows: + \code + // compute sum of positive matrix elements, iterator-based variant + double sum=0; + MatConstIterator_ it = M.begin(), it_end = M.end(); + for(; it != it_end; ++it) + sum += std::max(*it, 0.); + \endcode + + The matrix iterators are random-access iterators, so they can be passed + to any STL algorithm, including std::sort(). +*/ +class CV_EXPORTS Mat { - CV_DbgAssert( elemSize() == sizeof(_Tp) ); - MatConstIterator_<_Tp> it((const Mat_<_Tp>*)this); - it += total(); - return it; -} +public: + //! default constructor + Mat(); + //! 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 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=Range::all()); + Mat(const Mat& m, const Rect& roi); + Mat(const Mat& m, const Range* ranges); + //! builds matrix from std::vector with or without copying the data + template explicit Mat(const std::vector<_Tp>& vec, bool copyData=false); + //! builds matrix from cv::Vec; the data is copied by default + template explicit Mat(const Vec<_Tp, n>& vec, bool copyData=true); + //! builds matrix from cv::Matx; the data is copied by default + template explicit Mat(const Matx<_Tp, m, n>& mtx, bool copyData=true); + //! builds matrix from a 2D point + template explicit Mat(const Point_<_Tp>& pt, bool copyData=true); + //! builds matrix from a 3D point + template explicit Mat(const Point3_<_Tp>& pt, bool copyData=true); + //! builds matrix from comma initializer + template explicit Mat(const MatCommaInitializer_<_Tp>& commaInitializer); + + //! download data from GpuMat + explicit Mat(const cuda::GpuMat& m); + + //! destructor - calls release() + ~Mat(); + //! assignment operators + Mat& operator = (const Mat& m); + Mat& operator = (const MatExpr& expr); + + //! retrieve UMat from Mat + UMat getUMat(int accessFlags, UMatUsageFlags usageFlags = USAGE_DEFAULT) const; + + //! returns a new matrix header for the specified row + Mat row(int y) const; + //! returns a new matrix header for the specified column + Mat col(int x) const; + //! ... for the specified row span + Mat rowRange(int startrow, int endrow) const; + Mat rowRange(const Range& r) const; + //! ... for the specified column span + Mat colRange(int startcol, int endcol) const; + Mat colRange(const Range& r) const; + //! ... for the specified diagonal + // (d=0 - the main diagonal, + // >0 - a diagonal from the lower half, + // <0 - a diagonal from the upper half) + Mat diag(int d=0) const; + //! constructs a square diagonal matrix which main diagonal is vector "d" + static Mat diag(const Mat& d); + + //! returns deep copy of the matrix, i.e. the data is copied + Mat clone() const; + //! copies the matrix content to "m". + // It calls m.create(this->size(), this->type()). + void copyTo( OutputArray m ) const; + //! copies those matrix elements to "m" that are marked with non-zero mask elements. + void copyTo( OutputArray m, InputArray mask ) const; + //! converts matrix to another datatype with optional scalng. See cvConvertScale. + void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const; + + void assignTo( Mat& m, int type=-1 ) const; + + //! sets every matrix element to s + Mat& operator = (const Scalar& s); + //! sets some of the matrix elements to s, according to the mask + Mat& setTo(InputArray value, InputArray mask=noArray()); + //! 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; + //! matrix inversion by means of matrix expressions + MatExpr inv(int method=DECOMP_LU) const; + //! per-element matrix multiplication by means of matrix expressions + MatExpr mul(InputArray m, double scale=1) const; + + //! computes cross-product of 2 3D vectors + Mat cross(InputArray m) const; + //! computes dot-product + double dot(InputArray m) const; + + //! 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); + + //! allocates new matrix data unless the matrix already has specified size and type. + // 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; + // 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); + + //! reserves enough space to fit sz hyper-planes + void reserve(size_t sz); + //! resizes matrix to the specified number of hyper-planes + void resize(size_t sz); + //! resizes matrix to the specified number of hyper-planes; initializes the newly added elements + void resize(size_t sz, const Scalar& s); + //! internal function + void push_back_(const void* elem); + //! adds element to the end of 1d matrix (or possibly multiple elements when _Tp=Mat) + template void push_back(const _Tp& elem); + template void push_back(const Mat_<_Tp>& elem); + void push_back(const Mat& m); + //! removes several hyper-planes from bottom of the matrix + void pop_back(size_t nelems=1); + + //! locates matrix header within a parent matrix. See below + void locateROI( Size& wholeSize, Point& ofs ) const; + //! moves/resizes the current matrix ROI inside the parent matrix. + Mat& adjustROI( int dtop, int dbottom, int dleft, int dright ); + //! extracts a rectangular sub-matrix + // (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; + + template operator std::vector<_Tp>() const; + template operator Vec<_Tp, n>() const; + template operator Matx<_Tp, m, n>() const; + + //! returns true iff the matrix data is continuous + // (i.e. when there are no gaps between successive rows). + // similar to CV_IS_MAT_CONT(cvmat->type) + bool isContinuous() const; + + //! returns true if the matrix is a submatrix of another matrix + bool isSubmatrix() const; + + //! returns element size in bytes, + // similar to CV_ELEM_SIZE(cvmat->type) + size_t elemSize() const; + //! returns the size of element channel in bytes. + size_t elemSize1() const; + //! returns element type, similar to CV_MAT_TYPE(cvmat->type) + int type() const; + //! returns element type, similar to CV_MAT_DEPTH(cvmat->type) + int depth() const; + //! returns element type, similar to CV_MAT_CN(cvmat->type) + int channels() const; + //! returns step/elemSize1() + 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 N if the matrix is 1-channel (N x ptdim) or ptdim-channel (1 x N) or (N x 1); negative number otherwise + int checkVector(int elemChannels, int depth=-1, bool requireContinuous=true) const; + + //! returns pointer to i0-th submatrix along the dimension #0 + uchar* ptr(int i0=0); + const uchar* ptr(int i0=0) const; + + //! returns pointer to (i0,i1) submatrix along the dimensions #0 and #1 + uchar* ptr(int i0, int i1); + const uchar* ptr(int i0, int i1) const; + + //! returns pointer to (i0,i1,i3) submatrix along the dimensions #0, #1, #2 + uchar* ptr(int i0, int i1, int i2); + const uchar* ptr(int i0, int i1, int i2) const; + + //! returns pointer to the matrix element + uchar* ptr(const int* idx); + //! returns read-only pointer to the matrix element + const uchar* ptr(const int* idx) const; + + template uchar* ptr(const Vec& idx); + template const uchar* ptr(const Vec& idx) const; + + //! template version of the above method + template _Tp* ptr(int i0=0); + template const _Tp* ptr(int i0=0) const; + + template _Tp* ptr(int i0, int i1); + template const _Tp* ptr(int i0, int i1) const; + + template _Tp* ptr(int i0, int i1, int i2); + template const _Tp* ptr(int i0, int i1, int i2) const; + + template _Tp* ptr(const int* idx); + template const _Tp* ptr(const int* idx) const; + + template _Tp* ptr(const Vec& idx); + template const _Tp* ptr(const Vec& idx) const; + + //! the same as above, with the pointer dereferencing + template _Tp& at(int i0=0); + template const _Tp& at(int i0=0) const; + + template _Tp& at(int i0, int i1); + template const _Tp& at(int i0, int i1) const; + + template _Tp& at(int i0, int i1, int i2); + template const _Tp& at(int i0, int i1, int i2) const; + + template _Tp& at(const int* idx); + template const _Tp& at(const int* idx) const; + + template _Tp& at(const Vec& idx); + template const _Tp& at(const Vec& idx) const; + + //! special versions for 2D arrays (especially convenient for referencing image pixels) + template _Tp& at(Point pt); + template const _Tp& at(Point pt) const; + + //! template methods for iteration over matrix elements. + // the iterators take care of skipping gaps in the end of rows (if any) + template MatIterator_<_Tp> begin(); + template MatIterator_<_Tp> end(); + template MatConstIterator_<_Tp> begin() const; + template MatConstIterator_<_Tp> end() const; + + //! template methods for for operation over all matrix elements. + // the operations take care of skipping gaps in the end of rows (if any) + template void forEach(const Functor& operation); + template void forEach(const Functor& operation) const; + + enum { MAGIC_VAL = 0x42FF0000, AUTO_STEP = 0, CONTINUOUS_FLAG = CV_MAT_CONT_FLAG, SUBMATRIX_FLAG = CV_SUBMAT_FLAG }; + enum { MAGIC_MASK = 0xFFFF0000, TYPE_MASK = 0x00000FFF, DEPTH_MASK = 7 }; + + /*! includes several bit-fields: + - the magic signature + - continuity flag + - depth + - number of channels + */ + int flags; + //! the matrix dimensionality, >= 2 + int dims; + //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions + int rows, cols; + //! pointer to the data + uchar* data; + + //! helper fields used in locateROI and adjustROI + const uchar* datastart; + const uchar* dataend; + const uchar* datalimit; + + //! custom allocator + MatAllocator* allocator; + //! and the standard allocator + static MatAllocator* getStdAllocator(); + + //! interaction with UMat + UMatData* u; + + MatSize size; + MatStep step; + +protected: + template void forEach_impl(const Functor& operation); +}; -template inline MatIterator_<_Tp> Mat::begin() -{ - CV_DbgAssert( elemSize() == sizeof(_Tp) ); - return MatIterator_<_Tp>((Mat_<_Tp>*)this); -} -template inline MatIterator_<_Tp> Mat::end() -{ - CV_DbgAssert( elemSize() == sizeof(_Tp) ); - MatIterator_<_Tp> it((Mat_<_Tp>*)this); - it += total(); - return it; -} +///////////////////////////////// Mat_<_Tp> //////////////////////////////////// -template inline Mat::operator vector<_Tp>() const +/*! + Template matrix class derived from Mat + + The class Mat_ is a "thin" template wrapper on top of cv::Mat. It does not have any extra data fields, + nor it or cv::Mat have any virtual methods and thus references or pointers to these two classes + can be safely converted one to another. But do it with care, for example: + + \code + // create 100x100 8-bit matrix + Mat M(100,100,CV_8U); + // this will compile fine. no any data conversion will be done. + Mat_& M1 = (Mat_&)M; + // the program will likely crash at the statement below + M1(99,99) = 1.f; + \endcode + + While cv::Mat is sufficient in most cases, cv::Mat_ can be more convenient if you use a lot of element + access operations and if you know matrix type at compile time. Note that cv::Mat::at and + cv::Mat::operator() do absolutely the same thing and run at the same speed, but the latter is certainly shorter: + + \code + Mat_ M(20,20); + for(int i = 0; i < M.rows; i++) + for(int j = 0; j < M.cols; j++) + M(i,j) = 1./(i+j+1); + Mat E, V; + eigen(M,E,V); + cout << E.at(0,0)/E.at(M.rows-1,0); + \endcode + + It is easy to use Mat_ for multi-channel images/matrices - just pass cv::Vec as cv::Mat_ template parameter: + + \code + // allocate 320x240 color image and fill it with green (in RGB space) + Mat_ img(240, 320, Vec3b(0,255,0)); + // now draw a diagonal white line + for(int i = 0; i < 100; i++) + img(i,i)=Vec3b(255,255,255); + // and now modify the 2nd (red) channel of each pixel + for(int i = 0; i < img.rows; i++) + for(int j = 0; j < img.cols; j++) + img(i,j)[2] ^= (uchar)(i ^ j); // img(y,x)[c] accesses c-th channel of the pixel (x,y) + \endcode +*/ +template class Mat_ : public Mat { - vector<_Tp> v; - copyTo(v); - return v; -} +public: + typedef _Tp value_type; + typedef typename DataType<_Tp>::channel_type channel_type; + typedef MatIterator_<_Tp> iterator; + typedef MatConstIterator_<_Tp> const_iterator; + + //! default constructor + Mat_(); + //! equivalent to Mat(_rows, _cols, DataType<_Tp>::type) + Mat_(int _rows, int _cols); + //! constructor that sets each matrix element to specified value + Mat_(int _rows, int _cols, const _Tp& value); + //! equivalent to Mat(_size, DataType<_Tp>::type) + 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=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); + //! from a matrix expression + explicit Mat_(const MatExpr& e); + //! makes a matrix out of Vec, std::vector, Point_ or Point3_. The matrix will have a single column + explicit Mat_(const std::vector<_Tp>& vec, bool copyData=false); + template explicit Mat_(const Vec::channel_type, n>& vec, bool copyData=true); + template explicit Mat_(const Matx::channel_type, m, n>& mtx, bool copyData=true); + explicit Mat_(const Point_::channel_type>& pt, bool copyData=true); + explicit Mat_(const Point3_::channel_type>& pt, bool copyData=true); + explicit Mat_(const MatCommaInitializer_<_Tp>& commaInitializer); + + Mat_& operator = (const Mat& m); + Mat_& operator = (const Mat_& m); + //! set all the elements to s. + Mat_& operator = (const _Tp& s); + //! assign a matrix expression + Mat_& operator = (const MatExpr& e); + + //! iterators; they are smart enough to skip gaps in the end of rows + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + //! template methods for for operation over all matrix elements. + // the operations take care of skipping gaps in the end of rows (if any) + template void forEach(const Functor& operation); + template void forEach(const Functor& operation) const; + + //! equivalent to Mat::create(_rows, _cols, DataType<_Tp>::type) + 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; + //! data type conversion + template operator Mat_() const; + //! overridden forms of Mat::row() etc. + Mat_ row(int y) const; + Mat_ col(int x) const; + Mat_ diag(int d=0) const; + Mat_ clone() const; + + //! overridden forms of Mat::elemSize() etc. + size_t elemSize() const; + size_t elemSize1() const; + int type() const; + int depth() const; + int channels() const; + size_t step1(int i=0) const; + //! returns step()/sizeof(_Tp) + 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); + + //! some more overriden methods + 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; + + //! returns reference to the specified element + _Tp& operator ()(const int* idx); + //! returns read-only reference to the specified element + const _Tp& operator ()(const int* idx) const; + + //! returns reference to the specified element + template _Tp& operator ()(const Vec& idx); + //! returns read-only reference to the specified element + template const _Tp& operator ()(const Vec& idx) const; + + //! returns reference to the specified element (1D case) + _Tp& operator ()(int idx0); + //! returns read-only reference to the specified element (1D case) + const _Tp& operator ()(int idx0) const; + //! returns reference to the specified element (2D case) + _Tp& operator ()(int idx0, int idx1); + //! returns read-only reference to the specified element (2D case) + const _Tp& operator ()(int idx0, int idx1) const; + //! returns reference to the specified element (3D case) + _Tp& operator ()(int idx0, int idx1, int idx2); + //! returns read-only reference to the specified element (3D case) + const _Tp& operator ()(int idx0, int idx1, int idx2) const; + + _Tp& operator ()(Point pt); + const _Tp& operator ()(Point pt) const; + + //! conversion to vector. + operator std::vector<_Tp>() const; + //! conversion to Vec + template operator Vec::channel_type, n>() const; + //! conversion to Matx + template operator Matx::channel_type, m, n>() const; +}; -template inline Mat::operator Vec<_Tp, n>() const -{ - CV_Assert( data && dims <= 2 && (rows == 1 || cols == 1) && - rows + cols - 1 == n && channels() == 1 ); +typedef Mat_ Mat1b; +typedef Mat_ Mat2b; +typedef Mat_ Mat3b; +typedef Mat_ Mat4b; - if( isContinuous() && type() == DataType<_Tp>::type ) - return Vec<_Tp, n>((_Tp*)data); - Vec<_Tp, n> v; Mat tmp(rows, cols, DataType<_Tp>::type, v.val); - convertTo(tmp, tmp.type()); - return v; -} +typedef Mat_ Mat1s; +typedef Mat_ Mat2s; +typedef Mat_ Mat3s; +typedef Mat_ Mat4s; -template inline Mat::operator Matx<_Tp, m, n>() const -{ - CV_Assert( data && dims <= 2 && rows == m && cols == n && channels() == 1 ); +typedef Mat_ Mat1w; +typedef Mat_ Mat2w; +typedef Mat_ Mat3w; +typedef Mat_ Mat4w; - if( isContinuous() && type() == DataType<_Tp>::type ) - return Matx<_Tp, m, n>((_Tp*)data); - Matx<_Tp, m, n> mtx; Mat tmp(rows, cols, DataType<_Tp>::type, mtx.val); - convertTo(tmp, tmp.type()); - return mtx; -} +typedef Mat_ Mat1i; +typedef Mat_ Mat2i; +typedef Mat_ Mat3i; +typedef Mat_ Mat4i; +typedef Mat_ Mat1f; +typedef Mat_ Mat2f; +typedef Mat_ Mat3f; +typedef Mat_ Mat4f; -template inline void Mat::push_back(const _Tp& elem) -{ - if( !data ) - { - *this = Mat(1, 1, DataType<_Tp>::type, (void*)&elem).clone(); - return; - } - CV_Assert(DataType<_Tp>::type == type() && cols == 1 - /* && dims == 2 (cols == 1 implies dims == 2) */); - uchar* tmp = dataend + step[0]; - if( !isSubmatrix() && isContinuous() && tmp <= datalimit ) - { - *(_Tp*)(data + (size.p[0]++)*step.p[0]) = elem; - dataend = tmp; - } - else - push_back_(&elem); -} - -template inline void Mat::push_back(const Mat_<_Tp>& m) -{ - push_back((const Mat&)m); -} +typedef Mat_ Mat1d; +typedef Mat_ Mat2d; +typedef Mat_ Mat3d; +typedef Mat_ Mat4d; -inline Mat::MSize::MSize(int* _p) : p(_p) {} -inline Size Mat::MSize::operator()() const -{ - CV_DbgAssert(p[-1] <= 2); - return Size(p[1], p[0]); -} -inline const 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 const 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 -{ - CV_DbgAssert( p == buf ); - return buf[0]; -} -inline Mat::MStep& Mat::MStep::operator = (size_t s) +class CV_EXPORTS UMat { - CV_DbgAssert( p == buf ); - buf[0] = s; - return *this; -} +public: + //! default constructor + UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT); + //! constructs 2D matrix of the specified size and type + // (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.) + UMat(int rows, int cols, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT); + UMat(Size size, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT); + //! constucts 2D matrix and fills it with the specified value _s. + UMat(int rows, int cols, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT); + UMat(Size size, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT); + + //! constructs n-dimensional matrix + UMat(int ndims, const int* sizes, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT); + UMat(int ndims, const int* sizes, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT); + + //! copy constructor + UMat(const UMat& m); + + //! creates a matrix header for a part of the bigger matrix + UMat(const UMat& m, const Range& rowRange, const Range& colRange=Range::all()); + UMat(const UMat& m, const Rect& roi); + UMat(const UMat& m, const Range* ranges); + //! builds matrix from std::vector with or without copying the data + template explicit UMat(const std::vector<_Tp>& vec, bool copyData=false); + //! builds matrix from cv::Vec; the data is copied by default + template explicit UMat(const Vec<_Tp, n>& vec, bool copyData=true); + //! builds matrix from cv::Matx; the data is copied by default + template explicit UMat(const Matx<_Tp, m, n>& mtx, bool copyData=true); + //! builds matrix from a 2D point + template explicit UMat(const Point_<_Tp>& pt, bool copyData=true); + //! builds matrix from a 3D point + template explicit UMat(const Point3_<_Tp>& pt, bool copyData=true); + //! builds matrix from comma initializer + template explicit UMat(const MatCommaInitializer_<_Tp>& commaInitializer); + + //! destructor - calls release() + ~UMat(); + //! assignment operators + UMat& operator = (const UMat& m); + + Mat getMat(int flags) const; + + //! returns a new matrix header for the specified row + UMat row(int y) const; + //! returns a new matrix header for the specified column + UMat col(int x) const; + //! ... for the specified row span + UMat rowRange(int startrow, int endrow) const; + UMat rowRange(const Range& r) const; + //! ... for the specified column span + UMat colRange(int startcol, int endcol) const; + UMat colRange(const Range& r) const; + //! ... for the specified diagonal + // (d=0 - the main diagonal, + // >0 - a diagonal from the lower half, + // <0 - a diagonal from the upper half) + UMat diag(int d=0) const; + //! constructs a square diagonal matrix which main diagonal is vector "d" + static UMat diag(const UMat& d); + + //! returns deep copy of the matrix, i.e. the data is copied + UMat clone() const; + //! copies the matrix content to "m". + // It calls m.create(this->size(), this->type()). + void copyTo( OutputArray m ) const; + //! copies those matrix elements to "m" that are marked with non-zero mask elements. + void copyTo( OutputArray m, InputArray mask ) const; + //! converts matrix to another datatype with optional scalng. See cvConvertScale. + void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const; + + void assignTo( UMat& m, int type=-1 ) const; + + //! sets every matrix element to s + UMat& operator = (const Scalar& s); + //! sets some of the matrix elements to s, according to the mask + UMat& setTo(InputArray value, InputArray mask=noArray()); + //! creates alternative matrix header for the same data, with different + // number of channels and/or different number of rows. see cvReshape. + UMat reshape(int cn, int rows=0) const; + UMat reshape(int cn, int newndims, const int* newsz) const; + + //! matrix transposition by means of matrix expressions + UMat t() const; + //! matrix inversion by means of matrix expressions + UMat inv(int method=DECOMP_LU) const; + //! per-element matrix multiplication by means of matrix expressions + UMat mul(InputArray m, double scale=1) const; + + //! computes dot-product + double dot(InputArray m) const; + + //! Matlab-style matrix initialization + static UMat zeros(int rows, int cols, int type); + static UMat zeros(Size size, int type); + static UMat zeros(int ndims, const int* sz, int type); + static UMat ones(int rows, int cols, int type); + static UMat ones(Size size, int type); + static UMat ones(int ndims, const int* sz, int type); + static UMat eye(int rows, int cols, int type); + static UMat eye(Size size, int type); + + //! allocates new matrix data unless the matrix already has specified size and type. + // previous data is unreferenced if needed. + void create(int rows, int cols, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT); + void create(Size size, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT); + void create(int ndims, const int* sizes, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT); + + //! increases the reference counter; use with care to avoid memleaks + void addref(); + //! decreases reference counter; + // 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 UMat& m); + + //! locates matrix header within a parent matrix. See below + void locateROI( Size& wholeSize, Point& ofs ) const; + //! moves/resizes the current matrix ROI inside the parent matrix. + UMat& adjustROI( int dtop, int dbottom, int dleft, int dright ); + //! extracts a rectangular sub-matrix + // (this is a generalized form of row, rowRange etc.) + UMat operator()( Range rowRange, Range colRange ) const; + UMat operator()( const Rect& roi ) const; + UMat operator()( const Range* ranges ) const; + + //! returns true iff the matrix data is continuous + // (i.e. when there are no gaps between successive rows). + // similar to CV_IS_MAT_CONT(cvmat->type) + bool isContinuous() const; + + //! returns true if the matrix is a submatrix of another matrix + bool isSubmatrix() const; + + //! returns element size in bytes, + // similar to CV_ELEM_SIZE(cvmat->type) + size_t elemSize() const; + //! returns the size of element channel in bytes. + size_t elemSize1() const; + //! returns element type, similar to CV_MAT_TYPE(cvmat->type) + int type() const; + //! returns element type, similar to CV_MAT_DEPTH(cvmat->type) + int depth() const; + //! returns element type, similar to CV_MAT_CN(cvmat->type) + int channels() const; + //! returns step/elemSize1() + 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 N if the matrix is 1-channel (N x ptdim) or ptdim-channel (1 x N) or (N x 1); negative number otherwise + int checkVector(int elemChannels, int depth=-1, bool requireContinuous=true) const; + + void* handle(int accessFlags) const; + void ndoffset(size_t* ofs) const; + + enum { MAGIC_VAL = 0x42FF0000, AUTO_STEP = 0, CONTINUOUS_FLAG = CV_MAT_CONT_FLAG, SUBMATRIX_FLAG = CV_SUBMAT_FLAG }; + enum { MAGIC_MASK = 0xFFFF0000, TYPE_MASK = 0x00000FFF, DEPTH_MASK = 7 }; + + /*! includes several bit-fields: + - the magic signature + - continuity flag + - depth + - number of channels + */ + int flags; + //! the matrix dimensionality, >= 2 + int dims; + //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions + int rows, cols; -static inline Mat cvarrToMatND(const CvArr* arr, bool copyData=false, int coiMode=0) -{ - return cvarrToMat(arr, copyData, true, coiMode); -} + //! custom allocator + MatAllocator* allocator; + UMatUsageFlags usageFlags; // usage flags for allocator + //! and the standard allocator + static MatAllocator* getStdAllocator(); -///////////////////////////////////////////// SVD ////////////////////////////////////////////////////// + // black-box container of UMat data + UMatData* u; -inline SVD::SVD() {} -inline SVD::SVD( InputArray m, int flags ) { operator ()(m, flags); } -inline void SVD::solveZ( InputArray m, OutputArray _dst ) -{ - Mat mtx = m.getMat(); - SVD svd(mtx, (mtx.rows >= mtx.cols ? 0 : SVD::FULL_UV)); - _dst.create(svd.vt.cols, 1, svd.vt.type()); - Mat dst = _dst.getMat(); - svd.vt.row(svd.vt.rows-1).reshape(1,svd.vt.cols).copyTo(dst); -} - -template inline void - SVD::compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w, Matx<_Tp, m, nm>& u, Matx<_Tp, n, nm>& vt ) -{ - assert( nm == MIN(m, n)); - Mat _a(a, false), _u(u, false), _w(w, false), _vt(vt, false); - SVD::compute(_a, _w, _u, _vt); - CV_Assert(_w.data == (uchar*)&w.val[0] && _u.data == (uchar*)&u.val[0] && _vt.data == (uchar*)&vt.val[0]); -} - -template inline void -SVD::compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w ) -{ - assert( nm == MIN(m, n)); - Mat _a(a, false), _w(w, false); - SVD::compute(_a, _w); - CV_Assert(_w.data == (uchar*)&w.val[0]); -} - -template inline void -SVD::backSubst( const Matx<_Tp, nm, 1>& w, const Matx<_Tp, m, nm>& u, - const Matx<_Tp, n, nm>& vt, const Matx<_Tp, m, nb>& rhs, - Matx<_Tp, n, nb>& dst ) -{ - assert( nm == MIN(m, n)); - Mat _u(u, false), _w(w, false), _vt(vt, false), _rhs(rhs, false), _dst(dst, false); - SVD::backSubst(_w, _u, _vt, _rhs, _dst); - CV_Assert(_dst.data == (uchar*)&dst.val[0]); -} + // offset of the submatrix (or 0) + size_t offset; -///////////////////////////////// Mat_<_Tp> //////////////////////////////////// + MatSize size; + MatStep step; -template inline Mat_<_Tp>::Mat_() - : Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; } +protected: +}; -template inline Mat_<_Tp>::Mat_(int _rows, int _cols) - : Mat(_rows, _cols, DataType<_Tp>::type) {} -template inline Mat_<_Tp>::Mat_(int _rows, int _cols, const _Tp& value) - : Mat(_rows, _cols, DataType<_Tp>::type) { *this = value; } +/////////////////////////// multi-dimensional sparse matrix ////////////////////////// + +/*! + Sparse matrix class. + + The class represents multi-dimensional sparse numerical arrays. Such a sparse array can store 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, + so that the search time remains O(1) in average. Elements can be accessed using the following methods: + +
    +
  1. Query operations: cv::SparseMat::ptr() and the higher-level cv::SparseMat::ref(), + cv::SparseMat::value() and cv::SparseMat::find, for example: + \code + const int dims = 5; + int size[] = {10, 10, 10, 10, 10}; + SparseMat sparse_mat(dims, size, CV_32F); + for(int i = 0; i < 1000; i++) + { + int idx[dims]; + for(int k = 0; k < dims; k++) + idx[k] = rand()%sparse_mat.size(k); + sparse_mat.ref(idx) += 1.f; + } + \endcode + +
  2. 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. + SparseMatConstIterator_ + it = sparse_mat.begin(), + it_end = sparse_mat.end(); + double s = 0; + int dims = sparse_mat.dims(); + for(; it != it_end; ++it) + { + // print element indices and the element value + const Node* n = it.node(); + printf("(") + for(int i = 0; i < dims; i++) + printf("%3d%c", n->idx[i], i < dims-1 ? ',' : ')'); + printf(": %f\n", *it); + s += *it; + } + printf("Element sum is %g\n", s); + \endcode + If you run this loop, you will notice that elements are enumerated + in no any logical order (lexicographical etc.), + they come in the same order as they stored in the hash table, i.e. semi-randomly. + + You may collect pointers to the nodes and sort them to get the proper ordering. + Note, however, that pointers to the nodes may become invalid when you add more + elements to the matrix; this is because of possible buffer reallocation. + +
  3. A combination of the above 2 methods when you need to process 2 or more sparse + matrices simultaneously, e.g. this is how you can compute unnormalized + cross-correlation of the 2 floating-point sparse matrices: + \code + double crossCorr(const SparseMat& a, const SparseMat& b) + { + const SparseMat *_a = &a, *_b = &b; + // if b contains less elements than a, + // it's faster to iterate through b + if(_a->nzcount() > _b->nzcount()) + std::swap(_a, _b); + SparseMatConstIterator_ it = _a->begin(), + it_end = _a->end(); + double ccorr = 0; + for(; it != it_end; ++it) + { + // take the next element from the first matrix + float avalue = *it; + const Node* anode = it.node(); + // and try to find element with the same index in the second matrix. + // since the hash value depends only on the element index, + // we reuse hashvalue stored in the node + float bvalue = _b->value(anode->idx,&anode->hashval); + ccorr += avalue*bvalue; + } + return ccorr; + } + \endcode +
+*/ +class CV_EXPORTS SparseMat +{ +public: + typedef SparseMatIterator iterator; + typedef SparseMatConstIterator const_iterator; -template inline Mat_<_Tp>::Mat_(Size _sz) - : Mat(_sz.height, _sz.width, DataType<_Tp>::type) {} + enum { MAGIC_VAL=0x42FD0000, MAX_DIM=32, HASH_SCALE=0x5bd1e995, HASH_BIT=0x80000000 }; -template inline Mat_<_Tp>::Mat_(Size _sz, const _Tp& value) - : Mat(_sz.height, _sz.width, DataType<_Tp>::type) { *this = value; } + //! the sparse matrix header + struct CV_EXPORTS Hdr + { + Hdr(int _dims, const int* _sizes, int _type); + void clear(); + int refcount; + int dims; + int valueOffset; + size_t nodeSize; + size_t nodeCount; + size_t freeList; + std::vector pool; + std::vector hashtab; + int size[MAX_DIM]; + }; + + //! sparse matrix node - element of a hash table + struct CV_EXPORTS Node + { + //! hash value + size_t hashval; + //! index of the next node in the same hash table entry + size_t next; + //! index of the matrix element + int idx[MAX_DIM]; + }; + + //! default constructor + SparseMat(); + //! creates matrix of the specified size and type + SparseMat(int dims, const int* _sizes, int _type); + //! copy constructor + SparseMat(const SparseMat& m); + //! converts dense 2d matrix to the sparse form + /*! + \param m the input matrix + */ + explicit SparseMat(const Mat& m); + //! converts old-style sparse matrix to the new-style. All the data is copied + //SparseMat(const CvSparseMat* m); + //! the destructor + ~SparseMat(); + + //! assignment operator. This is O(1) operation, i.e. no data is copied + SparseMat& operator = (const SparseMat& m); + //! equivalent to the corresponding constructor + SparseMat& operator = (const Mat& 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 sparse matrix to dense matrix. + void copyTo( Mat& 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. + /*! + @param [out] m - output matrix; if it does not have a proper size or type before the operation, + it is reallocated + @param [in] rtype – desired output matrix type or, rather, the depth since the number of channels + are the same as the input has; if rtype is negative, the output matrix will have the + same type as the input. + @param [in] alpha – optional scale factor + @param [in] beta – optional delta added to the scaled values + */ + void convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const; + + // not used now + void assignTo( SparseMat& m, int type=-1 ) const; + + //! reallocates sparse matrix. + /*! + If the matrix already had the proper size and type, + it is simply cleared with clear(), otherwise, + the old matrix is released (using release()) and the new one is allocated. + */ + void create(int dims, const int* _sizes, int _type); + //! sets all the sparse matrix elements to 0, which means clearing the hash table. + void clear(); + //! manually increments the reference counter to the header. + void addref(); + // decrements the header reference counter. When the counter reaches 0, the header and all the underlying data are deallocated. + void release(); + + //! converts sparse matrix to the old-style representation; all the elements are copied. + //operator CvSparseMat*() const; + //! returns the size of each element in bytes (not including the overhead - the space occupied by SparseMat::Node elements) + size_t elemSize() const; + //! returns elemSize()/channels() + size_t elemSize1() const; + + //! returns type of sparse matrix elements + int type() const; + //! returns the depth of sparse matrix elements + int depth() const; + //! returns the number of channels + int channels() const; + + //! returns the array of sizes, or NULL if the matrix is not allocated + const int* size() const; + //! returns the size of i-th matrix dimension (or 0) + int size(int i) const; + //! returns the matrix dimensionality + int dims() const; + //! returns the number of non-zero elements (=the number of hash table nodes) + size_t nzcount() const; + + //! computes the element hash value (1D case) + size_t hash(int i0) const; + //! computes the element hash value (2D case) + size_t hash(int i0, int i1) const; + //! computes the element hash value (3D case) + size_t hash(int i0, int i1, int i2) const; + //! computes the element hash value (nD case) + size_t hash(const int* idx) const; + + //@{ + /*! + specialized variants for 1D, 2D, 3D cases and the generic_type one for n-D case. + + return pointer to the matrix element. +
    +
  • if the element is there (it's non-zero), the pointer to it is returned +
  • if it's not there and createMissing=false, NULL pointer is returned +
  • if it's not there and createMissing=true, then the new element + is created and initialized with 0. Pointer to it is returned +
  • if the optional hashval pointer is not NULL, the element hash value is + not computed, but *hashval is taken instead. +
+ */ + //! returns pointer to the specified element (1D case) + uchar* ptr(int i0, bool createMissing, size_t* hashval=0); + //! returns pointer to the specified element (2D case) + uchar* ptr(int i0, int i1, bool createMissing, size_t* hashval=0); + //! returns pointer to the specified element (3D case) + uchar* ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval=0); + //! returns pointer to the specified element (nD case) + uchar* ptr(const int* idx, bool createMissing, size_t* hashval=0); + //@} + + //@{ + /*! + return read-write reference to the specified sparse matrix element. + + ref<_Tp>(i0,...[,hashval]) is equivalent to *(_Tp*)ptr(i0,...,true[,hashval]). + The methods always return a valid reference. + If the element did not exist, it is created and initialiazed with 0. + */ + //! returns reference to the specified element (1D case) + template _Tp& ref(int i0, size_t* hashval=0); + //! returns reference to the specified element (2D case) + template _Tp& ref(int i0, int i1, size_t* hashval=0); + //! returns reference to the specified element (3D case) + template _Tp& ref(int i0, int i1, int i2, size_t* hashval=0); + //! returns reference to the specified element (nD case) + template _Tp& ref(const int* idx, size_t* hashval=0); + //@} + + //@{ + /*! + return value of the specified sparse matrix element. + + value<_Tp>(i0,...[,hashval]) is equivalent + + \code + { const _Tp* p = find<_Tp>(i0,...[,hashval]); return p ? *p : _Tp(); } + \endcode + + That is, if the element did not exist, the methods return 0. + */ + //! returns value of the specified element (1D case) + template _Tp value(int i0, size_t* hashval=0) const; + //! returns value of the specified element (2D case) + template _Tp value(int i0, int i1, size_t* hashval=0) const; + //! returns value of the specified element (3D case) + template _Tp value(int i0, int i1, int i2, size_t* hashval=0) const; + //! returns value of the specified element (nD case) + template _Tp value(const int* idx, size_t* hashval=0) const; + //@} + + //@{ + /*! + Return pointer to the specified sparse matrix element if it exists + + find<_Tp>(i0,...[,hashval]) is equivalent to (_const Tp*)ptr(i0,...false[,hashval]). + + If the specified element does not exist, the methods return NULL. + */ + //! returns pointer to the specified element (1D case) + template const _Tp* find(int i0, size_t* hashval=0) const; + //! returns pointer to the specified element (2D case) + template const _Tp* find(int i0, int i1, size_t* hashval=0) const; + //! returns pointer to the specified element (3D case) + template const _Tp* find(int i0, int i1, int i2, size_t* hashval=0) const; + //! returns pointer to the specified element (nD case) + template const _Tp* find(const int* idx, size_t* hashval=0) const; + + //! erases the specified element (2D case) + void erase(int i0, int i1, size_t* hashval=0); + //! erases the specified element (3D case) + void erase(int i0, int i1, int i2, size_t* hashval=0); + //! erases the specified element (nD case) + void erase(const int* idx, size_t* hashval=0); + + //@{ + /*! + return the sparse matrix iterator pointing to the first sparse matrix element + */ + //! returns the sparse matrix iterator at the matrix beginning + SparseMatIterator begin(); + //! returns the sparse matrix iterator at the matrix beginning + template SparseMatIterator_<_Tp> begin(); + //! returns the read-only sparse matrix iterator at the matrix beginning + SparseMatConstIterator begin() const; + //! returns the read-only sparse matrix iterator at the matrix beginning + template SparseMatConstIterator_<_Tp> begin() const; + //@} + /*! + return the sparse matrix iterator pointing to the element following the last sparse matrix element + */ + //! returns the sparse matrix iterator at the matrix end + SparseMatIterator end(); + //! returns the read-only sparse matrix iterator at the matrix end + SparseMatConstIterator end() const; + //! returns the typed sparse matrix iterator at the matrix end + template SparseMatIterator_<_Tp> end(); + //! returns the typed read-only sparse matrix iterator at the matrix end + template SparseMatConstIterator_<_Tp> end() const; + + //! returns the value stored in the sparse martix node + template _Tp& value(Node* n); + //! returns the value stored in the sparse martix node + template const _Tp& value(const Node* n) const; + + ////////////// some internal-use methods /////////////// + Node* node(size_t nidx); + const Node* node(size_t nidx) const; + + uchar* newNode(const int* idx, size_t hashval); + void removeNode(size_t hidx, size_t nidx, size_t previdx); + void resizeHashTab(size_t newsize); -template inline Mat_<_Tp>::Mat_(int _dims, const int* _sz) - : Mat(_dims, _sz, DataType<_Tp>::type) {} + int flags; + Hdr* hdr; +}; -template inline Mat_<_Tp>::Mat_(int _dims, const int* _sz, const _Tp& _s) - : Mat(_dims, _sz, DataType<_Tp>::type, Scalar(_s)) {} -template inline Mat_<_Tp>::Mat_(const Mat_<_Tp>& m, const Range* ranges) - : Mat(m, ranges) {} -template inline Mat_<_Tp>::Mat_(const Mat& m) - : Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; *this = m; } +///////////////////////////////// SparseMat_<_Tp> //////////////////////////////////// -template inline Mat_<_Tp>::Mat_(const Mat_& m) - : Mat(m) {} +/*! + The Template Sparse Matrix class derived from cv::SparseMat -template inline Mat_<_Tp>::Mat_(int _rows, int _cols, _Tp* _data, size_t steps) - : Mat(_rows, _cols, DataType<_Tp>::type, _data, steps) {} + The class provides slightly more convenient operations for accessing elements. -template inline Mat_<_Tp>::Mat_(const Mat_& m, const Range& _rowRange, const Range& _colRange) - : Mat(m, _rowRange, _colRange) {} + \code + SparseMat m; + ... + SparseMat_ m_ = (SparseMat_&)m; + m_.ref(1)++; // equivalent to m.ref(1)++; + m_.ref(2) += m_(3); // equivalent to m.ref(2) += m.value(3); + \endcode +*/ +template class SparseMat_ : public SparseMat +{ +public: + typedef SparseMatIterator_<_Tp> iterator; + typedef SparseMatConstIterator_<_Tp> const_iterator; + + //! the default constructor + SparseMat_(); + //! the full constructor equivelent to SparseMat(dims, _sizes, DataType<_Tp>::type) + SparseMat_(int dims, const int* _sizes); + //! the copy constructor. If DataType<_Tp>.type != m.type(), the m elements are converted + SparseMat_(const SparseMat& m); + //! the copy constructor. This is O(1) operation - no data is copied + SparseMat_(const SparseMat_& m); + //! converts dense matrix to the sparse form + SparseMat_(const Mat& 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 matrix to the sparse form + SparseMat_& operator = (const Mat& m); + + //! makes full copy of the matrix. All the elements are duplicated + SparseMat_ clone() const; + //! equivalent to cv::SparseMat::create(dims, _sizes, DataType<_Tp>::type) + void create(int dims, const int* _sizes); + //! converts sparse matrix to the old-style CvSparseMat. All the elements are copied + //operator CvSparseMat*() const; + + //! returns type of the matrix elements + int type() const; + //! returns depth of the matrix elements + int depth() const; + //! returns the number of channels in each matrix element + int channels() const; + + //! equivalent to SparseMat::ref<_Tp>(i0, hashval) + _Tp& ref(int i0, size_t* hashval=0); + //! equivalent to SparseMat::ref<_Tp>(i0, i1, hashval) + _Tp& ref(int i0, int i1, size_t* hashval=0); + //! equivalent to SparseMat::ref<_Tp>(i0, i1, i2, hashval) + _Tp& ref(int i0, int i1, int i2, size_t* hashval=0); + //! equivalent to SparseMat::ref<_Tp>(idx, hashval) + _Tp& ref(const int* idx, size_t* hashval=0); + + //! equivalent to SparseMat::value<_Tp>(i0, hashval) + _Tp operator()(int i0, size_t* hashval=0) const; + //! equivalent to SparseMat::value<_Tp>(i0, i1, hashval) + _Tp operator()(int i0, int i1, size_t* hashval=0) const; + //! equivalent to SparseMat::value<_Tp>(i0, i1, i2, hashval) + _Tp operator()(int i0, int i1, int i2, size_t* hashval=0) const; + //! equivalent to SparseMat::value<_Tp>(idx, hashval) + _Tp operator()(const int* idx, size_t* hashval=0) const; + + //! returns sparse matrix iterator pointing to the first sparse matrix element + SparseMatIterator_<_Tp> begin(); + //! returns read-only sparse matrix iterator pointing to the first sparse matrix element + SparseMatConstIterator_<_Tp> begin() const; + //! returns sparse matrix iterator pointing to the element following the last sparse matrix element + SparseMatIterator_<_Tp> end(); + //! returns read-only sparse matrix iterator pointing to the element following the last sparse matrix element + SparseMatConstIterator_<_Tp> end() const; +}; -template inline Mat_<_Tp>::Mat_(const Mat_& m, const Rect& roi) - : Mat(m, roi) {} -template template inline - Mat_<_Tp>::Mat_(const Vec::channel_type, n>& vec, bool copyData) - : Mat(n/DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&vec) -{ - CV_Assert(n%DataType<_Tp>::channels == 0); - if( copyData ) - *this = clone(); -} - -template template inline - Mat_<_Tp>::Mat_(const Matx::channel_type,m,n>& M, bool copyData) - : Mat(m, n/DataType<_Tp>::channels, DataType<_Tp>::type, (void*)&M) -{ - CV_Assert(n % DataType<_Tp>::channels == 0); - if( copyData ) - *this = clone(); -} -template inline Mat_<_Tp>::Mat_(const Point_::channel_type>& pt, bool copyData) - : Mat(2/DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&pt) -{ - CV_Assert(2 % DataType<_Tp>::channels == 0); - if( copyData ) - *this = clone(); -} +////////////////////////////////// MatConstIterator ////////////////////////////////// -template inline Mat_<_Tp>::Mat_(const Point3_::channel_type>& pt, bool copyData) - : Mat(3/DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&pt) +class CV_EXPORTS MatConstIterator { - CV_Assert(3 % DataType<_Tp>::channels == 0); - if( copyData ) - *this = clone(); -} +public: + typedef uchar* value_type; + typedef ptrdiff_t difference_type; + typedef const uchar** pointer; + typedef uchar* reference; -template inline Mat_<_Tp>::Mat_(const MatCommaInitializer_<_Tp>& commaInitializer) - : Mat(commaInitializer) {} +#ifndef OPENCV_NOSTL + typedef std::random_access_iterator_tag iterator_category; +#endif -template inline Mat_<_Tp>::Mat_(const vector<_Tp>& vec, bool copyData) - : Mat(vec, copyData) {} + //! 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 + const uchar* operator *() const; + //! returns the i-th matrix element, relative to the current + const 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; + const uchar* ptr; + const uchar* sliceStart; + const uchar* sliceEnd; +}; -template inline Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat& 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, m.dims, 0)); - } - CV_DbgAssert(DataType<_Tp>::channels == m.channels()); - m.convertTo(*this, type()); - return *this; -} - -template inline Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat_& m) -{ - Mat::operator=(m); - return *this; -} -template inline Mat_<_Tp>& Mat_<_Tp>::operator = (const _Tp& s) -{ - typedef typename DataType<_Tp>::vec_type VT; - Mat::operator=(Scalar((const VT&)s)); - return *this; -} -template inline void Mat_<_Tp>::create(int _rows, int _cols) -{ - Mat::create(_rows, _cols, DataType<_Tp>::type); -} +////////////////////////////////// MatConstIterator_ ///////////////////////////////// -template inline void Mat_<_Tp>::create(Size _sz) +/*! + Matrix read-only iterator + */ +template +class MatConstIterator_ : public MatConstIterator { - Mat::create(_sz, DataType<_Tp>::type); -} +public: + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; -template inline void Mat_<_Tp>::create(int _dims, const int* _sz) -{ - Mat::create(_dims, _sz, DataType<_Tp>::type); -} +#ifndef OPENCV_NOSTL + typedef std::random_access_iterator_tag iterator_category; +#endif + //! default constructor + MatConstIterator_(); + //! constructor that sets the iterator to the beginning of the matrix + MatConstIterator_(const Mat_<_Tp>* _m); + //! constructor that sets the iterator to the specified element of the matrix + 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); + + //! copy operator + MatConstIterator_& operator = (const MatConstIterator_& it); + //! returns the current matrix element + _Tp operator *() const; + //! returns the i-th matrix element, relative to the current + _Tp 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; +}; -template inline Mat_<_Tp> Mat_<_Tp>::cross(const Mat_& m) const -{ return Mat_<_Tp>(Mat::cross(m)); } -template template inline Mat_<_Tp>::operator Mat_() const -{ return Mat_(*this); } -template inline Mat_<_Tp> Mat_<_Tp>::row(int y) const -{ return Mat_(*this, Range(y, y+1), Range::all()); } -template inline Mat_<_Tp> Mat_<_Tp>::col(int x) const -{ return Mat_(*this, Range::all(), Range(x, x+1)); } -template inline Mat_<_Tp> Mat_<_Tp>::diag(int d) const -{ return Mat_(Mat::diag(d)); } -template inline Mat_<_Tp> Mat_<_Tp>::clone() const -{ return Mat_(Mat::clone()); } +//////////////////////////////////// MatIterator_ //////////////////////////////////// -template inline size_t Mat_<_Tp>::elemSize() const +/*! + Matrix read-write iterator +*/ +template +class MatIterator_ : public MatConstIterator_<_Tp> { - CV_DbgAssert( Mat::elemSize() == sizeof(_Tp) ); - return sizeof(_Tp); -} +public: + typedef _Tp* pointer; + typedef _Tp& reference; -template inline size_t Mat_<_Tp>::elemSize1() const -{ - CV_DbgAssert( Mat::elemSize1() == sizeof(_Tp)/DataType<_Tp>::channels ); - return sizeof(_Tp)/DataType<_Tp>::channels; -} -template inline int Mat_<_Tp>::type() const -{ - CV_DbgAssert( Mat::type() == DataType<_Tp>::type ); - return DataType<_Tp>::type; -} -template inline int Mat_<_Tp>::depth() const -{ - CV_DbgAssert( Mat::depth() == DataType<_Tp>::depth ); - return DataType<_Tp>::depth; -} -template inline int Mat_<_Tp>::channels() const -{ - CV_DbgAssert( Mat::channels() == DataType<_Tp>::channels ); - return DataType<_Tp>::channels; -} -template inline size_t Mat_<_Tp>::stepT(int i) const { return step.p[i]/elemSize(); } -template inline size_t Mat_<_Tp>::step1(int i) const { return step.p[i]/elemSize1(); } +#ifndef OPENCV_NOSTL + typedef std::random_access_iterator_tag iterator_category; +#endif -template inline Mat_<_Tp>& Mat_<_Tp>::adjustROI( int dtop, int dbottom, int dleft, int dright ) -{ return (Mat_<_Tp>&)(Mat::adjustROI(dtop, dbottom, dleft, dright)); } + //! the default constructor + MatIterator_(); + //! constructor that sets the iterator to the beginning of the matrix + MatIterator_(Mat_<_Tp>* _m); + //! constructor that sets the iterator to the specified element of the matrix + MatIterator_(Mat_<_Tp>* _m, int _row, int _col=0); + //! constructor that sets the iterator to the specified element of the matrix + MatIterator_(Mat_<_Tp>* _m, Point _pt); + //! constructor that sets the iterator to the specified element of the matrix + MatIterator_(Mat_<_Tp>* _m, const int* _idx); + //! copy constructor + MatIterator_(const MatIterator_& it); + //! copy operator + MatIterator_& operator = (const MatIterator_<_Tp>& it ); + + //! returns the current matrix element + _Tp& operator *() const; + //! returns the i-th matrix element, relative to the current + _Tp& operator [](ptrdiff_t i) const; + + //! shifts the iterator forward by the specified number of elements + MatIterator_& operator += (ptrdiff_t ofs); + //! shifts the iterator backward by the specified number of elements + MatIterator_& operator -= (ptrdiff_t ofs); + //! decrements the iterator + MatIterator_& operator --(); + //! decrements the iterator + MatIterator_ operator --(int); + //! increments the iterator + MatIterator_& operator ++(); + //! increments the iterator + MatIterator_ operator ++(int); +}; -template inline Mat_<_Tp> Mat_<_Tp>::operator()( const Range& _rowRange, const Range& _colRange ) const -{ return Mat_<_Tp>(*this, _rowRange, _colRange); } -template inline Mat_<_Tp> Mat_<_Tp>::operator()( const Rect& roi ) const -{ return Mat_<_Tp>(*this, roi); } -template inline Mat_<_Tp> Mat_<_Tp>::operator()( const Range* ranges ) const -{ return Mat_<_Tp>(*this, ranges); } +/////////////////////////////// SparseMatConstIterator /////////////////////////////// -template inline _Tp* Mat_<_Tp>::operator [](int y) -{ return (_Tp*)ptr(y); } -template inline const _Tp* Mat_<_Tp>::operator [](int y) const -{ return (const _Tp*)ptr(y); } +/*! + Read-Only Sparse Matrix Iterator. + Here is how to use the iterator to compute the sum of floating-point sparse matrix elements: -template inline _Tp& Mat_<_Tp>::operator ()(int i0, int i1) -{ - CV_DbgAssert( dims <= 2 && data && - (unsigned)i0 < (unsigned)size.p[0] && - (unsigned)i1 < (unsigned)size.p[1] && - type() == DataType<_Tp>::type ); - return ((_Tp*)(data + step.p[0]*i0))[i1]; -} - -template inline const _Tp& Mat_<_Tp>::operator ()(int 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 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 inline const _Tp& Mat_<_Tp>::operator ()(Point pt) const -{ - 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.p[0]*pt.y))[pt.x]; -} - -template inline _Tp& Mat_<_Tp>::operator ()(const int* idx) + \code + SparseMatConstIterator it = m.begin(), it_end = m.end(); + double s = 0; + CV_Assert( m.type() == CV_32F ); + for( ; it != it_end; ++it ) + s += it.value(); + \endcode +*/ +class CV_EXPORTS SparseMatConstIterator { - return Mat::at<_Tp>(idx); -} +public: + //! the default constructor + SparseMatConstIterator(); + //! the full constructor setting the iterator to the first sparse matrix element + SparseMatConstIterator(const SparseMat* _m); + //! the copy constructor + SparseMatConstIterator(const SparseMatConstIterator& it); + + //! the assignment operator + SparseMatConstIterator& operator = (const SparseMatConstIterator& it); + + //! template method returning the current matrix element + template const _Tp& value() const; + //! returns the current node of the sparse matrix. it.node->idx is the current element index + const SparseMat::Node* node() const; + + //! moves iterator to the previous element + SparseMatConstIterator& operator --(); + //! moves iterator to the previous element + SparseMatConstIterator operator --(int); + //! moves iterator to the next element + SparseMatConstIterator& operator ++(); + //! moves iterator to the next element + SparseMatConstIterator operator ++(int); + + //! moves iterator to the element after the last element + void seekEnd(); + + const SparseMat* m; + size_t hashidx; + uchar* ptr; +}; -template inline const _Tp& Mat_<_Tp>::operator ()(const int* idx) const -{ - return Mat::at<_Tp>(idx); -} -template template inline _Tp& Mat_<_Tp>::operator ()(const Vec& idx) -{ - return Mat::at<_Tp>(idx); -} -template template inline const _Tp& Mat_<_Tp>::operator ()(const Vec& idx) const -{ - return Mat::at<_Tp>(idx); -} +////////////////////////////////// SparseMatIterator ///////////////////////////////// -template inline _Tp& Mat_<_Tp>::operator ()(int i0) -{ - return this->at<_Tp>(i0); -} +/*! + Read-write Sparse Matrix Iterator -template inline const _Tp& Mat_<_Tp>::operator ()(int i0) const + The class is similar to cv::SparseMatConstIterator, + but can be used for in-place modification of the matrix elements. +*/ +class CV_EXPORTS SparseMatIterator : public SparseMatConstIterator { - return this->at<_Tp>(i0); -} +public: + //! the default constructor + SparseMatIterator(); + //! the full constructor setting the iterator to the first sparse matrix element + SparseMatIterator(SparseMat* _m); + //! the full constructor setting the iterator to the specified sparse matrix element + SparseMatIterator(SparseMat* _m, const int* idx); + //! the copy constructor + SparseMatIterator(const SparseMatIterator& it); + + //! the assignment operator + SparseMatIterator& operator = (const SparseMatIterator& it); + //! returns read-write reference to the current sparse matrix element + template _Tp& value() const; + //! returns pointer to the current sparse matrix node. it.node->idx is the index of the current element (do not modify it!) + SparseMat::Node* node() const; + + //! moves iterator to the next element + SparseMatIterator& operator ++(); + //! moves iterator to the next element + SparseMatIterator operator ++(int); +}; -template inline _Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2) -{ - return this->at<_Tp>(i0, i1, i2); -} -template inline const _Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2) const -{ - return this->at<_Tp>(i0, i1, i2); -} +/////////////////////////////// SparseMatConstIterator_ ////////////////////////////// -template inline Mat_<_Tp>::operator vector<_Tp>() const -{ - vector<_Tp> v; - copyTo(v); - return v; -} +/*! + Template Read-Only Sparse Matrix Iterator Class. -template template inline Mat_<_Tp>::operator Vec::channel_type, n>() const + This is the derived from SparseMatConstIterator class that + introduces more convenient operator *() for accessing the current element. +*/ +template class SparseMatConstIterator_ : public SparseMatConstIterator { - CV_Assert(n % DataType<_Tp>::channels == 0); - return this->Mat::operator Vec::channel_type, n>(); -} +public: -template template inline Mat_<_Tp>::operator Matx::channel_type, m, n>() const -{ - CV_Assert(n % DataType<_Tp>::channels == 0); +#ifndef OPENCV_NOSTL + typedef std::forward_iterator_tag iterator_category; +#endif - Matx::channel_type, m, n> res = this->Mat::operator Matx::channel_type, m, n>(); - return res; -} + //! the default constructor + SparseMatConstIterator_(); + //! the full constructor setting the iterator to the first sparse matrix element + SparseMatConstIterator_(const SparseMat_<_Tp>* _m); + SparseMatConstIterator_(const SparseMat* _m); + //! the copy constructor + SparseMatConstIterator_(const SparseMatConstIterator_& it); + + //! the assignment operator + SparseMatConstIterator_& operator = (const SparseMatConstIterator_& it); + //! the element access operator + const _Tp& operator *() const; + + //! moves iterator to the next element + SparseMatConstIterator_& operator ++(); + //! moves iterator to the next element + SparseMatConstIterator_ operator ++(int); +}; -template inline void -process( const Mat_& m1, Mat_& m2, Op op ) -{ - int y, x, rows = m1.rows, cols = m1.cols; - CV_DbgAssert( m1.size() == m2.size() ); - for( y = 0; y < rows; y++ ) - { - const T1* src = m1[y]; - T2* dst = m2[y]; +///////////////////////////////// SparseMatIterator_ ///////////////////////////////// - for( x = 0; x < cols; x++ ) - dst[x] = op(src[x]); - } -} +/*! + Template Read-Write Sparse Matrix Iterator Class. -template inline void -process( const Mat_& m1, const Mat_& m2, Mat_& m3, Op op ) + This is the derived from cv::SparseMatConstIterator_ class that + introduces more convenient operator *() for accessing the current element. +*/ +template class SparseMatIterator_ : public SparseMatConstIterator_<_Tp> { - int y, x, rows = m1.rows, cols = m1.cols; - - CV_DbgAssert( m1.size() == m2.size() ); - - for( y = 0; y < rows; y++ ) - { - const T1* src1 = m1[y]; - const T2* src2 = m2[y]; - T3* dst = m3[y]; - - for( x = 0; x < cols; x++ ) - dst[x] = op( src1[x], src2[x] ); - } -} - - -/////////////////////////////// Input/Output Arrays ///////////////////////////////// - -template inline _InputArray::_InputArray(const vector<_Tp>& vec) - : flags(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {} - -template inline _InputArray::_InputArray(const vector >& vec) - : flags(FIXED_TYPE + STD_VECTOR_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {} - -template inline _InputArray::_InputArray(const vector >& vec) - : flags(FIXED_TYPE + STD_VECTOR_MAT + DataType<_Tp>::type), obj((void*)&vec) {} +public: -template inline _InputArray::_InputArray(const Matx<_Tp, m, n>& mtx) - : flags(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type), obj((void*)&mtx), sz(n, m) {} +#ifndef OPENCV_NOSTL + typedef std::forward_iterator_tag iterator_category; +#endif -template inline _InputArray::_InputArray(const _Tp* vec, int n) - : flags(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type), obj((void*)vec), sz(n, 1) {} + //! the default constructor + SparseMatIterator_(); + //! the full constructor setting the iterator to the first sparse matrix element + SparseMatIterator_(SparseMat_<_Tp>* _m); + SparseMatIterator_(SparseMat* _m); + //! the copy constructor + SparseMatIterator_(const SparseMatIterator_& it); + + //! the assignment operator + SparseMatIterator_& operator = (const SparseMatIterator_& it); + //! returns the reference to the current element + _Tp& operator *() const; + + //! moves the iterator to the next element + SparseMatIterator_& operator ++(); + //! moves the iterator to the next element + SparseMatIterator_ operator ++(int); +}; -inline _InputArray::_InputArray(const Scalar& s) - : flags(FIXED_TYPE + FIXED_SIZE + MATX + CV_64F), obj((void*)&s), sz(1, 4) {} -template inline _InputArray::_InputArray(const Mat_<_Tp>& m) - : flags(FIXED_TYPE + MAT + DataType<_Tp>::type), obj((void*)&m) {} -template inline _OutputArray::_OutputArray(vector<_Tp>& vec) - : _InputArray(vec) {} -template inline _OutputArray::_OutputArray(vector >& vec) - : _InputArray(vec) {} -template inline _OutputArray::_OutputArray(vector >& vec) - : _InputArray(vec) {} -template inline _OutputArray::_OutputArray(Mat_<_Tp>& m) - : _InputArray(m) {} -template inline _OutputArray::_OutputArray(Matx<_Tp, m, n>& mtx) - : _InputArray(mtx) {} -template inline _OutputArray::_OutputArray(_Tp* vec, int n) - : _InputArray(vec, n) {} +/////////////////////////////////// NAryMatIterator ////////////////////////////////// + +/*! + n-Dimensional Dense Matrix Iterator Class. + + The class cv::NAryMatIterator 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. + + Here is the example on how the iterator can be used to normalize 3D histogram: + + \code + 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 + 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 = 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 Mat + double s = sum(hist)[0]; + hist.convertTo(hist, hist.type(), 1./s, 0); + #else + // and this is even shorter one + // (assuming that the histogram elements are non-negative) + normalize(hist, hist, 1, 0, NORM_L1); + #endif + } + \endcode + + You can iterate through several matrices simultaneously as long as they have the same geometry + (dimensionality and all the dimension sizes are the same), which is useful for binary + and n-ary operations on such matrices. Just pass those matrices to cv::MatNDIterator. + Then, during the iteration it.planes[0], it.planes[1], ... will + be the slices of the corresponding matrices +*/ +class CV_EXPORTS NAryMatIterator +{ +public: + //! the default constructor + NAryMatIterator(); + //! the full constructor taking arbitrary number of n-dim matrices + NAryMatIterator(const Mat** arrays, uchar** ptrs, int narrays=-1); + //! the full constructor taking arbitrary number of n-dim matrices + NAryMatIterator(const Mat** arrays, Mat* planes, int narrays=-1); + //! the separate iterator initialization method + void init(const Mat** arrays, Mat* planes, uchar** ptrs, int narrays=-1); + + //! proceeds to the next plane of every iterated matrix + NAryMatIterator& operator ++(); + //! proceeds to the next plane of every iterated matrix (postfix increment operator) + NAryMatIterator operator ++(int); + + //! the iterated arrays + const Mat** arrays; + //! the current planes + Mat* planes; + //! data pointers + uchar** ptrs; + //! the number of arrays + int narrays; + //! the number of hyper-planes that the iterator steps through + size_t nplanes; + //! the size of each segment (in elements) + size_t size; +protected: + int iterdepth; + size_t idx; +}; -template inline _OutputArray::_OutputArray(const vector<_Tp>& vec) - : _InputArray(vec) {flags |= FIXED_SIZE;} -template inline _OutputArray::_OutputArray(const vector >& vec) - : _InputArray(vec) {flags |= FIXED_SIZE;} -template inline _OutputArray::_OutputArray(const vector >& vec) - : _InputArray(vec) {flags |= FIXED_SIZE;} -template inline _OutputArray::_OutputArray(const Mat_<_Tp>& m) - : _InputArray(m) {flags |= FIXED_SIZE;} -template inline _OutputArray::_OutputArray(const Matx<_Tp, m, n>& mtx) - : _InputArray(mtx) {} -template inline _OutputArray::_OutputArray(const _Tp* vec, int n) - : _InputArray(vec, n) {} -//////////////////////////////////// Matrix Expressions ///////////////////////////////////////// +///////////////////////////////// Matrix Expressions ///////////////////////////////// class CV_EXPORTS MatOp { public: - MatOp() {}; - virtual ~MatOp() {}; + MatOp(); + virtual ~MatOp(); virtual bool elementWise(const MatExpr& expr) const; virtual void assign(const MatExpr& expr, Mat& m, int type=-1) const = 0; @@ -1213,41 +2253,31 @@ public: class CV_EXPORTS MatExpr { public: - MatExpr() : op(0), flags(0), a(Mat()), b(Mat()), c(Mat()), alpha(0), beta(0), s(Scalar()) {} - MatExpr(const MatOp* _op, int _flags, const Mat& _a=Mat(), const Mat& _b=Mat(), - const Mat& _c=Mat(), double _alpha=1, double _beta=1, const Scalar& _s=Scalar()) - : op(_op), flags(_flags), a(_a), b(_b), c(_c), alpha(_alpha), beta(_beta), s(_s) {} + MatExpr(); explicit MatExpr(const Mat& m); - operator Mat() const - { - Mat m; - op->assign(*this, m); - return m; - } - template operator Mat_<_Tp>() const - { - Mat_<_Tp> m; - op->assign(*this, m, DataType<_Tp>::type); - return m; - } + MatExpr(const MatOp* _op, int _flags, const Mat& _a = Mat(), const Mat& _b = Mat(), + const Mat& _c = Mat(), double _alpha = 1, double _beta = 1, const Scalar& _s = Scalar()); + + operator Mat() const; + template operator Mat_<_Tp>() const; + + Size size() const; + int type() const; MatExpr row(int y) const; MatExpr col(int x) const; - MatExpr diag(int d=0) const; + MatExpr diag(int d = 0) const; MatExpr operator()( const Range& rowRange, const Range& colRange ) const; MatExpr operator()( const Rect& roi ) const; - Mat cross(const Mat& m) const; - double dot(const Mat& m) const; - MatExpr t() const; MatExpr inv(int method = DECOMP_LU) const; MatExpr mul(const MatExpr& e, double scale=1) const; MatExpr mul(const Mat& m, double scale=1) const; - Size size() const; - int type() const; + Mat cross(const Mat& m) const; + double dot(const Mat& m) const; const MatOp* op; int flags; @@ -1321,75 +2351,6 @@ CV_EXPORTS MatExpr operator > (const Mat& a, const Mat& b); CV_EXPORTS MatExpr operator > (const Mat& a, double s); CV_EXPORTS MatExpr operator > (double s, const Mat& a); -CV_EXPORTS MatExpr min(const Mat& a, const Mat& b); -CV_EXPORTS MatExpr min(const Mat& a, double s); -CV_EXPORTS MatExpr min(double s, const Mat& a); - -CV_EXPORTS MatExpr max(const Mat& a, const Mat& b); -CV_EXPORTS MatExpr max(const Mat& a, double s); -CV_EXPORTS MatExpr max(double s, const Mat& a); - -template static inline MatExpr min(const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - return cv::min((const Mat&)a, (const Mat&)b); -} - -template static inline MatExpr min(const Mat_<_Tp>& a, double s) -{ - return cv::min((const Mat&)a, s); -} - -template static inline MatExpr min(double s, const Mat_<_Tp>& a) -{ - return cv::min((const Mat&)a, s); -} - -template static inline MatExpr max(const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - return cv::max((const Mat&)a, (const Mat&)b); -} - -template static inline MatExpr max(const Mat_<_Tp>& a, double s) -{ - return cv::max((const Mat&)a, s); -} - -template static inline MatExpr max(double s, const Mat_<_Tp>& a) -{ - return cv::max((const Mat&)a, s); -} - -template static inline void min(const Mat_<_Tp>& a, const Mat_<_Tp>& b, Mat_<_Tp>& c) -{ - cv::min((const Mat&)a, (const Mat&)b, (Mat&)c); -} - -template static inline void min(const Mat_<_Tp>& a, double s, Mat_<_Tp>& c) -{ - cv::min((const Mat&)a, s, (Mat&)c); -} - -template static inline void min(double s, const Mat_<_Tp>& a, Mat_<_Tp>& c) -{ - cv::min((const Mat&)a, s, (Mat&)c); -} - -template static inline void max(const Mat_<_Tp>& a, const Mat_<_Tp>& b, Mat_<_Tp>& c) -{ - cv::max((const Mat&)a, (const Mat&)b, (Mat&)c); -} - -template static inline void max(const Mat_<_Tp>& a, double s, Mat_<_Tp>& c) -{ - cv::max((const Mat&)a, s, (Mat&)c); -} - -template static inline void max(double s, const Mat_<_Tp>& a, Mat_<_Tp>& c) -{ - cv::max((const Mat&)a, s, (Mat&)c); -} - - CV_EXPORTS MatExpr operator & (const Mat& a, const Mat& b); CV_EXPORTS MatExpr operator & (const Mat& a, const Scalar& s); CV_EXPORTS MatExpr operator & (const Scalar& s, const Mat& a); @@ -1404,1216 +2365,19 @@ CV_EXPORTS MatExpr operator ^ (const Scalar& s, const Mat& a); CV_EXPORTS MatExpr operator ~(const Mat& m); -CV_EXPORTS MatExpr abs(const Mat& m); -CV_EXPORTS MatExpr abs(const MatExpr& e); - -template static inline MatExpr abs(const Mat_<_Tp>& m) -{ - return cv::abs((const Mat&)m); -} - -////////////////////////////// Augmenting algebraic operations ////////////////////////////////// - -inline Mat& Mat::operator = (const MatExpr& e) -{ - e.op->assign(e, *this); - return *this; -} - -template inline Mat_<_Tp>::Mat_(const MatExpr& e) -{ - e.op->assign(e, *this, DataType<_Tp>::type); -} - -template Mat_<_Tp>& Mat_<_Tp>::operator = (const MatExpr& e) -{ - e.op->assign(e, *this, DataType<_Tp>::type); - return *this; -} - -static inline Mat& operator += (const Mat& a, const Mat& b) -{ - add(a, b, (Mat&)a); - return (Mat&)a; -} +CV_EXPORTS MatExpr min(const Mat& a, const Mat& b); +CV_EXPORTS MatExpr min(const Mat& a, double s); +CV_EXPORTS MatExpr min(double s, const Mat& a); -static inline Mat& operator += (const Mat& a, const Scalar& s) -{ - add(a, s, (Mat&)a); - return (Mat&)a; -} +CV_EXPORTS MatExpr max(const Mat& a, const Mat& b); +CV_EXPORTS MatExpr max(const Mat& a, double s); +CV_EXPORTS MatExpr max(double s, const Mat& a); -template static inline -Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - add(a, b, (Mat&)a); - return (Mat_<_Tp>&)a; -} +CV_EXPORTS MatExpr abs(const Mat& m); +CV_EXPORTS MatExpr abs(const MatExpr& e); -template static inline -Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const Scalar& s) -{ - add(a, s, (Mat&)a); - return (Mat_<_Tp>&)a; -} +} // cv -static inline Mat& operator += (const Mat& a, const MatExpr& b) -{ - b.op->augAssignAdd(b, (Mat&)a); - return (Mat&)a; -} +#include "opencv2/core/mat.inl.hpp" -template static inline -Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const MatExpr& b) -{ - b.op->augAssignAdd(b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator -= (const Mat& a, const Mat& b) -{ - subtract(a, b, (Mat&)a); - return (Mat&)a; -} - -static inline Mat& operator -= (const Mat& a, const Scalar& s) -{ - subtract(a, s, (Mat&)a); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - subtract(a, b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -template static inline -Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const Scalar& s) -{ - subtract(a, s, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator -= (const Mat& a, const MatExpr& b) -{ - b.op->augAssignSubtract(b, (Mat&)a); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const MatExpr& b) -{ - b.op->augAssignSubtract(b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator *= (const Mat& a, const Mat& b) -{ - gemm(a, b, 1, Mat(), 0, (Mat&)a, 0); - return (Mat&)a; -} - -static inline Mat& operator *= (const Mat& a, double s) -{ - a.convertTo((Mat&)a, -1, s); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator *= (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - gemm(a, b, 1, Mat(), 0, (Mat&)a, 0); - return (Mat_<_Tp>&)a; -} - -template static inline -Mat_<_Tp>& operator *= (const Mat_<_Tp>& a, double s) -{ - a.convertTo((Mat&)a, -1, s); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator *= (const Mat& a, const MatExpr& b) -{ - b.op->augAssignMultiply(b, (Mat&)a); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator *= (const Mat_<_Tp>& a, const MatExpr& b) -{ - b.op->augAssignMultiply(b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator /= (const Mat& a, const Mat& b) -{ - divide(a, b, (Mat&)a); - return (Mat&)a; -} - -static inline Mat& operator /= (const Mat& a, double s) -{ - a.convertTo((Mat&)a, -1, 1./s); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - divide(a, b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -template static inline -Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, double s) -{ - a.convertTo((Mat&)a, -1, 1./s); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator /= (const Mat& a, const MatExpr& b) -{ - b.op->augAssignDivide(b, (Mat&)a); - return (Mat&)a; -} - -template static inline -Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, const MatExpr& b) -{ - b.op->augAssignDivide(b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -////////////////////////////// Logical operations /////////////////////////////// - -static inline Mat& operator &= (const Mat& a, const Mat& b) -{ - bitwise_and(a, b, (Mat&)a); - return (Mat&)a; -} - -static inline Mat& operator &= (const Mat& a, const Scalar& s) -{ - bitwise_and(a, s, (Mat&)a); - return (Mat&)a; -} - -template static inline Mat_<_Tp>& -operator &= (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - bitwise_and(a, b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -template static inline Mat_<_Tp>& -operator &= (const Mat_<_Tp>& a, const Scalar& s) -{ - bitwise_and(a, s, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator |= (const Mat& a, const Mat& b) -{ - bitwise_or(a, b, (Mat&)a); - return (Mat&)a; -} - -static inline Mat& operator |= (const Mat& a, const Scalar& s) -{ - bitwise_or(a, s, (Mat&)a); - return (Mat&)a; -} - -template static inline Mat_<_Tp>& -operator |= (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - bitwise_or(a, b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -template static inline Mat_<_Tp>& -operator |= (const Mat_<_Tp>& a, const Scalar& s) -{ - bitwise_or(a, s, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -static inline Mat& operator ^= (const Mat& a, const Mat& b) -{ - bitwise_xor(a, b, (Mat&)a); - return (Mat&)a; -} - -static inline Mat& operator ^= (const Mat& a, const Scalar& s) -{ - bitwise_xor(a, s, (Mat&)a); - return (Mat&)a; -} - -template static inline Mat_<_Tp>& -operator ^= (const Mat_<_Tp>& a, const Mat_<_Tp>& b) -{ - bitwise_xor(a, b, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -template static inline Mat_<_Tp>& -operator ^= (const Mat_<_Tp>& a, const Scalar& s) -{ - bitwise_xor(a, s, (Mat&)a); - return (Mat_<_Tp>&)a; -} - -/////////////////////////////// Miscellaneous operations ////////////////////////////// - -template void split(const Mat& src, vector >& mv) -{ split(src, (vector&)mv ); } - -////////////////////////////////////////////////////////////// - -template inline MatExpr Mat_<_Tp>::zeros(int rows, int cols) -{ - return Mat::zeros(rows, cols, DataType<_Tp>::type); -} - -template inline MatExpr Mat_<_Tp>::zeros(Size sz) -{ - return Mat::zeros(sz, DataType<_Tp>::type); -} - -template inline MatExpr Mat_<_Tp>::ones(int rows, int cols) -{ - return Mat::ones(rows, cols, DataType<_Tp>::type); -} - -template inline MatExpr Mat_<_Tp>::ones(Size sz) -{ - return Mat::ones(sz, DataType<_Tp>::type); -} - -template inline MatExpr Mat_<_Tp>::eye(int rows, int cols) -{ - return Mat::eye(rows, cols, DataType<_Tp>::type); -} - -template inline MatExpr Mat_<_Tp>::eye(Size sz) -{ - return Mat::eye(sz, DataType<_Tp>::type); -} - -//////////////////////////////// Iterators & Comma initializers ////////////////////////////////// - -inline MatConstIterator::MatConstIterator() - : m(0), elemSize(0), ptr(0), sliceStart(0), sliceEnd(0) {} - -inline MatConstIterator::MatConstIterator(const Mat* _m) - : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) -{ - if( m && m->isContinuous() ) - { - sliceStart = m->data; - sliceEnd = sliceStart + m->total()*elemSize; - } - seek((const int*)0); -} - -inline MatConstIterator::MatConstIterator(const Mat* _m, int _row, int _col) - : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) -{ - CV_Assert(m && m->dims <= 2); - if( m->isContinuous() ) - { - sliceStart = m->data; - sliceEnd = sliceStart + m->total()*elemSize; - } - int idx[]={_row, _col}; - seek(idx); -} - -inline MatConstIterator::MatConstIterator(const Mat* _m, Point _pt) - : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) -{ - CV_Assert(m && m->dims <= 2); - if( m->isContinuous() ) - { - sliceStart = m->data; - sliceEnd = sliceStart + m->total()*elemSize; - } - int idx[]={_pt.y, _pt.x}; - seek(idx); -} - -inline MatConstIterator::MatConstIterator(const MatConstIterator& it) - : m(it.m), elemSize(it.elemSize), ptr(it.ptr), sliceStart(it.sliceStart), sliceEnd(it.sliceEnd) -{} - -inline MatConstIterator& MatConstIterator::operator = (const MatConstIterator& it ) -{ - m = it.m; elemSize = it.elemSize; ptr = it.ptr; - sliceStart = it.sliceStart; sliceEnd = it.sliceEnd; - return *this; -} - -inline uchar* MatConstIterator::operator *() const { return ptr; } - -inline MatConstIterator& MatConstIterator::operator += (ptrdiff_t ofs) -{ - if( !m || ofs == 0 ) - return *this; - ptrdiff_t ofsb = ofs*elemSize; - ptr += ofsb; - if( ptr < sliceStart || sliceEnd <= ptr ) - { - ptr -= ofsb; - seek(ofs, true); - } - return *this; -} - -inline MatConstIterator& MatConstIterator::operator -= (ptrdiff_t ofs) -{ return (*this += -ofs); } - -inline MatConstIterator& MatConstIterator::operator --() -{ - if( m && (ptr -= elemSize) < sliceStart ) - { - ptr += elemSize; - seek(-1, true); - } - return *this; -} - -inline MatConstIterator MatConstIterator::operator --(int) -{ - MatConstIterator b = *this; - *this += -1; - return b; -} - -inline MatConstIterator& MatConstIterator::operator ++() -{ - if( m && (ptr += elemSize) >= sliceEnd ) - { - ptr -= elemSize; - seek(1, true); - } - return *this; -} - -inline MatConstIterator MatConstIterator::operator ++(int) -{ - MatConstIterator b = *this; - *this += 1; - return b; -} - -template inline MatConstIterator_<_Tp>::MatConstIterator_() {} - -template inline MatConstIterator_<_Tp>::MatConstIterator_(const Mat_<_Tp>* _m) - : MatConstIterator(_m) {} - -template inline MatConstIterator_<_Tp>:: - MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col) - : MatConstIterator(_m, _row, _col) {} - -template inline MatConstIterator_<_Tp>:: - MatConstIterator_(const Mat_<_Tp>* _m, Point _pt) - : MatConstIterator(_m, _pt) {} - -template inline MatConstIterator_<_Tp>:: - MatConstIterator_(const MatConstIterator_& it) - : MatConstIterator(it) {} - -template inline MatConstIterator_<_Tp>& - MatConstIterator_<_Tp>::operator = (const MatConstIterator_& it ) -{ - MatConstIterator::operator = (it); - return *this; -} - -template inline _Tp MatConstIterator_<_Tp>::operator *() const { return *(_Tp*)(this->ptr); } - -template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator += (ptrdiff_t ofs) -{ - MatConstIterator::operator += (ofs); - return *this; -} - -template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator -= (ptrdiff_t ofs) -{ return (*this += -ofs); } - -template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator --() -{ - MatConstIterator::operator --(); - return *this; -} - -template inline MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator --(int) -{ - MatConstIterator_ b = *this; - MatConstIterator::operator --(); - return b; -} - -template inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator ++() -{ - MatConstIterator::operator ++(); - return *this; -} - -template inline MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator ++(int) -{ - MatConstIterator_ b = *this; - MatConstIterator::operator ++(); - return b; -} - -template inline MatIterator_<_Tp>::MatIterator_() : MatConstIterator_<_Tp>() {} - -template inline MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m) - : MatConstIterator_<_Tp>(_m) {} - -template inline MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m, int _row, int _col) - : MatConstIterator_<_Tp>(_m, _row, _col) {} - -template inline MatIterator_<_Tp>::MatIterator_(const Mat_<_Tp>* _m, Point _pt) - : MatConstIterator_<_Tp>(_m, _pt) {} - -template inline MatIterator_<_Tp>::MatIterator_(const Mat_<_Tp>* _m, const int* _idx) - : MatConstIterator_<_Tp>(_m, _idx) {} - -template inline MatIterator_<_Tp>::MatIterator_(const MatIterator_& it) - : MatConstIterator_<_Tp>(it) {} - -template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator = (const MatIterator_<_Tp>& it ) -{ - MatConstIterator::operator = (it); - return *this; -} - -template inline _Tp& MatIterator_<_Tp>::operator *() const { return *(_Tp*)(this->ptr); } - -template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator += (ptrdiff_t ofs) -{ - MatConstIterator::operator += (ofs); - return *this; -} - -template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator -= (ptrdiff_t ofs) -{ - MatConstIterator::operator += (-ofs); - return *this; -} - -template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator --() -{ - MatConstIterator::operator --(); - return *this; -} - -template inline MatIterator_<_Tp> MatIterator_<_Tp>::operator --(int) -{ - MatIterator_ b = *this; - MatConstIterator::operator --(); - return b; -} - -template inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator ++() -{ - MatConstIterator::operator ++(); - return *this; -} - -template inline MatIterator_<_Tp> MatIterator_<_Tp>::operator ++(int) -{ - MatIterator_ b = *this; - MatConstIterator::operator ++(); - return b; -} - -template inline Point MatConstIterator_<_Tp>::pos() const -{ - if( !m ) - return Point(); - CV_DbgAssert( m->dims <= 2 ); - if( m->isContinuous() ) - { - ptrdiff_t ofs = (const _Tp*)ptr - (const _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); - } -} - -static inline bool -operator == (const MatConstIterator& a, const MatConstIterator& b) -{ return a.m == b.m && a.ptr == b.ptr; } - -template static inline bool -operator != (const MatConstIterator& a, const MatConstIterator& b) -{ return !(a == b); } - -template static inline bool -operator == (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) -{ return a.m == b.m && a.ptr == b.ptr; } - -template static inline bool -operator != (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) -{ return a.m != b.m || a.ptr != b.ptr; } - -template static inline bool -operator == (const MatIterator_<_Tp>& a, const MatIterator_<_Tp>& b) -{ return a.m == b.m && a.ptr == b.ptr; } - -template static inline bool -operator != (const MatIterator_<_Tp>& a, const MatIterator_<_Tp>& b) -{ return a.m != b.m || a.ptr != b.ptr; } - -static inline bool -operator < (const MatConstIterator& a, const MatConstIterator& b) -{ return a.ptr < b.ptr; } - -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; } - -static inline bool -operator >= (const MatConstIterator& a, const MatConstIterator& b) -{ return a.ptr >= b.ptr; } - -CV_EXPORTS ptrdiff_t operator - (const MatConstIterator& b, const MatConstIterator& a); - -static inline MatConstIterator operator + (const MatConstIterator& a, ptrdiff_t ofs) -{ MatConstIterator b = a; return b += ofs; } - -static inline MatConstIterator operator + (ptrdiff_t ofs, const MatConstIterator& a) -{ MatConstIterator b = a; return b += ofs; } - -static inline MatConstIterator operator - (const MatConstIterator& a, ptrdiff_t ofs) -{ MatConstIterator b = a; return b += -ofs; } - -template static inline MatConstIterator_<_Tp> -operator + (const MatConstIterator_<_Tp>& a, ptrdiff_t ofs) -{ MatConstIterator t = (const MatConstIterator&)a + ofs; return (MatConstIterator_<_Tp>&)t; } - -template static inline MatConstIterator_<_Tp> -operator + (ptrdiff_t ofs, const MatConstIterator_<_Tp>& a) -{ MatConstIterator t = (const MatConstIterator&)a + ofs; return (MatConstIterator_<_Tp>&)t; } - -template static inline MatConstIterator_<_Tp> -operator - (const MatConstIterator_<_Tp>& a, ptrdiff_t ofs) -{ MatConstIterator t = (const MatConstIterator&)a - ofs; return (MatConstIterator_<_Tp>&)t; } - -inline uchar* MatConstIterator::operator [](ptrdiff_t i) const -{ return *(*this + i); } - -template inline _Tp MatConstIterator_<_Tp>::operator [](ptrdiff_t i) const -{ return *(_Tp*)MatConstIterator::operator [](i); } - -template static inline MatIterator_<_Tp> -operator + (const MatIterator_<_Tp>& a, ptrdiff_t ofs) -{ MatConstIterator t = (const MatConstIterator&)a + ofs; return (MatIterator_<_Tp>&)t; } - -template static inline MatIterator_<_Tp> -operator + (ptrdiff_t ofs, const MatIterator_<_Tp>& a) -{ MatConstIterator t = (const MatConstIterator&)a + ofs; return (MatIterator_<_Tp>&)t; } - -template static inline MatIterator_<_Tp> -operator - (const MatIterator_<_Tp>& a, ptrdiff_t ofs) -{ MatConstIterator t = (const MatConstIterator&)a - ofs; return (MatIterator_<_Tp>&)t; } - -template inline _Tp& MatIterator_<_Tp>::operator [](ptrdiff_t i) const -{ return *(*this + i); } - -template inline MatConstIterator_<_Tp> Mat_<_Tp>::begin() const -{ return Mat::begin<_Tp>(); } - -template inline MatConstIterator_<_Tp> Mat_<_Tp>::end() const -{ return Mat::end<_Tp>(); } - -template inline MatIterator_<_Tp> Mat_<_Tp>::begin() -{ return Mat::begin<_Tp>(); } - -template inline MatIterator_<_Tp> Mat_<_Tp>::end() -{ return Mat::end<_Tp>(); } - -template inline MatCommaInitializer_<_Tp>::MatCommaInitializer_(Mat_<_Tp>* _m) : it(_m) {} - -template template inline MatCommaInitializer_<_Tp>& -MatCommaInitializer_<_Tp>::operator , (T2 v) -{ - CV_DbgAssert( this->it < ((const Mat_<_Tp>*)this->it.m)->end() ); - *this->it = _Tp(v); ++this->it; - return *this; -} - -template inline Mat_<_Tp> MatCommaInitializer_<_Tp>::operator *() const -{ - CV_DbgAssert( this->it == ((const Mat_<_Tp>*)this->it.m)->end() ); - return Mat_<_Tp>(*this->it.m); -} - -template inline MatCommaInitializer_<_Tp>::operator Mat_<_Tp>() const -{ - CV_DbgAssert( this->it == ((const Mat_<_Tp>*)this->it.m)->end() ); - return Mat_<_Tp>(*this->it.m); -} - -template static inline MatCommaInitializer_<_Tp> -operator << (const Mat_<_Tp>& m, T2 val) -{ - MatCommaInitializer_<_Tp> commaInitializer((Mat_<_Tp>*)&m); - return (commaInitializer, val); -} - -//////////////////////////////// SparseMat //////////////////////////////// - -inline SparseMat::SparseMat() -: flags(MAGIC_VAL), hdr(0) -{ -} - -inline SparseMat::SparseMat(int _dims, const int* _sizes, int _type) -: flags(MAGIC_VAL), hdr(0) -{ - create(_dims, _sizes, _type); -} - -inline SparseMat::SparseMat(const SparseMat& m) -: flags(m.flags), hdr(m.hdr) -{ - addref(); -} - -inline SparseMat::~SparseMat() -{ - release(); -} - -inline SparseMat& SparseMat::operator = (const SparseMat& m) -{ - if( this != &m ) - { - if( m.hdr ) - CV_XADD(&m.hdr->refcount, 1); - release(); - flags = m.flags; - hdr = m.hdr; - } - return *this; -} - -inline SparseMat& SparseMat::operator = (const Mat& m) -{ return (*this = SparseMat(m)); } - -inline SparseMat SparseMat::clone() const -{ - SparseMat temp; - this->copyTo(temp); - return temp; -} - - -inline void SparseMat::assignTo( SparseMat& m, int _type ) const -{ - if( _type < 0 ) - m = *this; - else - convertTo(m, _type); -} - -inline void SparseMat::addref() -{ if( hdr ) CV_XADD(&hdr->refcount, 1); } - -inline void SparseMat::release() -{ - if( hdr && CV_XADD(&hdr->refcount, -1) == 1 ) - delete hdr; - hdr = 0; -} - -inline size_t SparseMat::elemSize() const -{ return CV_ELEM_SIZE(flags); } - -inline size_t SparseMat::elemSize1() const -{ return CV_ELEM_SIZE1(flags); } - -inline int SparseMat::type() const -{ return CV_MAT_TYPE(flags); } - -inline int SparseMat::depth() const -{ return CV_MAT_DEPTH(flags); } - -inline int SparseMat::channels() const -{ return CV_MAT_CN(flags); } - -inline const int* SparseMat::size() const -{ - return hdr ? hdr->size : 0; -} - -inline int SparseMat::size(int i) const -{ - if( hdr ) - { - CV_DbgAssert((unsigned)i < (unsigned)hdr->dims); - return hdr->size[i]; - } - return 0; -} - -inline int SparseMat::dims() const -{ - return hdr ? hdr->dims : 0; -} - -inline size_t SparseMat::nzcount() const -{ - return hdr ? hdr->nodeCount : 0; -} - -inline size_t SparseMat::hash(int i0) const -{ - return (size_t)i0; -} - -inline size_t SparseMat::hash(int i0, int i1) const -{ - return (size_t)(unsigned)i0*HASH_SCALE + (unsigned)i1; -} - -inline size_t SparseMat::hash(int i0, int i1, int i2) const -{ - return ((size_t)(unsigned)i0*HASH_SCALE + (unsigned)i1)*HASH_SCALE + (unsigned)i2; -} - -inline size_t SparseMat::hash(const int* idx) const -{ - size_t h = (unsigned)idx[0]; - if( !hdr ) - return 0; - int i, d = hdr->dims; - for( i = 1; i < d; i++ ) - h = h*HASH_SCALE + (unsigned)idx[i]; - return h; -} - -template inline _Tp& SparseMat::ref(int i0, size_t* hashval) -{ return *(_Tp*)((SparseMat*)this)->ptr(i0, true, hashval); } - -template inline _Tp& SparseMat::ref(int i0, int i1, size_t* hashval) -{ return *(_Tp*)((SparseMat*)this)->ptr(i0, i1, true, hashval); } - -template inline _Tp& SparseMat::ref(int i0, int i1, int i2, size_t* hashval) -{ return *(_Tp*)((SparseMat*)this)->ptr(i0, i1, i2, true, hashval); } - -template inline _Tp& SparseMat::ref(const int* idx, size_t* hashval) -{ return *(_Tp*)((SparseMat*)this)->ptr(idx, true, hashval); } - -template inline _Tp SparseMat::value(int i0, size_t* hashval) const -{ - const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, false, hashval); - return p ? *p : _Tp(); -} - -template inline _Tp SparseMat::value(int i0, int i1, size_t* hashval) const -{ - const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, i1, false, hashval); - return p ? *p : _Tp(); -} - -template inline _Tp SparseMat::value(int i0, int i1, int i2, size_t* hashval) const -{ - const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, i1, i2, false, hashval); - return p ? *p : _Tp(); -} - -template inline _Tp SparseMat::value(const int* idx, size_t* hashval) const -{ - const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(idx, false, hashval); - return p ? *p : _Tp(); -} - -template inline const _Tp* SparseMat::find(int i0, size_t* hashval) const -{ return (const _Tp*)((SparseMat*)this)->ptr(i0, false, hashval); } - -template inline const _Tp* SparseMat::find(int i0, int i1, size_t* hashval) const -{ return (const _Tp*)((SparseMat*)this)->ptr(i0, i1, false, hashval); } - -template inline const _Tp* SparseMat::find(int i0, int i1, int i2, size_t* hashval) const -{ return (const _Tp*)((SparseMat*)this)->ptr(i0, i1, i2, false, hashval); } - -template inline const _Tp* SparseMat::find(const int* idx, size_t* hashval) const -{ return (const _Tp*)((SparseMat*)this)->ptr(idx, false, hashval); } - -template inline _Tp& SparseMat::value(Node* n) -{ return *(_Tp*)((uchar*)n + hdr->valueOffset); } - -template inline const _Tp& SparseMat::value(const Node* n) const -{ return *(const _Tp*)((const uchar*)n + hdr->valueOffset); } - -inline SparseMat::Node* SparseMat::node(size_t nidx) -{ return (Node*)(void*)&hdr->pool[nidx]; } - -inline const SparseMat::Node* SparseMat::node(size_t nidx) const -{ return (const Node*)(void*)&hdr->pool[nidx]; } - -inline SparseMatIterator SparseMat::begin() -{ return SparseMatIterator(this); } - -inline SparseMatConstIterator SparseMat::begin() const -{ return SparseMatConstIterator(this); } - -inline SparseMatIterator SparseMat::end() -{ SparseMatIterator it(this); it.seekEnd(); return it; } - -inline SparseMatConstIterator SparseMat::end() const -{ SparseMatConstIterator it(this); it.seekEnd(); return it; } - -template inline SparseMatIterator_<_Tp> SparseMat::begin() -{ return SparseMatIterator_<_Tp>(this); } - -template inline SparseMatConstIterator_<_Tp> SparseMat::begin() const -{ return SparseMatConstIterator_<_Tp>(this); } - -template inline SparseMatIterator_<_Tp> SparseMat::end() -{ SparseMatIterator_<_Tp> it(this); it.seekEnd(); return it; } - -template inline SparseMatConstIterator_<_Tp> SparseMat::end() const -{ SparseMatConstIterator_<_Tp> it(this); it.seekEnd(); return it; } - - -inline SparseMatConstIterator::SparseMatConstIterator() -: m(0), hashidx(0), ptr(0) -{ -} - -inline SparseMatConstIterator::SparseMatConstIterator(const SparseMatConstIterator& it) -: m(it.m), hashidx(it.hashidx), ptr(it.ptr) -{ -} - -static inline bool operator == (const SparseMatConstIterator& it1, const SparseMatConstIterator& it2) -{ return it1.m == it2.m && it1.ptr == it2.ptr; } - -static inline bool operator != (const SparseMatConstIterator& it1, const SparseMatConstIterator& it2) -{ return !(it1 == it2); } - - -inline SparseMatConstIterator& SparseMatConstIterator::operator = (const SparseMatConstIterator& it) -{ - if( this != &it ) - { - m = it.m; - hashidx = it.hashidx; - ptr = it.ptr; - } - return *this; -} - -template inline const _Tp& SparseMatConstIterator::value() const -{ return *(_Tp*)ptr; } - -inline const SparseMat::Node* SparseMatConstIterator::node() const -{ - return ptr && m && m->hdr ? - (const SparseMat::Node*)(void*)(ptr - m->hdr->valueOffset) : 0; -} - -inline SparseMatConstIterator SparseMatConstIterator::operator ++(int) -{ - SparseMatConstIterator it = *this; - ++*this; - return it; -} - - -inline void SparseMatConstIterator::seekEnd() -{ - if( m && m->hdr ) - { - hashidx = m->hdr->hashtab.size(); - ptr = 0; - } -} - -inline SparseMatIterator::SparseMatIterator() -{} - -inline SparseMatIterator::SparseMatIterator(SparseMat* _m) -: SparseMatConstIterator(_m) -{} - -inline SparseMatIterator::SparseMatIterator(const SparseMatIterator& it) -: SparseMatConstIterator(it) -{ -} - -inline SparseMatIterator& SparseMatIterator::operator = (const SparseMatIterator& it) -{ - (SparseMatConstIterator&)*this = it; - return *this; -} - -template inline _Tp& SparseMatIterator::value() const -{ return *(_Tp*)ptr; } - -inline SparseMat::Node* SparseMatIterator::node() const -{ - return (SparseMat::Node*)SparseMatConstIterator::node(); -} - -inline SparseMatIterator& SparseMatIterator::operator ++() -{ - SparseMatConstIterator::operator ++(); - return *this; -} - -inline SparseMatIterator SparseMatIterator::operator ++(int) -{ - SparseMatIterator it = *this; - ++*this; - return it; -} - - -template inline SparseMat_<_Tp>::SparseMat_() -{ flags = MAGIC_VAL | DataType<_Tp>::type; } - -template inline SparseMat_<_Tp>::SparseMat_(int _dims, const int* _sizes) -: SparseMat(_dims, _sizes, DataType<_Tp>::type) -{} - -template inline SparseMat_<_Tp>::SparseMat_(const SparseMat& m) -{ - if( m.type() == DataType<_Tp>::type ) - *this = (const SparseMat_<_Tp>&)m; - else - m.convertTo(*this, DataType<_Tp>::type); -} - -template inline SparseMat_<_Tp>::SparseMat_(const SparseMat_<_Tp>& m) -{ - this->flags = m.flags; - this->hdr = m.hdr; - if( this->hdr ) - CV_XADD(&this->hdr->refcount, 1); -} - -template inline SparseMat_<_Tp>::SparseMat_(const Mat& m) -{ - SparseMat sm(m); - *this = sm; -} - -template inline SparseMat_<_Tp>::SparseMat_(const CvSparseMat* m) -{ - SparseMat sm(m); - *this = sm; -} - -template inline SparseMat_<_Tp>& -SparseMat_<_Tp>::operator = (const SparseMat_<_Tp>& m) -{ - if( this != &m ) - { - if( m.hdr ) CV_XADD(&m.hdr->refcount, 1); - release(); - flags = m.flags; - hdr = m.hdr; - } - return *this; -} - -template inline SparseMat_<_Tp>& -SparseMat_<_Tp>::operator = (const SparseMat& m) -{ - if( m.type() == DataType<_Tp>::type ) - return (*this = (const SparseMat_<_Tp>&)m); - m.convertTo(*this, DataType<_Tp>::type); - return *this; -} - -template inline SparseMat_<_Tp>& -SparseMat_<_Tp>::operator = (const Mat& m) -{ return (*this = SparseMat(m)); } - -template inline SparseMat_<_Tp> -SparseMat_<_Tp>::clone() const -{ - SparseMat_<_Tp> m; - this->copyTo(m); - return m; -} - -template inline void -SparseMat_<_Tp>::create(int _dims, const int* _sizes) -{ - SparseMat::create(_dims, _sizes, DataType<_Tp>::type); -} - -template inline -SparseMat_<_Tp>::operator CvSparseMat*() const -{ - return SparseMat::operator CvSparseMat*(); -} - -template inline int SparseMat_<_Tp>::type() const -{ return DataType<_Tp>::type; } - -template inline int SparseMat_<_Tp>::depth() const -{ return DataType<_Tp>::depth; } - -template inline int SparseMat_<_Tp>::channels() const -{ return DataType<_Tp>::channels; } - -template inline _Tp& -SparseMat_<_Tp>::ref(int i0, size_t* hashval) -{ return SparseMat::ref<_Tp>(i0, hashval); } - -template inline _Tp -SparseMat_<_Tp>::operator()(int i0, size_t* hashval) const -{ return SparseMat::value<_Tp>(i0, hashval); } - -template inline _Tp& -SparseMat_<_Tp>::ref(int i0, int i1, size_t* hashval) -{ return SparseMat::ref<_Tp>(i0, i1, hashval); } - -template inline _Tp -SparseMat_<_Tp>::operator()(int i0, int i1, size_t* hashval) const -{ return SparseMat::value<_Tp>(i0, i1, hashval); } - -template inline _Tp& -SparseMat_<_Tp>::ref(int i0, int i1, int i2, size_t* hashval) -{ return SparseMat::ref<_Tp>(i0, i1, i2, hashval); } - -template inline _Tp -SparseMat_<_Tp>::operator()(int i0, int i1, int i2, size_t* hashval) const -{ return SparseMat::value<_Tp>(i0, i1, i2, hashval); } - -template inline _Tp& -SparseMat_<_Tp>::ref(const int* idx, size_t* hashval) -{ return SparseMat::ref<_Tp>(idx, hashval); } - -template inline _Tp -SparseMat_<_Tp>::operator()(const int* idx, size_t* hashval) const -{ return SparseMat::value<_Tp>(idx, hashval); } - -template inline SparseMatIterator_<_Tp> SparseMat_<_Tp>::begin() -{ return SparseMatIterator_<_Tp>(this); } - -template inline SparseMatConstIterator_<_Tp> SparseMat_<_Tp>::begin() const -{ return SparseMatConstIterator_<_Tp>(this); } - -template inline SparseMatIterator_<_Tp> SparseMat_<_Tp>::end() -{ SparseMatIterator_<_Tp> it(this); it.seekEnd(); return it; } - -template inline SparseMatConstIterator_<_Tp> SparseMat_<_Tp>::end() const -{ SparseMatConstIterator_<_Tp> it(this); it.seekEnd(); return it; } - -template inline -SparseMatConstIterator_<_Tp>::SparseMatConstIterator_() -{} - -template inline -SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMat_<_Tp>* _m) -: SparseMatConstIterator(_m) -{} - -template inline -SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMat* _m) -: SparseMatConstIterator(_m) -{ - CV_Assert( _m->type() == DataType<_Tp>::type ); -} - -template inline -SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMatConstIterator_<_Tp>& it) -: SparseMatConstIterator(it) -{} - -template inline SparseMatConstIterator_<_Tp>& -SparseMatConstIterator_<_Tp>::operator = (const SparseMatConstIterator_<_Tp>& it) -{ return reinterpret_cast&> - (*reinterpret_cast(this) = - reinterpret_cast(it)); } - -template inline const _Tp& -SparseMatConstIterator_<_Tp>::operator *() const -{ return *(const _Tp*)this->ptr; } - -template inline SparseMatConstIterator_<_Tp>& -SparseMatConstIterator_<_Tp>::operator ++() -{ - SparseMatConstIterator::operator ++(); - return *this; -} - -template inline SparseMatConstIterator_<_Tp> -SparseMatConstIterator_<_Tp>::operator ++(int) -{ - SparseMatConstIterator_<_Tp> it = *this; - SparseMatConstIterator::operator ++(); - return it; -} - -template inline -SparseMatIterator_<_Tp>::SparseMatIterator_() -{} - -template inline -SparseMatIterator_<_Tp>::SparseMatIterator_(SparseMat_<_Tp>* _m) -: SparseMatConstIterator_<_Tp>(_m) -{} - -template inline -SparseMatIterator_<_Tp>::SparseMatIterator_(SparseMat* _m) -: SparseMatConstIterator_<_Tp>(_m) -{} - -template inline -SparseMatIterator_<_Tp>::SparseMatIterator_(const SparseMatIterator_<_Tp>& it) -: SparseMatConstIterator_<_Tp>(it) -{} - -template inline SparseMatIterator_<_Tp>& -SparseMatIterator_<_Tp>::operator = (const SparseMatIterator_<_Tp>& it) -{ return reinterpret_cast&> - (*reinterpret_cast(this) = - reinterpret_cast(it)); } - -template inline _Tp& -SparseMatIterator_<_Tp>::operator *() const -{ return *(_Tp*)this->ptr; } - -template inline SparseMatIterator_<_Tp>& -SparseMatIterator_<_Tp>::operator ++() -{ - SparseMatConstIterator::operator ++(); - return *this; -} - -template inline SparseMatIterator_<_Tp> -SparseMatIterator_<_Tp>::operator ++(int) -{ - SparseMatIterator_<_Tp> it = *this; - SparseMatConstIterator::operator ++(); - return it; -} - -} - -#endif -#endif +#endif // __OPENCV_CORE_MAT_HPP__