opencv探索01-Mat结构

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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值