在图像处理的过程中,我们往往只对图像中的某个区域感兴趣,那么可以定义一个矩形Rect或指定感兴趣的行列范围(Range),这个就是感兴趣区域(简称ROI)。
一、矩形ROI
定义矩形ROI需要用到OpenCV中的Rect类型。Rect表示一个矩形,最基础的4个参数分别是(x,y,width,height),其中,x、y表示矩形的左上角坐标,width和height分别表示矩形的宽和高。因为矩形是一个二维平面,除了有宽和高,必须得注明矩形在某个图像中的坐标位置。另外,x、y、width、height都是int类型。
假如,图像的宽和高分别是500像素和300像素,要在这张图中定义一个感兴趣区域,那么,ROI的宽和高就不能超过500像素和300像素。当然,如果ROI的宽和高都等于0,那也没有意义。
Rect其实是Rect2i的别称。Rect2i是Rect_<int>类型,类似的还有Rect_<float>(别名为Rect2f),Rect_<double>(别名是Rect2d),由此可见,Rect_是一个模板类,类似C#中的泛型类。
观察下面代码
#include<opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
Mat girl = imread("images/girl.jpg", IMREAD_COLOR);//3通道(CV_8UC3)
if (girl.empty()) {
return 0;
}
imshow("girl", girl);//显示原图像
Rect rect(0, 0, girl.cols/2, girl.rows/2);
Mat photo = girl(rect);
//转为伪灰度
photo.forEach<Vec3b>([](Vec3b& pixel, const int* /*position*/) {
uchar gray = 0.299 * pixel[2] + 0.587 * pixel[1] + 0.114 * pixel[0];
pixel[0] = pixel[1] = pixel[2] = gray;
});
imshow("photo", photo);//显示ROI图像
imwrite("photo.jpg", photo);
imshow("girl2", girl);//显示原图像
imwrite("girl.jpg", girl);
waitKey(0);//等待按键
return 0;
}
在代码中,首先加载一张3通道8位图并显示,其原图的效果如下所示

Rect rect(0, 0, girl.cols/2, girl.rows/2);表示定义一个矩形,矩形左上角坐标为(0,0),矩形宽和高均为图像宽高的一半,那么这个矩形的面积等于图像的1/4。
Mat photo = girl(rect);表示以这个矩形从原图中获取一个ROI图像,注意,此时,photo和girl的图像数据共享内存,只不过,photo所能遍历的图像数据为原图的1/4。
接着将photo里面的图像数据转为伪灰度,最后分别显示photo和girl。最终效果如下两张图所示。


结论,虽然我们只是将ROI图像的彩色3通道转换为伪灰度,但是,原图左上角的1/4也同时被修改了。如果希望在修改ROI图像时,不影响原图。那么可以采用深拷贝技术,即:
Mat photo = girl(rect).clone();
二、感兴趣行列ROI
另一种定义ROI区域的方式是使用OpenCV提供Range,它有两个关键参数,分别是start和end,表示开始和结束的索引。下面是它的使用方式,同样可以达到上面的效果。
Mat photo = girl(Range(0, girl.rows/2), Range(0, girl.cols/2));
在这句代码中,一共定义了2个Range,前者表示从0行到图像行数的1/2,后者表示从0列到图像列数的1/2。
——重庆教主 2025年5月14日
若文章对您有帮助,可以激励一下我哦,祝您平安幸福!
微信 | 支付宝 |
---|---|
![]() |
![]() |