opencv之Mat类笔记

opencv版本:opencv-3.4.1 

Mat类 

class CV_EXPORTS Mat
{
public:

    //无参构造函数
    Mat();
    //创建行数为rows,列数为col,类型为type的图像;
    Mat(int rows, int cols, int type);
    //创建大小为size,类型为type的图像;
    Mat(Size size, int type);
    //创建行数为rows,列数为col,类型为type的图像,并将所有元素初始化为s
    Mat(int rows, int cols, int type, const Scalar& s);
    //创建大小为size,类型为type,并将所有元素初始化为值s;
    Mat(Size size, int type, const Scalar& s);
    ...

    ~Mat();

    Mat& operator = (const Mat& m);
    Mat& operator = (const MatExpr& expr);

    //提取矩阵第y行
    Mat row(int y) const;
    //提取矩阵第x列
    Mat col(int x) const;

    //为指定的行span创建一个新的矩形头,可取指定行区间元素;
    Mat rowRange(int startrow, int endrow) const;
    Mat rowRange(const Range& r) const;

    //为指定的列span创建一个矩形头,可取指定行区间元素;
    Mat colRange(int startcol, int endcol) const;
    Mat colRange(const Range& r) const;

     //为特定的矩阵对角线创建一个新的头;提取对角线元素
    Mat diag(int d=0) const;
    static Mat diag(const Mat& d);

    //创建一个数组及其基础数据的完整副本;
    Mat clone() const;

    //把矩阵复制到另一个矩阵中;
    void copyTo( OutputArray m ) const;
    void copyTo( OutputArray m, InputArray mask ) const;

    //在缩放或不缩放的情况下转换为另一种数据类型;
    void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;

    void assignTo( Mat& m, int type=-1 ) const;

    Mat& operator = (const Scalar& s);

    Mat& setTo(InputArray value, InputArray mask=noArray());

    Mat reshape(int cn, int rows=0) const;
    Mat reshape(int cn, int newndims, const int* newsz) const;
    Mat reshape(int cn, const std::vector<int>& newshape) const;

    MatExpr t() const;

    MatExpr inv(int method=DECOMP_LU) const;

    MatExpr mul(InputArray m, double scale=1) const;

    Mat cross(InputArray m) const;

    double dot(InputArray m) const;

    //返回指定的大小和类型的零数组
    static MatExpr zeros(int rows, int cols, int type);
    static MatExpr zeros(Size size, int type);
    static MatExpr zeros(int ndims, const int* sz, int type);

    //返回一个指定的大小和类型全为1的数组;
    static MatExpr ones(int rows, int cols, int type);
    static MatExpr ones(Size size, int type);
    static MatExpr ones(int ndims, const int* sz, int type);

    //返回指定大小和类型的单位矩阵
    static MatExpr eye(int rows, int cols, int type);
    static MatExpr eye(Size size, int type);

    /*
    若create()函数制定的参数与图像之前的相同,则不进行内存的申请
    若参数不同,则释放内存重新创建图像;
    使用create函数无法设置图像像素的初始值;
    */
    void create(int rows, int cols, int type);
    void create(Size size, int type);
    void create(int ndims, const int* sizes, int type);
    void create(const std::vector<int>& sizes, int type);

    void addref();

    void release();

    void deallocate();
   
    void copySize(const Mat& m);

    void reserve(size_t sz);

    void reserveBuffer(size_t sz);

    void resize(size_t sz);
    void resize(size_t sz, const Scalar& s);

    void push_back_(const void* elem);
    void push_back(const Mat& m);

    void pop_back(size_t nelems=1);

    void locateROI( Size& wholeSize, Point& ofs ) const;

    Mat operator()( const Rect& roi ) const;
    Mat operator()( const Range* ranges ) const;
    Mat operator()(const std::vector<Range>& ranges) const;

    bool isContinuous() const;

    bool isSubmatrix() const;
  
    size_t elemSize() const;
    size_t elemSize1() const;

    //返回矩阵元素类型
    int type() const;
    //返回矩阵元素深度
    int depth() const;

    //返回矩形通道的数目
    int channels() const;

    size_t step1(int i=0) const;

    //若数组没有elements,则返回true;
    bool empty() const;

    //返回指定数组元素的引用
    template<typename _Tp> _Tp& at(int i0=0);
    ...

    size_t total() const;
    size_t total(int startDim, int endDim=INT_MAX) const;

    int checkVector(int elemChannels, int depth=-1, bool requireContinuous=true) const;
   
    //可实现读取矩阵中的某个像素;
    //若要遍历图像,不推荐使用,效率不高;
    template<typename _Tp> _Tp& at(int i0=0);
   
    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 };

    /*flag参数中包含许多关于矩阵的信息;如
      Mat的标识;  
      数据是否连续;
      深度;
      通道数目;  
    */
    int flags; //标志位
	
    //>= 2 矩阵的维数
    int dims;
	
    //矩阵的行数和列数,如果矩阵超过 2 维,这两个变量的值都为-1
    int rows, cols;
	
    // 指向数据的指针
    uchar* data;

    //! helper fields used in locateROI and adjustROI
    const uchar* datastart;
    const uchar* dataend;
    const uchar* datalimit;

    //! interaction with UMat
    UMatData* u;

    MatSize size;
    MatStep step;

protected:
    template<typename _Tp, typename Functor> void forEach_impl(const Functor& operation);
};

        构造函数中的type取值可以是:CV_8UC1, CV_8UC2,CV_8SC1,CV_16UC1,CV_32SC1等,位于interface中;

        若需要更多的通道数,使用CV_8UC(n),CV_8UC(n),类推...

        如:Mat M(3,2, CV_8UC(5));//创建行数为 3,列数为 2,通道数为 5 的图像;

关于Mat类:需要知道:

(1) 不需要手动为其开辟空间;

(2) 使用c++接口时不需要考虑内存释放问题,采用引用计数机制释放内存;

(3) 赋值运算符和拷贝构造函数(构造函数)只复制信息头;

(4) 使用函数clone()或者copyTo()来复制一幅图像的矩阵;

代码示例1:

CV_8UC3:规则如下:

CV[位数][带符号与否][类型前缀C][通道数];

可指定存储元素的数据类型及每个矩阵点的通道数;

CV_8UC3:使用8位unsigned char型,每个像素由3个元素组成3通道;

//创建一个2行两列的图像,图像元素是8位无符号整数类型,且有3通道;图像的所有像素值被初始化为(0,0,255);
Mat A(2,2,CV_8UC3, Scalar(0,0,255));
//Mat从定义了<<操作符,可以很方便的输出所有像素;
std::cout << "A= " << std::endl << A << std::endl;
/*
A= 
[  0,   0, 255,   0,   0, 255;
   0,   0, 255,   0,   0, 255]
*/

Mat r = Mat(10, 3, CV_8UC3);
//产生随机值来填充矩阵
randu(r, Scalar::all(0), Scalar::all(255));
/*
std::cout << "r= " << std::endl << format(r, Formatter::FMT_CSV) << std::endl;

r= 
 91,   2,  79, 179,  52, 205, 236,   8, 181
239,  26, 248, 207, 218,  45, 183, 158, 101
102,  18, 118,  68, 210, 139, 198, 207, 211
181, 162, 197, 191, 196,  40,   7, 243, 230
 45,   6,  48, 173, 242, 125, 175,  90,  63
 90,  22, 112, 221, 167, 224, 113, 208, 123
214,  35, 229,   6, 143, 138,  98,  81, 118
187, 167, 140, 218, 178,  23,  43, 133, 154
150,  76, 101,   8,  38, 238,  84,  47,   7
117, 246, 163, 237,  69, 129,  60, 101,  41
*/ 

代码示例2:

Mat A(10, 8, CV_8UC1, cv::Scalar(5));

//获取矩阵行列数
std::cout << "A row: " << A.rows << std::endl;//10
std::cout << "A col: " << A.cols << std::endl;//8

//获取指定行列元素
std::cout << A.rowRange(1,3) << std::endl;
/*
[  5,   5,   5,   5,   5,   5,   5,   5;
   5,   5,   5,   5,   5,   5,   5,   5] */

std::cout << A.colRange(2,4) << std::endl;
/*
[  5,   5;
   5,   5;
   5,   5;
   5,   5;
   5,   5;
   5,   5;
   5,   5;
   5,   5;
   5,   5;
   5,   5]

*/

//创建8x8复数矩阵1+5j
Mat B(8, 8, CV_32FC2, cv::Scalar(1,5));

//利用create重新创建10x10的8位无符号3通道矩阵;
B.create(10,10,CV_8UC(3));

std::cout << "B channels = " << B.channels() << std::endl; //3

//转换矩阵类型
B.convertTo(B, CV_32F);
std::cout << "B depth = " << B.depth() << std::endl; //5

//zeros创建内容全为0的矩阵
Mat C = Mat::zeros(B.rows, B.cols, CV_8UC1);

//将A的第4行元素变换成A的第5行元素*2
A.row(4) = A.row(5) * 2;
std::cout << A << std::endl;
/*
[  5,   5,   5,   5,   5,   5,   5,   5;
   5,   5,   5,   5,   5,   5,   5,   5;
   5,   5,   5,   5,   5,   5,   5,   5;
   5,   5,   5,   5,   5,   5,   5,   5;
  10,  10,  10,  10,  10,  10,  10,  10;
   5,   5,   5,   5,   5,   5,   5,   5;
   5,   5,   5,   5,   5,   5,   5,   5;
   5,   5,   5,   5,   5,   5,   5,   5;
   5,   5,   5,   5,   5,   5,   5,   5;
   5,   5,   5,   5,   5,   5,   5,   5]
*/

//将D矩阵赋值位A的第4列;
Mat D = A.col(4);
std::cout << D << std::endl;
/*
[  5;
   5;
   5;
   5;
  10;
   5;
   5;
   5;
   5;
   5]

*/

//将A矩阵的第一列复制到D中;
A.col(1).copyTo(D);
std::cout << D << std::endl;
/*
[  5;
   5;
   5;
   5;
  10;
   5;
   5;
   5;
   5;
   5]
*/

 示例代码3:

Mat A, C;   //仅仅创建信息头部分
A = imread("./lena.jpg", 1); //这里为矩阵开辟内存
Mat B(A);  //拷贝构造函数;
C = A;     //赋值运算符;

/*注意:上面几行代码A,B,C类都指向一个数据矩阵,它们的信息头不同,通过任何一个对象对矩阵所作的改变都会影响其他两个; 采用引用计数方式,无论什么时候复制一个Mat对象的信息头,都会增加矩阵的引用次数; 反之,当一个头被释放后,这个引用计数减1; 当引用计数减为0时,矩阵内存被清理;*/

//若想复制矩阵本身,而不是矩阵信息头和矩阵指针呢? 使用clone()或copyTo()接口;
Mat D = A.clone();

Mat E;
A.copyTo(E);

 

Mat类存储模型

 为了解决矩阵数据的传递,引入引用计数机制; 

思路:每个Mat对象有自己的矩阵头信息(包含矩阵尺寸,存储方法,存储地址等信息); 但多个Mat对象可以共享矩阵数据;让其矩阵指针指向同一地址;很多函数只复制矩阵头信息,而不复制矩阵数据,节省时间;

实例:A,B,C共享同一矩阵数据; 

Mat A(100,100,CV_8UC1); 

Mat B = A;

Mat C = A(Rect(50,50,30,30));

 

用Range选择多行或多列

//可以用来表示矩阵中的多个连续的行或多个连续的列,表示的范围为[start~end)
//提取第 1 到 3 列(不包括 3)
//Mat B = A(Range::all(), Range(1, 3));

//提取B的第5~9行(不包括9)
Mat C = B(Range(5, 9), Range::all());

class CV_EXPORTS Range
{
public:
    Range();
    Range(int _start, int _end);
    int size() const;
    bool empty() const;
    static Range all();//静态方法

    int start, end;
};

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天未及海宽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值