在之前的OpenCV学习笔记(一)用到的几种显示图像的方法中其中一种就是Mat。Mat结构在OpenCV 2.0后才得到广泛应用,相对于OpenCV1.0时代中的IplImage,它有个好处就是不用再手动释放图像内存。而用IplImage格式存储图像的时候就必须在推出前将图像内存release掉,即添加语句cvReleaseImage(&iplImg);,否则会造成内存泄漏。除了这个好处外,它的操作也更加简单,比如用imshow显示图像,imread读取图像等等,跟Matlab有点接近。
Mat是一个类,它由两个数据部分组成:矩阵头和一个指向存储所有像素值的矩阵的指针。其中矩阵头包含了矩阵的尺寸、存储方法、储存地址等信息,由此可以看出矩阵头所占的内存很小,而具体储存所有像素值的矩阵则非常大。举个例子,比如一个班级,矩阵头就相当于储存了班级里有多少人、男女比多少、平均身高、平均体重等信息,而矩阵就储存了班级中所有同学的所有基本信息,每一个同学就相当于是一个像素点,而每个像素点的颜色信息、深度信息等一串数据就相当于是每个同学的身高、体重、性别等一系列信息组成的一串数据。
那么问题来了,假如说我有一张图A,我想要把A图复制给B图,理论上我是不是应该重新开一片内存,用来储存B图的信息?但是仔细想一想,我A图和B图一毛一样,如果我再开一片内存存储B图,那岂不是和存储A图的内存重复啦?是不是会造成内存的浪费。所以OpenCV中的图像存储结构Mat就很好地解决了这个问题。它使用了引用计数机制,该机制的思路就是让每个Mat对象有自己的信息头,但是共享同一个矩阵。也就是让A图和B图的矩阵指针指向同一地址,共用一片内存。复制图像的时候只是复制了矩阵头的信息和矩阵指针,并不是复制了整个矩阵。
这么一来如果不是很熟悉的话使用起来就会有点别扭了。因为通过复制后得到的图像虽然名字不一样,一个叫A,一个叫B,信息头不同,但是通过任何一个对象所做的改变也会影响到其他对象。这跟人们平常想的很不一样。通俗地讲,我现在从图A那边copy出了B,那么假如我在B图上画一笔,那么我在A图上也会出现同样的一笔。如果这发生在现实生活中,有木有很神奇!具体看以下这段代码:
#include<opencv2/opencv.hpp>
using na