在OpenCV中,普遍支持ROI和widthStep,函数的操作被限制于感兴趣的区域,要设置或者取消ROI,就要使用cvSetImageROI()和cvResetImage()函数.如过想设置ROI,可以使用函数cvSetImageROI(),并为其传递一个图像指针和矩形.而取消ROI,只需要为函数cvResetImageROI()传递一个图像指针
void cvSetImageROI( IplImage* image, CvRect rect );
void cvResetImageROI( IplImage* image );
如例3.12,读取一幅图像,并设置了想要的ROI的x,y,width,和height的值,最后将ROI区域都加上了一个整数,本例程中,通过内联的cvRrect()构造函数设置ROI.通过cvResetIMageROI()函数释放ROI是非常重要的,否则将忠实的显示ROI区域
plaincopy
- //例3.12 用imageROI来增加某范围的像素
- #include "stdafx.h"
- #include <cv.h>
- #include <highgui.h>
- int _tmain(int argc, _TCHAR* argv[])
- {
- IplImage* src;
- src = cvLoadImage("C:/Users/Administrator/Desktop/lena.bmp");
- if (src != nullptr)
- {
- int x = 20;
- int y = 20;
- int width = 150;
- int height = 150;
- int add = 150;
- cvSetImageROI(src,cvRect(x,y,width,height));
- cvAddS(src,cvScalar(add),src);
- cvResetImageROI(src);
- cvNamedWindow("ROI_add",1);
- cvShowImage("ROI_add",src);
- cvWaitKey();
- }
- return 0;
- }
通过巧妙地使用widthStep,我们可以打到同样的效果.要做到这一点,我们创建了另一个图像头,让他的width和height的值等于interest_rect的width和height的值.我们还需要按interest_rect 起点设置图像起点(左上角或者左下角),下一步,设置子图像的widthStep与较大的interest_img相同.这样,即可在子图像中逐步步进到大图像里子区域中下一行开始处的合适位置.最后设置子图像的imageData指针指向兴趣子区域的开始,如下例所示
plaincopy
- IplImage *interest_img;
- CvRect interest_rect;
- IplImage* sub_img = cvCreateImageHeader(cvSize(interest_rect.width,interest_rect.height),
- interest_img->depth,interest_img->nChannels);
- sub_img->origin = interest_img->origin;
- sub_img->widthStep = interest_img->widthStep;
- sub_img->imageData = interest_img->imageData +
- interest_rect.y * interest_img->widthStep +
- interest_rect.x * interest_img->nChannels;
- cvAddS(sub_img,cvScalar(1),sub_img);
- cvReleaseImageHeader(&sub_img);
看起来设置和重置ROI更方便一些,为什么还要使用widthStep? 原因是有些时候在处理的过程中,想在操作过程中设置和保持一副图像的多个子区域处于活动状态,但是ROI只能串行处理并且必须不断的设置和重置.
掩码和模版, 在代码示例中cvAddS()函数允许第四个参数默认值为空:const CvArr* mask = NULL.这是一个8位单通道数组,它允许把操作限制到任意形状的非0像素和掩码区,如果ROI随着掩码或者模版变化,进程将会被限制在ROI和掩码的交集区域.掩码或者模版只能在指定了其图像的函数中使用.