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

Posted

技术标签:

【中文标题】如何将像素数据的所有权传递给 cv::Mat【英文标题】:How do I pass ownership of pixel data to cv::Mat 【发布时间】:2014-03-19 16:09:12 【问题描述】:

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

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

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

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

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

有没有办法传递所有权?

【问题讨论】:

只做myMatrix=vImageResult有什么问题? @AldurDisciple vImageResult 可能不是 cv::Mat。这应该是“外部分配”的意思,也是我写答案时的假设。 我认为你不能这样做,因为 Mat 不知道你如何分配内存(malloc、new 等),因此也不知道如何释放它。 IIRC - 解决方案是创建 cv::Mat,获取底层字节并将它们传递给外部程序进行操作。这样 cv::Mat 保留所有权,因为它首先创建了它们。 【参考方案1】:

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

【讨论】:

复制后可以立即释放原始数据。这也是我的建议,尽管严格来说这不是问题的答案:D 右(两点)。据我在文档中看到的,没有办法传递所有权,所以这个选项最接近 OP 想要的。 @anderas 你假设vImageResult 不是cv::Mat 一定是对的,但是也许你应该添加一些关于如何使用clone() 来传递所有权的细节。【参考方案2】:

你不能。

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。它没有虚拟析构函数。

【讨论】:

以上是关于如何将像素数据的所有权传递给 cv::Mat的主要内容,如果未能解决你的问题,请参考以下文章

如何将 cv::mat 对象从 python 模块传递给 c++ 函数并返回返回的 cv::mat 类型的对象?

如何将 opencv Mat 类型传递给 Python 并返回一个数组?

OpenCV 使用 stride 从数组生成 cv::Mat

如何在openCV中修改cv::Mat的像素数据?

处理 cv::MAT 的像素不起作用

OpenCV 3:如何将 cv::Mat 作为可选参数传递