OpenCV中ROI

ROI(region of interest),也就是感兴趣区域,如果你设置了图像了ROI,那么在使用OpenCV的函数的时候,会只对ROI区域操作,其他区域忽略。举个例子:

原图:

现在要将这幅图的蓝色通道加150

如果没有设置ROI,则函数作用在这个图像上,整个图像的所有像素的蓝色通道都会被加上150

但是现在我设置了ROI,

Rect  ROI(0,100,width/2,height/2);

则函数只会作用在我设置的ROI区域,其他区域保持不变。效果如下图

在OpenCV1.0中,我们看一下IplImage的数据结构

[cpp] view plaincopy
  1. typedef struct _IplImage
  2. {
  3. int  nSize;             /* sizeof(IplImage) */
  4. int  ID;                /* version (=0)*/
  5. int  nChannels;         /* Most of OpenCV functions support 1,2,3 or 4 channels */
  6. int  alphaChannel;      /* Ignored by OpenCV */
  7. int  depth;             /* Pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S,
  8. IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported.  */
  9. char colorModel[4];     /* Ignored by OpenCV */
  10. char channelSeq[4];     /* ditto */
  11. int  dataOrder;         /* 0 - interleaved color channels, 1 - separate color channels.
  12. cvCreateImage can only create interleaved images */
  13. int  origin;            /* 0 - top-left origin,
  14. 1 - bottom-left origin (Windows bitmaps style).  */
  15. int  align;             /* Alignment of image rows (4 or 8).
  16. OpenCV ignores it and uses widthStep instead.    */
  17. int  width;             /* Image width in pixels.                           */
  18. int  height;            /* Image height in pixels.                          */
  19. struct _IplROI *roi;    /* Image ROI. If NULL, the whole image is selected. */
  20. struct _IplImage *maskROI;      /* Must be NULL. */
  21. void  *imageId;                 /* "           " */
  22. struct _IplTileInfo *tileInfo;  /* "           " */
  23. int  imageSize;         /* Image data size in bytes
  24. (==image->height*image->widthStep
  25. in case of interleaved data)*/
  26. char *imageData;        /* Pointer to aligned image data.         */
  27. int  widthStep;         /* Size of aligned image row in bytes.    */
  28. int  BorderMode[4];     /* Ignored by OpenCV.                     */
  29. int  BorderConst[4];    /* Ditto.                                 */
  30. char *imageDataOrigin;  /* Pointer to very origin of image data
  31. (not necessarily aligned) -
  32. needed for correct deallocation */
  33. }
  34. IplImage;

ROI的实现是通过结构体

[cpp] view plaincopy
  1. struct _IplROI *roi;

来实现的,其中定义如下

[cpp] view plaincopy
  1. typedef struct _IplROI
[cpp] view plaincopy
  1. {
  2. int  coi; /* 0 - no COI (all channels are selected), 1 - 0th channel is selected ...*/
  3. int  xOffset;
  4. int  yOffset;
  5. int  width;
  6. int  height;
  7. }
  8. IplROI;

示例代码:

[cpp] view plaincopy
  1. <span style="white-space:pre">    </span>IplImage *image = cvLoadImage(LENA_COLOR, -1);
  2. //输出
  3. cout<<"width:"<<image->width<<endl;
  4. cout<<"height:"<<image->height<<endl;
  5. cout<<"widthStep:"<<image->widthStep<<endl;
  6. //设置ROI
  7. cvSetImageROI(image, cvRect(0, 100, image->width / 2, image->height / 2));//设置ROI
  8. cvAddS(image, cvScalar(150), image);//将蓝色通道增加150
  9. //输出
  10. cout<<"width:"<<image->width<<endl;
  11. cout<<"height:"<<image->height<<endl;
  12. cout<<"widthStep:"<<image->widthStep<<endl;
  13. cvResetImageROI(image);//★释放ROI,否则,只会显示ROI区域
  14. cvNamedWindow("ROI", 1);
  15. cvShowImage("ROI", image);
  16. cvWaitKey(0);

图片采用了512*512的彩色Lena图,实验结果:

在OpenCV2.0中,ROI的实现方式就不同了

大致有两种方式

1.通过重载运算符(其实也是通过构造函数实现的)

Mat  B= A(Range::all(), Range(1, 3));

Mat  B=A(Rect(0,0,100,100));

2.通过构造函数

Mat(const Mat& m, const Range&rowRange, const Range& colRange=Range::all());

Mat(const Mat& m, const Rect& roi);

大家可以参考1.0的程序写出2.0的版本,实现也非常简单。

下面我想说的是,通过下面的方式创建ROI

Mat  B= A(Range::all(), Range(1, 3));

Mat  B=A(Rect(0,0,100,100));

则B和A是共享数据内存的,B使用的还是A的内存,只是B的Mat结构体中一些参数被修改了。

有的时候我们想拷贝数据,创建一个独立的ROI子图像,可以通过下面程序中的方式。

下面直接给出一个简单的示例程序:

[cpp] view plaincopy
  1. void Learn_ROI_Function()
  2. {
  3. //创建一个简单的图像
  4. Mat simpleImage=(Mat_<int>(3,3)<<1,2,1,
  5. 1,2,1,
  6. 1,2,1
  7. ;
  8. //不拷贝数据
  9. //设置ROI,!注意是共享内存的方式
  10. //方式1:Mat  B = A(Range::all(), Range(1, 3));
  11. //方式2: Mat  B= A(Rect(0,0,100,100));
  12. Mat ROI=simpleImage(Rect(1,1,2,2));
  13. //行,列和每行的通道数(步长)
  14. cout<<"/Not Copy Data///"<<endl;
  15. cout<<"rows:"<<ROI.rows<<endl;
  16. cout<<"cols:"<<ROI.cols<<endl;
  17. int widthStep=ROI.step1(0);
  18. cout<<"widthStep:"<<widthStep<<endl;//3:每行通道数没变
  19. //遍历ROI,注意内存模型
  20. //输出2,1,1,2
  21. cout<<"data:"<<" ";
  22. int *data=(int *)ROI.data;
  23. for (int i=0;i<=3;++i)
  24. {
  25. cout<<data[i]<<",";
  26. }
  27. //拷贝数据,创建独立ROI子图像///
  28. //采用数据拷贝方式创建独立的ROI图片
  29. IplImage iplImage=ROI;
  30. Mat copyedROI(&iplImage,true);
  31. //行,列和每行的通道数(步长)
  32. cout<<"\n\n/Copy Data///"<<endl;
  33. cout<<"rows:"<<copyedROI.rows<<endl;
  34. cout<<"cols:"<<copyedROI.cols<<endl;
  35. widthStep=copyedROI.step1(0);
  36. cout<<"widthStep:"<<widthStep<<endl;//3:每行通道数没变
  37. //遍历ROI,注意内存模型,输出2,1,2,1
[cpp] view plaincopy
  1. <span style="white-space:pre">    </span>cout<<"data:"<<" ";
[cpp] view plaincopy
  1. int *data2=(int *)copyedROI.data;
  2. for (int i=0;i<=3;++i)
  3. {
  4. cout<<data2[i]<<",";
  5. }
  6. cout<<endl;
  7. }

结果:

内存示意图

没有拷贝数据

拷贝数据之后

没有拷贝之前,ROI实际上共享simpleImage的内存,只是改变了一下ROI的Mat中的一些成员变量:

data,rows,cols,从内存示意图中可以看出。

这里要注意,ROI的步长step1(0)并没有改变,还是与原图像一样,这样支持ROI的OpenCV函数遍历图像的时候才不致出错.因为遍历图像的时候,都是使用步长控制的。

ROI中有效数据在内存中是不连续的,如果你采用上面连续访问形式,会出错的,得到的数据位2,1,1,2,而我们需要的实际数据应该是2,1,2,1。如果需要访问,可以采用OpenCV中at()方法,或者使用步长控制指针。读者可以自己实现一下,也比较简单。

拷贝数据后,copyedROI实际上是一副独立的图片.有效数据在内存中是连续的,所以输出的数据是对的。

ROI有个非常实用的功能,就是实现滑动窗口,下篇博客就来说说滑动窗口问题。

OpenCV中ROI相关推荐

  1. Opencv中的ROI介绍

    Opencv中的ROI介绍 (2013-03-27 13:36:26) 转载▼   分类: 模式识别         ROI(Region of Interest)是指图像中的一个矩形区域,可能你后续 ...

  2. OpenCV:将一幅图像复制到另一幅图像的指定区域中ROI

    用途: 使用一幅图像(或ROI)覆盖(替换)另一图像的指定区域,直接的方法是逐个像素进行复制,但这是一种效率很低的操作,下面介绍opencv中一种效率较高且简便的操作. 函数:roiImg.copyT ...

  3. 实战解惑 | OpenCV中如何提取不规则ROI区域

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 什么是ROI ROI是英文Region Of Interest的三 ...

  4. OpenCV中如何提取不规则ROI区域, 手眼标定hand_eye_calibration

    opencv提取ROI区域: 在做这个之前,首先来了解一下什么图像处理中的mask(遮罩),OpenCV中是如此定义Mask的:八位单通道的Mat对象,每个像素点值为零或者非零区域.当Mask对象添加 ...

  5. OpenCV 【一】—— OpenCV中数组指针、图像分块计算、指针取像素值与MatToEigen方法,内存对齐

    { Topic1: 高效开辟内存,使适用于大型数组.//开辟新数组,或者开辟新的0或者某一数值的数组/Mat或者Map直接使用memset //大数组操作效率较高 举例1:cv::Mat cv_ncc ...

  6. OpenCV中MeanShift算法视频移动对象分析

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 MeanShift算法 Mean Shift是一种聚类算法,在数据 ...

  7. OpenCV中图像显示你不知道的编程技巧

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 OpenCV 中最常用的一个API函数 imshow 各种编程与应 ...

  8. OpenCV中泛洪填充算法解析与应用

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:opencv学堂 泛洪填充(Flood Fill)很多时 ...

  9. 干货 | OpenCV中KLT光流跟踪原理详解与代码演示

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:opencv学堂 稀疏光流跟踪(KLT)详解 在视频移动 ...

  10. opencv的ROI操作

    在OpenCV中我们能够非常方便地获取指定ROI区域的子图像.如果你对图像设置了ROI,那么,Opencv的大多数函数只在该ROI区域内运算(只处理该ROI区域),如果没设ROI的话,就会出来整幅图像 ...

最新文章

  1. flower.php,flowerlist.php
  2. nmon 安装和使用
  3. CSS 选择器权重计算规则
  4. python判断是否为完全数_Python识别完美数
  5. java开源博客系统solo_15日开源软件更新,推荐JAVA博客系统 Solo
  6. 计算机应用技术与英语相关性,浅析计算机应用的技术专业的计算机专业英语的教学改进.doc...
  7. svn 合并分支 (svn操作手册)
  8. 不透明度16进制值对照表
  9. 【读书笔记】目标是什么
  10. 程序员幽默:当程序员当了爸爸
  11. 《C语言程序设计》江宝钏主编-习题6-2-排列数
  12. Couldnot load Project The file couldn‘t be opened
  13. 京东方GV185FHM-N10-DM30工业液晶屏 18.5寸全视角液晶屏
  14. BigDecimal 金额转换
  15. 精准鉴别初级、中级、高级程序员,你是哪一种?
  16. python编程计算器_Python设计实现的计算器功能完整实例
  17. java基础知识总结,javaweb参考资料大全
  18. 文房四宝用计算机取代的什么,现代文房四宝是哪些?
  19. python中subplot是什么意思_subplot(2,3,1)啥意思?
  20. java模拟抛硬币的结果

热门文章

  1. linux设置r镜像,一劳永逸,R的个性化默认配置
  2. (day 42 - 字符翻转 ) 剑指 Offer 58 - II. 左旋转字符串
  3. 阿里云centos 7下安装jdk
  4. python如何导入类里_Python中如何导入类示例详解
  5. 网上花店php语言添加信息,Laravel 添加多语言提示信息的方法
  6. 谷粒商城:04. 逆向工程完善微服务系统
  7. Javascript:js借助jQuery和fileSave将表格存储到world
  8. php httputils,Android 自定义网络加载工具类 HttpURLConnectionUtils
  9. SLAM_局部束调整(local Bundle Adjustment, BA)步骤与代码示例
  10. Ubuntu无法安装Xmind rpm包