从cv :: Mat初始化的IplImage的内存释放

时间:2012-09-28 08:01:26

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

我正在使用cvBlobs来跟踪视频中的某些对象。 cvBlobs使用旧的C接口和IplImage,cvMat等类型。我使用的是使用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 IplImages?

2 个答案:

答案 0 :(得分: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明确地执行此操作)

答案 1 :(得分:1)

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

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

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

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

构造

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

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