OpenCV(三) Opencv中 core 核心模块详解—— Mat类(一)

      之前列举了 OpenCV 中的12 个模块。现在对于每一个模块一一讲述,从 core 模块的 Mat 类开始 。

      1、什么是 Mat 类?

      Mat 类是用来保存图像以及其他矩阵数据结构(体素、向量场、直方图、张量、点云等)的数据结构,是从 OpenCV 2.0 以后才使用的,之前一直用 C 风格的 IplImage 。 使用 IplImage * 最大的问题就是容易造成内存泄露,管理内存相当麻烦 。而Mat 类的出现不需要我们手动为其开辟空间,也不需要在不需要它是立即释放。补充说明一下,很多 OpenCV 函数仍然手动地管理内存空间,这样不浪费内存,比如,传递一个已存在了的 Mat 对象时,开辟好了的那个空间会被再次使用。但,手动管理内存不再是必须的,对于初学者来说,完全不用考虑这些。    

      Mat 类由两部分组成:矩阵头和指向存储所有像素值的矩阵的指针。如何理解矩阵头呢?矩阵头相当于矩阵的说明书,它描述了矩阵的尺寸、存储方法、存储地址以及引用次数。何为引用次数?是这样的,矩阵头的尺寸是一个常数,不会随图像的变化而变化,但是存储图像的矩阵是随图像大小而变化的,一般来说,比矩阵头大好几个数量级。而在处理图像时,经常会遇到复制图像、传递图像的操作,此时如果复制整个矩阵,不仅耗费内存,还影响运行效率。所以,OpenCV中的“引用次数”,即“计数机制”,让每一个 Mat 对象都有一个矩阵头,但是它们共享一个矩阵。这是通过让矩阵指针指向同一个地址实现的。比如:

Mat A;    //仅仅创建了矩阵头
A = imread("1.jpg",1);   //为矩阵开辟一段内存,及创建了矩阵
Mat B(A);   // 拷贝构造函数
Mat C = A;  //赋值
      当利用 Mat 类定义的时候,只是创建了矩阵头。在使用拷贝构造或者赋值的时候,其实是新创建了不同的信息头和矩阵指针,它们共享一个矩阵。

     那有人说了,我就想复制整个矩阵,行吗?!当然行了,现在这世道,啥不行。此时可以使用 clone ()函数或者copyTo函数 。

Mat D = A.clone()  //D等于A的复制品
Mat E;
A.copyTo(E);//把A复制到E

      2、Mat 常见的构造方法

      (1)Mat ::Mat()      无参数构造法,例如 Mat 就是无参数构造法

      (2) Mat ::Mat(int rows, int cols, int type)  //行列构造法,type表示什么下面讲

      (3)Mat ::Mat(Size size, int type)    //大小为size 的图像。比如 Mat A(cv::Size(7,7),CV_8UC3 ),创建 7× 7大小的图片  

      (4)Mat ::Mat(int rows, int cols, int type,const Scalar&s)   //所有元素都初始化为 s

      (5)Mat ::Mat(Size size, int type, const Scalar&s) 

      (6)Mat::Mat(const Mat& m)   //将矩阵m 赋值给新创建的对象

      下面解释 type 。一般来说,有CV_8UC1、CV_16SC3、CV_32FC3  ,8,16,32表示位数; U表示无符号整数、S 表示有符号整数、F表示 double类型。C 表示通道数,1表示单通道,3表示三通道。以下为编程测试(在linux 下,如果在windows 下面,效果是一样的)

int main()
{	 
        Mat A;
        cout <<"矩阵A: "<< A << endl;
        
        Mat B(7,7,CV_8UC1);
        cout << "B矩阵为: "<< endl << B << endl;
        
        Mat C(7,7,CV_8UC3);
        cout << "C矩阵为: "<< endl << C << endl;
        
        Mat D(Size(7,7),CV_8UC1);   //和 B 矩阵是等价的
        cout << "D矩阵为: "<< endl << D << endl;
        
        Mat E(7,7,CV_8UC1,Scalar(1) );
        cout << "E矩阵为: "<< endl << E << endl;
        
        Mat F(7,7,CV_8UC3,Scalar(1) );
        cout << "F矩阵为: "<< endl << F << endl;
        
        Mat G(7,7,CV_8UC3,Scalar(1,2,3) );
        cout << "G矩阵为: "<< endl << G << endl;
        
        waitKey();
        return 0;
}
      输出结果如下

OpenCV(三) Opencv中 core 核心模块详解—— Mat类(一)_第1张图片


OpenCV(三) Opencv中 core 核心模块详解—— Mat类(一)_第2张图片


      最后,我想提一句,上面的矩阵由 Mat 定义出来了,你可以用 imshow()给输出出来,但是,尺寸要设置的大一些,不然你看不到输出结果,因为图片太小了。值得注意的是,利用无参数构造法会报错!


你可能感兴趣的:(视觉/图像处理opencv)