opencv中的Mat类讲解

Mat类

很久以前opencv还只是提供c接口的一个库。那时它使用一种c语言的结构体叫做IplImage来存储图像。后来实在是受不了了,因为使用c语言接口的用户需要自己来管理内存,实在特别麻烦并且容易出错。opencv维护者们就使用c++又翻新了一遍opencv库。新版本中(2.0往后)支持使用Mat来存储图像。

Mat的组成

Mat主要由两部分组成:

  1. 矩阵头信息:主要是矩阵大小矩阵存储方法矩阵地址等,矩阵头大小是固定的;

  2. 图像像素矩阵的指针对象,使用类似智能指针shared_ptr的方法来管理内存;

Mat对象的拷贝问题

Mat对象的拷贝构造函数、拷贝赋值运算符(重载的=)都是使用的浅拷贝,即只拷贝了指针的值,但是它们指向共同的一片区域。

Mat A, C;                          // creates just the header parts
A = imread(argv[1], IMREAD_COLOR); // here we'll know the method used (allocate matrix)
Mat B(A);                                 // Use the copy constructor
C = A;                                    // Assignment operator
Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle D中的指针指向A指针指向矩阵的一片长方形区域
Mat E = A(Range::all(), Range(1,3)); // using row and column boundaries 也是指向一部
区域,第一个参数代表行(全部行),第二个参数代表列(1~3列)

如上,A、B、C三个对象最终指向的都是同一片内存区域。即对它们三个任何一个的图像进行修改,另外两个也修改了。如果想要进行深拷贝,可以使用Mat类自带的两个函数:cv::Mat::clone()cv::Mat::copyTo(),使用方法如下:

Mat F = A.clone();
Mat G;
A.copyTo(G);

现在,A、F、G三个Mat对象分别管理属于自己的图像矩阵内存,不会互相干扰。

Mat对象的存储方法

使用imread("1.png"),默认参数是IMREAD_COLOR ,即总是将硬盘中的图片转换为8位的3通道BGR彩色图然后读入内存,并返回一个3通道BGR的mat类型

存储方法主要受两个参数影响:

  1. 颜色空间:决定了使用何种方法编码一个像素的颜色,比如灰度空间单通道描述、RGB三通道红绿蓝描述、RGBD四通道红绿蓝透明度四通道描述等等;

  2. 数据类型:使用何种数据类型来描述一个通道,如unsigned char(8位0~255)、signed char(8位-128~127)、float(32位)、double(64位)等,越大则图像占用内存越大,可描述的色彩越细微;

颜色空间主要有RGB、HSV、HLS、YCrCb等,想了解自己再查书吧。值得一提的是opencv标准显式中使用的RGB其实是BGR,即翻转了一下顺序。同时,RGB转灰度空间使用了如下公式:

Gray = R*0.299 + G*0.587 + B*0.114

关于颜色空间更多的知识可以查看这篇博文,在opencv中提供了将不同颜色空间的Mat进行转换的函数cv2.cvtColor

Mat中指针指向的矩阵中像素的组织形式(灰度空间与BGR空间)

像素的组织形式主要依赖于颜色空间类型的选择,下图是灰度空间下像素的组织形式: 

tutorial_how_matrix_stored_1

下面这张图是BGR颜色空间的组织形式,每个大列下会有三个小列依次代表着三种颜色通道(分别是B、G、R),其实就是每个像素由三个uchar组成(假设data_typeuchar): tutorial_how_matrix_stored_2

无论Mat是几通道的颜色空间,其矩阵都是两维的。只是两维矩阵的每一个元素的大小是通道数*数据类型的大小,即在一个元素中,各通道依次存储。同时有一点需要说明,如果内存足够大,在载入图像时,便会将下一行紧随着上一行存储,所以最后有可能整幅图像存成了一行。这种情况是可以帮我们提升扫描速度的(按照一维方式扫描只需要获得一次行首指针),我们可以使用opencv提供的cv::Mat::isContinuous()函数来确定是否是连续存储的。

Mat对象的创建与显示

Mat的创建有好多方式,同时它重载了<<,使得可以直接用cout进行输出显示,mat_creat_print.cpp中实现了各种创建与显示的方法,可以查看代码或者直接运行查看结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值