我在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");
}
答案 0 :(得分:3)
“内存不足”实际上意味着“当我尝试分配内存时出错”。
你很可能实际上已经在某个地方损坏了某些内容,而不是实际内存不足,尤其是这种代码风格。
答案 1 :(得分:2)
CloneImage的文档说:
制作完整的图像副本
IplImage * cvCloneImage(const IplImage * image);
图像 原始图像。
函数cvCloneImage完整 包括标题的图像副本, 投资回报率和数据
您正在每个循环创建一个深层副本,并使用相同的指针保存它。每个循环都会在没有释放内存的情况下松开前面的分配。
修改强>
此功能可以帮助您:
ReleaseImage
发布标题和图片数据
void cvReleaseImage(IplImage ** image );
图像 指向解除分配图像标题的双指针。
函数cvReleaseImage发布 标题和图像数据。这个
是一种缩短的形式if( *image ) { cvReleaseData( *image ); cvReleaseImageHeader( image ); }
尝试在while循环结束时释放内存。
答案 2 :(得分:1)
IplImage * img,* dest,* hsv;
检查文档,看看是否负责释放上述指针,然后再将它们分配给新值。
答案 3 :(得分:1)
老帖子,但这个问题肯定让我头疼了......
我完全遇到了同样的问题,我只是使用普通的绘图功能。你在这里基本上想要在每次迭代中复制一个图像。目前的情况是:
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中的内容将被覆盖=&gt;没有内存泄漏