Joe Verbout
/
main
opencv on mbed
Diff: opencv2/core/mat.hpp
- Revision:
- 0:ea44dc9ed014
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/opencv2/core/mat.hpp Thu Mar 31 21:16:38 2016 +0000 @@ -0,0 +1,3432 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// 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, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_MAT_HPP__ +#define __OPENCV_CORE_MAT_HPP__ + +#ifndef __cplusplus +# error mat.hpp header must be compiled as C++ +#endif + +#include "opencv2/core/matx.hpp" +#include "opencv2/core/types.hpp" + +#include "opencv2/core/bufferpool.hpp" + +namespace cv +{ + +//! @addtogroup core_basic +//! @{ + +enum { ACCESS_READ=1<<24, ACCESS_WRITE=1<<25, + ACCESS_RW=3<<24, ACCESS_MASK=ACCESS_RW, ACCESS_FAST=1<<26 }; + +class CV_EXPORTS _OutputArray; + +//////////////////////// Input/Output Array Arguments ///////////////////////////////// + +/** @brief This is the proxy class for passing read-only input arrays into OpenCV functions. + +It is defined as: +@code + typedef const _InputArray& InputArray; +@endcode +where _InputArray is a class that can be constructed from `Mat`, `Mat_<T>`, `Matx<T, m, n>`, +`std::vector<T>`, `std::vector<std::vector<T> >` or `std::vector<Mat>`. It can also be constructed +from a matrix expression. + +Since this is mostly implementation-level class, and its interface may change in future versions, we +do not describe it in details. There are a few key things, though, that should be kept in mind: + +- When you see in the reference manual or in OpenCV source code a function that takes + InputArray, it means that you can actually pass `Mat`, `Matx`, `vector<T>` etc. (see above the + complete list). +- Optional input arguments: If some of the input arrays may be empty, pass cv::noArray() (or + simply cv::Mat() as you probably did before). +- The class is designed solely for passing parameters. That is, normally you *should not* + declare class members, local and global variables of this type. +- If you want to design your own function or a class method that can operate of arrays of + multiple types, you can use InputArray (or OutputArray) for the respective parameters. Inside + a function you should use _InputArray::getMat() method to construct a matrix header for the + array (without copying data). _InputArray::kind() can be used to distinguish Mat from + `vector<>` etc., but normally it is not needed. + +Here is how you can use a function that takes InputArray : +@code + std::vector<Point2f> vec; + // points or a circle + for( int i = 0; i < 30; i++ ) + vec.push_back(Point2f((float)(100 + 30*cos(i*CV_PI*2/5)), + (float)(100 - 30*sin(i*CV_PI*2/5)))); + cv::transform(vec, vec, cv::Matx23f(0.707, -0.707, 10, 0.707, 0.707, 20)); +@endcode +That is, we form an STL vector containing points, and apply in-place affine transformation to the +vector using the 2x3 matrix created inline as `Matx<float, 2, 3>` instance. + +Here is how such a function can be implemented (for simplicity, we implement a very specific case of +it, according to the assertion statement inside) : +@code + void myAffineTransform(InputArray _src, OutputArray _dst, InputArray _m) + { + // get Mat headers for input arrays. This is O(1) operation, + // unless _src and/or _m are matrix expressions. + Mat src = _src.getMat(), m = _m.getMat(); + CV_Assert( src.type() == CV_32FC2 && m.type() == CV_32F && m.size() == Size(3, 2) ); + + // [re]create the output array so that it has the proper size and type. + // In case of Mat it calls Mat::create, in case of STL vector it calls vector::resize. + _dst.create(src.size(), src.type()); + Mat dst = _dst.getMat(); + + for( int i = 0; i < src.rows; i++ ) + for( int j = 0; j < src.cols; j++ ) + { + Point2f pt = src.at<Point2f>(i, j); + dst.at<Point2f>(i, j) = Point2f(m.at<float>(0, 0)*pt.x + + m.at<float>(0, 1)*pt.y + + m.at<float>(0, 2), + m.at<float>(1, 0)*pt.x + + m.at<float>(1, 1)*pt.y + + m.at<float>(1, 2)); + } + } +@endcode +There is another related type, InputArrayOfArrays, which is currently defined as a synonym for +InputArray: +@code + typedef InputArray InputArrayOfArrays; +@endcode +It denotes function arguments that are either vectors of vectors or vectors of matrices. A separate +synonym is needed to generate Python/Java etc. wrappers properly. At the function implementation +level their use is similar, but _InputArray::getMat(idx) should be used to get header for the +idx-th component of the outer vector and _InputArray::size().area() should be used to find the +number of components (vectors/matrices) of the outer vector. + */ +class CV_EXPORTS _InputArray +{ +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_HOST_MEM = 8 << KIND_SHIFT, + CUDA_GPU_MAT = 9 << KIND_SHIFT, + UMAT =10 << KIND_SHIFT, + STD_VECTOR_UMAT =11 << KIND_SHIFT, + STD_BOOL_VECTOR =12 << KIND_SHIFT, + STD_VECTOR_CUDA_GPU_MAT = 13 << KIND_SHIFT + }; + + _InputArray(); + _InputArray(int _flags, void* _obj); + _InputArray(const Mat& m); + _InputArray(const MatExpr& expr); + _InputArray(const std::vector<Mat>& vec); + template<typename _Tp> _InputArray(const Mat_<_Tp>& m); + template<typename _Tp> _InputArray(const std::vector<_Tp>& vec); + _InputArray(const std::vector<bool>& vec); + template<typename _Tp> _InputArray(const std::vector<std::vector<_Tp> >& vec); + template<typename _Tp> _InputArray(const std::vector<Mat_<_Tp> >& vec); + template<typename _Tp> _InputArray(const _Tp* vec, int n); + template<typename _Tp, int m, int n> _InputArray(const Matx<_Tp, m, n>& matx); + _InputArray(const double& val); + _InputArray(const cuda::GpuMat& d_mat); + _InputArray(const std::vector<cuda::GpuMat>& d_mat_array); + _InputArray(const ogl::Buffer& buf); + _InputArray(const cuda::HostMem& cuda_mem); + template<typename _Tp> _InputArray(const cudev::GpuMat_<_Tp>& m); + _InputArray(const UMat& um); + _InputArray(const std::vector<UMat>& umv); + + Mat getMat(int idx=-1) const; + Mat getMat_(int idx=-1) const; + UMat getUMat(int idx=-1) const; + void getMatVector(std::vector<Mat>& mv) const; + void getUMatVector(std::vector<UMat>& umv) const; + void getGpuMatVector(std::vector<cuda::GpuMat>& gpumv) const; + cuda::GpuMat getGpuMat() const; + ogl::Buffer getOGlBuffer() const; + + int getFlags() const; + void* getObj() const; + Size getSz() const; + + int kind() const; + int dims(int i=-1) const; + int cols(int i=-1) const; + int rows(int i=-1) const; + Size size(int i=-1) const; + int sizend(int* sz, int i=-1) const; + bool sameSize(const _InputArray& arr) const; + size_t total(int i=-1) const; + int type(int i=-1) const; + int depth(int i=-1) const; + int channels(int i=-1) const; + bool isContinuous(int i=-1) const; + bool isSubmatrix(int i=-1) const; + bool empty() const; + void copyTo(const _OutputArray& arr) const; + void copyTo(const _OutputArray& arr, const _InputArray & mask) const; + size_t offset(int i=-1) const; + size_t step(int i=-1) const; + bool isMat() const; + bool isUMat() const; + bool isMatVector() const; + bool isUMatVector() const; + bool isMatx() const; + bool isVector() const; + bool isGpuMatVector() const; + ~_InputArray(); + +protected: + int flags; + void* obj; + Size sz; + + void init(int _flags, const void* _obj); + void init(int _flags, const void* _obj, Size _sz); +}; + + +/** @brief This type is very similar to InputArray except that it is used for input/output and output function +parameters. + +Just like with InputArray, OpenCV users should not care about OutputArray, they just pass `Mat`, +`vector<T>` etc. to the functions. The same limitation as for `InputArray`: *Do not explicitly +create OutputArray instances* applies here too. + +If you want to make your function polymorphic (i.e. accept different arrays as output parameters), +it is also not very difficult. Take the sample above as the reference. Note that +_OutputArray::create() needs to be called before _OutputArray::getMat(). This way you guarantee +that the output array is properly allocated. + +Optional output parameters. If you do not need certain output array to be computed and returned to +you, pass cv::noArray(), just like you would in the case of optional input array. At the +implementation level, use _OutputArray::needed() to check if certain output array needs to be +computed or not. + +There are several synonyms for OutputArray that are used to assist automatic Python/Java/... wrapper +generators: +@code + typedef OutputArray OutputArrayOfArrays; + typedef OutputArray InputOutputArray; + typedef OutputArray InputOutputArrayOfArrays; +@endcode + */ +class CV_EXPORTS _OutputArray : public _InputArray +{ +public: + enum + { + 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<Mat>& vec); + _OutputArray(cuda::GpuMat& d_mat); + _OutputArray(std::vector<cuda::GpuMat>& d_mat); + _OutputArray(ogl::Buffer& buf); + _OutputArray(cuda::HostMem& cuda_mem); + template<typename _Tp> _OutputArray(cudev::GpuMat_<_Tp>& m); + template<typename _Tp> _OutputArray(std::vector<_Tp>& vec); + _OutputArray(std::vector<bool>& vec); + template<typename _Tp> _OutputArray(std::vector<std::vector<_Tp> >& vec); + template<typename _Tp> _OutputArray(std::vector<Mat_<_Tp> >& vec); + template<typename _Tp> _OutputArray(Mat_<_Tp>& m); + template<typename _Tp> _OutputArray(_Tp* vec, int n); + template<typename _Tp, int m, int n> _OutputArray(Matx<_Tp, m, n>& matx); + _OutputArray(UMat& m); + _OutputArray(std::vector<UMat>& vec); + + _OutputArray(const Mat& m); + _OutputArray(const std::vector<Mat>& vec); + _OutputArray(const cuda::GpuMat& d_mat); + _OutputArray(const std::vector<cuda::GpuMat>& d_mat); + _OutputArray(const ogl::Buffer& buf); + _OutputArray(const cuda::HostMem& cuda_mem); + template<typename _Tp> _OutputArray(const cudev::GpuMat_<_Tp>& m); + template<typename _Tp> _OutputArray(const std::vector<_Tp>& vec); + template<typename _Tp> _OutputArray(const std::vector<std::vector<_Tp> >& vec); + template<typename _Tp> _OutputArray(const std::vector<Mat_<_Tp> >& vec); + template<typename _Tp> _OutputArray(const Mat_<_Tp>& m); + template<typename _Tp> _OutputArray(const _Tp* vec, int n); + template<typename _Tp, int m, int n> _OutputArray(const Matx<_Tp, m, n>& matx); + _OutputArray(const UMat& m); + _OutputArray(const std::vector<UMat>& vec); + + bool fixedSize() const; + bool fixedType() const; + bool needed() const; + Mat& getMatRef(int i=-1) const; + UMat& getUMatRef(int i=-1) const; + cuda::GpuMat& getGpuMatRef() const; + std::vector<cuda::GpuMat>& getGpuMatVecRef() const; + ogl::Buffer& getOGlBufferRef() const; + cuda::HostMem& getHostMemRef() const; + void create(Size sz, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; + void create(int rows, int cols, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; + void create(int dims, const int* size, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; + void createSameSize(const _InputArray& arr, int mtype) const; + void release() const; + void clear() const; + void setTo(const _InputArray& value, const _InputArray & mask = _InputArray()) const; + + void assign(const UMat& u) const; + void assign(const Mat& m) const; +}; + + +class CV_EXPORTS _InputOutputArray : public _OutputArray +{ +public: + _InputOutputArray(); + _InputOutputArray(int _flags, void* _obj); + _InputOutputArray(Mat& m); + _InputOutputArray(std::vector<Mat>& vec); + _InputOutputArray(cuda::GpuMat& d_mat); + _InputOutputArray(ogl::Buffer& buf); + _InputOutputArray(cuda::HostMem& cuda_mem); + template<typename _Tp> _InputOutputArray(cudev::GpuMat_<_Tp>& m); + template<typename _Tp> _InputOutputArray(std::vector<_Tp>& vec); + _InputOutputArray(std::vector<bool>& vec); + template<typename _Tp> _InputOutputArray(std::vector<std::vector<_Tp> >& vec); + template<typename _Tp> _InputOutputArray(std::vector<Mat_<_Tp> >& vec); + template<typename _Tp> _InputOutputArray(Mat_<_Tp>& m); + template<typename _Tp> _InputOutputArray(_Tp* vec, int n); + template<typename _Tp, int m, int n> _InputOutputArray(Matx<_Tp, m, n>& matx); + _InputOutputArray(UMat& m); + _InputOutputArray(std::vector<UMat>& vec); + + _InputOutputArray(const Mat& m); + _InputOutputArray(const std::vector<Mat>& vec); + _InputOutputArray(const cuda::GpuMat& d_mat); + _InputOutputArray(const std::vector<cuda::GpuMat>& d_mat); + _InputOutputArray(const ogl::Buffer& buf); + _InputOutputArray(const cuda::HostMem& cuda_mem); + template<typename _Tp> _InputOutputArray(const cudev::GpuMat_<_Tp>& m); + template<typename _Tp> _InputOutputArray(const std::vector<_Tp>& vec); + template<typename _Tp> _InputOutputArray(const std::vector<std::vector<_Tp> >& vec); + template<typename _Tp> _InputOutputArray(const std::vector<Mat_<_Tp> >& vec); + template<typename _Tp> _InputOutputArray(const Mat_<_Tp>& m); + template<typename _Tp> _InputOutputArray(const _Tp* vec, int n); + template<typename _Tp, int m, int n> _InputOutputArray(const Matx<_Tp, m, n>& matx); + _InputOutputArray(const UMat& m); + _InputOutputArray(const std::vector<UMat>& vec); +}; + +typedef const _InputArray& InputArray; +typedef InputArray InputArrayOfArrays; +typedef const _OutputArray& OutputArray; +typedef OutputArray OutputArrayOfArrays; +typedef const _InputOutputArray& InputOutputArray; +typedef InputOutputArray InputOutputArrayOfArrays; + +CV_EXPORTS InputOutputArray noArray(); + +/////////////////////////////////// MatAllocator ////////////////////////////////////// + +//! Usage flags for allocator +enum UMatUsageFlags +{ + USAGE_DEFAULT = 0, + + // buffer allocation policy is platform and usage specific + USAGE_ALLOCATE_HOST_MEMORY = 1 << 0, + USAGE_ALLOCATE_DEVICE_MEMORY = 1 << 1, + USAGE_ALLOCATE_SHARED_MEMORY = 1 << 2, // It is not equal to: USAGE_ALLOCATE_HOST_MEMORY | USAGE_ALLOCATE_DEVICE_MEMORY + + __UMAT_USAGE_FLAGS_32BIT = 0x7fffffff // Binary compatibility hint +}; + +struct CV_EXPORTS UMatData; + +/** @brief Custom array allocator +*/ +class CV_EXPORTS MatAllocator +{ +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 char* id = NULL) const; +}; + + +//////////////////////////////// MatCommaInitializer ////////////////////////////////// + +/** @brief Comma-separated Matrix Initializer + + The class instances are usually not created explicitly. + Instead, they are created on "matrix << firstValue" operator. + + The sample below initializes 2x2 rotation matrix: + + \code + double angle = 30, a = cos(angle*CV_PI/180), b = sin(angle*CV_PI/180); + Mat R = (Mat_<double>(2,2) << a, -b, b, a); + \endcode +*/ +template<typename _Tp> class MatCommaInitializer_ +{ +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<typename T2> MatCommaInitializer_<_Tp>& operator , (T2 v); + //! another form of conversion operator + operator Mat_<_Tp>() const; +protected: + MatIterator_<_Tp> it; +}; + + +/////////////////////////////////////// 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; + + int flags; + void* handle; + void* userdata; + int allocatorFlags_; + int mapcount; + UMatData* originalUMatData; +}; + + +struct CV_EXPORTS UMatDataAutoLock +{ + explicit UMatDataAutoLock(UMatData* u); + ~UMatDataAutoLock(); + UMatData* u; +}; + + +struct CV_EXPORTS MatSize +{ + 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; + + int* p; +}; + +struct CV_EXPORTS MatStep +{ + 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&); +}; + +/** @example cout_mat.cpp +An example demonstrating the serial out capabilities of cv::Mat +*/ + + /** @brief n-dimensional dense array class + +The class Mat represents an n-dimensional dense numerical single-channel or multi-channel array. It +can be used to store real or complex-valued vectors and matrices, grayscale or color images, voxel +volumes, vector fields, point clouds, tensors, histograms (though, very high-dimensional histograms +may be better stored in a SparseMat ). The data layout of the array `M` is defined by the array +`M.step[]`, so that the address of element \f$(i_0,...,i_{M.dims-1})\f$, where \f$0\leq i_k<M.size[k]\f$, is +computed as: +\f[addr(M_{i_0,...,i_{M.dims-1}}) = M.data + M.step[0]*i_0 + M.step[1]*i_1 + ... + M.step[M.dims-1]*i_{M.dims-1}\f] +In case of a 2-dimensional array, the above formula is reduced to: +\f[addr(M_{i,j}) = M.data + M.step[0]*i + M.step[1]*j\f] +Note that `M.step[i] >= M.step[i+1]` (in fact, `M.step[i] >= M.step[i+1]*M.size[i+1]` ). This means +that 2-dimensional matrices are stored row-by-row, 3-dimensional matrices are stored plane-by-plane, +and so on. M.step[M.dims-1] is minimal and always equal to the element size M.elemSize() . + +So, the data layout in Mat is fully compatible with CvMat, IplImage, and CvMatND types from OpenCV +1.x. It is also compatible with the majority of dense array types from the standard toolkits and +SDKs, such as Numpy (ndarray), Win32 (independent device bitmaps), and others, that is, with any +array that uses *steps* (or *strides*) to compute the position of a pixel. Due to this +compatibility, it is possible to make a Mat header for user-allocated data and process it in-place +using OpenCV functions. + +There are many different ways to create a Mat object. The most popular options are listed below: + +- Use the create(nrows, ncols, type) method or the similar Mat(nrows, ncols, type[, fillValue]) +constructor. A new array of the specified size and type is allocated. type has the same meaning as +in the cvCreateMat method. For example, CV_8UC1 means a 8-bit single-channel array, CV_32FC2 +means a 2-channel (complex) floating-point array, and so on. +@code + // make a 7x7 complex matrix filled with 1+3j. + Mat M(7,7,CV_32FC2,Scalar(1,3)); + // and now turn M to a 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 to this chapter, create() allocates only a new array when the shape +or type of the current array are different from the specified ones. + +- Create a multi-dimensional array: +@code + // create a 100x100x100 8-bit array + int sz[] = {100, 100, 100}; + Mat bigCube(3, sz, CV_8U, Scalar::all(0)); +@endcode +It passes the number of dimensions =1 to the Mat constructor but the created array will be +2-dimensional with the number of columns set to 1. So, Mat::dims is always \>= 2 (can also be 0 +when the array is empty). + +- Use a copy constructor or assignment operator where there can be an array or expression on the +right side (see below). As noted in the introduction, the array assignment is an O(1) operation +because it only copies the header and increases the reference counter. The Mat::clone() method can +be used to get a full (deep) copy of the array when you need it. + +- Construct a header for a part of another array. It can be a single row, single column, several +rows, several columns, rectangular region in the array (called a *minor* in algebra) or a +diagonal. Such operations are also O(1) because the new header references the same data. You can +actually modify a part of the array using this feature, for example: +@code + // add the 5-th row, multiplied by 3 to the 3rd row + M.row(3) = M.row(3) + M.row(5)*3; + // now copy the 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 a new 320x240 image + Mat img(Size(320,240),CV_8UC3); + // select a ROI + 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 +Due to the additional datastart and dataend members, it is possible to compute a relative +sub-array position in the main *container* array using 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 case of whole matrices, if you need a deep copy, use the `clone()` method of the extracted +sub-matrices. + +- Make a header for user-allocated data. It can be useful to do the following: + -# Process "foreign" data using OpenCV (for example, when you implement a DirectShow\* filter or + a processing module for gstreamer, and so on). For example: + @code + void process_video_frame(const unsigned char* pixels, + int width, int height, int step) + { + Mat img(height, width, CV_8UC3, pixels, step); + GaussianBlur(img, img, Size(7,7), 1.5, 1.5); + } + @endcode + -# Quickly initialize small matrices and/or get a super-fast element access. + @code + double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}}; + Mat M = 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 Mat. For this purpose, there is function cv::cvarrToMat taking pointers to CvMat or + IplImage and the optional flag indicating whether to copy the data or not. + @snippet samples/cpp/image.cpp iplimage + +- Use MATLAB-style array initializers, zeros(), ones(), eye(), for example: +@code + // create a double-precision identity martix and add it to M. + M += Mat::eye(M.rows, M.cols, CV_64F); +@endcode + +- Use a comma-separated initializer: +@code + // create a 3x3 double-precision identity matrix + Mat M = (Mat_<double>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1); +@endcode +With this approach, you first call a constructor of the Mat class with the proper parameters, and +then you just put `<< operator` followed by comma-separated values that can be constants, +variables, expressions, and so on. Also, note the extra parentheses required to avoid compilation +errors. + +Once the array is created, it is automatically managed via a reference-counting mechanism. If the +array header is built on top of user-allocated data, you should handle the data by yourself. The +array data is deallocated when no one points to it. If you want to release the data pointed by a +array header before the array destructor is called, use Mat::release(). + +The next important thing to learn about the array class is element access. This manual already +described how to compute an address of each array element. Normally, you are not required to use the +formula directly in the code. If you know the array element type (which can be retrieved using the +method Mat::type() ), you can access the element \f$M_{ij}\f$ of a 2-dimensional array as: +@code + M.at<double>(i,j) += 1.f; +@endcode +assuming that `M` is a double-precision floating-point array. There are several variants of the method +at for a different number of dimensions. + +If you need to process a whole row of a 2D array, the most efficient way is to get the pointer to +the row first, and then just use the plain C operator [] : +@code + // compute sum of positive matrix elements + // (assuming that M isa double-precision matrix) + double sum=0; + for(int i = 0; i < M.rows; i++) + { + const double* Mi = M.ptr<double>(i); + for(int j = 0; j < M.cols; j++) + sum += std::max(Mi[j], 0.); + } +@endcode +Some operations, like the one above, do not actually depend on the array shape. They just process +elements of an array one by one (or elements from multiple arrays that have the same coordinates, +for example, array addition). Such operations are called *element-wise*. It makes sense to check +whether all the input/output arrays are continuous, namely, have no gaps at the end of each row. If +yes, process them as a long single row: +@code + // compute the 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<double>(i); + for(int j = 0; j < cols; j++) + sum += std::max(Mi[j], 0.); + } +@endcode +In case of the continuous matrix, the outer loop body is executed just once. So, the overhead is +smaller, which is especially noticeable in 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_<double> it = M.begin<double>(), it_end = M.end<double>(); + 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 +{ +public: + /** + These are various constructors that form a matrix. As noted in the AutomaticAllocation, often + the default constructor is enough, and the proper matrix will be allocated by an OpenCV function. + The constructed matrix can further be assigned to another matrix or matrix expression or can be + allocated with Mat::create . In the former case, the old content is de-referenced. + */ + Mat(); + + /** @overload + @param rows Number of rows in a 2D array. + @param cols Number of columns in a 2D array. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + */ + Mat(int rows, int cols, int type); + + /** @overload + @param size 2D array size: Size(cols, rows) . In the Size() constructor, the number of rows and the + number of columns go in the reverse order. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + */ + Mat(Size size, int type); + + /** @overload + @param rows Number of rows in a 2D array. + @param cols Number of columns in a 2D array. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + @param s An optional value to initialize each matrix element with. To set all the matrix elements to + the particular value after the construction, use the assignment operator + Mat::operator=(const Scalar& value) . + */ + Mat(int rows, int cols, int type, const Scalar& s); + + /** @overload + @param size 2D array size: Size(cols, rows) . In the Size() constructor, the number of rows and the + number of columns go in the reverse order. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + @param s An optional value to initialize each matrix element with. To set all the matrix elements to + the particular value after the construction, use the assignment operator + Mat::operator=(const Scalar& value) . + */ + Mat(Size size, int type, const Scalar& s); + + /** @overload + @param ndims Array dimensionality. + @param sizes Array of integers specifying an n-dimensional array shape. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + */ + Mat(int ndims, const int* sizes, int type); + + /** @overload + @param ndims Array dimensionality. + @param sizes Array of integers specifying an n-dimensional array shape. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + @param s An optional value to initialize each matrix element with. To set all the matrix elements to + the particular value after the construction, use the assignment operator + Mat::operator=(const Scalar& value) . + */ + Mat(int ndims, const int* sizes, int type, const Scalar& s); + + /** @overload + @param m Array that (as a whole or partly) is assigned to the constructed matrix. No data is copied + by these constructors. Instead, the header pointing to m data or its sub-array is constructed and + associated with it. The reference counter, if any, is incremented. So, when you modify the matrix + formed using such a constructor, you also modify the corresponding elements of m . If you want to + have an independent copy of the sub-array, use Mat::clone() . + */ + Mat(const Mat& m); + + /** @overload + @param rows Number of rows in a 2D array. + @param cols Number of columns in a 2D array. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + @param data Pointer to the user data. Matrix constructors that take data and step parameters do not + allocate matrix data. Instead, they just initialize the matrix header that points to the specified + data, which means that no data is copied. This operation is very efficient and can be used to + process external data using OpenCV functions. The external data is not automatically deallocated, so + you should take care of it. + @param step Number of bytes each matrix row occupies. The value should include the padding bytes at + the end of each row, if any. If the parameter is missing (set to AUTO_STEP ), no padding is assumed + and the actual step is calculated as cols*elemSize(). See Mat::elemSize. + */ + Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP); + + /** @overload + @param size 2D array size: Size(cols, rows) . In the Size() constructor, the number of rows and the + number of columns go in the reverse order. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + @param data Pointer to the user data. Matrix constructors that take data and step parameters do not + allocate matrix data. Instead, they just initialize the matrix header that points to the specified + data, which means that no data is copied. This operation is very efficient and can be used to + process external data using OpenCV functions. The external data is not automatically deallocated, so + you should take care of it. + @param step Number of bytes each matrix row occupies. The value should include the padding bytes at + the end of each row, if any. If the parameter is missing (set to AUTO_STEP ), no padding is assumed + and the actual step is calculated as cols*elemSize(). See Mat::elemSize. + */ + Mat(Size size, int type, void* data, size_t step=AUTO_STEP); + + /** @overload + @param ndims Array dimensionality. + @param sizes Array of integers specifying an n-dimensional array shape. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + @param data Pointer to the user data. Matrix constructors that take data and step parameters do not + allocate matrix data. Instead, they just initialize the matrix header that points to the specified + data, which means that no data is copied. This operation is very efficient and can be used to + process external data using OpenCV functions. The external data is not automatically deallocated, so + you should take care of it. + @param steps Array of ndims-1 steps in case of a multi-dimensional array (the last step is always + set to the element size). If not specified, the matrix is assumed to be continuous. + */ + Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0); + + /** @overload + @param m Array that (as a whole or partly) is assigned to the constructed matrix. No data is copied + by these constructors. Instead, the header pointing to m data or its sub-array is constructed and + associated with it. The reference counter, if any, is incremented. So, when you modify the matrix + formed using such a constructor, you also modify the corresponding elements of m . If you want to + have an independent copy of the sub-array, use Mat::clone() . + @param rowRange Range of the m rows to take. As usual, the range start is inclusive and the range + end is exclusive. Use Range::all() to take all the rows. + @param colRange Range of the m columns to take. Use Range::all() to take all the columns. + */ + Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all()); + + /** @overload + @param m Array that (as a whole or partly) is assigned to the constructed matrix. No data is copied + by these constructors. Instead, the header pointing to m data or its sub-array is constructed and + associated with it. The reference counter, if any, is incremented. So, when you modify the matrix + formed using such a constructor, you also modify the corresponding elements of m . If you want to + have an independent copy of the sub-array, use Mat::clone() . + @param roi Region of interest. + */ + Mat(const Mat& m, const Rect& roi); + + /** @overload + @param m Array that (as a whole or partly) is assigned to the constructed matrix. No data is copied + by these constructors. Instead, the header pointing to m data or its sub-array is constructed and + associated with it. The reference counter, if any, is incremented. So, when you modify the matrix + formed using such a constructor, you also modify the corresponding elements of m . If you want to + have an independent copy of the sub-array, use Mat::clone() . + @param ranges Array of selected ranges of m along each dimensionality. + */ + Mat(const Mat& m, const Range* ranges); + + /** @overload + @param vec STL vector whose elements form the matrix. The matrix has a single column and the number + of rows equal to the number of vector elements. Type of the matrix matches the type of vector + elements. The constructor can handle arbitrary types, for which there is a properly declared + DataType . This means that the vector elements must be primitive numbers or uni-type numerical + tuples of numbers. Mixed-type structures are not supported. The corresponding constructor is + explicit. Since STL vectors are not automatically converted to Mat instances, you should write + Mat(vec) explicitly. Unless you copy the data into the matrix ( copyData=true ), no new elements + will be added to the vector because it can potentially yield vector data reallocation, and, thus, + the matrix data pointer will be invalid. + @param copyData Flag to specify whether the underlying data of the STL vector should be copied + to (true) or shared with (false) the newly constructed matrix. When the data is copied, the + allocated buffer is managed using Mat reference counting mechanism. While the data is shared, + the reference counter is NULL, and you should not deallocate the data until the matrix is not + destructed. + */ + template<typename _Tp> explicit Mat(const std::vector<_Tp>& vec, bool copyData=false); + + /** @overload + */ + template<typename _Tp, int n> explicit Mat(const Vec<_Tp, n>& vec, bool copyData=true); + + /** @overload + */ + template<typename _Tp, int m, int n> explicit Mat(const Matx<_Tp, m, n>& mtx, bool copyData=true); + + /** @overload + */ + template<typename _Tp> explicit Mat(const Point_<_Tp>& pt, bool copyData=true); + + /** @overload + */ + template<typename _Tp> explicit Mat(const Point3_<_Tp>& pt, bool copyData=true); + + /** @overload + */ + template<typename _Tp> explicit Mat(const MatCommaInitializer_<_Tp>& commaInitializer); + + //! download data from GpuMat + explicit Mat(const cuda::GpuMat& m); + + //! destructor - calls release() + ~Mat(); + + /** @brief assignment operators + + These are available assignment operators. Since they all are very different, make sure to read the + operator parameters description. + @param m Assigned, right-hand-side matrix. Matrix assignment is an O(1) operation. This means that + no data is copied but the data is shared and the reference counter, if any, is incremented. Before + assigning new data, the old data is de-referenced via Mat::release . + */ + Mat& operator = (const Mat& m); + + /** @overload + @param expr Assigned matrix expression object. As opposite to the first form of the assignment + operation, the second form can reuse already allocated matrix if it has the right size and type to + fit the matrix expression result. It is automatically handled by the real function that the matrix + expressions is expanded to. For example, C=A+B is expanded to add(A, B, C), and add takes care of + automatic C reallocation. + */ + Mat& operator = (const MatExpr& expr); + + //! retrieve UMat from Mat + UMat getUMat(int accessFlags, UMatUsageFlags usageFlags = USAGE_DEFAULT) const; + + /** @brief Creates a matrix header for the specified matrix row. + + The method makes a new header for the specified matrix row and returns it. This is an O(1) + operation, regardless of the matrix size. The underlying data of the new matrix is shared with the + original matrix. Here is the example of one of the classical basic matrix processing operations, + axpy, used by LU and many other algorithms: + @code + inline void matrix_axpy(Mat& A, int i, int j, double alpha) + { + A.row(i) += A.row(j)*alpha; + } + @endcode + @note In the current implementation, the following code does not work as expected: + @code + Mat A; + ... + A.row(i) = A.row(j); // will not work + @endcode + This happens because A.row(i) forms a temporary header that is further assigned to another header. + Remember that each of these operations is O(1), that is, no data is copied. Thus, the above + assignment is not true if you may have expected the j-th row to be copied to the i-th row. To + achieve that, you should either turn this simple assignment into an expression or use the + Mat::copyTo method: + @code + Mat A; + ... + // works, but looks a bit obscure. + A.row(i) = A.row(j) + 0; + // this is a bit longer, but the recommended method. + A.row(j).copyTo(A.row(i)); + @endcode + @param y A 0-based row index. + */ + Mat row(int y) const; + + /** @brief Creates a matrix header for the specified matrix column. + + The method makes a new header for the specified matrix column and returns it. This is an O(1) + operation, regardless of the matrix size. The underlying data of the new matrix is shared with the + original matrix. See also the Mat::row description. + @param x A 0-based column index. + */ + Mat col(int x) const; + + /** @brief Creates a matrix header for the specified row span. + + The method makes a new header for the specified row span of the matrix. Similarly to Mat::row and + Mat::col , this is an O(1) operation. + @param startrow An inclusive 0-based start index of the row span. + @param endrow An exclusive 0-based ending index of the row span. + */ + Mat rowRange(int startrow, int endrow) const; + + /** @overload + @param r Range structure containing both the start and the end indices. + */ + Mat rowRange(const Range& r) const; + + /** @brief Creates a matrix header for the specified column span. + + The method makes a new header for the specified column span of the matrix. Similarly to Mat::row and + Mat::col , this is an O(1) operation. + @param startcol An inclusive 0-based start index of the column span. + @param endcol An exclusive 0-based ending index of the column span. + */ + Mat colRange(int startcol, int endcol) const; + + /** @overload + @param r Range structure containing both the start and the end indices. + */ + Mat colRange(const Range& r) const; + + /** @brief Extracts a diagonal from a matrix + + The method makes a new header for the specified matrix diagonal. The new matrix is represented as a + single-column matrix. Similarly to Mat::row and Mat::col, this is an O(1) operation. + @param d index of the diagonal, with the following values: + - `d=0` is the main diagonal. + - `d>0` is a diagonal from the lower half. For example, d=1 means the diagonal is set + immediately below the main one. + - `d<0` is a diagonal from the upper half. For example, d=-1 means the diagonal is set + immediately above the main one. + */ + Mat diag(int d=0) const; + + /** @brief creates a diagonal matrix + + The method makes a new header for the specified matrix diagonal. The new matrix is represented as a + single-column matrix. Similarly to Mat::row and Mat::col, this is an O(1) operation. + @param d Single-column matrix that forms a diagonal matrix + */ + static Mat diag(const Mat& d); + + /** @brief Creates a full copy of the array and the underlying data. + + The method creates a full copy of the array. The original step[] is not taken into account. So, the + array copy is a continuous array occupying total()*elemSize() bytes. + */ + Mat clone() const; + + /** @brief Copies the matrix to another one. + + The method copies the matrix data to another matrix. Before copying the data, the method invokes : + @code + m.create(this->size(), this->type()); + @endcode + so that the destination matrix is reallocated if needed. While m.copyTo(m); works flawlessly, the + function does not handle the case of a partial overlap between the source and the destination + matrices. + + When the operation mask is specified, if the Mat::create call shown above reallocates the matrix, + the newly allocated matrix is initialized with all zeros before copying the data. + @param m Destination matrix. If it does not have a proper size or type before the operation, it is + reallocated. + */ + void copyTo( OutputArray m ) const; + + /** @overload + @param m Destination matrix. If it does not have a proper size or type before the operation, it is + reallocated. + @param mask Operation mask. Its non-zero elements indicate which matrix elements need to be copied. + The mask has to be of type CV_8U and can have 1 or multiple channels. + */ + void copyTo( OutputArray m, InputArray mask ) const; + + /** @brief Converts an array to another data type with optional scaling. + + The method converts source pixel values to the target data type. saturate_cast\<\> is applied at + the end to avoid possible overflows: + + \f[m(x,y) = saturate \_ cast<rType>( \alpha (*this)(x,y) + \beta )\f] + @param m output matrix; if it does not have a proper size or type before the operation, it is + reallocated. + @param 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 alpha optional scale factor. + @param beta optional delta added to the scaled values. + */ + void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const; + + /** @brief Provides a functional form of convertTo. + + This is an internally used method called by the @ref MatrixExpressions engine. + @param m Destination array. + @param type Desired destination array depth (or -1 if it should be the same as the source type). + */ + void assignTo( Mat& m, int type=-1 ) const; + + /** @brief Sets all or some of the array elements to the specified value. + @param s Assigned scalar converted to the actual array type. + */ + Mat& operator = (const Scalar& s); + + /** @brief Sets all or some of the array elements to the specified value. + + This is an advanced variant of the Mat::operator=(const Scalar& s) operator. + @param value Assigned scalar converted to the actual array type. + @param mask Operation mask of the same size as \*this. + */ + Mat& setTo(InputArray value, InputArray mask=noArray()); + + /** @brief Changes the shape and/or the number of channels of a 2D matrix without copying the data. + + The method makes a new matrix header for \*this elements. The new matrix may have a different size + and/or different number of channels. Any combination is possible if: + - No extra elements are included into the new matrix and no elements are excluded. Consequently, + the product rows\*cols\*channels() must stay the same after the transformation. + - No data is copied. That is, this is an O(1) operation. Consequently, if you change the number of + rows, or the operation changes the indices of elements row in some other way, the matrix must be + continuous. See Mat::isContinuous . + + For example, if there is a set of 3D points stored as an STL vector, and you want to represent the + points as a 3xN matrix, do the following: + @code + std::vector<Point3f> vec; + ... + Mat pointMat = Mat(vec). // convert vector to Mat, O(1) operation + reshape(1). // make Nx3 1-channel matrix out of Nx1 3-channel. + // Also, an O(1) operation + t(); // finally, transpose the Nx3 matrix. + // This involves copying all the elements + @endcode + @param cn New number of channels. If the parameter is 0, the number of channels remains the same. + @param rows New number of rows. If the parameter is 0, the number of rows remains the same. + */ + Mat reshape(int cn, int rows=0) const; + + /** @overload */ + Mat reshape(int cn, int newndims, const int* newsz) const; + + /** @brief Transposes a matrix. + + The method performs matrix transposition by means of matrix expressions. It does not perform the + actual transposition but returns a temporary matrix transposition object that can be further used as + a part of more complex matrix expressions or can be assigned to a matrix: + @code + Mat A1 = A + Mat::eye(A.size(), A.type())*lambda; + Mat C = A1.t()*A1; // compute (A + lambda*I)^t * (A + lamda*I) + @endcode + */ + MatExpr t() const; + + /** @brief Inverses a matrix. + + The method performs a matrix inversion by means of matrix expressions. This means that a temporary + matrix inversion object is returned by the method and can be used further as a part of more complex + matrix expressions or can be assigned to a matrix. + @param method Matrix inversion method. One of cv::DecompTypes + */ + MatExpr inv(int method=DECOMP_LU) const; + + /** @brief Performs an element-wise multiplication or division of the two matrices. + + The method returns a temporary object encoding per-element array multiplication, with optional + scale. Note that this is not a matrix multiplication that corresponds to a simpler "\*" operator. + + Example: + @code + Mat C = A.mul(5/B); // equivalent to divide(A, B, C, 5) + @endcode + @param m Another array of the same type and the same size as \*this, or a matrix expression. + @param scale Optional scale factor. + */ + MatExpr mul(InputArray m, double scale=1) const; + + /** @brief Computes a cross-product of two 3-element vectors. + + The method computes a cross-product of two 3-element vectors. The vectors must be 3-element + floating-point vectors of the same shape and size. The result is another 3-element vector of the + same shape and type as operands. + @param m Another cross-product operand. + */ + Mat cross(InputArray m) const; + + /** @brief Computes a dot-product of two vectors. + + The method computes a dot-product of two matrices. If the matrices are not single-column or + single-row vectors, the top-to-bottom left-to-right scan ordering is used to treat them as 1D + vectors. The vectors must have the same size and type. If the matrices have more than one channel, + the dot products from all the channels are summed together. + @param m another dot-product operand. + */ + double dot(InputArray m) const; + + /** @brief Returns a zero array of the specified size and type. + + The method returns a Matlab-style zero array initializer. It can be used to quickly form a constant + array as a function parameter, part of a matrix expression, or as a matrix initializer. : + @code + Mat A; + A = Mat::zeros(3, 3, CV_32F); + @endcode + In the example above, a new matrix is allocated only if A is not a 3x3 floating-point matrix. + Otherwise, the existing matrix A is filled with zeros. + @param rows Number of rows. + @param cols Number of columns. + @param type Created matrix type. + */ + static MatExpr zeros(int rows, int cols, int type); + + /** @overload + @param size Alternative to the matrix size specification Size(cols, rows) . + @param type Created matrix type. + */ + static MatExpr zeros(Size size, int type); + + /** @overload + @param ndims Array dimensionality. + @param sz Array of integers specifying the array shape. + @param type Created matrix type. + */ + static MatExpr zeros(int ndims, const int* sz, int type); + + /** @brief Returns an array of all 1's of the specified size and type. + + The method returns a Matlab-style 1's array initializer, similarly to Mat::zeros. Note that using + this method you can initialize an array with an arbitrary value, using the following Matlab idiom: + @code + Mat A = Mat::ones(100, 100, CV_8U)*3; // make 100x100 matrix filled with 3. + @endcode + The above operation does not form a 100x100 matrix of 1's and then multiply it by 3. Instead, it + just remembers the scale factor (3 in this case) and use it when actually invoking the matrix + initializer. + @param rows Number of rows. + @param cols Number of columns. + @param type Created matrix type. + */ + static MatExpr ones(int rows, int cols, int type); + + /** @overload + @param size Alternative to the matrix size specification Size(cols, rows) . + @param type Created matrix type. + */ + static MatExpr ones(Size size, int type); + + /** @overload + @param ndims Array dimensionality. + @param sz Array of integers specifying the array shape. + @param type Created matrix type. + */ + static MatExpr ones(int ndims, const int* sz, int type); + + /** @brief Returns an identity matrix of the specified size and type. + + The method returns a Matlab-style identity matrix initializer, similarly to Mat::zeros. Similarly to + Mat::ones, you can use a scale operation to create a scaled identity matrix efficiently: + @code + // make a 4x4 diagonal matrix with 0.1's on the diagonal. + Mat A = Mat::eye(4, 4, CV_32F)*0.1; + @endcode + @param rows Number of rows. + @param cols Number of columns. + @param type Created matrix type. + */ + static MatExpr eye(int rows, int cols, int type); + + /** @overload + @param size Alternative matrix size specification as Size(cols, rows) . + @param type Created matrix type. + */ + static MatExpr eye(Size size, int type); + + /** @brief Allocates new array data if needed. + + This is one of the key Mat methods. Most new-style OpenCV functions and methods that produce arrays + call this method for each output array. The method uses the following algorithm: + + -# If the current array shape and the type match the new ones, return immediately. Otherwise, + de-reference the previous data by calling Mat::release. + -# Initialize the new header. + -# Allocate the new data of total()\*elemSize() bytes. + -# Allocate the new, associated with the data, reference counter and set it to 1. + + Such a scheme makes the memory management robust and efficient at the same time and helps avoid + extra typing for you. This means that usually there is no need to explicitly allocate output arrays. + That is, instead of writing: + @code + Mat color; + ... + Mat gray(color.rows, color.cols, color.depth()); + cvtColor(color, gray, COLOR_BGR2GRAY); + @endcode + you can simply write: + @code + Mat color; + ... + Mat gray; + cvtColor(color, gray, COLOR_BGR2GRAY); + @endcode + because cvtColor, as well as the most of OpenCV functions, calls Mat::create() for the output array + internally. + @param rows New number of rows. + @param cols New number of columns. + @param type New matrix type. + */ + void create(int rows, int cols, int type); + + /** @overload + @param size Alternative new matrix size specification: Size(cols, rows) + @param type New matrix type. + */ + void create(Size size, int type); + + /** @overload + @param ndims New array dimensionality. + @param sizes Array of integers specifying a new array shape. + @param type New matrix type. + */ + void create(int ndims, const int* sizes, int type); + + /** @brief Increments the reference counter. + + The method increments the reference counter associated with the matrix data. If the matrix header + points to an external data set (see Mat::Mat ), the reference counter is NULL, and the method has no + effect in this case. Normally, to avoid memory leaks, the method should not be called explicitly. It + is called implicitly by the matrix assignment operator. The reference counter increment is an atomic + operation on the platforms that support it. Thus, it is safe to operate on the same matrices + asynchronously in different threads. + */ + void addref(); + + /** @brief Decrements the reference counter and deallocates the matrix if needed. + + The method decrements the reference counter associated with the matrix data. When the reference + counter reaches 0, the matrix data is deallocated and the data and the reference counter pointers + are set to NULL's. If the matrix header points to an external data set (see Mat::Mat ), the + reference counter is NULL, and the method has no effect in this case. + + This method can be called manually to force the matrix data deallocation. But since this method is + automatically called in the destructor, or by any other method that changes the data pointer, it is + usually not needed. The reference counter decrement and check for 0 is an atomic operation on the + platforms that support it. Thus, it is safe to operate on the same matrices asynchronously in + different threads. + */ + void release(); + + //! deallocates the matrix data + void deallocate(); + //! internal use function; properly re-allocates _size, _step arrays + void copySize(const Mat& m); + + /** @brief Reserves space for the certain number of rows. + + The method reserves space for sz rows. If the matrix already has enough space to store sz rows, + nothing happens. If the matrix is reallocated, the first Mat::rows rows are preserved. The method + emulates the corresponding method of the STL vector class. + @param sz Number of rows. + */ + void reserve(size_t sz); + + /** @brief Changes the number of matrix rows. + + The methods change the number of matrix rows. If the matrix is reallocated, the first + min(Mat::rows, sz) rows are preserved. The methods emulate the corresponding methods of the STL + vector class. + @param sz New number of rows. + */ + void resize(size_t sz); + + /** @overload + @param sz New number of rows. + @param s Value assigned to the newly added elements. + */ + void resize(size_t sz, const Scalar& s); + + //! internal function + void push_back_(const void* elem); + + /** @brief Adds elements to the bottom of the matrix. + + The methods add one or more elements to the bottom of the matrix. They emulate the corresponding + method of the STL vector class. When elem is Mat , its type and the number of columns must be the + same as in the container matrix. + @param elem Added element(s). + */ + template<typename _Tp> void push_back(const _Tp& elem); + + /** @overload + @param elem Added element(s). + */ + template<typename _Tp> void push_back(const Mat_<_Tp>& elem); + + /** @overload + @param m Added line(s). + */ + void push_back(const Mat& m); + + /** @brief Removes elements from the bottom of the matrix. + + The method removes one or more rows from the bottom of the matrix. + @param nelems Number of removed rows. If it is greater than the total number of rows, an exception + is thrown. + */ + void pop_back(size_t nelems=1); + + /** @brief Locates the matrix header within a parent matrix. + + After you extracted a submatrix from a matrix using Mat::row, Mat::col, Mat::rowRange, + Mat::colRange, and others, the resultant submatrix points just to the part of the original big + matrix. However, each submatrix contains information (represented by datastart and dataend + fields) that helps reconstruct the original matrix size and the position of the extracted + submatrix within the original matrix. The method locateROI does exactly that. + @param wholeSize Output parameter that contains the size of the whole matrix containing *this* + as a part. + @param ofs Output parameter that contains an offset of *this* inside the whole matrix. + */ + void locateROI( Size& wholeSize, Point& ofs ) const; + + /** @brief Adjusts a submatrix size and position within the parent matrix. + + The method is complimentary to Mat::locateROI . The typical use of these functions is to determine + the submatrix position within the parent matrix and then shift the position somehow. Typically, it + can be required for filtering operations when pixels outside of the ROI should be taken into + account. When all the method parameters are positive, the ROI needs to grow in all directions by the + specified amount, for example: + @code + A.adjustROI(2, 2, 2, 2); + @endcode + In this example, the matrix size is increased by 4 elements in each direction. The matrix is shifted + by 2 elements to the left and 2 elements up, which brings in all the necessary pixels for the + filtering with the 5x5 kernel. + + adjustROI forces the adjusted ROI to be inside of the parent matrix that is boundaries of the + adjusted ROI are constrained by boundaries of the parent matrix. For example, if the submatrix A is + located in the first row of a parent matrix and you called A.adjustROI(2, 2, 2, 2) then A will not + be increased in the upward direction. + + The function is used internally by the OpenCV filtering functions, like filter2D , morphological + operations, and so on. + @param dtop Shift of the top submatrix boundary upwards. + @param dbottom Shift of the bottom submatrix boundary downwards. + @param dleft Shift of the left submatrix boundary to the left. + @param dright Shift of the right submatrix boundary to the right. + @sa copyMakeBorder + */ + Mat& adjustROI( int dtop, int dbottom, int dleft, int dright ); + + /** @brief Extracts a rectangular submatrix. + + The operators make a new header for the specified sub-array of \*this . They are the most + generalized forms of Mat::row, Mat::col, Mat::rowRange, and Mat::colRange . For example, + `A(Range(0, 10), Range::all())` is equivalent to `A.rowRange(0, 10)`. Similarly to all of the above, + the operators are O(1) operations, that is, no matrix data is copied. + @param rowRange Start and end row of the extracted submatrix. The upper boundary is not included. To + select all the rows, use Range::all(). + @param colRange Start and end column of the extracted submatrix. The upper boundary is not included. + To select all the columns, use Range::all(). + */ + Mat operator()( Range rowRange, Range colRange ) const; + + /** @overload + @param roi Extracted submatrix specified as a rectangle. + */ + Mat operator()( const Rect& roi ) const; + + /** @overload + @param ranges Array of selected ranges along each array dimension. + */ + 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<typename _Tp> operator std::vector<_Tp>() const; + template<typename _Tp, int n> operator Vec<_Tp, n>() const; + template<typename _Tp, int m, int n> operator Matx<_Tp, m, n>() const; + + /** @brief Reports whether the matrix is continuous or not. + + The method returns true if the matrix elements are stored continuously without gaps at the end of + each row. Otherwise, it returns false. Obviously, 1x1 or 1xN matrices are always continuous. + Matrices created with Mat::create are always continuous. But if you extract a part of the matrix + using Mat::col, Mat::diag, and so on, or constructed a matrix header for externally allocated data, + such matrices may no longer have this property. + + The continuity flag is stored as a bit in the Mat::flags field and is computed automatically when + you construct a matrix header. Thus, the continuity check is a very fast operation, though + theoretically it could be done as follows: + @code + // alternative implementation of Mat::isContinuous() + bool myCheckMatContinuity(const Mat& m) + { + //return (m.flags & Mat::CONTINUOUS_FLAG) != 0; + return m.rows == 1 || m.step == m.cols*m.elemSize(); + } + @endcode + The method is used in quite a few of OpenCV functions. The point is that element-wise operations + (such as arithmetic and logical operations, math functions, alpha blending, color space + transformations, and others) do not depend on the image geometry. Thus, if all the input and output + arrays are continuous, the functions can process them as very long single-row vectors. The example + below illustrates how an alpha-blending function can be implemented: + @code + template<typename T> + void alphaBlendRGBA(const Mat& src1, const Mat& src2, Mat& dst) + { + const float alpha_scale = (float)std::numeric_limits<T>::max(), + inv_scale = 1.f/alpha_scale; + + CV_Assert( src1.type() == src2.type() && + src1.type() == CV_MAKETYPE(DataType<T>::depth, 4) && + src1.size() == src2.size()); + Size size = src1.size(); + dst.create(size, src1.type()); + + // here is the idiom: check the arrays for continuity and, + // if this is the case, + // treat the arrays as 1D vectors + if( src1.isContinuous() && src2.isContinuous() && dst.isContinuous() ) + { + size.width *= size.height; + size.height = 1; + } + size.width *= 4; + + for( int i = 0; i < size.height; i++ ) + { + // when the arrays are continuous, + // the outer loop is executed only once + const T* ptr1 = src1.ptr<T>(i); + const T* ptr2 = src2.ptr<T>(i); + T* dptr = dst.ptr<T>(i); + + for( int j = 0; j < size.width; j += 4 ) + { + float alpha = ptr1[j+3]*inv_scale, beta = ptr2[j+3]*inv_scale; + dptr[j] = saturate_cast<T>(ptr1[j]*alpha + ptr2[j]*beta); + dptr[j+1] = saturate_cast<T>(ptr1[j+1]*alpha + ptr2[j+1]*beta); + dptr[j+2] = saturate_cast<T>(ptr1[j+2]*alpha + ptr2[j+2]*beta); + dptr[j+3] = saturate_cast<T>((1 - (1-alpha)*(1-beta))*alpha_scale); + } + } + } + @endcode + This approach, while being very simple, can boost the performance of a simple element-operation by + 10-20 percents, especially if the image is rather small and the operation is quite simple. + + Another OpenCV idiom in this function, a call of Mat::create for the destination array, that + allocates the destination array unless it already has the proper size and type. And while the newly + allocated arrays are always continuous, you still need to check the destination array because + Mat::create does not always allocate a new matrix. + */ + bool isContinuous() const; + + //! returns true if the matrix is a submatrix of another matrix + bool isSubmatrix() const; + + /** @brief Returns the matrix element size in bytes. + + The method returns the matrix element size in bytes. For example, if the matrix type is CV_16SC3 , + the method returns 3\*sizeof(short) or 6. + */ + size_t elemSize() const; + + /** @brief Returns the size of each matrix element channel in bytes. + + The method returns the matrix element channel size in bytes, that is, it ignores the number of + channels. For example, if the matrix type is CV_16SC3 , the method returns sizeof(short) or 2. + */ + size_t elemSize1() const; + + /** @brief Returns the type of a matrix element. + + The method returns a matrix element type. This is an identifier compatible with the CvMat type + system, like CV_16SC3 or 16-bit signed 3-channel array, and so on. + */ + int type() const; + + /** @brief Returns the depth of a matrix element. + + The method returns the identifier of the matrix element depth (the type of each individual channel). + For example, for a 16-bit signed element array, the method returns CV_16S . A complete list of + matrix types contains the following values: + - CV_8U - 8-bit unsigned integers ( 0..255 ) + - CV_8S - 8-bit signed integers ( -128..127 ) + - CV_16U - 16-bit unsigned integers ( 0..65535 ) + - CV_16S - 16-bit signed integers ( -32768..32767 ) + - CV_32S - 32-bit signed integers ( -2147483648..2147483647 ) + - CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN ) + - CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN ) + */ + int depth() const; + + /** @brief Returns the number of matrix channels. + + The method returns the number of matrix channels. + */ + int channels() const; + + /** @brief Returns a normalized step. + + The method returns a matrix step divided by Mat::elemSize1() . It can be useful to quickly access an + arbitrary matrix element. + */ + size_t step1(int i=0) const; + + /** @brief Returns true if the array has no elements. + + The method returns true if Mat::total() is 0 or if Mat::data is NULL. Because of pop_back() and + resize() methods `M.total() == 0` does not imply that `M.data == NULL`. + */ + bool empty() const; + + /** @brief Returns the total number of array elements. + + The method returns the number of array elements (a number of pixels if the array represents an + image). + */ + 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; + + /** @brief Returns a pointer to the specified matrix row. + + The methods return `uchar*` or typed pointer to the specified matrix row. See the sample in + Mat::isContinuous to know how to use these methods. + @param i0 A 0-based row index. + */ + uchar* ptr(int i0=0); + /** @overload */ + const uchar* ptr(int i0=0) const; + + /** @overload */ + uchar* ptr(int i0, int i1); + /** @overload */ + const uchar* ptr(int i0, int i1) const; + + /** @overload */ + uchar* ptr(int i0, int i1, int i2); + /** @overload */ + const uchar* ptr(int i0, int i1, int i2) const; + + /** @overload */ + uchar* ptr(const int* idx); + /** @overload */ + const uchar* ptr(const int* idx) const; + /** @overload */ + template<int n> uchar* ptr(const Vec<int, n>& idx); + /** @overload */ + template<int n> const uchar* ptr(const Vec<int, n>& idx) const; + + /** @overload */ + template<typename _Tp> _Tp* ptr(int i0=0); + /** @overload */ + template<typename _Tp> const _Tp* ptr(int i0=0) const; + /** @overload */ + template<typename _Tp> _Tp* ptr(int i0, int i1); + /** @overload */ + template<typename _Tp> const _Tp* ptr(int i0, int i1) const; + /** @overload */ + template<typename _Tp> _Tp* ptr(int i0, int i1, int i2); + /** @overload */ + template<typename _Tp> const _Tp* ptr(int i0, int i1, int i2) const; + /** @overload */ + template<typename _Tp> _Tp* ptr(const int* idx); + /** @overload */ + template<typename _Tp> const _Tp* ptr(const int* idx) const; + /** @overload */ + template<typename _Tp, int n> _Tp* ptr(const Vec<int, n>& idx); + /** @overload */ + template<typename _Tp, int n> const _Tp* ptr(const Vec<int, n>& idx) const; + + /** @brief Returns a reference to the specified array element. + + The template methods return a reference to the specified array element. For the sake of higher + performance, the index range checks are only performed in the Debug configuration. + + Note that the variants with a single index (i) can be used to access elements of single-row or + single-column 2-dimensional arrays. That is, if, for example, A is a 1 x N floating-point matrix and + B is an M x 1 integer matrix, you can simply write `A.at<float>(k+4)` and `B.at<int>(2*i+1)` + instead of `A.at<float>(0,k+4)` and `B.at<int>(2*i+1,0)`, respectively. + + The example below initializes a Hilbert matrix: + @code + Mat H(100, 100, CV_64F); + for(int i = 0; i < H.rows; i++) + for(int j = 0; j < H.cols; j++) + H.at<double>(i,j)=1./(i+j+1); + @endcode + @param i0 Index along the dimension 0 + */ + template<typename _Tp> _Tp& at(int i0=0); + /** @overload + @param i0 Index along the dimension 0 + */ + template<typename _Tp> const _Tp& at(int i0=0) const; + /** @overload + @param i0 Index along the dimension 0 + @param i1 Index along the dimension 1 + */ + template<typename _Tp> _Tp& at(int i0, int i1); + /** @overload + @param i0 Index along the dimension 0 + @param i1 Index along the dimension 1 + */ + template<typename _Tp> const _Tp& at(int i0, int i1) const; + + /** @overload + @param i0 Index along the dimension 0 + @param i1 Index along the dimension 1 + @param i2 Index along the dimension 2 + */ + template<typename _Tp> _Tp& at(int i0, int i1, int i2); + /** @overload + @param i0 Index along the dimension 0 + @param i1 Index along the dimension 1 + @param i2 Index along the dimension 2 + */ + template<typename _Tp> const _Tp& at(int i0, int i1, int i2) const; + + /** @overload + @param idx Array of Mat::dims indices. + */ + template<typename _Tp> _Tp& at(const int* idx); + /** @overload + @param idx Array of Mat::dims indices. + */ + template<typename _Tp> const _Tp& at(const int* idx) const; + + /** @overload */ + template<typename _Tp, int n> _Tp& at(const Vec<int, n>& idx); + /** @overload */ + template<typename _Tp, int n> const _Tp& at(const Vec<int, n>& idx) const; + + /** @overload + special versions for 2D arrays (especially convenient for referencing image pixels) + @param pt Element position specified as Point(j,i) . + */ + template<typename _Tp> _Tp& at(Point pt); + /** @overload + special versions for 2D arrays (especially convenient for referencing image pixels) + @param pt Element position specified as Point(j,i) . + */ + template<typename _Tp> const _Tp& at(Point pt) const; + + /** @brief Returns the matrix iterator and sets it to the first matrix element. + + The methods return the matrix read-only or read-write iterators. The use of matrix iterators is very + similar to the use of bi-directional STL iterators. In the example below, the alpha blending + function is rewritten using the matrix iterators: + @code + template<typename T> + void alphaBlendRGBA(const Mat& src1, const Mat& src2, Mat& dst) + { + typedef Vec<T, 4> VT; + + const float alpha_scale = (float)std::numeric_limits<T>::max(), + inv_scale = 1.f/alpha_scale; + + CV_Assert( src1.type() == src2.type() && + src1.type() == DataType<VT>::type && + src1.size() == src2.size()); + Size size = src1.size(); + dst.create(size, src1.type()); + + MatConstIterator_<VT> it1 = src1.begin<VT>(), it1_end = src1.end<VT>(); + MatConstIterator_<VT> it2 = src2.begin<VT>(); + MatIterator_<VT> dst_it = dst.begin<VT>(); + + for( ; it1 != it1_end; ++it1, ++it2, ++dst_it ) + { + VT pix1 = *it1, pix2 = *it2; + float alpha = pix1[3]*inv_scale, beta = pix2[3]*inv_scale; + *dst_it = VT(saturate_cast<T>(pix1[0]*alpha + pix2[0]*beta), + saturate_cast<T>(pix1[1]*alpha + pix2[1]*beta), + saturate_cast<T>(pix1[2]*alpha + pix2[2]*beta), + saturate_cast<T>((1 - (1-alpha)*(1-beta))*alpha_scale)); + } + } + @endcode + */ + template<typename _Tp> MatIterator_<_Tp> begin(); + template<typename _Tp> MatConstIterator_<_Tp> begin() const; + + /** @brief Returns the matrix iterator and sets it to the after-last matrix element. + + The methods return the matrix read-only or read-write iterators, set to the point following the last + matrix element. + */ + template<typename _Tp> MatIterator_<_Tp> end(); + template<typename _Tp> MatConstIterator_<_Tp> end() const; + + /** @brief Invoke with arguments functor, and runs the functor over all matrix element. + + The methods runs operation in parallel. Operation is passed by arguments. Operation have to be a + function pointer, a function object or a lambda(C++11). + + All of below operation is equal. Put 0xFF to first channel of all matrix elements: + @code + Mat image(1920, 1080, CV_8UC3); + typedef cv::Point3_<uint8_t> Pixel; + + // first. raw pointer access. + for (int r = 0; r < image.rows; ++r) { + Pixel* ptr = image.ptr<Pixel>(0, r); + const Pixel* ptr_end = ptr + image.cols; + for (; ptr != ptr_end; ++ptr) { + ptr->x = 255; + } + } + + // Using MatIterator. (Simple but there are a Iterator's overhead) + for (Pixel &p : cv::Mat_<Pixel>(image)) { + p.x = 255; + } + + // Parallel execution with function object. + struct Operator { + void operator ()(Pixel &pixel, const int * position) { + pixel.x = 255; + } + }; + image.forEach<Pixel>(Operator()); + + // Parallel execution using C++11 lambda. + image.forEach<Pixel>([](Pixel &p, const int * position) -> void { + p.x = 255; + }); + @endcode + position parameter is index of current pixel: + @code + // Creating 3D matrix (255 x 255 x 255) typed uint8_t, + // and initialize all elements by the value which equals elements position. + // i.e. pixels (x,y,z) = (1,2,3) is (b,g,r) = (1,2,3). + + int sizes[] = { 255, 255, 255 }; + typedef cv::Point3_<uint8_t> Pixel; + + Mat_<Pixel> image = Mat::zeros(3, sizes, CV_8UC3); + + image.forEachWithPosition([&](Pixel& pixel, const int position[]) -> void{ + pixel.x = position[0]; + pixel.y = position[1]; + pixel.z = position[2]; + }); + @endcode + */ + template<typename _Tp, typename Functor> void forEach(const Functor& operation); + /** @overload */ + template<typename _Tp, typename Functor> void forEach(const Functor& operation) const; + +#ifdef CV_CXX_MOVE_SEMANTICS + Mat(Mat&& m); + Mat& operator = (Mat&& m); +#endif + + 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(); + static MatAllocator* getDefaultAllocator(); + static void setDefaultAllocator(MatAllocator* allocator); + + //! interaction with UMat + UMatData* u; + + MatSize size; + MatStep step; + +protected: + template<typename _Tp, typename Functor> void forEach_impl(const Functor& operation); +}; + + +///////////////////////////////// Mat_<_Tp> //////////////////////////////////// + +/** @brief Template matrix class derived from Mat + +@code + template<typename _Tp> class Mat_ : public Mat + { + public: + // ... some specific methods + // and + // no new extra fields + }; +@endcode +The class `Mat_<_Tp>` is a *thin* template wrapper on top of the Mat class. It does not have any +extra data fields. Nor this class nor Mat has any virtual methods. Thus, references or pointers to +these two classes can be freely but carefully converted one to another. For example: +@code + // create a 100x100 8-bit matrix + Mat M(100,100,CV_8U); + // this will be compiled fine. no any data conversion will be done. + Mat_<float>& M1 = (Mat_<float>&)M; + // the program is likely to crash at the statement below + M1(99,99) = 1.f; +@endcode +While Mat is sufficient in most cases, Mat_ can be more convenient if you use a lot of element +access operations and if you know matrix type at the compilation time. Note that +`Mat::at(int y,int x)` and `Mat_::operator()(int y,int x)` do absolutely the same +and run at the same speed, but the latter is certainly shorter: +@code + Mat_<double> 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<double>(0,0)/E.at<double>(M.rows-1,0); +@endcode +To use Mat_ for multi-channel images/matrices, pass Vec as a Mat_ parameter: +@code + // allocate a 320x240 color image and fill it with green (in RGB space) + Mat_<Vec3b> 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 scramble 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); +@endcode + */ +template<typename _Tp> class Mat_ : public Mat +{ +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<int n> explicit Mat_(const Vec<typename DataType<_Tp>::channel_type, n>& vec, bool copyData=true); + template<int m, int n> explicit Mat_(const Matx<typename DataType<_Tp>::channel_type, m, n>& mtx, bool copyData=true); + explicit Mat_(const Point_<typename DataType<_Tp>::channel_type>& pt, bool copyData=true); + explicit Mat_(const Point3_<typename DataType<_Tp>::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<typename Functor> void forEach(const Functor& operation); + template<typename Functor> 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<typename T2> operator Mat_<T2>() 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<int n> _Tp& operator ()(const Vec<int, n>& idx); + //! returns read-only reference to the specified element + template<int n> const _Tp& operator ()(const Vec<int, n>& idx) const; + + //! returns reference to the specified element (1D case) + _Tp& operator ()(int idx0); + //! returns read-only reference to the specified element (1D case) + const _Tp& operator ()(int idx0) const; + //! returns reference to the specified element (2D case) + _Tp& operator ()(int idx0, int idx1); + //! returns read-only reference to the specified element (2D case) + const _Tp& operator ()(int idx0, int idx1) const; + //! returns reference to the specified element (3D case) + _Tp& operator ()(int idx0, int idx1, int idx2); + //! returns read-only reference to the specified element (3D case) + const _Tp& operator ()(int idx0, int idx1, int idx2) const; + + _Tp& operator ()(Point pt); + const _Tp& operator ()(Point pt) const; + + //! conversion to vector. + operator std::vector<_Tp>() const; + //! conversion to Vec + template<int n> operator Vec<typename DataType<_Tp>::channel_type, n>() const; + //! conversion to Matx + template<int m, int n> operator Matx<typename DataType<_Tp>::channel_type, m, n>() const; + +#ifdef CV_CXX_MOVE_SEMANTICS + Mat_(Mat_&& m); + Mat_& operator = (Mat_&& m); + + Mat_(Mat&& m); + Mat_& operator = (Mat&& m); + + Mat_(MatExpr&& e); +#endif +}; + +typedef Mat_<uchar> Mat1b; +typedef Mat_<Vec2b> Mat2b; +typedef Mat_<Vec3b> Mat3b; +typedef Mat_<Vec4b> Mat4b; + +typedef Mat_<short> Mat1s; +typedef Mat_<Vec2s> Mat2s; +typedef Mat_<Vec3s> Mat3s; +typedef Mat_<Vec4s> Mat4s; + +typedef Mat_<ushort> Mat1w; +typedef Mat_<Vec2w> Mat2w; +typedef Mat_<Vec3w> Mat3w; +typedef Mat_<Vec4w> Mat4w; + +typedef Mat_<int> Mat1i; +typedef Mat_<Vec2i> Mat2i; +typedef Mat_<Vec3i> Mat3i; +typedef Mat_<Vec4i> Mat4i; + +typedef Mat_<float> Mat1f; +typedef Mat_<Vec2f> Mat2f; +typedef Mat_<Vec3f> Mat3f; +typedef Mat_<Vec4f> Mat4f; + +typedef Mat_<double> Mat1d; +typedef Mat_<Vec2d> Mat2d; +typedef Mat_<Vec3d> Mat3d; +typedef Mat_<Vec4d> Mat4d; + +/** @todo document */ +class CV_EXPORTS UMat +{ +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<typename _Tp> explicit UMat(const std::vector<_Tp>& vec, bool copyData=false); + //! builds matrix from cv::Vec; the data is copied by default + template<typename _Tp, int n> explicit UMat(const Vec<_Tp, n>& vec, bool copyData=true); + //! builds matrix from cv::Matx; the data is copied by default + template<typename _Tp, int m, int n> explicit UMat(const Matx<_Tp, m, n>& mtx, bool copyData=true); + //! builds matrix from a 2D point + template<typename _Tp> explicit UMat(const Point_<_Tp>& pt, bool copyData=true); + //! builds matrix from a 3D point + template<typename _Tp> explicit UMat(const Point3_<_Tp>& pt, bool copyData=true); + //! builds matrix from comma initializer + template<typename _Tp> 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; + +#ifdef CV_CXX_MOVE_SEMANTICS + UMat(UMat&& m); + UMat& operator = (UMat&& m); +#endif + + 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; + + //! custom allocator + MatAllocator* allocator; + UMatUsageFlags usageFlags; // usage flags for allocator + //! and the standard allocator + static MatAllocator* getStdAllocator(); + + // black-box container of UMat data + UMatData* u; + + // offset of the submatrix (or 0) + size_t offset; + + MatSize size; + MatStep step; + +protected: +}; + + +/////////////////////////// multi-dimensional sparse matrix ////////////////////////// + +/** @brief The class SparseMat represents multi-dimensional sparse numerical arrays. + +Such a sparse array can store elements of any type that Mat can store. *Sparse* means that only +non-zero elements are stored (though, as a result of operations on a sparse matrix, some of its +stored elements can actually become 0. It is up to you to detect such elements and delete them +using SparseMat::erase ). The non-zero elements are stored in a hash table that grows when it is +filled so that the search time is O(1) in average (regardless of whether element is there or not). +Elements can be accessed using the following methods: +- Query operations (SparseMat::ptr and the higher-level SparseMat::ref, SparseMat::value and + 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.ref<float>(idx) += 1.f; + } + @endcode +- Sparse matrix iterators. They are similar to MatIterator but different from NAryMatIterator. + That is, the iteration loop is familiar to STL users: + @code + // prints elements of a sparse floating-point matrix + // and the sum of elements. + SparseMatConstIterator_<float> + it = sparse_mat.begin<float>(), + it_end = sparse_mat.end<float>(); + double s = 0; + int dims = sparse_mat.dims(); + for(; it != it_end; ++it) + { + // print element indices and the element value + const SparseMat::Node* n = it.node(); + printf("("); + for(int i = 0; i < dims; i++) + printf("%d%s", n->idx[i], i < dims-1 ? ", " : ")"); + printf(": %g\n", it.value<float>()); + s += *it; + } + printf("Element sum is %g\n", s); + @endcode + If you run this loop, you will notice that elements are not enumerated in a logical order + (lexicographical, and so on). They come in the same order as they are stored in the hash table + (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 may happen due to possible buffer reallocation. +- Combination of the above 2 methods when you need to process 2 or more sparse matrices + simultaneously. For example, this is how you can compute unnormalized cross-correlation of the 2 + floating-point sparse matrices: + @code + double cross_corr(const SparseMat& a, const SparseMat& b) + { + const SparseMat *_a = &a, *_b = &b; + // if b contains less elements than a, + // it is faster to iterate through b + if(_a->nzcount() > _b->nzcount()) + std::swap(_a, _b); + SparseMatConstIterator_<float> it = _a->begin<float>(), + it_end = _a->end<float>(); + 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 an element with the same index in the second matrix. + // since the hash value depends only on the element index, + // reuse the hash value stored in the node + float bvalue = _b->value<float>(anode->idx,&anode->hashval); + ccorr += avalue*bvalue; + } + return ccorr; + } + @endcode + */ +class CV_EXPORTS SparseMat +{ +public: + typedef SparseMatIterator iterator; + typedef SparseMatConstIterator const_iterator; + + enum { MAGIC_VAL=0x42FD0000, MAX_DIM=32, HASH_SCALE=0x5bd1e995, HASH_BIT=0x80000000 }; + + //! 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<uchar> pool; + std::vector<size_t> 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]; + }; + + /** @brief Various SparseMat constructors. + */ + SparseMat(); + + /** @overload + @param dims Array dimensionality. + @param _sizes Sparce matrix size on all dementions. + @param _type Sparse matrix data type. + */ + SparseMat(int dims, const int* _sizes, int _type); + + /** @overload + @param m Source matrix for copy constructor. If m is dense matrix (ocvMat) then it will be converted + to sparse representation. + */ + SparseMat(const SparseMat& m); + + /** @overload + @param m Source matrix for copy constructor. If m is dense matrix (ocvMat) then it will be converted + to sparse representation. + */ + explicit SparseMat(const Mat& 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<typename _Tp> _Tp& ref(int i0, size_t* hashval=0); + //! returns reference to the specified element (2D case) + template<typename _Tp> _Tp& ref(int i0, int i1, size_t* hashval=0); + //! returns reference to the specified element (3D case) + template<typename _Tp> _Tp& ref(int i0, int i1, int i2, size_t* hashval=0); + //! returns reference to the specified element (nD case) + template<typename _Tp> _Tp& ref(const int* idx, size_t* hashval=0); + //!@} + + //!@{ + /*! + return value of the specified sparse matrix element. + + `value<_Tp>(i0,...[,hashval])` is equivalent to + @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<typename _Tp> _Tp value(int i0, size_t* hashval=0) const; + //! returns value of the specified element (2D case) + template<typename _Tp> _Tp value(int i0, int i1, size_t* hashval=0) const; + //! returns value of the specified element (3D case) + template<typename _Tp> _Tp value(int i0, int i1, int i2, size_t* hashval=0) const; + //! returns value of the specified element (nD case) + template<typename _Tp> _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<typename _Tp> const _Tp* find(int i0, size_t* hashval=0) const; + //! returns pointer to the specified element (2D case) + template<typename _Tp> const _Tp* find(int i0, int i1, size_t* hashval=0) const; + //! returns pointer to the specified element (3D case) + template<typename _Tp> const _Tp* find(int i0, int i1, int i2, size_t* hashval=0) const; + //! returns pointer to the specified element (nD case) + template<typename _Tp> 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<typename _Tp> 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<typename _Tp> 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<typename _Tp> SparseMatIterator_<_Tp> end(); + //! returns the typed read-only sparse matrix iterator at the matrix end + template<typename _Tp> SparseMatConstIterator_<_Tp> end() const; + + //! returns the value stored in the sparse martix node + template<typename _Tp> _Tp& value(Node* n); + //! returns the value stored in the sparse martix node + template<typename _Tp> 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); + + int flags; + Hdr* hdr; +}; + + + +///////////////////////////////// SparseMat_<_Tp> //////////////////////////////////// + +/** @brief Template sparse n-dimensional array class derived from SparseMat + +SparseMat_ is a thin wrapper on top of SparseMat created in the same way as Mat_ . It simplifies +notation of some operations: +@code + int sz[] = {10, 20, 30}; + SparseMat_<double> M(3, sz); + ... + M.ref(1, 2, 3) = M(4, 5, 6) + M(7, 8, 9); +@endcode + */ +template<typename _Tp> 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; +}; + + + +////////////////////////////////// MatConstIterator ////////////////////////////////// + +class CV_EXPORTS MatConstIterator +{ +public: + typedef uchar* value_type; + typedef ptrdiff_t difference_type; + typedef const uchar** pointer; + typedef uchar* reference; + +#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* _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; +}; + + + +////////////////////////////////// MatConstIterator_ ///////////////////////////////// + +/** @brief Matrix read-only iterator + */ +template<typename _Tp> +class MatConstIterator_ : public MatConstIterator +{ +public: + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + +#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; +}; + + + +//////////////////////////////////// MatIterator_ //////////////////////////////////// + +/** @brief Matrix read-write iterator +*/ +template<typename _Tp> +class MatIterator_ : public MatConstIterator_<_Tp> +{ +public: + typedef _Tp* pointer; + typedef _Tp& reference; + +#ifndef OPENCV_NOSTL + typedef std::random_access_iterator_tag iterator_category; +#endif + + //! 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); +}; + + + +/////////////////////////////// SparseMatConstIterator /////////////////////////////// + +/** @brief Read-Only Sparse Matrix Iterator. + + Here is how to use the iterator to compute the sum of floating-point sparse matrix elements: + + \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<float>(); + \endcode +*/ +class CV_EXPORTS SparseMatConstIterator +{ +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<typename _Tp> 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; +}; + + + +////////////////////////////////// SparseMatIterator ///////////////////////////////// + +/** @brief Read-write Sparse Matrix Iterator + + 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 +{ +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<typename _Tp> _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); +}; + + + +/////////////////////////////// SparseMatConstIterator_ ////////////////////////////// + +/** @brief Template Read-Only Sparse Matrix Iterator Class. + + This is the derived from SparseMatConstIterator class that + introduces more convenient operator *() for accessing the current element. +*/ +template<typename _Tp> class SparseMatConstIterator_ : public SparseMatConstIterator +{ +public: + +#ifndef OPENCV_NOSTL + typedef std::forward_iterator_tag iterator_category; +#endif + + //! 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); +}; + + + +///////////////////////////////// SparseMatIterator_ ///////////////////////////////// + +/** @brief Template Read-Write Sparse Matrix Iterator Class. + + This is the derived from cv::SparseMatConstIterator_ class that + introduces more convenient operator *() for accessing the current element. +*/ +template<typename _Tp> class SparseMatIterator_ : public SparseMatConstIterator_<_Tp> +{ +public: + +#ifndef OPENCV_NOSTL + typedef std::forward_iterator_tag iterator_category; +#endif + + //! 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); +}; + + + +/////////////////////////////////// NAryMatIterator ////////////////////////////////// + +/** @brief n-ary multi-dimensional array iterator. + +Use the class to implement unary, binary, and, generally, n-ary element-wise operations on +multi-dimensional arrays. Some of the arguments of an n-ary function may be continuous arrays, some +may be not. It is possible to use conventional MatIterator 's for each array but incrementing all of +the iterators after each small operations may be a big overhead. In this case consider using +NAryMatIterator to iterate through several matrices simultaneously as long as they have the same +geometry (dimensionality and all the dimension sizes are the same). On each iteration `it.planes[0]`, +`it.planes[1]`,... will be the slices of the corresponding matrices. + +The example below illustrates how you can compute a normalized and threshold 3D color histogram: +@code + void computeNormalizedColorHist(const Mat& image, Mat& hist, int N, double minProb) + { + const int histSize[] = {N, N, N}; + + // make sure that the histogram has a proper size and type + hist.create(3, histSize, CV_32F); + + // and clear it + hist = Scalar(0); + + // the loop below assumes that the image + // is a 8-bit 3-channel. check it. + CV_Assert(image.type() == CV_8UC3); + MatConstIterator_<Vec3b> it = image.begin<Vec3b>(), + it_end = image.end<Vec3b>(); + for( ; it != it_end; ++it ) + { + const Vec3b& pix = *it; + hist.at<float>(pix[0]*N/256, pix[1]*N/256, pix[2]*N/256) += 1.f; + } + + minProb *= image.rows*image.cols; + Mat plane; + NAryMatIterator it(&hist, &plane, 1); + double s = 0; + // iterate through the matrix. on each iteration + // it.planes[*] (of type Mat) will be set to the current plane. + for(int p = 0; p < it.nplanes; p++, ++it) + { + threshold(it.planes[0], it.planes[0], minProb, 0, THRESH_TOZERO); + s += sum(it.planes[0])[0]; + } + + s = 1./s; + it = NAryMatIterator(&hist, &plane, 1); + for(int p = 0; p < it.nplanes; p++, ++it) + it.planes[0] *= s; + } +@endcode + */ +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; +}; + + + +///////////////////////////////// Matrix Expressions ///////////////////////////////// + +class CV_EXPORTS MatOp +{ +public: + MatOp(); + virtual ~MatOp(); + + virtual bool elementWise(const MatExpr& expr) const; + virtual void assign(const MatExpr& expr, Mat& m, int type=-1) const = 0; + virtual void roi(const MatExpr& expr, const Range& rowRange, + const Range& colRange, MatExpr& res) const; + virtual void diag(const MatExpr& expr, int d, MatExpr& res) const; + virtual void augAssignAdd(const MatExpr& expr, Mat& m) const; + virtual void augAssignSubtract(const MatExpr& expr, Mat& m) const; + virtual void augAssignMultiply(const MatExpr& expr, Mat& m) const; + virtual void augAssignDivide(const MatExpr& expr, Mat& m) const; + virtual void augAssignAnd(const MatExpr& expr, Mat& m) const; + virtual void augAssignOr(const MatExpr& expr, Mat& m) const; + virtual void augAssignXor(const MatExpr& expr, Mat& m) const; + + virtual void add(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const; + virtual void add(const MatExpr& expr1, const Scalar& s, MatExpr& res) const; + + virtual void subtract(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const; + virtual void subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const; + + virtual void multiply(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res, double scale=1) const; + virtual void multiply(const MatExpr& expr1, double s, MatExpr& res) const; + + virtual void divide(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res, double scale=1) const; + virtual void divide(double s, const MatExpr& expr, MatExpr& res) const; + + virtual void abs(const MatExpr& expr, MatExpr& res) const; + + virtual void transpose(const MatExpr& expr, MatExpr& res) const; + virtual void matmul(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const; + virtual void invert(const MatExpr& expr, int method, MatExpr& res) const; + + virtual Size size(const MatExpr& expr) const; + virtual int type(const MatExpr& expr) const; +}; + +/** @brief Matrix expression representation +@anchor MatrixExpressions +This is a list of implemented matrix operations that can be combined in arbitrary complex +expressions (here A, B stand for matrices ( Mat ), s for a scalar ( Scalar ), alpha for a +real-valued scalar ( double )): +- Addition, subtraction, negation: `A+B`, `A-B`, `A+s`, `A-s`, `s+A`, `s-A`, `-A` +- Scaling: `A*alpha` +- Per-element multiplication and division: `A.mul(B)`, `A/B`, `alpha/A` +- Matrix multiplication: `A*B` +- Transposition: `A.t()` (means A<sup>T</sup>) +- Matrix inversion and pseudo-inversion, solving linear systems and least-squares problems: + `A.inv([method]) (~ A<sup>-1</sup>)`, `A.inv([method])*B (~ X: AX=B)` +- Comparison: `A cmpop B`, `A cmpop alpha`, `alpha cmpop A`, where *cmpop* is one of + `>`, `>=`, `==`, `!=`, `<=`, `<`. The result of comparison is an 8-bit single channel mask whose + elements are set to 255 (if the particular element or pair of elements satisfy the condition) or + 0. +- Bitwise logical operations: `A logicop B`, `A logicop s`, `s logicop A`, `~A`, where *logicop* is one of + `&`, `|`, `^`. +- Element-wise minimum and maximum: `min(A, B)`, `min(A, alpha)`, `max(A, B)`, `max(A, alpha)` +- Element-wise absolute value: `abs(A)` +- Cross-product, dot-product: `A.cross(B)`, `A.dot(B)` +- Any function of matrix or matrices and scalars that returns a matrix or a scalar, such as norm, + mean, sum, countNonZero, trace, determinant, repeat, and others. +- Matrix initializers ( Mat::eye(), Mat::zeros(), Mat::ones() ), matrix comma-separated + initializers, matrix constructors and operators that extract sub-matrices (see Mat description). +- Mat_<destination_type>() constructors to cast the result to the proper type. +@note Comma-separated initializers and probably some other operations may require additional +explicit Mat() or Mat_<T>() constructor calls to resolve a possible ambiguity. + +Here are examples of matrix expressions: +@code + // compute pseudo-inverse of A, equivalent to A.inv(DECOMP_SVD) + SVD svd(A); + Mat pinvA = svd.vt.t()*Mat::diag(1./svd.w)*svd.u.t(); + + // compute the new vector of parameters in the Levenberg-Marquardt algorithm + x -= (A.t()*A + lambda*Mat::eye(A.cols,A.cols,A.type())).inv(DECOMP_CHOLESKY)*(A.t()*err); + + // sharpen image using "unsharp mask" algorithm + Mat blurred; double sigma = 1, threshold = 5, amount = 1; + GaussianBlur(img, blurred, Size(), sigma, sigma); + Mat lowContrastMask = abs(img - blurred) < threshold; + Mat sharpened = img*(1+amount) + blurred*(-amount); + img.copyTo(sharpened, lowContrastMask); +@endcode +*/ +class CV_EXPORTS MatExpr +{ +public: + MatExpr(); + explicit MatExpr(const Mat& 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<typename _Tp> 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 operator()( const Range& rowRange, const Range& colRange ) const; + MatExpr operator()( const Rect& roi ) 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; + + Mat cross(const Mat& m) const; + double dot(const Mat& m) const; + + const MatOp* op; + int flags; + + Mat a, b, c; + double alpha, beta; + Scalar s; +}; + +//! @} core_basic + +//! @relates cv::MatExpr +//! @{ +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); +CV_EXPORTS MatExpr operator + (const MatExpr& e, const Mat& m); +CV_EXPORTS MatExpr operator + (const Mat& m, const MatExpr& e); +CV_EXPORTS MatExpr operator + (const MatExpr& e, const Scalar& s); +CV_EXPORTS MatExpr operator + (const Scalar& s, const MatExpr& e); +CV_EXPORTS MatExpr operator + (const MatExpr& e1, const MatExpr& e2); + +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); +CV_EXPORTS MatExpr operator - (const MatExpr& e, const Mat& m); +CV_EXPORTS MatExpr operator - (const Mat& m, const MatExpr& e); +CV_EXPORTS MatExpr operator - (const MatExpr& e, const Scalar& s); +CV_EXPORTS MatExpr operator - (const Scalar& s, const MatExpr& e); +CV_EXPORTS MatExpr operator - (const MatExpr& e1, const MatExpr& e2); + +CV_EXPORTS MatExpr operator - (const Mat& m); +CV_EXPORTS MatExpr operator - (const MatExpr& e); + +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 operator * (const MatExpr& e, const Mat& m); +CV_EXPORTS MatExpr operator * (const Mat& m, const MatExpr& e); +CV_EXPORTS MatExpr operator * (const MatExpr& e, double s); +CV_EXPORTS MatExpr operator * (double s, const MatExpr& e); +CV_EXPORTS MatExpr operator * (const MatExpr& e1, const MatExpr& e2); + +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 operator / (const MatExpr& e, const Mat& m); +CV_EXPORTS MatExpr operator / (const Mat& m, const MatExpr& e); +CV_EXPORTS MatExpr operator / (const MatExpr& e, double s); +CV_EXPORTS MatExpr operator / (double s, const MatExpr& e); +CV_EXPORTS MatExpr operator / (const MatExpr& e1, const MatExpr& e2); + +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 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 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 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 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 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 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); + +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); + +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); + +CV_EXPORTS MatExpr operator ~(const Mat& m); + +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); + +/** @brief Calculates an absolute value of each matrix element. + +abs is a meta-function that is expanded to one of absdiff or convertScaleAbs forms: +- C = abs(A-B) is equivalent to `absdiff(A, B, C)` +- C = abs(A) is equivalent to `absdiff(A, Scalar::all(0), C)` +- C = `Mat_<Vec<uchar,n> >(abs(A*alpha + beta))` is equivalent to `convertScaleAbs(A, C, alpha, +beta)` + +The output matrix has the same size and the same type as the input one except for the last case, +where C is depth=CV_8U . +@param m matrix. +@sa @ref MatrixExpressions, absdiff, convertScaleAbs + */ +CV_EXPORTS MatExpr abs(const Mat& m); +/** @overload +@param e matrix expression. +*/ +CV_EXPORTS MatExpr abs(const MatExpr& e); +//! @} relates cv::MatExpr + +} // cv + +#include "opencv2/core/mat.inl.hpp" + +#endif // __OPENCV_CORE_MAT_HPP__ +