Robert
Robert

Reputation: 38213

How do I pass ownership of pixel data to cv::Mat

I am creating a cv::Mat passing with pixel data that I have allocated externally.

cv::Mat myMatrix(vImageResult.height,
                 vImageResult.width,
                 CV_8UC1,
                 vImageResult.data);

I would like the cv::Mat to take ownership of the bytes (i.e. create a refCount and free the bytes when it reaches zero) . However the documentation says

Matrix constructors that take data and step parameters do not allocate matrix data. Instead, they just initialize the matrix header that points to the specified data, which means that no data is copied. This operation is very efficient and can be used to process external data using OpenCV functions. The external data is not automatically deallocated, so you should take care of it.

Is there a way to pass ownership?

Upvotes: 2

Views: 2979

Answers (2)

CuriousGeorge
CuriousGeorge

Reputation: 7400

You can't.

cv::Mat does not know how you allocated the memory(malloc, new, etc), and hence, does not know how to free it.

If you are allocating the data yourself, you could always call cv::Mat::create(...) to allocate the memory you need, and then pass the pointer myMatrix.data to whatever function you are using to load the data.

If you're referring to pre-allocated memory provided to you through a video capture stream or external library, you're out of luck.

Andreas' solution will work, but can be slow if used frequently.

A compromise may be to wrap cv::Mat in your own type:

struct MyMat
{
    cv::Mat mat;
    MyMat(int width, int height, int format, char *data)
        : mat(height, width, format, data){}
    ~MyMat() { delete [] mat.data; }
};

Note: it was intentional not to try and subclass cv::Mat. It does not have a virtual destructor.

Upvotes: 5

anderas
anderas

Reputation: 5854

An option is to copy the data to a new matrix using Mat::clone(), which performs a deep copy of the data. The new matrix will then have ownership of the cloned data.

For example:

// create temporary matrix that holds the external/old data
cv::Mat tmp(vImageResult.height,
            vImageResult.width,
            CV_8UC1,
            vImageResult.data); 
cv::Mat myMatrix = tmp.clone(); // myMatrix now has ownership of a clone of the data.

Upvotes: 5

Related Questions