如何使用C++在OpenCV中使用感兴趣区域「ROI」?

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功能轻松实现。

后端开发标签