打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
OpenCV使用中“内存泄露”的探索 - 追梦的日志 - 网易博客

OpenCV使用中“内存泄露”的探索

机器视觉 2010-04-14 20:04:20 阅读45 评论0 字号:

OpenCV使用中“内存泄露”的探索

戏剧性阶段一:问题的出现 

最近在使用opencv的时候,发现在图像函数部分,opencv的内存管理存在一定问题。在使用IplImage的图像cvcloneImage()后,调用cvReleaseImage()时,内存并不能全部释放。在实时视频处理程序中,伴随程序运行,很容易造成系统内存消耗殆尽。

   举例来说,看下面的一个最简单代码:

#include"cv.h"

#include"highgui.h"

#pragma comment(lib,"cv.lib")

#pragma comment(lib,"highgui.lib")

#pragma comment(lib,"cxcore.lib")

int _tmain(int argc, _TCHAR* argv[])

{

 CvCapture* capture = cvCreateCameraCapture(0);

 IplImage* frame;

 cvNamedWindow("ExampleShow",CV_WINDOW_AUTOSIZE);

 while(1)

 {

  frame = cvQueryFrame(capture);

  if(!frame)

   break;

  cvShowImage("ExampleShow",frame);

  char c = cvWaitKey(33);

  if(c == 27)

   break;

 }

 cvReleaseCapture(&capture);

 cvDestroyWindow("ExampleShow");

 return 0;

}

运行程序,此时,打开资源管理器,可以看到其所占的“内存使用”一直保持稳定。而如果,简单修改下上面的程序,改变如下:

#include"cv.h"

#include"highgui.h"

#pragma comment(lib,"cv.lib")

#pragma comment(lib,"highgui.lib")

#pragma comment(lib,"cxcore.lib")

int _tmain(int argc, _TCHAR* argv[])

{

 CvCapture* capture = cvCreateCameraCapture(0);

 IplImage* frame;

 IplImage* clImage;

 cvNamedWindow("ExampleShow",CV_WINDOW_AUTOSIZE);

 cvNamedWindow("Example_Clone",CV_WINDOW_AUTOSIZE);

 while(1)

 {

  frame = cvQueryFrame(capture);

  if(!frame)

   break;

  cvShowImage("ExampleShow",frame);

  clImage = cvCreateImage(cvSize(frame->width,frame->height),frame->depth,frame->nChannels);

  clImage = cvCloneImage(frame);

  cvShowImage("Example_Clone",clImage);

  char c = cvWaitKey(33);

  if(c == 27)

   break;

 cvReleaseImage(&clImage);

 }

 cvReleaseCapture(&capture);

 cvDestroyWindow("ExampleShow");

 cvDestroyWindow("Example_Clone");

 return 0;

}

同样,运行程序,打开资源管理器,可以看到“内存使用”中,该程序的内存使用量在不断增加。虽然,程序中对拷贝的图像进行了释放,但是,事实上,却没有看到多少效果!

  虽然发现了这个问题,也在网络上看到相关的这个问题的讨论,试验了几种方法,发现并不work。在此提出问题,继续探索吧。

 戏剧性阶段二:“改良方法”的出现

   在网络上看到,除了cvCloneImage()还有cvLoadImage()也有内存泄露问题。最终的有效解决办法是使用cvCopy()来替换代码中的cvCloneImage(),这时候,不会出现内存不断递增的情况。而cvLoadImage()可以CvvImage类的图像装载函数,然后拷贝到目标图像即可。

戏剧性三:真正原因的捕获和分析 

内存无法释放的原因分析:

    今天偶然想起,在观察上面的代码时,发现在其中存在一句:clImage = cvCreateImage(cvSize(frame->width,frame->height),frame->depth,frame->nChannels);

,这句是向内存申请一片空间,用于存放目的图像的空间。造成内存泄露的真正原因是这句。在使用cvCloneImage()的时候,其实是对源图像指针所指向的图像头、数据、ROI等进行了一个完全的拷贝,放在一个新的内存区域,函数结果使得目标图像指向新的内存,而原来用cvCreateImage()所分配的区域没有被正确释放,成为一片“悬挂地址区域”。在后面调用cvReleaseImage()的时候,释放的是后面其所指向的区域。

   因此,要避免这种情况的出现,一种方法是:可以在cvCloneImage()前,先调用cvReleaseImage()来释放之前分配的地址区域。然后执行克隆函数cvCloneImage()操作。也可以在前面不分配空间,直接调用克隆操作。另外一种方法,如果使用cvCopy()函数操作,由于该函数并不会对图像指针分配空间,所以需要先自己用cvCreateImage()分配一段区域,然后调用拷贝函数cvCopy(),来对图像赋值。这样最后释放的是图像指针所指的地址区域。这两种方法都不会出现内存泄露的问题了。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
cvCopy与cvCloneImage的区别
cvcloneimage注意
#pragma comment(lib,"*.lib")
OpenCV图像处理 空间域图像增强(图像锐化 1 基于拉普拉斯算子)
局部二值模式(LBP)中间过程的可视化
#pragma
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服