Mat是matrix矩阵的简写,Mat类中数据部分主要分为两个部分:头和数据指针。头中定义一些矩阵的行数、列数、通道数、维度等信息;数据指针中定义uchar* data的数据地址。函数部分主要包括大量构造函数、大量模版函数以及一些非模版函数。
我们知道在c++中类实例化的对象中,真正拥有的是数据部分。
int flags; //signature
int dims; //维数,灰度图像二维,rgb图像三维
int rows, cols; //行数和列数,这里说的是逻辑上的矩阵的行数和列数,而不是物理存储时
uchar* data; // 矩阵元素数据的首地址,类型是uchar*,在c/c++中通常最小的数据处理大小是一个字节
//图像ROI的辅助指针
uchar* datastart;
uchar* dataend;
uchar* datalimit;
MSize size; //一行含有的字节数,MSize和MStep是定义的结构体
MStep step;
//...
1.2.1 构造函数和析构函数
Mat();
Mat(int rows, int cols, int type);
Mat(Size size, int type);
Mat(int rows, int cols, int type, const Scalar& s);
Mat(Size size, int type, const Scalar& s);
Mat(int ndims, const int* sizes, int type);
Mat(int ndims, const int* sizes, int type, const Scalar& s);
Mat(const Mat& m);
Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);
Mat(Size size, int type, void* data, size_t step=AUTO_STEP);
Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0);
Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all());
Mat(const Mat& m, const Rect& roi);
Mat(const Mat& m, const Range* ranges);
Mat(const IplImage* img, bool copyData=false);
//...
~Mat();
1.2.2 运算符重载
Mat& operator = (const Mat& m); //赋值运算符重载,做的是浅拷贝
Mat& operator = (const MatExpr& expr);
Mat& operator = (const Scalar& s);
Mat operator()( Range rowRange, Range colRange ) const;
Mat operator()( const Rect& roi ) const;
Mat operator()( const Range* ranges ) const;
CV_EXPORTS MatExpr operator * (const Mat& a, const Mat& b);//矩阵内积
operator CvMat() const;
operator CvMatND() const;
operator IplImage() const;
template<typename _Tp> operator 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;
1.2.3 数据访问函数
ptr函数
// 返回矩阵元素指针
uchar* ptr(const int* idx);
const uchar* ptr(const int* idx) const;
template<typename _Tp> _Tp* ptr(int i0=0);
template<typename _Tp> const _Tp* ptr(int i0=0) const;
template<typename _Tp> _Tp* ptr(int i0, int i1);
template<typename _Tp> const _Tp* ptr(int i0, int i1) const;
template<typename _Tp> _Tp* ptr(int i0, int i1, int i2);
template<typename _Tp> const _Tp* ptr(int i0, int i1, int i2) const;
template<typename _Tp> _Tp* ptr(const int* idx);
template<typename _Tp> const _Tp* ptr(const int* idx) const;
template<typename _Tp, int n> _Tp* ptr(const Vec<int, n>& idx);
template<typename _Tp, int n> const _Tp* ptr(const Vec<int, n>& idx) const;
at函数
template<typename _Tp> _Tp& at(int i0=0);
template<typename _Tp> const _Tp& at(int i0=0) const;
template<typename _Tp> _Tp& at(int i0, int i1);
template<typename _Tp> const _Tp& at(int i0, int i1) const;
template<typename _Tp> _Tp& at(int i0, int i1, int i2);
template<typename _Tp> const _Tp& at(int i0, int i1, int i2) const;
template<typename _Tp> _Tp& at(const int* idx);
template<typename _Tp> const _Tp& at(const int* idx) const;
template<typename _Tp, int n> _Tp& at(const Vec<int, n>& idx);
template<typename _Tp, int n> const _Tp& at(const Vec<int, n>& idx) const;
//! special versions for 2D arrays (especially convenient for referencing image pixels)
template<typename _Tp> _Tp& at(Point pt);
template<typename _Tp> const _Tp& at(Point pt) const;
迭代器函数
template<typename _Tp> MatIterator_<_Tp> begin();
template<typename _Tp> MatIterator_<_Tp> end();
template<typename _Tp> MatConstIterator_<_Tp> begin() const;
template<typename _Tp> MatConstIterator_<_Tp> end() const;
1.2.4 其它常用函数
- matlab风格的初始化函数,静态函数
- 矩阵运算
- 返回通道数等
- 深拷贝函数
//matlab风格的初始化函数,静态函数
static MatExpr zeros(int rows, int cols, int type);
static MatExpr zeros(Size size, int type);
static MatExpr ones(int rows, int cols, int type);
static MatExpr ones(Size size, int type);
static MatExpr eye(int rows, int cols, int type);
static MatExpr eye(Size size, int type);
//矩阵运算
Mat cross(InputArray m) const; //一维向量的叉乘,即外积
double dot(InputArray m) const; //一维向量内积,结果是一个数
MatExpr mul(InputArray m, double scale=1) const; //矩阵对应元素的乘积
//两个矩阵的内积有重载的*可以实现 即 C=A*B,A的行数要与B的列数一致
MatExpr inv(int method=DECOMP_LU) const; //矩阵的逆矩阵
MatExpr t() const; //矩阵转置
//
size_t total() const;//返回图像中像素点总数量=rows*cols
int type() const; //返回类型CV_8UC1 CV_16SC1 CV_32FC3等
int depth() const;
int channels() const; //返回通道数
size_t elemSize() const; //返回像素元素的大小以字节的方式,包括通道。
bool isContinuous() const; //判断数据存储是否连续
void create(int rows, int cols, int type); //如果之前矩阵没有创建数据,可以创建
//深拷贝函数
Mat clone() const;
void copyTo( OutputArray m ) const;
void copyTo( OutputArray m, InputArray mask ) const;
//...
uchar data;对应的是数据的首元素存储地址。
数据存储时,逐步扫描行,在内存中按照读的顺序存储。
根据数据的存储方式,可知要获取一个图像或矩阵的元素的数据,有几个关键点:
- 获得存储数据的首地址,即uchar* data;
- 获得图像或矩阵的通道数,是单通道(灰度图像)还是三通道(RGB)图像,即
Mat src;
int src.channels();
- 获得每个元素的字节大小。
src.elemSize(); //返回元素所有通道一共的字节大小。如CV_8UC3,返回的就是1*3=3
src.elemSize1(); //返回元素单通道的字节大小。如CV_8UC3,返回的就是1
//data 是数据存储的首地址,
//channels是图像的通道数,
//elemSize是每个元素单通道中的字节数
// rows 行数
// cols 列数
void work(uchar* data,int channels,int elemSize,int rows,int cols)
{
for (int i=0;i<rows;i++)
{
uchar* p = data + cols*channels*elemSize*i; //获得i行的首地址
for (int j=0;j<cols;j++)
{
uchar* pj = p+j*channels*elemSize; //获得第j列的首地址
//do something
}
}
}