OpenCV-----Mat

Mat是OpenCV中最为重要的属性。Mat的官方解释可以参看OpenCV的help文档。以下是Mat中一些重要的性质:


1.浅拷贝和深拷贝

OpenCV is an image processing library. It contains a large collection of image processing functions. To solve a computational challenge, most of the time you will end up using multiple functions of the library. Because of this, passing images to functions is a common practice. We should not forget that we are talking about image processing algorithms, which tend to be quite computationally heavy. The last thing we want to do is further decrease the speed of your program by making unnecessary copies of potentially large images.(大致意思为:OpenCV是一个图像处理的库。它包含了大量的图像处理函数。为了解决计算这一挑战,大多你会选择各种各样的函数而结束。正因为如此,将图片传递至函数是一个常见的步骤。我们应该注意到我们所讨论的是计算量将非常大的图像处理算子。最后一件事情是大图像没有必要的拷贝将会降低的程序的运行速率。)

To tackle this issue OpenCV uses a reference counting system. The idea is that each Mat object has its own header, however the matrix may be shared between two instance of them by having their matrix pointers point to the same address. Moreover, the copy operators will only copy the headers and the pointer to the large matrix, not the data itself.(大致译为:为了解决这一问题,OpenCV使用了“reference counting system”。每一个Mat对象都有自己的头,然而两个不同的头的Mat可能享用同一个矩阵内容。拷贝操作只是拷贝了头和指向数据矩阵的指针,自身数据内容没有被拷贝。)

1
2
3
4
5
6
Mat A, C;                                 // creates just the header parts
A = imread(argv[1], CV_LOAD_IMAGE_COLOR); // here we'll know the method used (allocate matrix)

Mat B(A);                                 // Use the copy constructor

C = A;                                    // Assignment operator

All the above objects, in the end, point to the same single data matrix. Their headers are different,however, and making a modification using any of them will affect all the other ones as well. (以上对于任意一个Mat的修改会影响其他所有的Mat,属于浅拷贝)In practice the different objects just provide different access method to the same underlying data. Nevertheless, their header parts are different. The real interesting part is that you can create headers which refer to only a subsection of the full data.(最为有趣的是你可以产生一个头指向一部分数据。) For example, to create a region of interest (ROI) in an image you just create a new header with the new boundaries:

1
2
Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle
Mat E = A(Range::all(), Range(1,3)); // using row and column boundaries

Now you may ask if the matrix itself may belong to multiple Mat objects who takes responsibility for cleaning it up when it’s no longer needed. The short answer is: the last object that used it. This is handled by using a reference counting mechanism. Whenever somebody copies a header of a Mat object, a counter is increased for the matrix. Whenever a header is cleaned this counter is decreased. When the counter reaches zero the matrix too is freed. Sometimes you will want to copy the matrix itself too, so OpenCV provides the clone() and copyTo() functions.

1
2
3
Mat F = A.clone();
Mat G;
A.copyTo(G);

Now modifying F or G will not affect the matrix pointed by the Mat header. What you need to remember from all this is that:

  • Output image allocation for OpenCV functions is automatic (unless specified otherwise).
  • You do not need to think about memory management with OpenCVs C++ interface.
  • The assignment operator and the copy constructor only copies the header.
  • The underlying matrix of an image may be copied using the clone() and copyTo() functions.

有一张经典的图解释浅拷贝和深拷贝如下:

浅拷贝与深拷贝运行时间:(一下例子中浅拷贝时间为0s,深拷贝为0.005s(取决于图片大小))
int main() 
{

	clock_t t1, t2, t3, t4;

	Mat srcImage = imread("C:/Users/SLJ/Desktop/pic7.bmp", 0);
    
	t1 = clock();
	Mat srcA(srcImage);
	t2 = clock();

	cout << "Mat srcA(srcImage)所花费的时间为: " << (double)(t2 - t1) / CLOCKS_PER_SEC << "s" <<endl;

	t3 = clock();
	Mat srcB = srcImage.clone();
	t4 = clock();

	cout << "Mat srcB = srcImage.clone()所花费的时间为: " << (double)(t4 - t3) / CLOCKS_PER_SEC << "s" <<endl;

	system("pause");


}

2.Mat支持每一行的插入,与vector容器类似,不需要实现知道rows的大小
     Mat支持每一行插入(Mat::push_back),这一点与vector类似,将一行Mat插入到另外 一个Mat我们只需要保证两者的cols是相同的。如Mat mean;表示Mat的一行,现需要重复多行将mean压缩至Mat descripTop(mean.cols,0)当中,我们不需要特意指出descripTop矩阵中的rows的大小,即不需要事先知道rows的大小:
     然后执行descripTop.push_back(mean);即可。
     






猜你喜欢

转载自blog.csdn.net/wwwssszheren/article/details/77967485