OpenCV недостаточно памяти - PullRequest
       6

OpenCV недостаточно памяти

1 голос
/ 06 апреля 2011

Я использую следующий код на Visual C ++ 2008 и OpenCV 2.1. Это работает некоторое время (скажем, 3 минуты), а затем прерывается с ошибкой, говорящей

"Недостаточно памяти (не удалось выделить 92610 байт) в неизвестной функции, файл ........ \ ocv \ opencv \ src \ cxcore \ cxalloc.cpp, строка 52"

Должно быть, где-то произошла утечка памяти (возможно, при создании образа), но я не могу этого понять.

#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <iostream>
#include <math.h>

using namespace std;

void main()
{
    int i, j;
    int **arr = new int*[480], blob[6][8]={0};
    int max, maxi=-10, maxj=-10, div=80;
    int xmax=480, ymax=640;
    int frameH, frameW, fps, numFrames;
    double hue, sat, lum;
    int maxcolor, mincolor, maxcolval, mincolval;
    char key='a';
    CvScalar pix, destpix, destpix2, destpix3;
    IplImage *img, *dest, *hsv;

    for(i=0; i<480; i++)
        arr[i] = new int[640];

    CvCapture *capture = cvCaptureFromCAM(0);
    if(!capture)
    {
        cout<<"Cannot read video!!!!";
        exit(0);
    }

    frameH    = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
    frameW    = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
    fps       = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
    numFrames = (int) cvGetCaptureProperty(capture,  CV_CAP_PROP_FRAME_COUNT);
    printf("Width=%d Height=%d FPS=%d Count=%d\n", frameH, frameW, fps, numFrames);

    cvNamedWindow("win1", CV_WINDOW_AUTOSIZE);
    cvMoveWindow("win1", 10, 10);
    cvNamedWindow("win2", CV_WINDOW_AUTOSIZE);
    cvMoveWindow("win2", 600, 300);

    destpix.val[0]=0;
    destpix.val[1]=255;
    destpix.val[2]=0;
    destpix2.val[0]=0;
    destpix2.val[1]=0;
    destpix2.val[2]=0;
    destpix3.val[0]=255;
    destpix3.val[1]=255;
    destpix3.val[2]=255;

    while(key != 'q')
    {
        max=0;
        maxi=-10;
        maxj=-10;

        img = cvQueryFrame(capture);
        if(img == 0)break;

        dest = cvCloneImage(img);
        hsv = cvCloneImage(img);

        cvCvtColor(img, hsv, CV_BGR2HSV);

        for(i=0; i<xmax; i++)
            for(j=0; j<ymax; j++)
            {
                arr[i][j]=0;
                blob[i/div][j/div]=0;
            }           

        cout<<endl<<cvGet2D(hsv, 5, 5).val[0];
        //Looping through each pixel
        for(i=0; i<xmax; i++)
        {
            for(j=0; j<ymax; j++)
            {
                //Getting the current pixel (i, j)
                pix = cvGet2D(hsv, i, j);

                //Setting all pixels to black
                cvSet2D(dest, i, j, destpix2);

                hue = pix.val[0];
                sat = pix.val[1];
                lum = pix.val[2];

                //Looking for color red
                if((hue<5 || hue>177) && sat>120 && lum>60)
                {
                    arr[i][j] = 1;
                    cvSet2D(dest, i, j, destpix);
                }

                /*//Looking for color green
                if((hue>90 && hue<100) && sat>120 && lum>60)
                {
                    arr[i][j] = 1;
                    cvSet2D(dest, i, j, destpix);
                }*/

                /*//Looking for color blue
                if((hue>100 && hue<110) && sat>120 && lum>60)
                {
                    arr[i][j] = 1;
                    cvSet2D(dest, i, j, destpix);
                }*/

                /*//Looking for color yellow
                if((hue>30 && hue<40) && sat>120 && lum>60)
                {
                    arr[i][j] = 1;
                    cvSet2D(dest, i, j, destpix);
                }*/
            }   
        }

        //Counting the blobs in each grid
        for(i=0; i<xmax; i++)
        {
            for(j=0; j<ymax; j++)
            {
                if(arr[i][j])
                {
                    blob[i/div][j/div]++;
                }
            }
        }

        //Finding the grid with the largest blob
        for(i=0; i<xmax/div; i++)
            for(j=0; j<ymax/div; j++)
                if(blob[i][j]>max)
                {
                    max=blob[i][j];
                    maxi=i;
                    maxj=j;
                }

        if(max>200)
        {
            //Borders
            for(i=maxi*div; i<maxi*div+2; i++)
                for(j=maxj*div; j<maxj*div+div; j++)
                    cvSet2D(dest, i, j, destpix3);

            for(i=maxi*div+div-2; i<maxi*div+div; i++)
                for(j=maxj*div; j<maxj*div+div; j++)
                    cvSet2D(dest, i, j, destpix3);

            for(i=maxi*div; i<maxi*div+div; i++)
                for(j=maxj*div; j<maxj*div+2; j++)
                    cvSet2D(dest, i, j, destpix3);

            for(i=maxi*div; i<maxi*div+div; i++)
                for(j=maxj*div+div-2; j<maxj*div+div; j++)
                    cvSet2D(dest, i, j, destpix3);

            //Center
            for(i=maxi*div+(div/2)-5; i<maxi*div+(div/2)+5; i++)
                for(j=maxj*div+(div/2)-5; j<maxj*div+(div/2)+5; j++)
                    cvSet2D(dest, i, j, destpix3);
        }

        //Creating Windows
        //cvCvtColor(fin, dest, CV_HSV2BGR);
        key = cvWaitKey(20);
        cvShowImage("win1", dest);
        cvShowImage("win2", img);
    }

    cvWaitKey(0);
    cvReleaseCapture(&capture);
    cvReleaseImage(&dest);
    cvDestroyWindow("win1");
    cvDestroyWindow("win2");
}

Ответы [ 4 ]

3 голосов
/ 06 апреля 2011

«Недостаточно памяти» действительно означает «Произошла ошибка при попытке выделить память».

Вполне вероятно, что вы где-то что-то испортили, а не исчерпали память, особенно с этим стилем кода.

2 голосов
/ 06 апреля 2011

Документация CloneImage гласит:

Делает полную копию изображения

IplImage * cvCloneImage (const IplImage * image);

image Исходное изображение.

Функция cvCloneImage делает полную копию изображения, включая заголовок, ROI и данные

Вы создаете глубокую копию в каждом цикле и сохраняете ее, используя один и тот же указатель.Каждый цикл, который вы теряете, отслеживает распределение предыдущих значений без освобождения памяти.

РЕДАКТИРОВАНИЕ

Эта функция может помочь вам:

ReleaseImage

Освобождает данные заголовка и изображения

void cvReleaseImage (IplImage ** image);

image Двойной указатель на заголовок освобожденного изображения.

Функция cvReleaseImage освобождает заголовок и данные изображения.Этот вызов является сокращенной формой

if( *image )
{
    cvReleaseData( *image );
    cvReleaseImageHeader( image );
}

Попробуйте освободить память в конце цикла while.

1 голос
/ 25 октября 2013

Старый пост, но, конечно, эта проблема недавно доставила мне головную боль ...

У меня была та же самая проблема, я просто работал с простыми функциями рисования. Вы здесь в основном хотите копировать изображение в каждой итерации. Текущая ситуация такова:

dest = cvCloneImage(img) выделит память, клонирует в нее все изображение и вернет указатель на эту новую память, ТАК ЧТО вы потеряете значение указателя, которое dest ранее имело. Итак, если вы еще не освободили память с cvReleaseImage(img), у вас будет утечка памяти.

Должен быть более легкий путь, и он действительно есть:

    /* Copies source array to destination array */
    CVAPI(void)  cvCopy( const CvArr* src, CvArr* dst,
                         const CvArr* mask CV_DEFAULT(NULL) );

Так что вам просто нужно использовать cvCopy(img, dest); То, что было в dest, будет перезаписано => нет утечки памяти

1 голос
/ 06 апреля 2011

IplImage * img, * dest, * hsv;

Проверьте документацию и посмотрите, несете ли вы ответственность за освобождение вышеуказанных указателей, прежде чем присваивать им новые значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...