2
votes

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?

1
OpenCV is open source project, did you try to give a look at source code?Elvis Dukaj
I believe there's a fairly comprehensive documentation provided for the cv::Mat class.πάντα ῥεῖ
@Aniruddha It was me who downvoted. Don't accuse people guessing by your impressions. Explain what yoiu don't understand from the documentation I mentioned specifically please.πάντα ῥεῖ
@πάνταῥεῖ Could you help explain which part is header?Aniruddha
based on the source here, I don't see any members marked or described explicitly as the "header". Could you provide the context for that quote?kmdreko

1 Answers

4
votes

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]