• opencv编程入门技巧


    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(这个比较好用)

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

  • 相关阅读:
    点击CheckBox让Gridview控件在编辑与正常状态之间切换
    BMP图片转换为JPEG图片
    ASP.NET截取网页注释行之间的内容
    Mouse点击之后,复制GridView控件的数据行
    Mouse单击高亮GridView数据行
    ASP.NET div信息提示框显示几秒后隐藏
    RDLC报表带搜索与传参数功能演示(ASP.NET MVC)
    ASP.NET MVC应用程序使用axd格式文件
    Nginx通过geo模式实现限速白名单和全局负载均衡
    MySQL 下mysqladmin日常管理命令总结
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3203179.html
Copyright © 2020-2023  润新知