2

我正在使用 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 个 IplImages?

4

2 回答 2

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实例是如何创建的——如果它是从set to创建IplImage*的,那么你需要释放原始实例。如果它是使用set to创建的,那么instance 会自动处理它(除非您明确地使用)copyDatafalseIplImagecopyDatatrueMatMat::release

于 2012-09-28T08:22:00.093 回答
1

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

而且因为 cv::Mat 有一个自动内存管理,你不需要释放任何东西。

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

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

构造

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

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

于 2012-09-28T08:44:26.857 回答