1. 什么是感兴趣区域ROI
在OpenCV中,感兴趣区域(ROI)是指在一副图像中,选择一个区域(子图像)进行操作的方法。这个ROI可以指定图像任何部分,比如图像的某个特定区域,也可以是整个图像本身。在使用OpenCV进行图像处理时,ROI十分常见,它在图像裁剪、图像放大缩小、特征提取等方面有着广泛的应用。
1.1 ROI的选择方法
选择ROI的方法有很多,其中比较常用的有两种:矩形框选和手工指定。使用矩形框选方法可以用命令:
Rect roi(x, y, w, h); //定义感兴趣的区域
Mat subImg = srcImg(roi); //获取感兴趣区域的图像
上述方法定义了一个矩形的感兴趣区域,其左上角坐标为(x,y),宽度为w,高度为h。使用Mat类的括号运算符可以获取到感兴趣区域对应的图像子矩阵对象。
手工指定ROI可以使用OpenCV提供的图形界面,比如cv::selectROI方法:
cv::Mat img = imread("lena.jpg");
Rect roi = cv::selectROI(img); //手工选定ROI所在的矩形
cv::Mat subImg = img(roi); //获取感兴趣区域的图像
实际上,在标准的OpenCV库中有一个名为"ROI"的头文件,其目的就是为了支持在图像中处理指定的感兴趣区域。要使用ROI功能,必须在使用相关函数之前调用
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/video/video.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/flann/flann.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/ml/ml.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/stitching/stitcher.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/tracking/tracking.hpp"
#include "opencv2/videoio/videoio.hpp"
#include "opencv2/optflow.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/core/hal/interface.h"
#include "opencv2/imgproc/types_c.h"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/video/tracking_c.h"
#include "opencv2/video/background_segm.hpp"
#include "opencv2/aruco.hpp"
#include "opencv2/bgsegm.hpp"
#include "opencv2/ccalib.hpp"
#include "opencv2/cudaobjdetect.hpp"
#include "opencv2/cudabgsegm.hpp"
#include "opencv2/cudafeatures2d.hpp"
#include "opencv2/cudafilters.hpp"
#include "opencv2/cudaimgproc.hpp"
#include "opencv2/cudalegacy.hpp"
#include "opencv2/cudaarithm.hpp"
#include "opencv2/cudacodec.hpp"
#include "opencv2/cudastereo.hpp"
#include "opencv2/cudawarping.hpp"
#include "opencv2/cudacodec.hpp"
#include "opencv2/xfeatures2d.hpp"
#include "opencv2/ximgproc.hpp"
#include "opencv2/xobjdetect.hpp"
#include "opencv2/xphoto.hpp"
using namespace cv;
int main(int argc, char* argv[])
{
Mat srcImage, dstImage;
srcImage = imread("lena.jpg", 1);
imshow("原图像", srcImage);
waitKey(0);
Rect rect(0, 0, 300, 300); // 矩形ROI,矩形左上角横坐标、纵坐标、宽度、高度
Mat roi = Mat(srcImage, rect); // 待裁剪图像
dstImage = Mat::zeros(roi.rows, roi.cols, roi.type()); //初始化,定义原图像左上角为矩形ROI的图像像素变量
roi.copyTo(dstImage); //图像复制,将roi区域的像素复制给dstImage
imshow("裁剪后的图像", dstImage);
waitKey(0);
return 0;
}
使用ROI功能时,可是通过直接设定感兴趣区域矩形ROI的方式实现。如通过创建一个裁剪后的Mat类型的变量,获取原图像上的某个范围区间。接下来,通过复制ROI区域的方式来得到裁剪后的图像。
2. OpenCV处理感兴趣的区域ROI
在OpenCV中,可以通过一个矩形框来定义感兴趣的区域,然后将ROI区域上的处理应用到整幅图像上。
2.1 绘制矩形框
在图像上选取矩形框提取ROI时,需要用矩形框将感兴趣区域框出来,再进行相关处理。比如,在图像上画出一个矩形框,选中区域作为ROI,可以使用cv::rectangle()函数来实现。
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("pic6.tif");
Mat img = src.clone();
//draw the rectangle around the object of interest
Rect r(950, 550, 1700, 1100); //selected ROI
rectangle(img, r, Scalar(0, 0, 255), 5); //draw rectangle and color
imshow("Image", img);
waitKey(0);
return 0;
}
这段代码使用了imread()读取一张图像,然后克隆了它,保留了原始图像的副本。接着,使用cv::rectangle()函数绘制一个矩形框。cv::rectangle()函数有四个参数:被绘制图像的引用、矩形框Rectangle、颜色、线条的宽度。
2.2 应用处理到感兴趣的区域
在提取出ROI之后,可以将任何处理应用到这个子区域内。一些常见的例子包括:
旋转感兴趣区域
应用基本滤波器
显著性区域检测
图像分割
比如,对一个ROI进行灰度化的处理,可以使用以下代码:
Mat img = imread("lena.jpg", CV_LOAD_IMAGE_UNCHANGED);
Rect roi(10, 10, 100, 100);
Mat roiImg = img(roi);
Mat grayImg;
cvtColor(roiImg, grayImg, CV_RGB2GRAY);
imshow("gray", grayImg);
waitKey(0);
代码通过imread()函数读取一张图像。然后通过定义矩形选择感兴趣区域。接着,用Mat类的括号运算符可以获取到感兴趣区域对应的图像子矩阵对象。通过cvtColor()函数可以将ROI区域的图像转化成灰色图像。
2.3 在感兴趣的区域上绘制文本
有时想在感兴趣的区域上显示文本,可以先使用cv::putText()将文本写入Mat对象中,然后利用ROi功能将文本图像的部分合并到原始图像中。
下面的代码展示如何将文本添加到给定的ROI中:
Mat img = imread("lena.jpg");
Rect roi(30,50,200,100);
Mat roiImg = img(roi);
putText(roiImg, "Hello,I am ROI area!",Point(50,50), FONT_HERSHEY_SCRIPT_SIMPLEX,1,Scalar(0,255,0),4);
imshow("src",img);
waitKey(0);
代码通过imread()函数读取一张图像,然后通过定义矩形选择感兴趣区域。接着,用Mat类的括号运算符可以获取到感兴趣区域对应的图像子矩阵对象。使用cv::putText()函数可以在感兴趣区域的图像上绘制文本。
3. 综合示例:图像模糊处理
作为一个综合性的例子,我们来介绍如何在感兴趣区域上应用图像模糊处理。
3.1 图像模糊
图像模糊是一种常用的用于去除图像噪声和保护隐私的技术。在OpenCV中,使用函数cv::blur()对图像进行模糊处理。cv::blur()函数有四个参数,分别是:输入图像、输出图像、内核尺寸、内核形状。这里,我们主要关注内核尺寸和内核形状。在图像处理中,内核就是一幅图像的子集,通常用于对像素周围的区域进行计算。内核尺寸应该是奇数。
下面是cv::blur()函数的使用示例:
Mat img = imread("lena.jpg");
Mat dst1, dst2, dst3;
blur(img, dst1, Size(3, 3), Point(-1, -1)); // 矩形框内部分均值滤波,周边透明
blur(img, dst2, Size(3, 3), Point(-1, -1), BORDER_DEFAULT); // 不透明,边缘像素执行borderType类型的边界归一化
blur(img, dst3, Size(3, 3), Point(-1, -1),BORDER_ISOLATED); // 不透明,边缘像素自身复制扩展到边界的像素处
imshow("src", img);
imshow("dst1", dst1);
imshow("dst2", dst2);
imshow("dst3", dst3);
waitKey(0);
在这段代码中,函数blui()首先读取一幅图像,然后使用cv::blur()函数进行模糊处理。这里使用了多个函数调用来演示三个不同内核形状的算法,其中矩形框内部分均值滤波、周边透明,不透明下常用的方式选用BORDER_DEFAULT做为边界归一化方式,BORDER_ISOLATED起到透明放大的功能。
3.2 在感兴趣的区域上使用图像模糊
在感兴趣的区域上应用图像模糊,可以使用Mat类中的ROI功能。下面是一个利用ROI对图像进行均值滤波处理的示例:
Mat img = imread("lena.jpg");
Rect roi(10,10,100,100);
Mat roiImg = img(roi);
blur(roiImg, roiImg, Size(5,5));
imshow("src",img);
imshow("ROI",roiImg);
waitKey(0);
在这个例子,在图像中选择一个矩形ROI,使用Mat类中的括号运算符,得到一个感兴趣区域。接着,调用cv::blur()函数将实现均值滤波处理,改变ROI图像的一部分。最后,使用imshow()函数将源图像和修改的ROI区域显示出来。
4. 总结
本文通过例子的方式来介绍了如何使用OpenCV中的ROI功能。这些例子包括如何选择图像的感兴趣区域、如何应用处理到感兴趣的区域、如何使用ROI功能绘制文本等。如果在开发过程中用到感兴趣区域选取,可以通过OpenCV的ROI功能轻松实现。