图像处理

单通道图像灰度取值

IplImage * pSrcImage = cvLoadImage("Sunset.jpg",CV_LOAD_IMAGE_GRAYSCALE);
uchar * pSrcData = (uchar *)pSrcImage->imageData;
for (int i = 0; i < pSrcImage->height; i++)
   {
      for (int j = 0; j < pSrcImage->width; j++)
      {
         int n = i * pSrcImage->width + j;
         char a = pSrcData[n];// 这个即是像素值
      }
   }
cvReleaseImage(&pSrcImage);

分配与释放图像空间

  • 分配图像空间:IplImage* cvCreateImage(CvSize size, int depth, int channels);

    size:   cvSize(width,height);

    depth: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,
              IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F, IPL_DEPTH_64F

    channels: 1, 2, 3 or 4.
         注意数据为交叉存取.彩色图像的数据编排为b0 g0 r0 b1 g1 r1 ...

    举例:

    // 分配一个单通道字节图像
    IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);

    // 分配一个三通道浮点图像
    IplImage* img2=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);

  • 释放图像空间:IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
    cvReleaseImage(&img);
  • 复制图像:IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
    IplImage* img2;
    img2=cvCloneImage(img1);
  • 设定/获取兴趣区域:void   cvSetImageROI(IplImage* image, CvRect rect);
    void   cvResetImageROI(IplImage* image);
    vRect cvGetImageROI(const IplImage* image);

    大部分OpenCV函数都支持ROI.

  • 设定/获取兴趣通道:void cvSetImageCOI(IplImage* image, int coi); // 0=all
    int cvGetImageCOI(const IplImage* image);

    大部分OpenCV函数暂不支持COI.

读取存储图像

  • 从文件中载入图像:   IplImage* img=0;
       img=cvLoadImage(fileName);
       if(!img) printf("Could not load image file: %s\n",fileName);

    Supported image formats: BMP, DIB, JPEG, JPG, JPE, PNG, PBM, PGM, PPM,
                                SR, RAS, TIFF, TIF

    载入图像默认转为3通道彩色图像. 如果不是,则需加flag:

    img=cvLoadImage(fileName,flag);

    flag: >0 载入图像转为三通道彩色图像
             =0 载入图像转为单通道灰度图像
             <0 不转换载入图像(通道数与图像文件相同).

  • 图像存储为图像文件:   if(!cvSaveImage(outFileName,img)) printf("Could not save: %s\n",outFileName);

    输入文件格式由文件扩展名决定.

存取图像元素

  • 假设需要读取在i行j列像点的第k通道. 其中, 行数i的范围为[0, height-1], 列数j的范围为[0, width-1], 通道k的范围为[0, nchannels-1].
  • 间接存取:(比较通用, 但效率低, 可读取任一类型图像数据)
    • 对单通道字节图像:IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
      CvScalar s;
      s=cvGet2D(img,i,j); // get the (i,j) pixel value
      printf("intensity=%f\n",s.val[0]);
      s.val[0]=111;
      cvSet2D(img,i,j,s); // set the (i,j) pixel value
    • 对多通道浮点或字节图像:IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
      CvScalar s;
      s=cvGet2D(img,i,j); // get the (i,j) pixel value
      printf("B=%f, G=%f, R=%f\n",s.val[0],s.val[1],s.val[2]);
      s.val[0]=111;
      s.val[1]=111;
      s.val[2]=111;
      cvSet2D(img,i,j,s); // set the (i,j) pixel value
  • 直接存取:(效率高, 但容易出错)
    • 对单通道字节图像:IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
      ((uchar *)(img->imageData + i*img->widthStep))[j]=111;
    • 对多通道字节图像:IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
      ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
      ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
      ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R
    • 对多通道浮点图像:IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
      ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
      ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
      ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R
  • 用指针直接存取 :(在某些情况下简单高效)
    • 对单通道字节图像:IplImage* img   = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
      int height      = img->height;
      int width       = img->width;
      int step        = img->widthStep/sizeof(uchar);
      uchar* data     = (uchar *)img->imageData;
      data[i*step+j] = 111;
    • 对多通道字节图像:IplImage* img   = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
      int height      = img->height;
      int width       = img->width;
      int step        = img->widthStep/sizeof(uchar);
      int channels    = img->nChannels;
      uchar* data     = (uchar *)img->imageData;
      data[i*step+j*channels+k] = 111;
    • 对单通道浮点图像(假设用4字节调整):IplImage* img   = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
      int height      = img->height;
      int width       = img->width;
      int step        = img->widthStep/sizeof(float);
      int channels    = img->nChannels;
      float * data     = (float *)img->imageData;
      data[i*step+j*channels+k] = 111;
  • 使用 c++ wrapper 进行直接存取:(简单高效)
    • 对单/多通道字节图像,多通道浮点图像定义一个 c++ wrapper:template<class T> class Image
      {
         private:
         IplImage* imgp;
         public:
         Image(IplImage* img=0) {imgp=img;}
         ~Image(){imgp=0;}
         void operator=(IplImage* img) {imgp=img;}
         inline T* operator[](const int rowIndx) {
           return ((T *)(imgp->imageData + rowIndx*imgp->widthStep));}
      };

      typedef struct{
         unsigned char b,g,r;
      } RgbPixel;

      typedef struct{
         float b,g,r;
      } RgbPixelFloat;

      typedef Image<RgbPixel>        RgbImage;
      typedef Image<RgbPixelFloat>   RgbImageFloat;
      typedef Image<unsigned char>   BwImage;
      typedef Image<float>           BwImageFloat;

    • 单通道字节图像:IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
      BwImage imgA(img);
      imgA[i][j] = 111;
    • 多通道字节图像:IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
      RgbImage   imgA(img);
      imgA[i][j].b = 111;
      imgA[i][j].g = 111;
      imgA[i][j].r = 111;
    • 多通道浮点图像:IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
      RgbImageFloat imgA(img);
      imgA[i][j].b = 111;
      imgA[i][j].g = 111;
      imgA[i][j].r = 111;

图像转换

  • 转为灰度或彩色字节图像:cvConvertImage(src, dst, flags=0);

    src = float/byte grayscale/color image
       dst = byte grayscale/color image
       flags = CV_CVTIMG_FLIP      (flip vertically)
               CV_CVTIMG_SWAP_RB   (swap the R and B channels)

  • 转换彩色图像为灰度图像:

    使用OpenCV转换函数:

    cvCvtColor(cimg,gimg,CV_BGR2GRAY); // cimg -> gimg

    直接转换:

    for(i=0;i<cimg->height;i++) for(j=0;j<cimg->width;j++)
       gimgA[i][j]= (uchar)(cimgA[i][j].b*0.114 +
                            cimgA[i][j].g*0.587 +
                            cimgA[i][j].r*0.299);

  • 颜色空间转换:
    cvCvtColor(src,dst,code); // src -> dst

    code     = CV_<X>2<Y>
       <X>/<Y> = RGB, BGR, GRAY, HSV, YCrCb, XYZ, Lab, Luv, HLS

    e.g.: CV_BGR2GRAY, CV_BGR2HSV, CV_BGR2Lab

绘图命令

  • 画长方体:// 用宽度为1的红线在(100,100)与(200,200)之间画一长方体
    cvRectangle(img, cvPoint(100,100), cvPoint(200,200), cvScalar(255,0,0), 1);
  • 画圆:// 在(100,100)处画一半径为20的圆,使用宽度为1的绿线
    cvCircle(img, cvPoint(100,100), 20, cvScalar(0,255,0), 1);
  • 画线段:// 在(100,100)与(200,200)之间画绿色线段,宽度为1
    cvLine(img, cvPoint(100,100), cvPoint(200,200), cvScalar(0,255,0), 1);
  • 画一组线段:CvPoint   curve1[]={10,10,   10,100,   100,100,   100,10};
    CvPoint   curve2[]={30,30,   30,130,   130,130,   130,30,   150,10};
    CvPoint* curveArr[2]={curve1, curve2};
    int       nCurvePts[2]={4,5};
    int       nCurves=2;
    int       isCurveClosed=1;
    int       lineWidth=1;

    cvPolyLine(img,curveArr,nCurvePts,nCurves,isCurveClosed,cvScalar(0,255,255),lineWidth);

  • 画内填充色的多边形:cvFillPoly(img,curveArr,nCurvePts,nCurves,cvScalar(0,255,255));
  • 添加文本:CvFont font;
    double hScale=1.0;
    double vScale=1.0;
    int     lineWidth=1;
    cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC, hScale,vScale,0,lineWidth);

    cvPutText (img,"My comment",cvPoint(200,400), &font, cvScalar(255,255,0));

    Other possible fonts:

    CV_FONT_HERSHEY_SIMPLEX, CV_FONT_HERSHEY_PLAIN,
    CV_FONT_HERSHEY_DUPLEX, CV_FONT_HERSHEY_COMPLEX,
    CV_FONT_HERSHEY_TRIPLEX, CV_FONT_HERSHEY_COMPLEX_SMALL,
    CV_FONT_HERSHEY_SCRIPT_SIMPLEX, CV_FONT_HERSHEY_SCRIPT_COMPLEX,

OpenCV分配与释放图像空间相关推荐

  1. C/C++动态二维数组的内存分配和释放

    C语言: 1 //二维数组动态数组分配和释放 2 //数组指针的内存分配和释放 3 //方法一 4 char (*a)[N];//指向数组的指针 5 a = (char (*)[N])malloc(s ...

  2. 利用二叉树的思想来实现分配和释放内存方法

    虽然大部分系统都有提供内存动态分配和释放函数(即C语言中的malloc和free函数),但是在嵌入式开发中由于系统的限制往往需要自己来实现内存管理,如在有些平台上可动态申请的最大空间不能满足程序设计的 ...

  3. 如何简化临时内存的分配与释放

    描述:在编制 C++ 程序时,最常遇到的一个令人恼火的问题便是临时资源的分配与释放问题, 由于程序的逻辑关系通常很复杂,引发异常的可能性也很多,为了妥善处理运行时异常, 我们不得不在可能引发异常的任何 ...

  4. C++/C--动态二维数组的内存分配与释放【转载】

    1 C语言_二维数组动态数组分配和释放 1.1 数组指针的内存分配和释放 //方法一 char (*a)[N];//指向数组的指针 a = (char (*)[N])malloc(sizeof(cha ...

  5. 分配和释放 BSTR 的内存

    本文档已存档,并且将不进行维护. 分配和释放 BSTR 的内存 Visual Studio .NET 2003                  转自: https://msdn.microsoft. ...

  6. FFmpeg源代码简单分析:内存的分配和释放(av_malloc()、av_free()等)

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  7. java怎么释放分配的内存,linux 内存的分配和释放,linux分配释放

    linux 内存的分配和释放,linux分配释放 了解内存分配机制(共享映射与请求分页) 通过 pmap 命令,可以获取用户进程逻辑地址空间中映射的内存信息: pmap -x $pid 其中 -x 表 ...

  8. C语言中多维数组的内存分配和释放(malloc与free)(转)

    C语言中多维数组的内存分配和释放(malloc与free)(转) 写代码的时候会碰到多维数组的内存分配和释放问题,在分配和释放过程中很容易出现错误.下面贴上一些示例代码,以供参考. 如果要给二维数组( ...

  9. 指针分配和释放空间(转)

    指针分配和释放空间(转) (2012-06-06 12:42:04) 转载▼ 标签: 指针 分类: C/Cplusplus 20.1 理解指针的两种"改变" 普通变量(非指针,简单 ...

最新文章

  1. stm32 温湿度_基于STM32单片机大棚温湿度检测无线蓝牙APP控制设计
  2. CodeForces-1294B排序+pair使用
  3. Java并发编程中的若干核心技术,向高手进阶
  4. 以太坊智能合约生命周期(Ethereum smart contracts lifecycle)
  5. golang map的定义语法
  6. docker中部署hadoop、zookeeper、hbase伪分布式并上传到阿里云远程仓库
  7. getopt长参数(长选项)获取不到参数BUG
  8. java 不兼容类型_java – 不兼容的类型和新鲜的类型变量
  9. 今天看到一个热搜,说一个美团会员配送费6元,普通用户2元,导致轩然大波
  10. 065_VFPage中CallBack回调函数的解释
  11. 利润表模板excel_分享用了8年的excel记账系统,一键录入,多表生成,记账很简单...
  12. s7200cpu224xp手册_西门子S7-200 CPU224XP
  13. Gerber文件解析
  14. 第9章 Linux文件核心属性知识
  15. OpenCV函数remap详解
  16. 带你简化理解Spring 基于注解配置的原理
  17. 工业4.0:换热站最酷设计—— Web SCADA 工业组态软件界面
  18. 海康威视录像机如何添加大华摄像头
  19. win10运行快捷键_阿销带你看世界——电脑技巧之电脑快捷键(WIN篇2)
  20. 啊哈C语言第四章99乘法表

热门文章

  1. 地图上制作线路的动画_魔兽争霸重制版不只是表面上这么简单,新版编辑器制作地图更容易...
  2. 牛顿斯科特MATLAB求积分,详解Matlab求积分的各种方法
  3. 华为云计算之存储的分类
  4. Java高并发编程(十一):Java中线程池
  5. Shell脚本实现生成SSL自签署证书
  6. Linux中介绍who命令实例
  7. SSM 返回静态页面HTML Controller 被递归调用引起的StackOverflowError
  8. vivado编译出错 [Synth 8-729] [Synth 8-787]
  9. 韩信点兵-中国剩余定理(练习)
  10. android里Conversion to Dalvik format failed with error 1错误的解决