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

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

本文关键字:cv Mat 所有权 像素 数据 像素数      更新时间:2023-10-16

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

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

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

接受数据和步进参数的矩阵构造函数不分配矩阵数据。相反,它们只是初始化指向指定数据的矩阵头,这意味着不会复制任何数据。这个操作非常高效,可以使用OpenCV函数来处理外部数据。外部数据不会自动释放,所以你应该注意它

  • 如果我立即释放底层vImageResult.data,那么我将在线路的某个地方得到一个糟糕的访问崩溃。
  • 如果我不释放底层vImageResult.data,那么数据将会泄漏。

是否有传递所有权的方法?

你不能。

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

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

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

Andreas的解决方案可以工作,但如果经常使用可能会很慢。

一种折衷的方法可能是用自己的类型包装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; }
};

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

一个选项是使用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.