opencv编程入门技巧

最近在项目中负责图像处理模块的编程工作,主要分为两个板块,一是视频图像去雾,二是可视、红外图像融合。为了提升开发效率,遂开始学习并使用opencv图像类库,效果很好的说~因为平台是vc6.0,比较老,加之对opencv的运用是入门级,所以选择使用opencv1.0版。下面提出几个我使用时遇到的问题及解决方法,同是opencv入门的同志可以略作参考。

1、         两个重要结构体类型。IplImage、CvMat。

(下文中变量,mat开头为矩阵CvMat类型,im开头为图像IplImage类型)

其中IplImage主要用来读入图像和存储处理结果的图像并显示。而CvMat作为矩阵类,主要用于过程中的数据处理。

推荐的建立方式如下:

IplImage* imResult=cvCreateImage(cvGetSize(matRes),8,3);

其中第一个参数需要cvSize类型(matRes为矩阵),8表示颜色深度,3表示通道(若建立灰度图像,3改成1)。

CvMat *   src=cvCreateMat(matV->height,matV->width,CV_32FC3);

三个参数分别是矩阵行数、列数、以及数据类型。数据类型请自己查看相关文献,这里的CV_32FC3表示float   3通道,若是灰度图像,改为CV_32FC1。

二者的相互转换方法如下:

IplImage——》CvMat

CvMat*   matRes=cvCreateMat(matV->height,matV->width,CV_32FC3);

cvConvert(imRes,matRes)

CvMat——》IplImage

IplImage* imRes=cvCreateImage(cvGetSize(matRes),8,3);

cvGetImage(matRes,imRes);

2、            CvMat的数据读取和写入

这个很重要,因为一直要用。方法似乎也好几种,可以用opencv的函数接口,也可以用指针。用指针寻址快,效率高,但是容易出错,况且我们平时编程似乎对程序时间消耗没有太大的刚性需求,所以这里讨论一下用现成函数接口的方法。注意cvmGet,cvmSet只能读取写入float和double类型数据,所以定义矩阵时最后的参数需设置为CV_32FC。

对灰度图像,一般用cvmGet和cvmSet

cvmGet(matRes,i,j);

cvmSet(matRes,i,j,tempres);

注意的是上面的i都是行坐标,是图像的height坐标轴。

对3通道彩色图像,一般使用cvGet2D,cvSet2D

cvGet2D(imRes,i,j),这样得到的是一个cvScalar的数据结构,里面存了该像素位置的rgb三个分量。得到三个分量各分量值的方法是

cvScalar s= cvGet2D(imRes,i,j);

int b=s.val[0];

int g=s.val[1];

int r=s.val[2]

注意,存储顺序是b,g,r。

用cvSet2D一样,先建立cvScalar s,对s的三个分量赋值,再用cvSet2D写入矩阵。

3、            内存泄露的解决方法

我在程序运行过程中碰到了严重的内存泄露问题,程序跑20来秒,我的内存就被占用光了,程序崩溃。下面说几条解决方法:

首先,因为CvMat类型是图像处理的中间环节,所以在得到处理结果并转化为IplImage后,对所有的CvMat类型进行清理,方法是

cvReleaseMat(&matRes);

一些图像内存也需要释放:

cvReleaseImage(&imRes);

另外,有时需要将一个矩阵内容拷贝到另一个矩阵,opencv提供了两种方法,cvCopy和cvCloneMat。此时需要慎重,使用cvCloneMat时,会开辟新的存储空间,而cvCopy不会。所以拷贝矩阵时,可使用以下两种方法:

CvMat *src=cvCreateMat(matV->height,matV->width,CV_32FC3);

cvCopy(matV,src);//将前者拷贝到后者

CvMat *src= cvCloneMat(matV);

再者,使用cvGetRows,cvGetCols时也需要注意,他们也会开辟新的内存空间,所以在之前需要释放目标矩阵的数据区域,如

CvMat * matRes=cvCreateMat(height,width,CV_32FC3);

cvRealeaseData(matRes);

cvGetRows(mat,matRes,0,height);

CvMat *matRes=cvCreateMatHeader(height,width,CV_32FC3);

cvGetRows(mat,matRes,0,height);

4、            再写几个小问题

矩阵的三个维度合为一个三维矩阵方法

cvMerge(matRes1,matRes2,matRes3,NULL,matRes);

将三维矩阵拆成三个一维似乎没有现成函数接口,自己写循环实现吧。

矩阵的加减乘除运算,这个也用得很多的,写在这里。

矩阵-矩阵操作:

CvMat *Ma, *Mb, *Mc;

cvAdd(Ma, Mb, Mc); //Ma+Mb -> Mc

cvSub(Ma, Mb, Mc);//Ma-Mb -> Mc

cvMatMul(Ma, Mb, Mc); //Ma*Mb -> Mc

按元素的矩阵操作:

CvMat *Ma, *Mb, *Mc;

cvMul(Ma, Mb, Mc);// Ma.*Mb -> Mc

cvDiv(Ma, Mb, Mc);// Ma./Mb -> Mc

cvAddS(Ma, cvScalar(-10.0), Mc);// Ma.-10 -> Mc(这个比较好用)

在整个开发过程中,似乎也就遇到这几个问题,在此记录下来,以供大家参考。哈哈,第一篇博文完成啦,开心~

最新文章

  1. Array基本操作
  2. Autolayout及VFL经验分享
  3. hudson项目中的运用
  4. C# unix时间戳转换
  5. Oracle 手工清除回滚段的几种方法
  6. 自定义控件和XControl控件
  7. To fix sql server 2008 r2 Evaluation period has expired by change the key
  8. C语言中volatilekeyword的作用
  9. 如何将你牛逼的iOS代码分享到CocoaPod(转)
  10. 【iOS】MD5数据加密和网络安全
  11. 记录python题
  12. 关于页面缩放时css错乱的处理方法---之一
  13. hadoop 核心概念及入门
  14. CentOS7使用命令连接网络配置
  15. 福大软工 · BETA 版冲刺前准备之拖鞋旅游队
  16. 如何减少block的嵌套层次?
  17. Java-JDK & Android SDK下载安装及配置教程
  18. redis常用命令记录
  19. java并发编程:线程安全管理类--原子操作类--AtomicIntegerFieldUpdater<T>
  20. Redis数据结构(三)

热门文章

  1. IBM、京东、携程、eBay 的 OpenStack 云
  2. 超酷的jQuery百叶窗图片滑块实现教程
  3. Android的5样的调试信息
  4. Web开发的发展
  5. PHP 调用asp.net Web Services服务问题总结
  6. SQL Server 性能调优 之运行计划(Execution Plan)调优
  7. SQL Server的链接服务器(MySQL、Oracle、Ms_sql、Access、SYBASE)
  8. hexo github
  9. ASP.NET MVC Model绑定
  10. Bootstrap 导航