openCV_C++笔记 : Mat类

Mat常用成员属性

  1. data 是指向矩阵数据的uchar类指针,用*解引用后再强转为int可以读到第一个像素数据。
  2. dims 矩阵的维度,例如5*6矩阵是二维矩阵,则dims=2,三维矩阵dims=3。
  3. rows 矩阵的行数。
  4. cols 矩阵的列数。
  5. size 矩阵的大小,返回一个向量,二维矩阵即为 行数 x 列数。

Mat常用成员方法

  1. channels() 矩阵元素拥有的通道数,例如常见的彩色图像,每一个像素由RGB三部分组成,则image.channels() = 3
  2. type() 表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数)。
  3. depth() 矩阵中元素的一个通道的数据类型,这个值和type是相关的。例如 type为 CV_16SC2,一个2通道的16位的有符号整数。那么,depth则是CV_16S。depth也是一系列的预定义值,

常用的构造函数有:

Mat::Mat() 无参数构造方法;
Mat::Mat(int rows, int cols, int type) 创建行数为 rows,列数为 col,类型为 type 的图像;
Mat::Mat(Size size, int type) 创建大小为 size,类型为 type 的图像;
Mat::Mat(int rows, int cols, int type, const Scalar& s) 创建行数为 rows,列数为 col,类型为 type 的图像,并将所有元素初始化为值 s;
Mat::Mat(Size size, int type, const Scalar& s) 创建大小为 size,类型为 type 的图像,并将所有元素初始化为值 s;
Mat::Mat(const Mat& m) 将 m 赋值给新创建的对象,此处不会对图像数据进行复制,m 和新对象共用图像数据;
Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP) 创建行数为 rows,列数为 col,类型为 type 的图像,此构造函数不创建图像数据所需内存,而是直接使用 data 所指内存,图像的行步长由 step指定。
Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP) 创建大小为 size,类型为 type 的图像,此构造函数不创建图像数据所需内存,而是直接使用 data 所指内存,图像的行步长由 step 指定。
Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange) 创建的新图像为 m 的一部分,具体的范围由 rowRange 和 colRange 指定,此构造函数也不进行图像数据的复制操作,新图像与 m 共用图像数据;
Mat::Mat(const Mat& m, const Rect& roi) 创建的新图像为 m 的一部分,具体的范围 roi 指定,此构造函数也不进行图像数据的复制操作,新图像与 m 共用图像数据。
● 这些构造函数中,很多都涉及到类型type。type可以是CV_8UC1,CV_16SC1,…,CV_64FC4 等。里面的 8U 表示 8 位无符号整数,16S 表示 16 位有符号整数,64F表示 64 位浮点数(即 double 类型);C 后面的数表示通道数,例如 C1 表示一个通道的图像,C4 表示 4 个通道的图像,以此类推。如果你需要更多的通道数,需要用宏 CV_8UC(n),

create()函数

Mat类的create()函数可以重新分配内存空间:

Mat M(2,2, CV_8UC3);//构造函数创建图像
M.create(3,2, CV_8UC2);//释放内存重新创建图像

使用 create()函数无法设置图像像素的初始值

零矩阵等Matlab风格函数zeros(),ones(),eye()

OpenCV 2 中提供了 Matlab 风格的函数,如 zeros(),ones()和 eyes()。可以方便指定图像大小和类型等,使用方法如下:

Mat Z = Mat::zeros(2,3, CV_8UC1);
cout << "Z = " << endl << " " << Z << endl;
Mat O = Mat::ones(2, 3, CV_32F);
cout << "O = " << endl << " " << O << endl;
Mat E = Mat::eye(2, 3, CV_64F);
cout << "E = " << endl << " " << E << endl;

读写像素函数at()

at()可以用来读取像素值或者写入像素值,使用方法如下:

uchar value = grayim.at<uchar>(i,j);//读出第 i 行第 j 列像素值
grayim.at<uchar>(i,j)=128; //将第 i 行第 j 列像素值设置为 128

使用at()进行遍历效率不高

迭代器-矩阵元素遍历

使用迭代器就不需要再使用两个for 和ij了。能够加大效率

Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)
{
    // accept only char type matrices
    CV_Assert(I.depth() != sizeof(uchar));     
    
    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; 
}

选取图像局部

  1. 单行和单列选择

    //参数 i 和 j 分别是行标和列标。例如取出 A 矩阵的第 i 行可以使用如下代码:
    Mat line = A.row(i);
    //例如取出 A 矩阵的第 i 行,将这一行的所有元素都乘以 2,然后赋值给第 j行,可以这样写:
    A.row(j) = A.row(i)*2;
    
  2. 选择多行或多列-Range
    a. 该类有两个关键变量 star 和 end。Range 对象可以用来表示矩阵的多个连续的行或者多个连续的列。其表示的范围为从 start到 end,包含 start,但不包含 end。
    b. Range 类还提供了一个静态方法 all(),这个方法的作用如同 Matlab 中的“:”,表示所有的行或者所有的列。

    //创建一个单位阵
    Mat A = Mat::eye(10, 10, CV_32S);
    //提取第 1 到 3 列(不包括 3)
    Mat B = A(Range::all(), Range(1, 3));
    //提取 B 的第 5 至 9 行(不包括 9)
    //其实等价于 C = A(Range(5, 9), Range(1, 3))
    Mat C = B(Range(5, 9), Range::all());
    
  3. 感兴趣区域 (关于Rect类见openCV_Rect笔记
    a. 使用构造函数:

    //创建宽度为 320,高度为 240 的 3 通道图像
    Mat img(Size(320,240),CV_8UC3);
    //roi 是表示 img 中 Rect(10,10,100,100)区域的对象
    Mat roi(img, Rect(10,10,100,100));
    

    b. 使用括号运算符:

    Mat roi2 = img(Rect(10,10,100,100));
    

    c. 使用range对象:

    //使用括号运算符
    Mat roi3 = img(Range(10,100),Range(10,100));
    //使用构造函数
    Mat roi4(img, Range(10,100),Range(10,100));
    
  4. 对角线元素

    a. 矩阵的对角线元素可以使用 Mat 类的 diag()函数获取,该函数的定义如下:
    Mat Mat::diag(int d) const
    b.参数 d=0 时,表示取主对角线;当参数 d>0 是,表示取主对角线下方的次对角线,如 d=1 时,表示取主对角线下方,且紧贴主多角线的元素;当参数 d<0 时,表示取主对角线上方的次对角线。
    c.如同row()和col()函数,diag()函数也不进行内存复制操作,其复杂度也是O(1)。

Mat表达式-矩阵运算

利用 C++中的运算符重载,OpenCV 2 中引入了 Mat 运算表达式。这一新特点使得使用 C++进行编程时,就如同写 Matlab 脚本,代码变得简洁易懂,也便于维护。
如:C = A + B + 1;
以下为Mat支持的运算方法:
● 加法,减法,取负:A+B,A-B,A+s,A-s,s+A,s-A,-A
● 缩放取值范围:A * alpha
● 矩阵对应元素的乘法和除法: A.mul(B),A/B,alpha/A
● 矩阵乘法:A*B (注意此处是矩阵乘法,而不是矩阵对应元素相乘)
● 矩阵转置:A.t()
● 矩阵求逆和求伪逆:A.inv()
● 矩阵比较运算:A cmpop B,A cmpop alpha,alpha cmpop A。此处 cmpop可以是>,>=,==,!=,<=,<。如果条件成立,则结果矩阵(8U 类型矩阵)的对应元素被置为 255;否则置 0。
● 矩阵位逻辑运算:A logicop B,A logicop s,s logicop A,~A,此处 logicop可以是&,|和^。
● 矩阵对应元素的最大值和最小值:min(A, B),min(A, alpha),max(A, B),max(A, alpha)。
● 矩阵中元素的绝对值:abs(A)
● 叉积和点积:A.cross(B),A.dot(B)

Mat_类

如果使用 Mat_类,那么就可以在变量声明时确定元素的类型,访问元素时不再需要指定元素类型,即使得代码简洁,又减少了出错的可能性。

//在变量声明时指定矩阵元素类型
Mat_<uchar> M1 = (Mat_<uchar>&)M;

参考文献:

  1. https://blog.csdn.net/zhjm07054115/article/details/25503781

  2. OpenCV 入门教程.于仕琪/shiqi.yu@szu.edu.cn./http://www.opencv.org.cn

  3. https://blog.csdn.net/kakiebu/article/details/79085556

  4. https://blog.csdn.net/mc_linfen/article/details/82115594

编写时间

20210719
给个三连吧爹爹们,比心心

/*
 * **************************************************************************
 * ********************                                  ********************
 * ********************      COPYRIGHT INFORMATION       ********************
 * ********************                                  ********************
 * **************************************************************************
 *                                                                          *
 *                                   _oo8oo_                                *
 *                                  o8888888o                               *
 *                                  88" . "88                               *
 *                                  (| -_- |)                               *
 *                                  0\  =  /0                               *
 *                                ___/'==='\___                             *
 *                              .' \\|     |// '.                           *
 *                             / \\|||  :  |||// \                          *
 *                            / _||||| -:- |||||_ \                         *
 *                           |   | \\\  -  /// |   |                        *
 *                           | \_|  ''\---/''  |_/ |                        *
 *                           \  .-\__  '-'  __/-.  /                        *
 *                         ___'. .'  /--.--\  '. .'___                      *
 *                      ."" '<  '.___\_<|>_/___.'  >' "".                   *
 *                     | | :  `- \`.:`\ _ /`:.`/ -`  : | |                  *
 *                     \  \ `-.   \_ __\ /__ _/   .-` /  /                  *
 *                 =====`-.____`.___ \_____/ ___.`____.-`=====              *
 *                                   `=---=`                                *
 * **************************************************************************
 * ********************                                  ********************
 * ********************      				 ********************
 * ********************         佛祖保佑 永远无BUG       ********************
 * ********************                                  ********************
 * **************************************************************************
 */

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值