OpenCV中的内存泄露问题(cvLoadImage,cvCloneImage)

【OpenCV】有关内存释放 总结 转载请注明出处:http://blog.youkuaiyun.com/xiaowei_cqu/article/details/7586847 前一天把系统整个重写了一遍,脉络清晰了很多,也终于解决了以前很多崩溃,异常退出的问题。这里小小总结一下自己遇到的麻烦。 1、内存泄露 内存泄露是说没有释放已经不能使用的内存,这里一般指堆的内存才需要显示的释放。比如用malloc,calloc,realloc,ne 阅读详情
OpenCV中的内存泄露问题(cvLoadImage,cvCloneImage)

在做项目的过程中,使用OpenCV经常会出现一些内存泄露问题,自己编写的程序出现问题还情有可原,但若是库函数调用和使用时出现,却很令我恼火。花了好长时间和实践的经验告诉我应该客服它。下面把一些检测出的问题进行化解。(可能是水平不够,这些函数使用不当,望高手指点)

cvLoadImage函数:

可能大家还觉察不出来,但我深有体会,在程序中这个函数使用一次两次感觉不来,但在处理序列图像循环调用这个函数时,内存泄露的可能让你目瞪口呆!即使你在最后使用cvReleaseImage(&pImg);进行了释放,实验证明:视乎不能成功释放。

解决方法:

使用CvvImage类代替。并且使用CvvImage类的Load函数。

使用过程大概如下:

//变量定义:

CvvImage pSrcImg;

IplImag *pSrcImgCopy ;//使用IplImag变量做个拷贝。毕竟IplImag 类处理方便。

//获取图像:

pSrcImg.Load(str);//str为Cstring类型的图像文件名
pSrcImgCopy = pSrcImg.GetImage();//拷贝出pSrcImg的图像数据。

//释放内存

pSrcImg变量不需要每次释放,因为每次Load时是覆盖以前的内存区域。pSrcImgCopy 同样。

不过在程序结束时要释放,以免产生内存泄露或者别人以为你忘了。

cvReleaseImage(&pSrcImgCopy );
pSrcImg.Destroy();

不过要正确释放pSrcImgCopy 时,声明时必须create下:

pSrcImgCopy = cvCreateImage(cvSize(IMGWIDHT,IMGHEIGHT),IPL_DEPTH_8U, 3);

//IMGWIDHT,IMGHEIGHT为图像宽和高。

cvCloneImage函数:

这个函数也会出现内存泄露!虽然可以释放,但程序复杂不知道在那里释放,因为它每次拷贝是制作图像的完整拷贝包括头、ROI和数据。不会覆盖以前的内容。每次使用时编译器会分配内存空间。一个752*480大小的图像,每次泄露的内存大约为1M。

解决方法:

使用cvCopy函数代替。

cvCopy(pSrcImg,pImg,NULL);//代替 pImg = cvCloneImage(pSrcImg);

pImg初始化时必须分配空间,否则上述函数不能执行。

pImg = cvCreateImage(cvSize(IMGWIDHT,IMGHEIGHT),IPL_DEPTH_8U, 3);

 

最近一直在用opencv编写算法程序,但是cvCloneImage、cvCopyImage和cvCloneMat、cvCopyMat这几个函数让我痛苦了好一阵子,程序代码没有任何问题,但是就是得不到结果,在子函数中返回值根本不是我想要的,由于代码挺庞大的,一直没找到问题出在哪里,于是设置一个个断点,通过步步调试,终于发现问题出在了cvCloneImage、cvCopyImage和cvCloneMat、cvCopyMat这几个函数的误用,cvCloneImage与cvCloneMat是在赋值的同时会开辟一个新的空间给定义的变量,cvCopyImage与cvCopyMat只复制值,并不会分配一个空间给赋值对象,因此cvCloneImage与cvCloneMat只适合用于变量开始定义,千万不要用在算法处理中间,否则会产生一个新的地址空间,会将赋值对象的指针地址改变,这样会导致整个程序有不可预测的错误发生,最明显的就是你本来想把子函数中的新变量值送回上一层函数,但是由于指针的指向已经改变,所以返回后的值并不会改变。在程序中间进行复制时候建议使用cvCopyImage与cvCopyMat。

因此当使用opencv函数时候,不同函数实现同一个功能,但是一定要注意他们之间的区别,不然会让你很痛苦,寻找这种错误真的很烦人。

http://benson.is-programmer.com/posts/21042.html

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

最近在使用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(),来对图像赋值。这样最后释放的是图像指针所指的地址区域。这两种方法都不会出现内存泄露的问题了。

 

 1. cvCloneImage()

        ......
        IplImag *img = cvCreateImage( cvSize(frame->width,frame->hight), frame->depth, frame->nChannels );
        img = cvCloneImage(frame);

    这里出现内存泄露,因为调用cvCloneImage()之前已经用cvCreateImage()为图像分配了内存空间,而cvCloneImage()函数是对源图像的所有数据的拷贝,包括图像头、数据、ROI等,这就导致原来分配的内存空间变成了内存碎片,造成内存泄露。.解决方法如下:

        IplImag *img = cvCloneImage(frame);

    或 

        IplImag *img = cvCreateImage( cvSize(frame->width,frame->hight), frame->depth, frame->nChannels );

        cvReleaseImage(&img);
        img = cvCloneImage(frame);

    或

        IplImag *img = cvCreateImage( cvSize(frame->width,frame->hight), frame->depth, frame->nChannels );
        img = cvCloneImage(frame);

        cvCopy(frame,img,NULL);

 

    2. cvGetCols()、cvGetRows()

    ......

    CvMat *srcMat = cvCreateMat(width, height, CV_8UC3);  // 创建一个三通道无符号整数类型的矩阵
    cvGetCols(frame,srcMat,0,width);

    这里出现内存泄露,因为cvGetCols()、cvGetRows() 是为目标矩阵分配一块新的数据内存区域,如果目标矩阵的数据区域之前已经分配了内存,则会原始数据内存区域将变成内存碎片,造成内存泄露。解决方法如下:

        CvMat *srcMat = cvCreateMat(width, height, CV_8UC3);  // 创建一个三通道无符号整数类型的矩阵

        cvReleaseData(srcMat);    // 先释放目标矩阵的数据区

        cvGetCols(frame,srcMat,0,width);

    或者

         cvCreateMatHeader(width, height, CV_8UC3);

         cvGetCols(frame,srcMat,0,width);

 

    3. IplImag*、CvMat*、CvHistogram* 等结构体指针在使用后要释放。

         IplImage *frame= cvCreateImage(cvSize(width,height),8,1);

         CvMat *srcMat = cvCreateMat(width, height, CV_8U);

         ......

         CvHistogram *hist = cvCreateHist(1,&histSize,CV_HIST_ARRAY,ranges,1);

         ......

         cvReleaseMat(&srcMat);
         cvReleaseImage(&frame);  
         cvReleaseHist(&hist);

opencv中cvLoadImage和cvCloneImage的内存泄露问题 cvLoadImage函数: 可能大家还觉察不出来,但我深有体会,在程序中这个函数使用一次两次感觉不来,但在处理序列图像循环调用这个函数时,内存泄露的可能让你目瞪口呆!即使你在最后使用cvReleaseImage(&pImg);进行了释放,实验证明:视乎不能成功释放。 解决方法: 使用CvvImage类代替。并且使用CvvImage类的Load函数。 使用过程大概如下: 阅读详情

相关推荐

OpenCV内存泄漏检测

通过启用内存分配器的跟踪功能,我们可以在程序运行时收集内存分配和释放的信息,并分析这些信息以确定是否存在内存泄漏。总结起来,通过使用OpenCV内置的内存跟踪工具,我们可以及时发现和解决内存泄漏问题,确保我们的图像处理和计算机视觉应用程序在运行时使用内存的效率和安全性。因此,在解决内存泄漏问题时,我们需要仔细分析代码并进行必要的优化和改进。总结起来,通过使用OpenCV内置的内存跟踪工具,我们可以及时发现和解决内存泄漏问题,确保我们的图像处理和计算机视觉应用程序在运行时使用内存的效率和安全性。

WzisTypescript的博客 882

cvCopy与cvCloneImage、cvCopyimage的区别

1----如果设定了ROI等参数的时候,cvCopy只是复制被设定的区域,复制到一个和所设定参数相吻合的新的IplImage中       而cvCloneImage则是将整个IplImage结构复制到新的IplImage中,其中的ROI等参数也会一同复制。新的IplImage将会和原来的一模一样。 2----cvCloneImage的原型是:IplImage* cvCloneImage(

maweifei的博客 871

OpenCV中的内存泄露问题(cvLoadImage,cvCloneImage)【转】

OpenCV中的内存泄露问题(cvLoadImage,cvCloneImage) 在利用opencv时,有时候即使你觉得释放了资源,依然会造成内存泄露,原因究竟何在,这里给你答案!

[OpenCV]OpenCV中的内存泄露问题(cvLoadImage,cvCloneImage)【转】

OpenCV中的内存泄露问题(cvLoadImage,cvCloneImage)【转】 发布时间:2011-07-19 13:20:28 技术类别:软件开发         http://bbs.ednchina.com/BLOG_ARTICLE_2108648.HTM   再用cvCopy()之前,不仅需要分配内存,同时IplImage的ROI也要一起设置。   ...

534

SQLite → PostgreSQL 迁移脚本与踩坑清单

本文提供了SQLite迁移到PostgreSQL的两种可靠路径:首选使用pgloader工具自动转换schema和数据,支持类型映射和并行复制;备选方案通过sqlite3导出CSV再用PostgreSQL的COPY命令导入,适合需要自定义清洗的场景。重点介绍了数据类型映射规则、迁移步骤、校验方法和常见问题,包括自增主键、布尔值、时间类型等关键差异处理。迁移后需进行行数核对、哈希抽样等校验,并给出了性能优化建议。最后强调迁移不仅是数据转移,更需要同步升级数据模型和索引策略,根据业务场景选择合适的数据库方案。

aifs2025的博客 1885

云漾AI创作平台实战:如何用GPT4.0+Midjourney快速生成商业级插画(附Prompt模板)

本文详细介绍了如何利用云漾AI创作平台结合GPT4.0和Midjourney快速生成商业级插画。通过智能文案生成与视觉化工作流,大幅提升创作效率,适用于电商、社交媒体等多种场景。文章包含实用Prompt模板和参数调整技巧,帮助设计师和内容创作者高效产出专业插画。

weixin_29251567的博客 218

OpenCV-OpenCV中的内存泄露问题(cvLoadImage,cvCloneImage)

cvCloneImage与cvCloneMat是在赋值的同时会开辟一个新的空间给定义的变量,cvCopyImage与cvCopyMat只复制值,并不会分配一个空间给赋值对象,因此cvCloneImage与cvCloneMat只适合用于变量开始定义,千万不要用在算法处理中间,否则会产生一个新的地址空间,会将赋值对象的指针地址改变,这样会导致整个程序有不可预测的错误发生,最明显的就是你本来想把子函数中

661

PVT(Process Voltage Temperature)

芯片PVT

网始如芯个人博客 3万+

OpenCV中的内存泄露问题(cvLoadIm…

在做项目的过程中,使用OpenCV经常会出现一些内存泄露问题,自己编写的程序出现问题还情有可原,但若是库函数调用和使用时出现,却很令我恼火。花了好长时间和实践的经验告诉我应该客服它。下面把一些检测出的问题进行化解。(可能是水平不够,这些函数使用不当,望高手指点) cvLoadImage函数: 可能大家还觉察不出来,但我深有体会,在程序中这个函数使用一次两次感觉不来,但在处理序列图像循环调用这个

shangyaowei的专栏 1610

紫光同创FPGA中ADF网表文件的黑匣子封装与PDS环境实战指南

本文详细介绍了在紫光同创FPGA开发环境中使用ADF网表文件进行黑匣子封装的实战指南。通过PDS环境配置、加密ADF生成、黑匣子集成及验证调试等步骤,帮助开发者实现核心IP保护,同时保持设计性能。特别适用于需要模块级代码保护的企业级FPGA开发场景。

weixin_33725239的博客 341

ubuntu20.04屏幕亮度无法调节(亮度条调节无效)的简单靠谱解决方案及踩坑历程

0 前言   网上关于ubuntu系统亮度无法调节的问题的解决方法有很多,但是绝大部分并没有什么用(这也是我自己的亲身体会),或者并不靠谱。在遍尝各路方法过后,我终于解决了这一棘手的问题(毕竟最大亮度真的非常刺眼,无法长时间直视),在此记录一下踩坑历程以及最后的解决方案。 1 Naive方法   由于使用需要,最近在电脑原有的win10基础上安装了ubuntu双系统。我安装的是当前新版的ubuntu20.04.2.0,靠谱的安装教程可以参考这里。   之前师兄说双ssd安装双系统会有系统启动引导的问题出现,

zeeq的博客 4万+

OpenCv函数cvCloneImage内存泄漏问题

声明:文章一转载自http://www.360doc.com/content/11/0621/16/6408986_128481830.shtml     文章二转载自http://hi.baidu.com/cateyefish/item/794ab51f2535a4737a5f2526      谢谢文章原作者的分享。 文章一: 1、imgcopy=cvCloneImage(im

嵌入式学习交流平台 3651

Android 13.0 Launcher3中去掉Hotseat功能实现

在13.0系统产品定制化开发中,在Launcher3的定制化需求也是特别多的,由产品是小屏幕的产品,所以产品需求Launcher3 页面布局的原因,要求Launcher3 需要去掉Hotseat 不显示Hotseat下面几个图标,而做满屏app的显示,从而达到美观的效果,下面就来分析去掉Hotseat从而实现这个功能

安卓兼职framework和app工程师的博客 1327

cvLoadImage,cvCloneImage的内存泄露问题

针对openCV中,隐蔽的内存泄露,大家需要重视,拯救为数不多的内存,拯救应用程序的速度       在做项目的过程中,使用OpenCV经常会出现一些内存泄露问题,自己编写的程序出现问题还情有可原,但若是库函数调用和使用时出现,却很令我恼火。花了好长时间和实践的经验告诉我应该客服它。下面把一些检测出的问题进行化解。(可能是水平不够,这些函数使用不当,望高手指点)     cvLo

XYLiu的专栏 803

YOLOV5 自动刷图脚本实战(十五)之如何找到正确的门

DXF是一个2D游戏,我们所看到的人物移动,其实是后面的背景在移动,我们所看到的画面,不过是一个完整背景中的一个镜头视角而已想要正确找到门的坐标,我们需要对不同的地图中的每个房间做一些配置信息。

qq_38892949的博客 2808

Codex 调试记录获取完全指南:日志查看、工具调用与实战排查教程

本文主要介绍了Codex 调试记录获取完全指南:日志查看、工具调用与实战排查教程,希望能对使用Codex的同学们有所帮助。 文章目录 1. 背景 2. 实战教程

weixin_43178406的博客 6万+

opencv各种内存泄露情况的大总结

opencv各种内存泄露情况的大总结 以下文章共总结出cvLoadImage cvCloneImage cvGetRow 三个函数容易由于使用不当而泄露内存,要注意! OpenCV中的内存泄露问题(cvLoadImage函数) 摘自:http://h

C_arm的专栏 1万+

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

上一篇: opencv应该注意的几个问题
下一篇: 未能创建.NET Frameworks PropertyGrid组件(解决方案)
wangwanguo08
博客等级 码龄18年 65粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值