【问题标题】:Memory leak in OpenCV function: cvQueryFrame()OpenCV 函数中的内存泄漏:cvQueryFrame()
【发布时间】:2012-02-25 03:21:21
【问题描述】:

我对从cvQueryFrame 返回的IplImage* 有疑问...它的内存永远不会被库释放。文档说:

返回的图片不应被用户发布或修改。

嗯……我该如何恢复记忆?程序会吃掉内存,直到崩溃。我想在帧处理完成后为每个 IplImage* 释放分配的内存。代码是这样的:

// In `process` thread:
CvCapture* camera;
camera = cvCreateCameraCapture(1);
assert(camera);
while(true)
{
    main = cvQueryFrame(camera);
    // Do something useful with images 
    emit sendImage(main); // Send Image to the UI thread
}

更新: 这是QThread 子类:

#include <QThread>
class ImageFetcher : public QThread
{
    Q_OBJECT
public:
    explicit ImageFetcher(QObject *parent = 0);
signals:
    void run();
public slots:
};

实施:

void ImageFetcher::run()
{
    CvCapture* camera = cvCreateCameraCapture(0);
    IplImage* image;
    while(true)
    {
        image = cvQueryFrame(camera);
        // process image
    }
    // exec();
}

main():

int main(int argc, char *argv[])
{
    QApplication a(argc,argv);
    ImageFetcher thread;
    thread.start();
    return a.exec();
}

【问题讨论】:

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


    【解决方案1】:

    据我测试,Linux 的 v2.3.1 没有泄漏。

    发生的情况是:第一次调用此函数时,cvQueryFrame() 分配了一个图像,然后在所有后续调用cvQueryFrame() 时重复使用该图像。第一次调用后不会创建新的镜像,镜像只在cvReleaseCapture()释放。

    所以你看,如果你遇到内存泄漏(你是如何找到它的,确切地说?)和崩溃,它很可能是由你的代码的其他部分引起的。如果sendImage() 不同步(即非阻塞)直接传递main 图像可能会导致问题。我不知道你在这个函数中做了什么,所以我假设问题出在它里面。

    您可以做的一个测试是复制main 框架,然后将该副本传递给sendImage(),然后在您不再需要它时释放它。

    【讨论】:

    • 不,这绝对是OpenCVQt 的泄露!我发现只有在主线程以外的线程中调用cvQueryFrame() 时才会发生这种情况。这只发生在 Qt 的线程(QThread 的子类)中,我用std::thread 测试过没有问题。 POSIX 可能也可以,(未测试)。我认为这是泄漏,因为当我打开监视器时,我可以看到程序的内存快速且无限地增长。 (每秒 100 兆字节)。如果它很重要,那么疯狂增长的内存就在堆上(如监视器所示)。我尝试删除 emit sendImage(main) 但没有帮助。
    • 您使用的是什么 OpenCV 版本?您需要确保在程序执行期间只调用一次cvCreateCameraCapture()。如果您需要多次调用它,请确保将其与适当的cvReleaseCapture() 配对。如果您无法解决此问题,我建议您查看qt-opencv-multithreaded,看看他们是如何做到的。
    • This post 也可能包含一些有趣的信息。您是否考虑过使用QtConcurrent?我想看一个重现您所观察到的问题的最小示例。 =)
    • 是的,cvCreateCameraCapture() 被调用一次,有一个对应的cvReleaseCapture()。我没有使用QtConcurrent,将尝试告诉结果。我会在几分钟内编辑帖子...
    • 糟糕!我做了cvResize(main,anotherImage) ...它应该是main的克隆,可以由cvReleaseImage()发布。没有泄漏,对不起:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 2014-03-01
    • 2015-10-05
    • 1970-01-01
    • 2015-12-05
    相关资源
    最近更新 更多