fececagec812
fececagec812

Reputation: 394

if a is a cv::Mat and cv::Mat b=a.row(1),then What is the difference between the two cv::Mat instances?

Mat a = (Mat_(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);
cv::Mat b=a.row(1);

cv::Mat has a field called data, that is a pointer which is pointed to the actual memory for the Mat.
I know this is shallow copy, no new memory will be allocated to store the elements in a.row(1) for b .
a and b will share a same piece of memory.
And the data field of b will be the same as a 's data field.

My question is:
if The data field of b is the same as a 's data field, then what is the difference between a and b ?
Their data fields are the same , but other functions know a and b are different !!
How do they know this?

Upvotes: 1

Views: 272

Answers (1)

fececagec812
fececagec812

Reputation: 394

My assumption was wrong !
Although no new memory is allocated, the data fields of a and b are different!!

Here's a snippet code of the headers in mat.hpp,where cv::Mat is defined as this:

class CV_EXPORTS Mat
{
public:
    // ... a lot of methods ...
    ...

        /*! includes several bit-fields:
        - the magic signature
        - continuity flag
        - depth
        - number of channels
        */
        int flags;
    //! the array dimensionality, >= 2
    int dims;
    //! the number of rows and columns or (-1, -1) when the array has more than 2 dimensions
    int rows, cols;
    uchar* data;

    //! pointer to the reference counter;
    // when array points to user-allocated data, the pointer is NULL 
    int* refcount;

    // other members
    ...
};

when you are doing shallow copy, only the pointer , data (not the things data pointed to )would be copied.
no new memory will be allocated.
say , we have a cv::Mat called a.

cv::Mat b=a;

b's data field will be the same as a's. No new memory will be allocated for b.

But what about the following code:

cv::Mat b=a.col(1);

Here's a snippet code of matrix.cpp , which including the implementations of cv::Mat functions :

Mat::Mat(const Mat& m, const Range* ranges)
    : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
      datalimit(0), allocator(0), u(0), size(&rows)
 {
int i, d = m.dims;

CV_Assert(ranges);
for( i = 0; i < d; i++ )
{
    Range r = ranges[i];
    CV_Assert( r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]) );
}
*this = m;
for( i = 0; i < d; i++ )
{
    Range r = ranges[i];
    if( r != Range::all() && r != Range(0, size.p[i]))
    {
        size.p[i] = r.end - r.start;
        data += r.start*step.p[i];
        flags |= SUBMATRIX_FLAG;
    }
}
updateContinuityFlag(*this);
}

cv::Mat::col() will return a new cv::Mat, it needs to call a constructor.
The constructor above is for constructing a cv::Mat with another cv::Mat reference,and a cv::Range.
Note that the data field is not a copy of the data field of m 's (m is the parameter passed to the constructor) data.

so,for my question..
the data fields of a and b are different!

Upvotes: 1

Related Questions