一直使用mat,很好用,但是细扣又说不清楚到底是怎样的一种数据类型,今天学习下。

一、先上硬货结论:

  1. 浅拷贝:拷贝构造函数和赋值运算符只复制信息头,即实际上还是同个图像数据、mat中存储同个数据地址;
Mat A,C;
A=imread("1.jpg",type);
Mat B(A);//拷贝构造函数
C=A;//直接赋值符
  1. 深拷贝:使用函数clone(),或者copyTo(),同时复制信息头、和新拷贝一份图像数据(对应新的数据地址)
Mat F=A.clone();
Mat G;
A.copyTo(G);
  1. 不管深拷贝还是浅拷贝,都不必手动为其开辟空间
  2. 不管深拷贝还是浅拷贝,都不必手动释放空间
  3. 如果需要给某函数传图像,因为图像数据量是非常大的,所以一般是传存放图像数据的指针,也可以传Mat:例如
    void function(uint8_t* p_image)或void function(Mat& image);


二、Mat数据类型的说明

1. Mat类常用成员函数和成员变量

由于 Mat 类使用的非常广泛,使用的形式也非常之多,这里只对较为常用的成员函数和成员变量做出了整理;

1.1 构造函数

(1)默认构造函数**

cv::Mat::Mat()

默认构造函数:生成一个矩阵并由OpenCV提供的函数(一般是Mat::create() 和 cv::imread() )来分配储存空间。

Mat类可以分为两个部分:矩阵头指向像素数据的矩阵指针

矩阵头:包括数字图像的矩阵尺寸、存储方法、存储地址和引用次数等,矩阵头的大小是一个常数,不会随着图像的大小而改变,但是保存图像像素数据的矩阵则会随着图像的大小而改变,通常数据量会很大,比矩阵头大几个数量级。这样,在图像复制和传递过程中,主要的开销是由存放图像像素的矩阵而引起的。因此,OpenCV使用了引用次数,当进行图像复制和传递时,不再复制整个Mat数据,而只是复制矩阵头和指向像素矩阵的指针,例如:

cv::Mat a ;                 //默认构造函数,创建矩阵头
a = cv::imread("test.jpg"); //读入图像,矩阵指针指向该像素数据
cv::Mat b = a ;             //复制 

上面的a,b有各自的矩阵头,但是其矩阵指针指向同一个矩阵,也就是其中任何一个改变了矩阵数据都会影响另外一个。那么,多个Mat共用一个矩阵数据,最后谁来释放矩阵数据呢?
这就是引用计数的作用,当Mat对象每被复制一次时,就会将引用计数加1,而每销毁一个Mat对象(共用同一个矩阵数据)时引用计数会被减1,当引用计数为0时,矩阵数据会被清理。
(2)常用构造函数——1

cv::Mat::Mat(int rows,int cols,int type)

重载的构造函数,这也是常用构造函数之一,在创建对象同时,提供矩阵的大小(rows,行数;cols ,列数),以及存储类型(type)
该类型表示矩阵中每一个元素在计算机内存的存储类型,如CV_8UC3,具体含义为“3通道8位无符号数”。eg:

Mat src(10,10,CV_32FC3);  //表示src是一个10*10的矩阵,且矩阵元素以32位float型存储

类似,OpenCV还提供了一种Size() 数据结构来构造Mat对象
(3)常用构造函数——2

cv::Mat::Mat(Size size,int type )

Size类等效于一个成对数据,size::Size(cols,rows),特别注意 cols和rows的位置

eg:

Mat src1(3, 4, CV_32FC3);
Mat src2(Size(3, 4), CV_32FC3);
cout << "src1.rows=" << src1.rows << " src1.cols=" << src1.cols <<endl;
cout << "src2.rows=" << src2.rows << " src2.cols=" << src2.cols << endl;
cout << "src1.size="<<src1.size() << endl <<"src2.size=" << src2.size() <<endl;

不得不说,这个Size类的数据结构有点“反人类”,但这样做的好处是方便了计算机内部的运算(比如OpenCV很多函数计算Size相关的数据也是按这个顺序来的,具体为什么这样,我也不太清楚,个人理解为行业标准);
还有,我们平时所说分辨率,也是Size的类型,比如屏幕分别率 1440*900,其中cols=1440,rows=900;
(4)常用构造函数——3

cv::Mat::Mat(int ndims,const int *  sizes,int type,const Scalar& s)

该构造函数与使用了Scalar参数,作用是能够通过Scalar数据类来初始化元素值,例如,我们要生成一张白色背景的图片:

Mat src1(300, 400, CV_8UC3,Scalar(255,255,255));
imshow("test", src1);

其中,(255,255,255)对应以8位无符号数存储,RGB色域的白色值。
(5)常用构造函数——4

cv::Mat::Mat(const Mat & m)

引用m矩阵,注意,这里是引用值;

1.2 成员函数

(1)at函数
at函数的功能是访问矩阵元素,根据不同的使用场景,有多个重载函数可供选择。
如,访问一个二维的矩阵,可用at函数原型为:

_Tp& cv::Mat::at(int i0,int i1)

eg:

Mat src = imread("test.jpg");
int elem = src.at<int>(0,0);

访问test.jpg图像的(0 , 0)元素
(2)channels函数

int cv::Mat::channels()  const

返回图像的通道数
(3)clone函数

Mat cv::Mat::clone()    const

矩阵复制
(4)convertTo函数

void cv::Mat::convertTo(OutputArray m,int rtype,double alpha = 1,double beta = 0)   const

转换矩阵存储类型,具体计算公式如下:

m(x,y)=saturate_cast(α(∗this)(x,y)+β)

m是输入矩阵,rtype是目标类型,alpha是放缩系数,beta是增减标量
(5)copyTo函数

void cv::Mat::copyTo(OutputArray    m)  const

从m矩阵复制data数据单元,与clone函数的作用类似
(6)create函数

void cv::Mat::create(int rows,int cols,int type)

分配矩阵的存储单元,一般和默认构造函数配合使用
(7)depth函数

int cv::Mat::depth()    const

返回图像深度,即矩阵元素的存储方式
(8)diag函数

Mat cv::Mat::diag(int d = 0)  const

提取矩阵的对角元素
(9)mul函数

MatExpr cv::Mat::mul(InputArray m,double scale = 1)    const

矩阵的乘法
(10)inv函数

MatExpr cv::Mat::inv(int method = DECOMP_LU)   const

求逆矩阵
(11)t函数

MatExpr cv::Mat::t() const

求转置矩阵

(12)total函数

size_t cv::Mat::total() const

返回矩阵的元素总个数,如30*40的图像,存在1200个像素点
(13)pop_back函数

eg:

object.pop_back();   //object是一个矩阵,该函数功能是弹出最后一行元素

(14)release函数

在必要的情况下,递减引用计数并释放该矩阵。

C++: void Mat::release()

该方法递减与矩阵的数据关联的引用计数。当引用计数减为0时,矩阵的数据将被释放,数据和引用计数器指针设置为 NULL。如果矩阵头指向外部数据集 (见 Mat::Mat()), 引用计数为 NULL,并且该方法在这种情况下无效。

可以手动调用此方法强制矩阵数据释放。但由于这种方法在析构函数中是自动调用的,或以更改数据指针的其他方法,因此通常不需要调用这个函数。在支持它的平台上,引用计数器递减并检查是否为0 是一个原子操作。因此,在不同的线程异步调用相同的矩阵是安全的操作。
(15) Mat::ones()函数

Mat m = Mat::ones(2, 2, CV_8UC3); 相当于:Mat m = Mat(2, 2, CV_8UC3, 1);

// OpenCV replaces 1 with Scalar(1,0,0)相当于每个像素的第一个通道为1,其余两个通道为0;
(16) Mat::zeros()函数

Mat m = Mat::zeros(2, 2, CV_8UC3);

//相当于创建一张黑色的图,每个像素的每个通道都为0,Scalar(0,0,0);

1.3 成员变量

int cv::Mat::cols;     //返回矩阵的列数int cv::Mat::rows      // 返回矩阵行数uchar* cv::Mat::data   // 指向矩阵的数据单元的指针int cv::Mat::dims      // 返回矩阵维度,该维度≥2MatSize cv::Mat::size  // 返回矩阵大小

参考链接 c++ mat类 opencv

c++版opencv中的Mat数据类型的说明相关推荐

  1. OpenCV中图像Mat,二维指针和CxImage类之间的转换

    在做图像处理中,常用的函数接口有Opencv中的Mat图像类,有时候需要直接用二维指针开辟内存直接存储图像数据,有时候需要用到CxImage类存储图像.本文主要是总结下这三类存储方式之间的图像数据的转 ...

  2. opencv中的Mat图使用CDC显示

    需求:MFC显示opencv读取的Mat图 代码: 1.中间转化的函数: //************************************ // 函数名称: Show2DC // 访问权限 ...

  3. OpenCV中图像Mat存储格式和MATLAB中图像Mat存储格式的区别

    首先,看一下图像中的宽高与笛卡尔坐标系之间的关系如下图所示,即x与width(cols)对应,y与height(rows)对应,x是按列来进行变化,y按行变化. OpenCV读入图像以Mat形式存储时 ...

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

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

  5. opencv中查看mat位图的像素幅度(Cv::matStep)

    实例 其中step里的 ,其中数据指针首地址是p=0x000000000028d7b0,1280是每行数据所占的字节数,1是每个元素的字节数. Mat的作用 The class Mat represe ...

  6. C语言使用指针处理opencv中的Mat图像数据

    1.在处理图像时,一般直接使用opencv中的imread函数获取图片,但是获取到图片后没有用到opencv中的其他算法时,直接用图片处理就会出现耗时严重的情况,所以需要将图片形式转换成指针数组形式处 ...

  7. 遍历opencv中的mat像素的几种方法和概念

    今天在看矩形滤波的时候忽然脑子短路,把一些概念全弄混了,现总结一下,以便下次再混的时候可以参考确认下,自己的理解,有错的地方还请指正. 首先,在Opencv2中基本上都是用的Mat来表示图像了,C++ ...

  8. opencv中的Mat类型

    Mat类型主要是跟matlab中的数据类型一样.故用起来很方便. Mat最大的优势跟STL很相似,都是对内存进行动态的管理,不需要之前用户手动的管理内存,对于一些大型的开发,有时候投入的lpImage ...

  9. 利用FreeImage将gif图像转为opencv中的Mat

    原文:http://www.cnblogs.com/monkeyhey/p/3927857.html 网上有将gif转为iplimg的版本,只是用惯了C++的接口,所以就写了个转Mat的版本,代码比较 ...

最新文章

  1. 慕课《深入理解计算机系统》袁林枫老师章节测试1-9
  2. 在本机快速创建YUM源
  3. 机器学习系统设计——误差矩阵
  4. vue 分享微信传参_vue实现微信分享链接添加动态参数的方法
  5. 极简 响应式 html5,HTML5----响应式(自适应)网页设计
  6. django的视图与模板
  7. Python为你打开一扇门
  8. Python: 如何安装 torch 对应的 torchvision 版本?
  9. Python学习1——语法
  10. 什么情况下会用上568A线序
  11. Java:关于“StringBuilder“的运用
  12. 天啦噜!原来Android补间动画可以这么玩
  13. 洛谷 B2006 地球人口承载力估计
  14. 学校计算机教室解说词词,小学各专用教室解说词.doc
  15. 在Linux系统中的安装cpolar内网穿透
  16. SQL审核 | SQLE-SQL审核平台体验报告
  17. tvOS 开发第一个tvOS应用
  18. Python 元组() (元素不能修改),元组的定义,元组与列表的转换,元组的应用场景
  19. 倒车与移库-汽车倒车移库技巧
  20. 应用回归分析(知识点整理)(三)——SPSS处理异方差

热门文章

  1. JZOJ 2307. 【中山市选2011】新年礼物
  2. 大数据课程适合那些基础的人学习呢?适合学习大数据课程的四类人
  3. 库克清华演讲:乔布斯弥留之际的一句话
  4. 快嘴旺旺群群发 官方
  5. [数据分析自学帮手]数据分析必备的统计学知识大梳理,还不赶紧收藏?
  6. 无线通信设计秘密一:跳频技术
  7. 电路与电子3.3.4共射放大电路的阻抗与密勒效应
  8. 变频拖动电机 减少电机噪音
  9. 动手学深度学习V2.0(Pytorch)——10.感知机(激活函数)
  10. GNSS无人机编队表演方案