OpenCV insufficient memory

2020-04-28 06:56发布

问题:

I am running the following code on Visual C++ 2008 and OpenCV 2.1. It works for a while (say 3 minutes) and then aborts with an error saying

"Insufficient Memory (Failed to allocate 92610 bytes) in unknown function, file ........\ocv\opencv\src\cxcore\cxalloc.cpp, line 52"

There must be some memory leak somewhere (probably with image creation) but I can't seem to get hold of it.

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

回答1:

"Insufficient memory" really means "There was an error when I tried to allocate memory".

It's quite likely that you've actually corrupted something somewhere, rather than actually run out of memory, particularly with this style of code.



回答2:

The documentation of CloneImage says:

Makes a full copy of image

IplImage* cvCloneImage( const IplImage* image );

image Original image.

The function cvCloneImage makes a full copy of the image including header, ROI and data

You are creating a deep copy at every loop and save it using the same pointer. Every loop you loose track of the previos allocation without free the memory.

EDIT

This function may help you:

ReleaseImage

Releases header and image data

void cvReleaseImage( IplImage** image );

image Double pointer to the header of the deallocated image.

The function cvReleaseImage releases the header and the image data. This call is a shortened form of

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

Try to release the memory at the end of your while loop.



回答3:

IplImage *img, *dest, *hsv;

Check the documentation and see if you are responsible for freeing the above pointers, before assigning them to new values.



回答4:

Old post, but surely this problem gave me a headache recently...

I totally had the same problem, I was just working with plain drawing functions. You here basically want to copy an image in every iteration. Current situation is:

dest = cvCloneImage(img) will allocate memory, clone the whole image into it and return the pointer to this new memory, THUS you will lose the pointer value dest had previously. So, if you hadn't already released the memory with cvReleaseImage(img) by then, you'll have a memory leak.

There has to be an easier way, and there really is:

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

So you just need to use cvCopy(img, dest); What was in dest will be overwritten => no memory leak