Deep Copy of OpenCV cv::Mat

flyinggip picture flyinggip · Feb 9, 2014 · Viewed 48.6k times · Source

The behaviour of copying cv::Mat is confusing me.

I understand from the documentation that Mat::copyTo() is deep copy while the assignment operator is not. My questions:

  1. what should I do to return a cv::Mat from a function, such as: cv::Mat func()?

  2. According to the documentation, if I return a cv::Mat it'll have no use, because after the function returns the local copy of the cv::Mat in that function will be destroyed and therefore the one accepting the returned value outside the function should be pointing to some random address. The weird thing is that (most of times) it works correctly. For example, the following works:

    cv::Mat CopyOneImage(const cv::Mat& orgImage)
    {
    
        cv::Mat image;
        orgImage.copyTo(image);
        return image;
    
    }
    
    int main()
    {
    
        std::string orgImgName("a.jpg");        
        cv::Mat orgImage;
        orgImage = cv::imread(orgImgName);
    
        cv::Mat aCopy;
        aCopy = CopyOneImage(orgImage);
    
        return 1;
    }
    

But why? It's not a deep copy.

Question 3. And also sometimes the assignment operator seems to be deep copy, too:

    int main()
    {

        std::string orgImgName("a.jpg");        
        cv::Mat orgImage;
        orgImage = cv::imread(orgImgName);

        cv::Mat aCopy;
        orgImage.copyTo(aCopy);

        cv::Mat copyCopy1;
        copyCopy1 = aCopy;

        cv::namedWindow("smallTest", 1);
        cv::imshow("smallTest", copyCopy1);
        uchar key = (uchar)cv::waitKey();

        cv::Mat orgImage2 = cv::imread("b.jpg");
        orgImage2.copyTo(aCopy);

        cv::imshow("smallTest", copyCopy1);
        return 1;
    }

Then the two displays shows the same image, a.jpg. Why? And some other times it doesn't work. (The original code is too long but it can be also simplified to the above case). In those times the assignment operator seem to be actually 'shallow' copying. Why?

Thanks a lot!

Answer

Andrey  Smorodov picture Andrey Smorodov · Feb 9, 2014

I think, that using assignment is not the best way of matrix copying. If you want new full copy of the matrix, use:

Mat a=b.clone(); 

If you want copy matrix for replace the data from another matrix (for avoid memory reallocation) use:

Mat a(b.size(),b.type());
b.copyTo(a);

When you assign one matrix to another, the counter of references of smart pointer to matrix data increased by one, when you release matrix (it can be done implicitly when leave code block) it decreases by one. When it becomes equal zero the allocated memory deallocated.

If you want get result from the function use references it is faster:

void Func(Mat& input,Mat& output)
{
 somefunc(input,output);
}

int main(void)
{
...
  Mat a=Mat(.....);
  Mat b=Mat(.....);
  Func(a,b);
...
}