简体   繁体   中英

Mat class in OpenCV (c++)

As per opencv documentation Mat class is described as: Mat is basically a class with two data parts: the matrix header (containing information such as the size of the matrix, the method used for storing, at which address is the matrix stored, and so on) a pointer to the matrix containing the pixel values

Could someone help understand what is that header and how is the class declared?

According to OpenCV 2.4.xxx :

Mat is basically a class with two data parts : the matrix header (containing information such as the size of the matrix, the method used for storing, at which address is the matrix stored, and so on) and a pointer to the matrix containing the pixel values (taking any dimensionality depending on the method chosen for storing) . The matrix header size is constant , however the size of the matrix itself may vary from image to image and usually is larger by orders of magnitude.

A simple formular: a Mat object = the matrix header + the matrix data pointer .

Ok, what is the matrix data pointer? It is uchar* data , that points to the matrix data.

Then all others in cv::Mat called matrix header .

What is the advantage of two parts? We can do shallow copy of a matrix, and use reference counter for memory management. As for reference counter(counting) , it's an important topic in programming. From wiki reference counter(counting) : 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.


There are two important function in cv::Mat for reference counter you maybe interested in:

void cv::Mat::addref() and 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();

Of course, maybe you just need to notice:

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 

A demo :

#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;

}

The result:

----- 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]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM