如何将像素数据的所有权传递给 cv::Mat

Rob*_*ert 2 c c++ opencv memory-management

我正在创建一个 cv::Mat 传递我在外部分配的像素数据。

cv::Mat myMatrix(vImageResult.height,
                 vImageResult.width,
                 CV_8UC1,
                 vImageResult.data);
Run Code Online (Sandbox Code Playgroud)

我希望 cv::Mat 获得字节的所有权(即创建一个 refCount 并在它达到零时释放字节)。但是文档

接受数据和步骤参数的矩阵构造函数不分配矩阵数据。相反,它们只是初始化指向指定数据的矩阵头,这意味着没有数据被复制。此操作非常高效,可用于使用 OpenCV 函数处理外部数据。外部数据不会自动解除分配,因此您应该注意它。

  • 如果我vImageResult.data立即释放底层,我将在某处发生错误的访问崩溃。
  • 如果我不释放底层vImageResult.data数据,那么数据就会泄漏。

有没有办法传递所有权?

and*_*ras 5

一个选项是使用 将数据复制到一个新矩阵Mat::clone(),这会执行数据的深层复制。然后新矩阵将拥有克隆数据的所有权。

例如:

// 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.
Run Code Online (Sandbox Code Playgroud)


bit*_*ise 5

你不能。

cv::Mat 不知道如何分配内存(malloc、new 等),因此不知道如何释放它。

如果您自己分配数据,则始终可以调用cv::Mat::create(...)来分配所需的内存,然后将指针传递myMatrix.data给用于加载数据的任何函数。

如果您指的是通过视频捕获流或外部库提供给您的预分配内存,那么您就不走运了。

安德烈亚斯的解决方案可以工作,但如果频繁使用,可能会很慢。

一种折衷方案可能是包装cv::Mat您自己的类型:

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

注意:故意不尝试子类化 cv::Mat。它没有虚拟析构函数。