OpenCV中回调函数中的内存泄露

今天想在OpenCV中实现鼠标在图像中移动时以鼠标为中心固定大小区域的放大显示,就像在淘宝中鼠标移动到宝贝图片上的效果。这样的例子有很多,我就想自己实现该功能,于是写了如下代码:

const char *window_original="original";
const char *window_test="test";
CvPoint p_start,p_end;
const int band=60;
IplImage *img=NULL;
IplImage *temp=NULL;
void mouse_callback(int event,int x,int y,int flags,void* param)
{
	IplImage *img_resize=cvCreateImage(cvSize(200,200),IPL_DEPTH_8U,3);
	temp=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3);
	cvCopyImage(img,temp);
	CvPoint p_start,p_end;
	switch(event)
	{
	case CV_EVENT_MOUSEMOVE:
		if(x-band/2<0)
		{
			if(y-band/2<0)
			{
				p_start=cvPoint(0,0);
				p_end=cvPoint(x+band/2,y+band/2);
			}
			else if(y+band/2>temp->height)
			{
				p_start=cvPoint(0,y-band/2);
				p_end=cvPoint(x+band/2,temp->height);
			}
			else
			{
				p_start=cvPoint(0,y-band/2);
				p_end=cvPoint(x+band/2,y+band/2);
			}
		}
		else if(x+band/2>temp->width)
		{
			if(y-band/2<0)
			{
				p_start=cvPoint(x-band/2,0);
				p_end=cvPoint(temp->width,y+band/2);
			}
			else if(y+band/2>temp->height)
			{
				p_start=cvPoint(x-band/2,y-band/2);
				p_end=cvPoint(temp->width,temp->height);
			}
			else
			{
				p_start=cvPoint(x-band/2,y-band/2);
				p_end=cvPoint(temp->width,y+band/2);
			}
		}
		else
		{
			if(y-band/2<0)
			{
				p_start=cvPoint(x-band/2,0);
				p_end=cvPoint(x+band/2,y+band/2);
			}
			else if(y>temp->height-band/2)
			{
				p_start=cvPoint(x-band/2,y-band/2);
				p_end=cvPoint(x+band/2,temp->height);
			}
			else
			{
				p_start=cvPoint(x-band/2,y-band/2);
				p_end=cvPoint(x+band/2,y+band/2);
			}
		}
		cvRectangle(temp,p_start,p_end,cvScalar(0x00,0xff,0x00));
		cvShowImage(window_original,temp);
		cvSetImageROI(temp,cvRect(MIN(p_start.x,p_end.x),MIN(p_start.y,p_end.y),CV_IABS(p_start.x-p_end.x),CV_IABS(p_start.y-p_end.y)));
		cvResize(temp,img_resize);
		cvShowImage(window_test,img_resize);
		cvResetImageROI(temp);
		cvReleaseImage(&img_resize);
		break;
	}
		
}
int main(int argc, char* argv[])
{	
	img=cvLoadImage("E:/opencv_project/console/Debug/Lena.jpg");
	cvNamedWindow(window_original,CV_WINDOW_AUTOSIZE);
	cvNamedWindow(window_test,CV_WINDOW_AUTOSIZE);
	cvShowImage(window_original,img);
	cvSetMouseCallback(window_original,mouse_callback,0);
	while(1)
	{
		if(cvWaitKey(15)==27)
			break;
	}
	cvDestroyAllWindows();
	cvReleaseImage(&img);
	cvReleaseImage(&temp);
	return 0;
}

结果,功能正常,但是运行一段时间后就报cv::exception错误。打开任务管理一看,鼠标移动后程序所占用的内存几乎是直线上升。经过一段时间的查找后发现,程序问题在以下部分:

	IplImage *img_resize=cvCreateImage(cvSize(200,200),IPL_DEPTH_8U,3);
	temp=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3);

以上两句代码在回调函数中为变量分配空间,每次调用回调函数都会分配空间并且不能释放,导致内存泄露。解决方法是将img_resize定义为全局变量,并且变量初始化放在main函数中,如下所示:

const char *window_original="original";
const char *window_test="test";
CvPoint p_start,p_end;
const int band=60;
IplImage *img=NULL;
IplImage *temp=NULL;
IplImage *img_resize=NULL;
void mouse_callback(int event,int x,int y,int flags,void* param)
{
	//IplImage *img_resize=cvCreateImage(cvSize(200,200),IPL_DEPTH_8U,3);
	//temp=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3);
	cvCopyImage(img,temp);
	CvPoint p_start,p_end;
	switch(event)
	{
	case CV_EVENT_MOUSEMOVE:
		if(x-band/2<0)
		{
			if(y-band/2<0)
			{
				p_start=cvPoint(0,0);
				p_end=cvPoint(x+band/2,y+band/2);
			}
			else if(y+band/2>temp->height)
			{
				p_start=cvPoint(0,y-band/2);
				p_end=cvPoint(x+band/2,temp->height);
			}
			else
			{
				p_start=cvPoint(0,y-band/2);
				p_end=cvPoint(x+band/2,y+band/2);
			}
		}
		else if(x+band/2>temp->width)
		{
			if(y-band/2<0)
			{
				p_start=cvPoint(x-band/2,0);
				p_end=cvPoint(temp->width,y+band/2);
			}
			else if(y+band/2>temp->height)
			{
				p_start=cvPoint(x-band/2,y-band/2);
				p_end=cvPoint(temp->width,temp->height);
			}
			else
			{
				p_start=cvPoint(x-band/2,y-band/2);
				p_end=cvPoint(temp->width,y+band/2);
			}
		}
		else
		{
			if(y-band/2<0)
			{
				p_start=cvPoint(x-band/2,0);
				p_end=cvPoint(x+band/2,y+band/2);
			}
			else if(y>temp->height-band/2)
			{
				p_start=cvPoint(x-band/2,y-band/2);
				p_end=cvPoint(x+band/2,temp->height);
			}
			else
			{
				p_start=cvPoint(x-band/2,y-band/2);
				p_end=cvPoint(x+band/2,y+band/2);
			}
		}
		cvRectangle(temp,p_start,p_end,cvScalar(0x00,0xff,0x00));
		cvShowImage(window_original,temp);
		cvSetImageROI(temp,cvRect(MIN(p_start.x,p_end.x),MIN(p_start.y,p_end.y),CV_IABS(p_start.x-p_end.x),CV_IABS(p_start.y-p_end.y)));
		cvResize(temp,img_resize);
		cvShowImage(window_test,img_resize);
		cvResetImageROI(temp);
		break;
	}
		
}
int main(int argc, char* argv[])
{	
	img=cvLoadImage("E:/opencv_project/console/Debug/Lena.jpg");
	temp=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3);
	img_resize=cvCreateImage(cvSize(200,200),IPL_DEPTH_8U,3);
	cvNamedWindow(window_original,CV_WINDOW_AUTOSIZE);
	cvNamedWindow(window_test,CV_WINDOW_AUTOSIZE);
	cvShowImage(window_original,img);
	cvSetMouseCallback(window_original,mouse_callback,0);
	while(1)
	{
		if(cvWaitKey(15)==27)
			break;
	}
	cvDestroyAllWindows();
	cvReleaseImage(&img);
	cvReleaseImage(&temp);
	return 0;
}

重新运行程序,以上问题解决。

猜你喜欢

转载自blog.csdn.net/DY580C/article/details/32196313
今日推荐