Mat类

基本介绍

Mat类是OpenCV中使用最频繁的类之一,用于储存矩阵数据及相关操作,也是程序中图像的主要形式。

Mat类主要由两部分组成:一个描述头(matrix header)及一个指向矩阵数据的指针。其中,描述头包含了矩阵的一些基本信息,如矩阵的尺寸,所占空间大小等。

Mat类有以下几个特点:

  1. Mat类会自动分配内存,使用者无需考虑内存的管理。(老版的OpenCV中使用IPIImage类,需要用户自己管理内存)
  2. Mat类使用了引用计数系统(Reference Counting System),不同的Mat对象可共享同一个矩阵的数据。
  3. 赋值号和拷贝构造只会拷贝描述头,不会开辟新的空间保存矩阵数据。在下面的例子中,如果B,C的值发生变化,那么A的值也会发生变化。
Mat A,C;
Mat B(A);
C = A;
  1. 如果想要矩阵数据一同被拷贝,则可用cv::Mat::clone()命令。
Mat D = A.clone();

声明与初始化

1. cv::Mat A(2, 2, cv::CV_8UC3, cv::Scalar(0,0,255));
2. cv::Mat B = cv::Mat::eye(4, 4, cv::CV_64F); // 单位矩阵
3. cv::Mat C = cv::Mat::ones(2, 2, cv::CV_32F); // 元素均为1的矩阵
4. cv::Mat D = cv::Mat::zeros(3, 3, cv::CV_8UC1); // 元素均为0的矩阵

其中,CV_8UC3中的’8’表示8个比特,'U’表示无符号(unsigned),'C3’表示通道有三个通道。即,A中像素值都为无符号类型,有8个比特长,并且有3个通道。

存储形式

Mat 类本质上是一个通用的矩阵类型,可存储不同类型的图像。灰度图和RGB图的存储形式有所不同,具体看下图。

除此之外,一般而言,每一行的数据在内存中的地址都是连续的,但不同的行之间不一定。可以用isContinuous()成员函数判断行与行之间地址是否连续。

访问Mat中的任意元素

可使用at()函数来访问任意元素。at()是一个函数模板,需要指定元素类型,一般而言,灰度图的元素类型为uchar,RGB图的元素类型为Vec3b,是一个三维的向量。具体使用方式如下 :

uchar gray = img_gray.at<uchar>(i,j); // 灰度图
auto r = img_rgb.at<cv::Vec3b>(i,j)[0]; // RGB图
auto g = img_rgb.at<cv::Vec3b>(i,j)[1];
auto b = img_rgb.at<cv::Vec3b>(i,j)[2];
img_rgb.at<cv::Vec3b>(i,j) = cv::Vec3b(0,0,0); // 将某一点赋值为0

获得 Mat 的维度

cv::Mat m;
// do something to m
int channels = m.channels(); // 通道数
int rows = m.rows; // 行数
int cols = m.cols; // 列数

扫描整副图像

扫描图像上的每个元素,本质上就是要访问Mat矩阵中的每个元素。主要有三种方式扫描图像:

  1. 用指针扫描:
    用成员函数ptr< type >()获取矩阵某一行首元素的指针,达到访问元素的目的。由于每一行的内存是连续的,因此能够按顺序扫描矩阵,效率较高。
// 用C语言的[]运算符访问
Mat &ScanImageAndReduceC(Mat& I, const uchar* const table) {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;}uchar *p;for (int i = 0; i < nRows; ++i) {p = I.ptr<uchar>(i);//获得第i行的首指针for (int j = 0; j < nCols; ++j) {p[j] = table[p[j]];}}return I;
}
  1. 用迭代器扫描
    成员函数begin< type >()和end< type >()可获取Mat类的迭代器,进行数据元素的遍历。这种方法相比第一种方法更安全,不会有下标溢出的问题,但效率更低。
// 用迭代器迭代
Mat& ScanImageAndReduceIterator (Mat &I, const uchar* const table) {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]];}break;}}return I;
}
  1. 通过at()函数扫描
    该方法本质上是依次任意访问矩阵中的每一个元素,在遍历时,每一个循环都要重新计算指针的地址,因此效率更低。但这种方式最直观,可读性高。
// 利用at()函数随机访问元素,达到扫描的效果
Mat& ScanImageAndReduceRandomAccess (Mat &I, const uchar* const table) {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:{for (int i = 0; i < I.rows; ++i) {for (int j = 0; j < I.cols; ++j) {I.at<Vec3b>(i,j)[0] = table[I.at<Vec3b>(i,j)[0]];I.at<Vec3b>(i,j)[1] = table[I.at<Vec3b>(i,j)[1]];I.at<Vec3b>(i,j)[2] = table[I.at<Vec3b>(i,j)[2]];}}break;}}return I;
}

图像操作

Input/Output/Visualizing

Mat img = imread(filename, IMREAD_GRAYSCALE);
// Mat img = imread(filename, IMREAD_COLOR);
if (img.empty()) {cout << "something wrong\n";
}
imwrite(filename, img);
namedWiodow("demo", WINDOW_AUTOSIZE);
imshow("image", img);
waitKey(0);

访问某一像素值

  1. 灰度图:
Scalar intensity = img.at<uchar>(y,x);
  1. RGB图:
Vec3b intensity = img.at<Vec3b>(y,x);
uchar b = intensity.val[0];
uchar g = intensity.val[1];
uchar b = intensity.val[2];

选择某一子区域

Rect r(top_x, top_y, width, height);
Mat subMatrix = img(r);

颜色空间转换

Mat img = imread(filename, IMREAD_COLOR);
Mat grey;
cvColor(img, grey, COLOR_BGR2GRAY);

线性加权

可使用addWeighted函数进行线性加权:

addWeighted(src1, alpha, src2, beta, 0.0, dst);

其中,参数含义如下:

模板运算

可使用filter2D()函数对图片进行模板运算。

Mat kernel = (Mat_<char>(3,3) <<  0, -1,  0,-1,  5, -1,0, -1,  0);
filter2D(src, dst, src.depth(), kernel);

其他常用函数

  • saturat_cast< T >(): 防止数值溢出
  • CV_Assert(): 相当于Python中的assert

OpenCV(c++) 矩阵 Mat 类的用法与注意事项相关推荐

  1. 【从零学习OpenCV 4】Mat类介绍

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门 ...

  2. 基于c++版本的opencv操作(Mat类)

    图像的基本操作(一) 前言 一.Mat类? 1.c++版本代码 添加链接描述 前言 一.Mat类? 1.c++版本代码 1.1 at()函数 1.2 使用迭代器 2.代码结果展示 2.1 at()函数 ...

  3. openCV图像矩阵Mat和二维数组的互相转换

    openCV图像矩阵Mat和二维数组的互相转换 在openCV的应用中,我们获取图像的矩阵信息很简单.但是我们可能想调用其他的矩阵运算库(比如Eigen库)来进行计算.那么我们就需要把openCV读取 ...

  4. 【从零学习OpenCV 4】Mat类构造与赋值

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门 ...

  5. 如何将OpenCV中的Mat类绑定为OpenGL中的纹理

    https://blog.csdn.net/TTTTzTTTT/article/details/53456324 如果要调用外接的USB摄像头获取图像通常使用OpenCV来调用,如何调用摄像头请参考本 ...

  6. Opencv中Mat类详细解读(学习笔记)

    基于windows10.vs2015.OpenCv4.1.0. 目录 1.Mat类简介 2.Mat类的构造与赋值 2.1.Mat类的构造 2.2.Mat类的赋值 3.Mat类支持的运算 3.1Mat类 ...

  7. OpenCV Mat类详解和用法(官网原文)

    参考文章:OpenCV Mat类详解和用法 我马克一下,日后更 官网原文链接:https://docs.opencv.org/3.2.0/d6/d6d/tutorial_mat_the_basic_i ...

  8. OpenCV Mat类详解和用法

    OpenCV Mat类详解和用法 我们有多种方法可以获得从现实世界的数字图像:数码相机.扫描仪.计算机体层摄影或磁共振成像就是其中的几种.在每种情况下我们(人类)看到了什么是图像.但是,转换图像到我们 ...

  9. OpenCV中Mat类的重载运算符operator()的用法

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 定义如下: inline Mat Mat::op ...

最新文章

  1. java圆周率流程图,流程图、PI图入门知识 课件.doc
  2. IT项目管理总结:第九章 项目人力资源管理
  3. 【推荐一位Python大佬】 从程序员到创业者,再到自由职业
  4. 阿里云张毅萍:构建边缘云全站加速网络体系
  5. 二叉树的最小深度Python解法
  6. linux超级工具,linux运维超级工具--sysdig
  7. 对于原型链的彻底理解
  8. Learn For Flutter
  9. 回顾2019,展望2020
  10. 谭浩强c语言第六版答案,C语言谭浩强版本第6章课后练习题答案
  11. TP340G+硬改山寨UBNT,
  12. [ZJOI2008]树的统计
  13. dota2服务器位置设置在哪里,《DOTA2》自走棋国服怎么进入 自走棋国服服务器进入方法...
  14. 苹果macbookpro多少钱_买一套可用的苹果全家桶,要花多少钱?
  15. MySQL 排序 输出序号
  16. IPSEC对称解密以及非对称加密
  17. MySql存储过程与函数
  18. Code_Aster comm命令文件结构与说明(by Yang 2017.3.30)
  19. N+1 架构支持更高的电源可靠性
  20. 声源分离算法性能评估指标SIR、SDR、SAR

热门文章

  1. 换行样式不要首行缩进_CSS实现文章段落首行缩进两个字符不再每次空格
  2. 工业互联网平台七大核心技术
  3. 工业大数据云平台,设备大数据云平台
  4. cv2.imwrite()不能成功保存图片
  5. 杰里之AC695N/AC696N 蓝牙耳机PCB LAYOUT 说明【篇4】
  6. 互联网日报 | 天猫京东618再创新纪录;字节跳动成立抖音电商部门;全国普速铁路20日起实施电子客票...
  7. StartCom 申请 免费的SSL 证书(绑定多个域名)
  8. 生成带图片无白边的二维码
  9. linux more 结合 grep查询日志信息
  10. unity 网络检测