Mat结构分析
数据成员
//图片的标志,含有魔数,是否连续,数据类型,深度
int flags;
//维度,图片是2维。
int dims;
//视图宽高
int cols, rows;
//视图数据起始位置
uchar* data;
//原图起始位置
const uchar* datastart;
//原图未对齐结束位置
const uchar* dataend;
//原图对齐结束位置
const uchar* datalimit;
//自定义分配器
MatAllocator* allocator;
//原图内部数据
UMatData* u;
//视图大小
MatSize size;
//步长,step[0]=>行步长 step[1]=>通道数
MatStep step;
原图是一张5x10大小的图片,具有RGB3个通道,depth为CV_8U,还有6个字节的padding。
原图:Mat src(Size(5,10),CV_8UC3,userdata,3*5+6);
视图:Mat roi = src(Rect(1,2,3,6));
roi分析图如下:
成员函数
数据操作
/**
* 对原图应用蒙版mask,结果保存在目的m中。假如mask的值不等于0,就复制原图的值到m中。
* 当m的大小和类型不符合原图时候,首先调用m.create(this->size(), this->type());
* @param m 目的图
* @param mask 蒙版 单通道,3通道皆可以
* 伪代码:m[i] = mask[i] == 0? 0 : src[i];
*/
void copyTo( OutputArray m, InputArray mask ) const;
/**
* 对原图进行rtype数据类型转换,结果保存在m中。
* @param m 目的图
* @param mask 蒙版 单通道,3通道皆可以
* 伪代码:m[i] = (rtype)(src[i]*alpha+beta);
*/
void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;
/**
* 和convertTo等价,少几个参数而已
*/
void assignTo( Mat& m, int type=-1 ) const;
/**
* 根据蒙版,对于原图像素进行赋值value。
* @param value 目的值
* @param mask 蒙版 单通道,3通道皆可以
* 伪代码:src[i] = mask[i]==0? src[i] : value;
*/
Mat& setTo(InputArray value, InputArray mask=noArray());
/**
* 把原图像素全部变成目的值s
* @param s 目的值
* 伪代码:src[i] = s;
*/
Mat& operator = (const Scalar& s);
子矩阵操作
根据startx,starty,endx,endy,在原图上创建一个子矩阵.其中,数据部分是公用的。
/**
* 把原图某一行像素变成目的值s
* @param y 目的行
*/
Mat row(int y) const;
/**
* 把原图某一列像素变成目的值s
* @param x 目的列
*/
Mat col(int x) const;
/**
* 把原图多行像素变成目的值s
* @param startrow 起始行
* @param endrow 结束行
*/
Mat rowRange(int startrow, int endrow) const;
Mat rowRange(const Range& r) const;
/**
* 把原图多列像素变成目的值s
* @param startcol 起始列
* @param endcol 结束列
*/
Mat colRange(int startcol, int endcol) const;
Mat colRange(const Range& r) const;
/**
* 调整roi
**/
Mat& adjustROI( int dtop, int dbottom, int dleft, int dright );
/**
* 获取子矩阵roi,存储在wholeSize,ofs中
*/
void locateROI( Size& wholeSize, Point& ofs ) const;
/**
* 重载()符号,传递不同参数,返回一个新的子矩阵Mat.
**/
Mat operator()( Range rowRange, Range colRange ) const;
Mat operator()( const Rect& roi ) const;
Mat operator()( const Range* ranges ) const;
Mat operator()(const std::vector<Range>& ranges) const;
//子矩阵
bool isSubmatrix() const;
矩阵运算
/**
* 矩阵加法有以下两种方式
* 矩阵+矩阵
* 矩阵+标量
*/
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);
/**
* 矩阵乘法有以下两种方式
* 矩阵*矩阵
* 矩阵*double
*/
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);
/**
* 矩阵除法有以下两种方式
* 矩阵/矩阵
* 矩阵/double
*/
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);
//矩阵倒置,第i行变成第i列,Mi,j => Mj,i
MatExpr t() const;
//逆矩阵,AB=E => B=E/A
MatExpr inv(int method=DECOMP_LU) const;
//矩阵点乘,返回标量,几何意义是B在A上的投影,可以用来判断方向
double dot(InputArray m) const;
//矩阵叉乘,返回向量,几何意义是垂直于A,B向量的法向量。
Mat cross(InputArray m) const;
矩阵遍历
速度来说,指针>迭代器>for+at
1.指针
//行指针,列指针遍历
Mat& ScanImageAndReduceC(Mat& I, const uchar* const table)
{
// accept only char type matrices
CV_Assert(I.depth() == CV_8U);
int channels = I.channels();
int nRows = I.rows;
int nCols = I.cols * channels;
if (I.isContinuous())
{
nCols *= nRows;
nRows = 1;
}
int i,j;
uchar* p;
for( i = 0; i < nRows; ++i)
{
p = I.ptr<uchar>(i);
for ( j = 0; j < nCols; ++j)
{
p[j] = table[p[j]];
}
}
return I;
}
//直接数据指针遍历
uchar* p = I.data;
for( unsigned int i = 0; i < ncol*nrows; ++i)
*p++ = table[*p];
2.迭代器
//维护迭代器内部数据需要耗时
Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)
{
// accept only char type matrices
CV_Assert(I.depth() == CV_8U);
const int channels = I.channels();
switch(channels)
{
case 1:
{
MatIterator_<uchar> it, end;
for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
*it = table[*it];
break;
}
case 3:
{
MatIterator_<Vec3b> it, end;
for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it)
{
(*it)[0] = table[(*it)[0]];
(*it)[1] = table[(*it)[1]];
(*it)[2] = table[(*it)[2]];
}
}
}
return I;
}
3.for循环+at方法
//at方法最慢是因为每一次都要通过参数计算目的数据地址。
template<typename _Tp> inline
const _Tp& Mat::at(int i0, int i1) const
{
return ((const _Tp*)(data + step.p[0] * i0))[i1];
}
Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table)
{
// accept only char type matrices
CV_Assert(I.depth() == CV_8U);
const int channels = I.channels();
switch(channels)
{
case 1:
{
for( int i = 0; i < I.rows; ++i)
for( int j = 0; j < I.cols; ++j )
I.at<uchar>(i,j) = table[I.at<uchar>(i,j)];
break;
}
case 3:
{
Mat_<Vec3b> _I = I;
for( int i = 0; i < I.rows; ++i)
for( int j = 0; j < I.cols; ++j )
{
_I(i,j)[0] = table[_I(i,j)[0]];
_I(i,j)[1] = table[_I(i,j)[1]];
_I(i,j)[2] = table[_I(i,j)[2]];
}
I = _I;
break;
}
}
return I;
}