【问题标题】:Memory deallocation of IplImage initialised from cv::Mat从 cv::Mat 初始化的 IplImage 的内存释放
【发布时间】:2012-09-28 08:01:26
【问题描述】:

我正在使用 cvBlobs 来跟踪视频中的一些对象。 cvBlobs 使用具有 IplImage、cvMat、.. 等类型的旧 C 接口,而我使用的是使用 cv::Mat 的 C++ 接口。

所以我必须在这两种类型之间进行转换才能使用该库。这有效,但我无法释放内存。我的程序使用的内存不断增长。

这是我的代码,在底部您可以看到我尝试释放内存(编译器错误)。

void Tracker::LabelConnectedComponents(Mat& Frame, Mat& Foreground)
{
    // Convert to old format, this is the method used in the opencv cheatsheet
    IplImage IplFrame = Frame;
    IplImage IplForeground = Foreground;

    IplImage *LabelImg = cvCreateImage(cvGetSize(&IplFrame), IPL_DEPTH_LABEL, 1);

    // Make blobs (IplForeground is the segmented frame, 1 is foreground, 0 background)
    unsigned int result = cvLabel(&IplForeground, LabelImg, Blobs);

    // Remove small blobs
    cvFilterByArea(Blobs, 500, 1000000);

    // Draw bounding box
    cvRenderBlobs(LabelImg, Blobs, &IplFrame, &IplFrame, CV_BLOB_RENDER_BOUNDING_BOX | CV_BLOB_RENDER_CENTROID);

    // Convert back to c++ format
    Frame = cvarrToMat(&IplFrame);

    // Here are the problems
    cvReleaseImage(&IplFrame); // error
    cvReleaseImage(&IplForeground); // error
    cvReleaseImage(&LabelImg); // ok
}

cvReleaseImage 有一个 IplImage** 类型作为参数,这是编译器错误:

tracker.cpp|35 col 33 error| cannot convert ‘IplImage* {aka _IplImage*}’ to ‘IplImage** {aka _IplImage**}’ for argument ‘1’ to ‘void cvReleaseImage(IplImage**)’

我知道 &IplFrame 不是正确的论点,但 &&IplFrame 不起作用。如何释放这 2 个 IplImage?

【问题讨论】:

    标签: c++ memory-management opencv memory-leaks computer-vision


    【解决方案1】:

    问题是您在这里创建了对象的副本:

    IplImage IplFrame = Frame;
    IplImage IplForeground = Foreground;
    

    因此,这些调用:

    cvReleaseImage(IplFrame); 
    cvReleaseImage(IplForeground);
    

    即使可以编译,也不会发布原始图像。如果您已经在删除对象(即更改它们),为什么要将它们作为引用而不是指针发送给方法?我有点困惑,因为您似乎正在做这样的事情:

    Mat frame = ...
    Mat fg = ...
    LabelConnectedComponents(frame, fg); // function releases the frame/fg memory
    // at this point you are left with invalid frame/fg
    

    我查看了文档,上面写着Mat::operator IplImage() doesn't copy data,这意味着IplFrame不拥有内存,所以释放它是不正确的。

    我认为这取决于Mat 实例的创建方式——如果它是从IplImage* 创建的,copyData 设置为false,那么您需要释放原始的IplImage 实例。如果它是在将copyData 设置为true 的情况下创建的,那么Mat 实例会自动处理它(除非您使用Mat::release 明确地这样做)

    【讨论】:

    • 感谢您的解释!我现在不必担心那 2 个 IplImages。我重新检查了我的代码,结果发现我注释掉了“cvReleaseImage(&LabelImg);”调试时。那一个仍然必须被释放:)
    【解决方案2】:

    您不需要取消分配从 Mat 对象构造的 IplImages。这些是瘦包装器,不会复制数据,因此您不需要释放任何东西。

    而且由于 cv::Mat 具有自动内存管理功能,因此您无需释放任何内容。

    并且,作为完成,要调用 cvReleaseImage,您需要发送一个指向指针的指针:

    IplImage* pimg= cvLoadImage();
    ...
    cvReleaseImage(pimg);
    

    结构

    IplImage img;
    ... 
    cvReleaseImage(&&img);
    

    不起作用,因为 &img 是一个地址,(内存地址)但不表示变量。因此,下一次评估 &(&img) 将给出编译器错误,因为 &img 是一个值。该值不能有地址,但它是一个简单的数字。

    【讨论】:

      猜你喜欢
      • 2023-03-18
      • 1970-01-01
      • 2013-04-02
      • 1970-01-01
      • 2013-03-30
      • 2017-01-12
      • 1970-01-01
      • 2011-06-07
      • 1970-01-01
      相关资源
      最近更新 更多