Bootstrap

Opencv 如何获取roi区域

关于图片处理,经常遇到的一个问题是如何获取roi区域(说白了就是抠图),并对roi区域赋值,比如说赋值成黑色。

首先,关于如何获取roi区域,opencv的Mat类中提供了两种方法。代码如下:

Mat 	operator() (Range rowRange, Range colRange) const 
 
Mat 	operator() (const Rect &roi) const

上述两种获取roi的方式是通过重载()运算符实现的,根据上面的描述可以看到通过上面两种方法仅可以实现矩形roi区域的获取。使用实例如下:

Mat img = imread("...."); //加载图片到img中
//subImg就是从图像img中截取的Roi区域,该区域的大小就是指定的矩形的大小
Mat subImg = img(Range(30,100), Range(50,150));


//方法二
Mat img1 = img(Rect(50,50.100.100)); //通过Rect的方式截取Roi区域

上面的两中方法均可以实现矩形ROI区域的截取,截取的结果可以在IMAGE WATCH中查看。

思考:除了矩形的ROI,是否存在非矩形ROI区域的截取?答案是肯定的,那我们如何在一个图片任意的获取ROI区域呢?通常来说我们采用的就是通过mask(掩膜)的方式来实现,Mat提供了setto和copyto的接口,其中setto方法是浅拷贝,而copyto是深拷贝。以setto举例来说。如果我们想在原图上截取一个任意多边形的ROI区域?我们首先要创建一个MASK,该mask的大小必须与操作图像的size保持一致,否则mask是无效的。然后通过图像的基本绘制方法(circle/rectangle/ellipse/polylines/fillpoly/drawContours)绘制基本图形,并将绘制的图形进行填充(注意一定要填充为非0值,这与掩膜的原理有关系,只有mask掩膜的值非0的区域才会进行操作,以setto为例,第二个参数就是mask,mask中非0的位置才会将第一个参数的值付给对应位置的像素)。mask(掩膜)制作完成后,一定调用setto方法对原图像进行赋值处理。结果就是原图像mask中非0区域的值已经设置为对应的值。代码如下:

Mat img = imread("...."); //加载图片到img中
Mat mask = img(Size(img.cols,img.rows),CV_32FC1); //创建掩膜,该掩膜的大小与img一致
circle(mask, Point(50,50),50,Scalar(1));  //画一个圆需要指定圆心坐标和半径
img.setTo(0, mask);  //将mask非0的区域对应的图像设置为黑色
img.setTo(Vec3b(23, 23, 23),mask);  //设置三通道数据

copyto方法的使用同理,只不过一个修改的原图像,一个是修改的新图像,需要注意的是调用copyTo方法生成的图片的大小还是与原图像一致的,虽然仅仅显示了ROI区域的内容。

再进一步的思考:我们是否可以灵活的指定ROI区域呢?

答案同样是肯定,举一个例子,我们可以通过鼠标事件来获取感兴趣区域的坐标然后进行“抠图”操作,方法还是一样的。

;