<IplImage> 在 OpenCv 中使用 Ptr 会导致内存异常


void hello(Mat original)
{
  Mat a=original.clone();
  Ptr<IplImage> b = &a.operator IplImage();
  return;
}

此函数将导致内存异常。因为我必须使用参数为IplImage*的旧函数,所以我将Mat转换为Ptr并导致内存异常。上面的函数只是一个简化的版本。

From OpenCV doc

操作符为矩阵创建IplImage头,而不复制底层数据。当使用IplImage头文件时,你应该确保原始矩阵没有被释放

您可以将返回的头的引用传递给接受IplImage*的函数,如下面代码中的void foo(IplImage* img):

#include <opencv2opencv.hpp>
using namespace cv;
void foo(IplImage* img)
{
    // Set to blue
    cvSet(img, Scalar(255,0,0));
}
int main()
{
    // Small green image
    Mat3b img(10, 10, Vec3b(0, 255, 0));
    {
        // Doesn't modify original image
        Mat mat = img.clone();
        IplImage ipl = mat;
        foo(&ipl);
        // ipl and mat are blue now
        // img is still green
    }
    {
        // Modify original image
        IplImage ipl = img;
        foo(&ipl);
        // ipl and img are blue now
    }
    // img is blue
    return 0;
}

Ptr<T>是一个自动销毁包装对象指针的模板类(更多信息请参阅官方文档)。

在您的代码片段中,ab都是函数hello中的局部变量,因此它们将在该函数返回时被销毁,并且以相反的构造顺序,因此a将在b销毁之后被销毁。

内存异常可能发生,因为两个变量(ab)引用相同的内存区域:事实上,函数Mat::operator IplImage 并不复制Mat对象的底层数据,而是为这些矩阵数据创建IplImage头。

因此,当Mat析构函数试图销毁对象a时,专用于底层数据的那部分内存已经被b释放了。

最新更新