OpenCv - утечка памяти при захвате кадров с веб-камеры

0

Я пишу приложение C, которое захватывает изображения с веб-камеры с помощью OpenCv, а затем сохраняет изображения в файл. Он работает на Raspian OS Wheezy против OpenCv 2.3.1-11.

Если я просто открываю и закрываю веб-камеру, так что утечки памяти нет, поэтому я не думаю, что столкнулся с более старой ошибкой в отношении "налога на открытие веб-камеры":

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

Однако, когда я на самом деле начинаю приобретать изображения, потребление памяти взрывается, и каждая итерация разыгрывает еще 2 МБ в памяти. Я подтвердил с помощью 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>

Есть смесь opencv и opencv2 там, казалось бы, но я не могу найти способ иметь только заголовки opencv и иметь доступ к камере без них. Я был обеспокоен, возможно, это вызывает определенные фрагменты C++ - только код, который будет инициализирован неопределенным образом. Любая помощь в устранении утечки памяти или, при необходимости, создание эквивалентного кода в C++ без утечки будет очень полезной.

Спасибо за помощь.

  • 1
    cvReleaseImage on frame, it has no effect Как вы знаете, это не имеет никакого эффекта? Если вы используете диспетчер задач или какой-либо другой инструмент ОС для определения утечки памяти, не используйте его. Использование таких инструментов не будет определять утечку памяти.
  • 0
    @PaulMcKenzie Независимо от того, насколько хорошо эти инструменты могут работать или не работать, если я отслеживаю вывод free -s 2 на консоли, я вижу падение общего объема доступной системной памяти каждый раз, когда я вручную запускаю получение другого изображения. Я также могу профилировать приложение и подтвердить, что оно расходует больше памяти.
Показать ещё 7 комментариев
Теги:
opencv
memory-leaks
gtk

3 ответа

0
Лучший ответ

После значительного тестирования выяснилось, что OpenCv 2.3.1-11 имеет некоторое неудобное поведение при работе с pthread s.

Если я просто использую следующее в цикле в 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, это приведет к по меньшей мере 2 МБ потери памяти на итерацию. Однако, если в pthread я только один раз вызываю capture = cvCreateCameraCapture(0) и cvReleaseCapture(&capture), проблема больше не присутствует.

Кроме того, если я вызываю cvCreateCameraCapture(0) в главном и присваиваю ему что-то доступное из потока (т. cvCreateCameraCapture(0) Глобальную переменную или сохраняя ее в переменной контекста, передающей указатель на поток, когда я создаю поток) Я получаю поведение утечки памяти при каждом вызове в pthread в cvQueryFrame().

Короче говоря, если вы используете API C (устаревший, я знаю) в многопоточной программе, существует множество способов, которыми вы можете стрелять себе в ногу. Спасибо всем за ваш вклад.

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

Можете ли вы попробовать последний пример? Если он протекает, у вас, вероятно, действительно есть проблемы с неправильными заголовками или связанными библиотеками.

  • 0
    безусловно, поскольку cvReleaseCapture(&capture) никогда не cvReleaseCapture(&capture) из-за while(1) это тоже своего рода утечка, но использование памяти не должно увеличиваться со временем для последнего примера.
  • 0
    Я разместил дополнительные комментарии в верхней части. Ваш пример сработал, когда я запустил его как цикл в main() , но когда он запускается в отдельном pthread возобновляется утечка памяти.
1

Я проверил сегодня [01/04/2015], по текущему файлу wheezy/main repository. Dev-пакеты 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

Надеюсь, это поможет.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню