簡體   English   中英

OpenCv-從網絡攝像頭捕獲幀時內存泄漏

[英]OpenCv - Memory leak when capturing frames from webcam

我正在編寫一個C應用程序,該程序使用OpenCv從網絡攝像頭捕獲圖像,然后將圖像保存到文件中。 它在針對OpenCv 2.3.1-11的Raspian OS Wheezy上運行。

如果我像這樣打開和關閉網絡攝像頭,則不會發生內存泄漏,因此我認為我沒有遇到關於“網絡攝像頭開征稅”的舊錯誤:

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存儲的數據。 如果我在frame上使用cvReleaseImage ,則沒有任何效果。 實際上, cvQueryFrame調用來看,內存使用量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 ++中創建等效代碼而不泄漏的任何幫助都將非常有幫助。

謝謝您的幫助。

這個不會泄漏給我:

#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);
}

您可以嘗試最后一個例子嗎? 如果確實泄漏,則可能是標題錯誤或鏈接庫確實存在一些問題。

我今天檢查[01/04/2015],在當前的wheezy / main存儲庫中,opencv(除gpu之外)的Dev程序包已鏈接到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

希望能有所幫助。

經過大量測試后,發現使用pthread時,OpenCv 2.3.1-11有一些奇怪的行為。

如果我只是在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(我已棄用),則有多種方法可以使自己立足。 謝謝大家的意見。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM