OpenCv - 从网络摄像头捕获帧时内存泄漏

时间:2015-01-04 04:54:07

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

我正在编写一个C应用程序,使用OpenCv从网络摄像头捕获图像,然后将图像保存到文件中。它在Raspian OS Wheezy上运行,针对OpenCv 2.3.1-11。

如果我这样打开和关闭网络摄像头,就没有内存泄漏,所以我不认为我遇到了一个关于“网络摄像头开放税”的旧bug:

CvCapture* capture;
while (1) {
  // No increase in memory consumption at all
  capture = cvCreateCameraCapture(0);
  cvReleaseCapture(&capture);
}

但是,当我真正开始获取图像时,内存消耗会爆炸,每次迭代都会在内存中再次淹没2MB。我在命令行通过free -s 2确认了手动触发图像采集,并注意到最终,我的应用程序抱怨没有足够的内存来获取图像。

capture = cvCreateCameraCapture(0);
while (1) {
   if (capture) {
      frame = cvQueryFrame(capture);
   }
   if (frame) {
      CvSize size = cvSize(100, 100);
      tmp = cvCreateImage(size, IPL_DEPTH_8U, 3);
      cvResize(frame, tmp, CV_INTER_CUBIC);
      // Do some stuff with tmp
   }
}
cvReleaseCapture(&capture);

我在网上查了各种帖子,并说我不支持修改frame中存储的数据。如果我在cvReleaseImage上使用frame,则无效。实际上,内存使用仅仅来自cvQueryFrame调用。即使以下示例也会弹出此问题:

capture = cvCreateCameraCapture(0);
while (1) {
   if (capture) {
      frame = cvQueryFrame(capture);
   }
}
cvReleaseCapture(&capture);

我该如何解决这个问题?

我是否真的必须使用C ++ API(目前不是我的选择),或者还有其他方法吗?这是一个Gtk + -2.0应用程序,我所包含的唯一标题是:

/*******************************************************************************
 * Preprocessor Directives
 ******************************************************************************/
#include "opencv/cxcore.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"

#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>

似乎有opencvopencv2的混合,但我找不到只有opencv标题的方法,并且可以访问没有它们的相机。我担心这可能会导致某些C ++片段 - 仅以未定义的方式初始化代码。任何解决内存泄漏的帮助,或者如果需要,在没有泄漏的情况下用C ++创建等效代码都会非常有帮助。

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

这个对我来说不泄密:

#include <opencv2\opencv.hpp>
int main()
{
    CvCapture* capture;
    IplImage* frame;

    capture = cvCreateCameraCapture(0);
    while (1) 
    {
       if (capture) 
       {
          frame = cvQueryFrame(capture);
       }
    }
    cvReleaseCapture(&capture);
}

这个显然确实泄漏了:

int main()
{
    CvCapture* capture;
    IplImage* frame;
    IplImage* tmp;

    capture = cvCreateCameraCapture(0);
    while (1) {
       if (capture) {
          frame = cvQueryFrame(capture);
       }
       if (frame) {
          CvSize size = cvSize(100, 100);
          tmp = cvCreateImage(size, IPL_DEPTH_8U, 3);
          cvResize(frame, tmp, CV_INTER_CUBIC);
          // Do some stuff with tmp
       }
    }
    cvReleaseCapture(&capture);
}

虽然这个没有泄漏:

int main()
{
    CvCapture* capture;
    IplImage* frame;
    IplImage* tmp;

    capture = cvCreateCameraCapture(0);
    while (1) {
       if (capture) {
          frame = cvQueryFrame(capture);
       }
       if (frame) {
          CvSize size = cvSize(100, 100);
          tmp = cvCreateImage(size, IPL_DEPTH_8U, 3);
          cvResize(frame, tmp, CV_INTER_CUBIC);
          // Do some stuff with tmp

          // release tmp:
          cvReleaseImage(&tmp);
       }
    }
    cvReleaseCapture(&capture);
}

你能试试最后一个例子吗?如果它确实泄漏,您可能确实遇到了错误标题或链接库的问题。

答案 1 :(得分:1)

我今天查了[01/04/2015],在当前的wheezy / main存储库中,opencv的开发包(除了gpu)链接到openCV 2.4.1。这里测试步骤:

安装包:

sudo apt-get install cmake build-essential libopencv-core-dev libcv-dev libcvaux-dev libhighgui-dev libopencv-calib3d-dev libopencv-contrib-dev libopencv-core-dev libopencv-dev libopencv-features2d-dev libopencv-flann-dev libopencv-highgui-dev libopencv-imgproc-dev libopencv-legacy-dev libopencv-ml-dev libopencv-objdetect-dev libopencv-video-dev

验证openCv库安装版本:

sudo ldconfig -v | grep opencv

结果:

libopencv_imgproc.so.2.4 -> libopencv_imgproc.so.2.4.1
libopencv_highgui.so.2.4 -> libopencv_highgui.so.2.4.1
libopencv_legacy.so.2.4 -> libopencv_legacy.so.2.4.1
libopencv_objdetect.so.2.4 -> libopencv_objdetect.so.2.4.1
libopencv_calib3d.so.2.4 -> libopencv_calib3d.so.2.4.1
libopencv_videostab.so.2.4 -> libopencv_videostab.so.2.4.1
libopencv_ml.so.2.4 -> libopencv_ml.so.2.4.1
libopencv_core.so.2.4 -> libopencv_core.so.2.4.1
libopencv_ts.so.2.4 -> libopencv_ts.so.2.4.1
libopencv_stitching.so.2.4 -> libopencv_stitching.so.2.4.1
libopencv_photo.so.2.4 -> libopencv_photo.so.2.4.1
libopencv_flann.so.2.4 -> libopencv_flann.so.2.4.1
libopencv_features2d.so.2.4 -> libopencv_features2d.so.2.4.1
libopencv_video.so.2.4 -> libopencv_video.so.2.4.1
ibopencv_contrib.so.2.4 -> libopencv_contrib.so.2.4.1

测试程序

#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <errno.h>

#include "opencv/cxcore.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"

int main(int argc, char * const argv[])
{
    struct rusage usage;
    long max_resident_set_size = 0;
    long frame_no = 0;

    CvCapture* capture;
    IplImage*  frame;
    capture = cvCreateCameraCapture(0);

    if (!capture) {
        // error getting webcam
        return 1;
    }

    //  test 100 frames to check memory usage
    while (frame_no < 100) {
        frame = cvQueryFrame(capture);
        frame_no++;

        errno = 0;
        getrusage(RUSAGE_SELF, &usage);
        if (errno == EFAULT)
            printf("Error: EFAULT\n");
        else if (errno == EINVAL)
            printf("Error: EINVAL\n");
        else if (max_resident_set_size != usage.ru_maxrss) {

            printf("frame %ld maximum resident set size: %ld\n", frame_no, usage.ru_maxrss);
            printf("frame %ld maximum resident set size diff : %ld\n", frame_no, (usage.ru_maxrss - max_resident_set_size));

            max_resident_set_size = usage.ru_maxrss;
        }
    }

    cvReleaseCapture(&capture);
    return 0;
}

使用OpenCV 2.4上面的代码我没有内存问题。

我建议您卸载openCV 2.3.1软件包,更新系统并安装最新版本并使用openCV2表示法。

列出已安装的软件包:

sudo dpkg --get-selections | grep -v deinstall | grep cv

希望得到这个帮助。

答案 2 :(得分:0)

经过大量测试后,发现OpenCv 2.3.1-11在使用pthread时有一些不稳定的行为。

如果我只是在main()的循环中使用以下内容,则不会出现问题。

int main()
{
    CvCapture* capture;
    IplImage* frame;
    IplImage* tmp;

    capture = cvCreateCameraCapture(0);
    while (1) {
       if (capture) {
          frame = cvQueryFrame(capture);
       }
       if (frame) {
          CvSize size = cvSize(100, 100);
          tmp = cvCreateImage(size, IPL_DEPTH_8U, 3);
          cvResize(frame, tmp, CV_INTER_CUBIC);
          // Do some stuff with tmp

          // release tmp:
          cvReleaseImage(&tmp);
       }
    }
    cvReleaseCapture(&capture);
}

如果我在pthread中使用相同的循环,则每次迭代将导致至少2MB的内存丢失。但是,如果在pthread中,我只调用capture = cvCreateCameraCapture(0)cvReleaseCapture(&capture)一次,则该问题不再存在。

另外,如果我在main中调用cvCreateCameraCapture(0)并将其分配给可从线程访问的内容(即:全局变量,或将其存储在上下文变量中,我在生成时传递指向该线程的指针线程),我在pthreadcvQueryFrame()内的每次调用都会遇到内存泄漏行为。

因此,简而言之,如果在多线程程序中使用C API(我不知道),有很多方法可以让你自己动手。谢谢大家的意见。

相关问题