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);开发者_Go百科
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");
}
"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.
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.
IplImage *img, *dest, *hsv;
Check the documentation and see if you are responsible for freeing the above pointers, before assigning them to new values.
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
精彩评论