一、Mat类
Mat类是C++实现的OpenCV库的核心,表示一个N维度单通或多通道阵列,可以用来存储实数或复数值向量和数组,灰度或彩色图像,向量场,张量及直方图(当然高纬度的直方图存储在稀疏Mat类更合适),OpenCV是一个图像处理库。它包含大量的图像处理功能。为了解决计算上的挑战,大多数时候你最终会使用库的多个功能。因此,将图像传递给函数是一种常见的做法。我们不应该忘记,我们正在讨论图像处理算法,这些算法往往计算量很大。我们想要做的最后一件事是通过制作不必要的大型图像副本来进一步降低程序的速度。
为了解决这个问题,OpenCV使用了一个引用计数系统。这个想法是,每个Mat对象都有自己的头部,但是矩阵可以通过让它们的矩阵指针指向相同的地址而在它们的两个实例之间共享。而且,复制操作符只会复制标题和指向大矩阵的指针,而不是数据本身。
1.1创建一个Mat对象
从上可以看出Mat基本上是一个包含两个数据部分的类:矩阵头(包含矩阵大小,用于存储的方法,存储矩阵的地址等信息)以及包含像素值(取决于选择用于存储的方法的任何维度)。矩阵头部大小是恒定的,但是矩阵本身的大小可能随着图像而变化,并且通常比数量级大。
创建一个Mat类型对象可以没有大小和数据类型,然后通过成员函数create()来分配指定,例如创建一个二维数组,可以使用create(int rows, int cols, types)备注:仅限于二维数组,第三个参数类型既指定了元素的类型又说明了通道数,这些类型都定义在矩阵头中,格式为:CV_{8U,16S,16U,32S,32F,64F}C{1,2,3},然后通过setTo()函数设定每个通道上的具体数值;
通常定义创建一个Mat类型的对象可以通过构造函数在创建矩阵时即分配内存,其中一个构造函数的参数与create()函数参数相同;
1 //演示示例:创建一个Mat对象数组
2 #include
3 #include
4 #include
5
6 using namespacestd;7 using namespacecv;8
9 intmain()10 {11 Mat array_test;12 array_test.create( 3, 2, CV_32FC3 ); //create array header
13 array_test.setTo(Scalar(1.0f,2.0f,3.0f)); //set array data
14
15 cout << "array_test =" << endl << array_test <
17 Mat array_test_con( 3, 2, CV_32FC3, Scalar(1.0f,2.0f,3.0f) );18 cout << "array_test_con =" << endl << array_test_con <
1.2 Mat类对象的数据和Mat类矩阵头
如上叙述,为了解决图像处理繁杂计算问题,OpenCV使用了一个引用计数系统。这个想法是,针对图像的数据,每个Mat对象都有自己的头部相对应,通过让它们的矩阵指针指向相同的地址而在它们的两个实例对象之间共享。而且,复制操作符只会复制标题和指向大矩阵的指针,而不是数据本身。
1 //演示示例:矩阵头Array Header和矩阵数据Array data关系
2 #include
3 #include
4 #include
5 using namespacestd;6 using namespacecv;7
8 intmain()9 {10 Mat A( 2, 2, CV_8UC3, Scalar(10, 20, 30));11
12 cout << "A =" << endl << A <
14 cout <
16 Mat B(A);17 cout << "B =" << endl << B <
19 cout <
21 Mat C =A;22 cout << "C =" << endl << C <
24 cout << endl << "After Mat algebra..." <
26 Mat A1( 2, 2, CV_8UC3, Scalar(1, 2, 3));27
28 A = A +A1;29
30 cout << "A =" << endl << A <
34 return 0;35 }
上述所有对象最后指向相同的单一数据矩阵。然而,它们的标头是不同的,并且使用它们中的任何一个进行修改也会影响所有其他标签。实际上,不同的对象只是为相同的底层数据提供不同的访问方法。不过,它们的矩阵头部分是真正相互独立的。这样,可以创建一个仅包含矩阵数据的一部分的矩阵对象。例如,要在图像中创建感兴趣的区域(ROI),您只需创建一个带有新边界的新矩阵头:
1 #include
2 #include
3 #include
4
5 using namespacestd;6 using namespacecv;7
8 intmain()9 {10 Mat A( 4, 4, CV_8UC3, Scalar(10, 20, 30));11 cout << "A =" << endl << A <
13 cout <
15 Mat B(A);16 cout << "B =" << endl << B <
18 cout <
20 Mat C =A;21
22 cout << "C =" << endl << C <
24 cout << endl << "After Mat algebra..." <
26 Mat A1( 4, 4, CV_8UC3, Scalar(1, 2, 3));27
28 A = A +A1;29
30 cout << "A =" << endl << A <
34 Mat D(A, Rect(0,0,2,2));35 cout << "D =" << endl << D <
37 D.setTo(Scalar(1, 2, 3));38 cout << "A =" << endl << A <
40 //创建一个带有新边界的新矩阵头
41 Mat E = A(Range::all(), Range(2,3));42 cout << "E =" << endl << E <
44 E.setTo(Sca