Search code examples
opencvmemory-managementmemory-leaksdestructormat

Avoiding memory leaks while using vector<Mat>


I am trying to write a code that uses opencv Mat objects it goes something like this

Mat img;
vector<Mat> images;
for (i = 1; i < 5; i++)
{
  img.create(h,w,type) // h,w and type are given correctly
  // input an image from somewhere to img correctly. 
  images.push_back(img);
  img.release()
}
for (i = 1; i < 5; i++)
  images[i].release();

I however still seem to have memory leakage can anyone tell me why it is so? I thought that if the refcount of a mat object = 0 then the memory should be automatically deallocated


Solution

  • You rarely need to call release explicitly, since OpenCV Mat objects take automatically care of internal memory.

    Also take care that Mat copy just copies creates a new header pointing to the same data. If the original Mat goes out of scope you are left with an invalid matrix. So when you push the image into the vector, use a deep copy (clone()) to avoid that it the image into the vector becomes invalid.

    Since you mentioned:

    I have a large 3D image stored in a Mat object. I am running over it using for loops. creating a 2D mat called "image" putting the slices into image, pushing back image to vector images. releasing the image. And later doing a for loop on the images vector releasing all the matrices one by one.

    You can store all slices into the vector with the following code. To release the images in the vector, just clear the vector.

    #include <opencv2/opencv.hpp>
    #include <vector>
    using namespace cv;
    using namespace std;
    
    int main() 
    {
        // Init the multidimensional image
        int sizes[] = { 10, 7, 5 };
        Mat data(3, sizes, CV_32F);
        randu(data, Scalar(0, 0, 0), Scalar(1,1,1));
    
        // Put slices into images
        vector<Mat> images;
        for (int z = 0; z < data.size[2]; ++z)
        {
            // Create the slice
            Range ranges[] = { Range::all(), Range::all(), Range(z, z + 1) };
            Mat slice(data(ranges).clone()); // with clone slice is continuous, but still 3d
            Mat slice2d(2, &data.size[0], data.type(), slice.data); // make the slice a 2d image
    
            // Clone the slice into the vector, or it becomes invalid when slice goes of of scope.
            images.push_back(slice2d.clone());
        }
    
        // You can deallocate the multidimensional matrix now, if needed
        data.release();
    
        // Work with slices....
    
        // Release the vector of slices
        images.clear();
    
        return 0;
    }