根据 OpenCV 2.4.xxx :
Mat 基本上是 a class with two data parts : the matrix header (包含诸如矩阵大小,用于存储的方法,存储矩阵的地址等信息)和 a pointer to the matrix containing the pixel values (根据选择的存储方法取任何维度)。该 matrix header size is constant 然而,矩阵本身的大小可能因图像而异,并且通常大一个数量级。
Mat
a class with two data parts
the matrix header
a pointer to the matrix containing the pixel values
matrix header size is constant
一个简单的公式: a Mat object = the matrix header + the matrix data pointer 。
a Mat object
the matrix data pointer
好的,矩阵数据指针是什么?它是 uchar* data ,指向矩阵数据。
uchar* data
然后所有其他人 cv::Mat 叫 matrix header 。
cv::Mat
matrix header
两部分有什么优势?我们可以做矩阵的浅拷贝,并使用参考计数器进行内存管理。至于 参考柜台(计数) ,这是编程中的一个重要主题。来自维基 参考柜台(计数) : In computer science, reference counting is a technique of storing the number of references, pointers, or handles to a resource such as an object, block of memory, disk space or other resource.
In computer science, reference counting is a technique of storing the number of references, pointers, or handles to a resource such as an object, block of memory, disk space or other resource.
有两个重要的功能 cv::Mat 您可能感兴趣的参考柜台:
void cv :: Mat :: addref()和void cv :: Mat :: release()
/** @brief Increments the reference counter. The method increments the reference counter associated with the matrix data. If the matrix header points to an external data set (see Mat::Mat ), the reference counter is NULL, and the method has no effect in this case. Normally, to avoid memory leaks, the method should not be called explicitly. It is called implicitly by the matrix assignment operator. The reference counter increment is an atomic operation on the platforms that support it. Thus, it is safe to operate on the same matrices asynchronously in different threads. */ void addref(); /** @brief Decrements the reference counter and deallocates the matrix if needed. The method decrements the reference counter associated with the matrix data. When the reference counter reaches 0, the matrix data is deallocated and the data and the reference counter pointers are set to NULL's. If the matrix header points to an external data set (see Mat::Mat ), the reference counter is NULL, and the method has no effect in this case. This method can be called manually to force the matrix data deallocation. But since this method is automatically called in the destructor, or by any other method that changes the data pointer, it is usually not needed. The reference counter decrement and check for 0 is an atomic operation on the platforms that support it. Thus, it is safe to operate on the same matrices asynchronously in different threads. */ void release();
当然,也许你只需要注意:
cv::Mat a = cv::Mat::zeros(2,2,CV_8UC1); cv::Mat b,c; b = a; // shallow copy, share the same matrix data by the data pointer a.copyTo(c); // deep copy, allocate matrix data memory, and assign the new pointer
演示:
#include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main(){ cv::Mat a = cv::Mat::zeros(2,2,CV_8UC1); cv::Mat b,c; b = a; // shallow copy, share the same matrix data pointer a.copyTo(c); // deep copy, allocate matrix data memory, and assign the new pointer std::cout << "----- a -----\n" << a << "\n----- b -----\n" << b << "\n----- c -----\n" << c << std::endl; std::cout << "\nModify a, b, c:\n"; a.at<unsigned char>(0,0) = 1; // a, b share the same matrix data b.at<unsigned char>(1,0) = 2; c.at<unsigned char>(1,1) = 3; // c has independent matrix data std::cout << "----- a -----\n" << a << "\n----- b -----\n" << b << "\n----- c -----\n" << c << std::endl; return 0; }
结果:
----- a ----- [ 0, 0; 0, 0] ----- b ----- [ 0, 0; 0, 0] ----- c ----- [ 0, 0; 0, 0] Modify a, b, c: ----- a ----- [ 1, 0; 2, 0] ----- b ----- [ 1, 0; 2, 0] ----- c ----- [ 0, 0; 0, 3]