Ask Your Question
0

Mat::clone and Mat::operator =

asked 2014-01-30 06:48:54 -0600

stefangachter gravatar image

Similar questions have been raised, but I am still unsure, when to use clone and when to use = operator. clone makes a full copy, whereas = creates a new header only, but shares the pixel data. Does this mean that in Example 1, the pixel data of image are modified and visible to the caller? If yes, I have to clone the image, where the image by the caller is preserved, as in Example 2?

Example 1:

void GFTTDetector::detectImpl( const Mat& image, std::vector<KeyPoint>& keypoints, const Mat& mask) const
{
    Mat grayImage = image;
    if( image.type() != CV_8U ) cvtColor( image, grayImage, COLOR_BGR2GRAY );
    ...
}

Example 2:

void GFTTDetector::detectImpl( const Mat& image, std::vector<KeyPoint>& keypoints, const Mat& mask) const
{
    Mat grayImage = image.clone();
    if( image.type() != CV_8U ) cvtColor( image, grayImage, COLOR_BGR2GRAY );
    ...
}
edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
0

answered 2014-01-30 07:14:18 -0600

updated 2014-01-30 07:16:01 -0600

Yes the second approach is correct if you want to preserve the original data. Actually the first approach will have two elements with different headers but with a data pointer pointing to the exact same memory location.

In your first approach

Mat grayImage = image;
if( image.type() != CV_8U ) cvtColor( image, grayImage, COLOR_BGR2GRAY );

could simply be replaced by

cvtColor( image, image, COLOR_BGR2GRAY );

because you are creating unneccesary extra headers. However, some functions in openCV do a check of the headers, because they don't allow identical matrices to be used for writing and reading. However only having different headers will still create problems when executing the function itself.

edit flag offensive delete link more
1

answered 2014-01-30 07:26:37 -0600

Nghia gravatar image

It turns out for cvtColor the destination matrix will always be allocated new memory so it will never point to the same data as the source. I was curious so I wrote a short test code:

void DoStuff(const Mat& img)
{
    Mat gray = img;

    cvtColor(img, gray, COLOR_BGR2GRAY);

    cout << "    gray: " << gray << endl;
    cout << "    img.data: " << (void*)img.data << endl;
    cout << "    gray.data: " << (void*)gray.data << endl;
}

int main()
{
    Mat img = Mat(1,1,CV_8UC3);

    img.at<Vec3b>(0)[0] = 0;
    img.at<Vec3b>(0)[1] = 100;
    img.at<Vec3b>(0)[2] = 200;

    cout << "img before: " << img << endl;

    DoStuff(img);

    cout << "img after: " << img << endl;
}

results in

img before: [0, 100, 200]
    gray: [118]
    img.data: 0x14eeb10
    gray.data: 0x14eeb40
img after: [0, 100, 200]
edit flag offensive delete link more

Comments

Okay nice answer :)

StevenPuttemans gravatar imageStevenPuttemans ( 2014-01-30 07:34:16 -0600 )edit
1

Thanks for giving the example. This helps. Thus, depends on the function's content which approach to use. If I want to be sure, i have to do a clone.

stefangachter gravatar imagestefangachter ( 2014-01-30 07:37:53 -0600 )edit

Question Tools

Stats

Asked: 2014-01-30 06:48:54 -0600

Seen: 890 times

Last updated: Jan 30 '14