6.Mat类介绍
代码清单2-1 创建Mat类 cv::Mat a; //创建一个名为a的矩阵头 a = cv::imread(“test.jpg”); //向a中赋值图像数据,矩阵指针指向像素数据 cv::Mat b=a; //复制矩阵头,并命名为b
上面这段代码首先创建了一个名为a的矩阵头,之后读入一张图像并将a中的矩阵指针指向该图像的像素数据,最后将a矩阵头中的内容复制到b矩阵头中。虽然a、b有各自的矩阵头,但是其矩阵指针指向的是同一个矩阵数据,通过任意一个矩阵头修改矩阵中的数据,另一个矩阵头指向的数据也会跟着发生改变。但是当删除a变量时,b变量并不会指向一个空数据,只有当两个变量都删除后,才会释放矩阵数据。因为矩阵头中引用次数标记了引用某个矩阵数据的次数,只有当矩阵数据引用次数为0的时候才会释放矩阵数据。根据官方给出的Mat类继承图,Mat类可以存储的数据类型包含double、float、uchar、unsigned char以及自定义的模板等。我们可以通过代码清单2-2的方式声明一个存放指定类型的Mat类变量:
代码清单2-2 声明一个指定类型的Mat类 cv::Mat A = Mat_<double>(3,3);//创建一个3*3的矩阵用于存放double类型数据
由于OpenCV提出Mat类主要用于存储图像,而像素值的最大值又决定了图像的质量,如果用8位无符号整数去存储16位图像,会造成严重的图像颜色失真或造成数据错误。而由于不同位数的编译器对数据长度定义不同,为了避免在不同环境下因变量位数长度不同而造成程序执行问题,OpenCV根据数值变量存储位数长度定义了数据类型,表2-1中列出了OpenCV中的数据类型与取值范围。
表2-1 OpenCV中的数据类型与取值范围
数据类型 | 具体类型 | 取值范围 |
CV_8U | 8位无符号整数 | 0-255 |
CV_8S | 8位符号整数 | -128—127 |
CV_16U | 16位无符号整数 | 0-65535 |
CV_16S | 16位符号整数 | -32768—32767 |
CV_32S | 32位符号整数 | -2147483648—2147483647 |
CV_32F | 32位浮点整数 | -FLT_MAX—FLT_MAX, INF, NAN |
CV_64F | 64位浮点整数 | -DBL_MAX—DBL_MAX, INF, NAN |
仅有数据类型是不够的,还需要定义图像数据的通道(Channel)数,例如灰度图像数据是单通道数据,彩色图像数据是3通道或者4通道数据。因此针对这个情况,OpenCV还定义了通道数标识,C1、C2、C3、C4分别表示单通道、双通道、3通道和4通道。每一种数据类型都存在多个通道的情况,所以将数据类型与通道数表示结合便得到了OpenCV中对图像数据类型的完整定义,例如CV_8UC1表示的就是8位单通道数据,用于表示8位灰度图,而CV_8UC3表示的是8位3通道数据,用于表示8位彩色图。我们可以通过代码清单2-3的方式创建一个声明通道数和数据类型的Mat类:
代码清单2-3 通过OpenCV数据类型创建Mat类 cv::Mat a(640,480,CV_8UC3) //创建一个640*480的3通道矩阵用于存放彩色图像 cv::Mat a(3,3,CV_8UC1) //创建一个3*3的8位无符号整数的单通道矩阵 cv::Mat a(3,3,CV_8U) //创建单通道矩阵C1标识可以省略