一、概念:
Mat类是opencv中用来存储图像的类。
Mat类由矩阵头(包含矩阵尺寸、存储方法、存储地址等信息)和一个指向存储所有像素值矩阵(根据所选存储方法的不同,矩阵可以是不同的维数)的指针。矩阵头的尺寸是常数值,但矩阵本身的尺寸会因图像的不同而不同,通常比矩阵头的尺寸大好几个数量级。因此,当在程序中传递图像并创建副本时,大的开销是由矩阵造成的,而不是矩阵头。OpenCV是一个图像处理库,其中包含大量的图像处理函数。为了解决问题,通常要使用库中的多个函数,因此经常需要在函数中传递图像。同时,对于那些计算量很大的图像处理算法,除非万不得已,否则不应该复制“大”图像,因为这会降低程序运行速度。
为了解决这个问题,OpenCV使用引用计数机制,其思路是让每个Mat对象有自己的矩阵头,但共享同一个矩阵(通过让矩阵指针指向同一地址来实现)。当使用复制构造函数(又称拷贝构造函数)时,只需复制矩阵头和矩阵指针即可,而不用复制矩阵本身。
如果矩阵属于多个Mat对象,那么当不再需要它时谁来负责清理?简单的回答是最后一个使用它的对象。清理工作可以通过引用计数机制来实现。无论用户什么时候复制一个Mat对象的矩阵头,都会增加矩阵的引用次数;反之,当一个矩阵头被释放之后,这个计数被减1;当计数值为0,矩阵就会被清理。但在某些时候确实需要完全复制矩阵本身(不只是矩阵头和矩阵指针),这时可以使用函数clone()或者copyTo()实现深复制。
总结:
①OpenCV函数中输出图像的内存分配是自动完成的(如果不特别指定的话)。
②使用OpenCV的Mat类时不需要考虑内存释放问题。
③赋值运算符和复制构造函数只复制矩阵头。
④函数clone()或者copyTo()可用来复制表示图像的矩阵。
Mat类的构造函数:
Mat(int rows,int cols,int type)
(常用)Mat(Size size,int type)
(常用)Mat(int rows,int cols,int type,const Scalar &s)
Mat(Size size,int type,const Scalar &s)
Mat(int ndims,const int* sizes,int type)
Mat(int ndims,const int* sizes,int type,const Scalar &s)
二、示例代码:
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
void test01()
{
// 1.使用Mat()创建Mat对象
// 创建一个类型为8位uchar,颜色为三通道黄色的2*2的Mat对象
Mat image(2,2,CV_8UC3,Scalar(0,255,255));
cout<<"矩阵元素"<<endl<<image<<endl;
// 将图像保存
if(imwrite("D:/test.jpg",image))
{
cout<<"图片保存成功!"<<endl;
}
else
{
cout<<"图片保存失败!"<<endl;
}
// 2.创建一个超二维的矩阵
int sz[3]={2,2,2};
Mat image2(3,sz,CV_8UC1,Scalar(0));
// 3.使用create()函数创建Mat对象
Mat img;
img.create(4,4,CV_8UC(2));
cout<<"img = "<<endl<<img<<endl;
}