OpenCV定义感兴趣区域

204 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情

前言

在有些情况下,图像处理函数只需要应用于图像的一部分。OpenCV 中使用了一种优雅而简单的机制来定义图像中的子区域并将其作为常规图像进行操作。本节中,我们将学习如何定义图像内的感兴趣区域 (region of interest, ROI)。

 

定义感兴趣区域

假设我们想将一个小图像复制到一个更大的图像上。例如,假设我们要将 OpenCV logo 插入到测试图像中。

为了完成该目标,需要定义可以应用复制操作的 ROIROI 的位置将决定 logo 在图像中的插入位置。

首先,读取 logo 图像并定义 ROI。我们可以使用 Rect 来定义 ROI

// 读取 logo
cv::Mat logo=  cv::imread("logo.png");
cv::Rect myRoi = cv::Rect(image.cols-log.cols,image.rows-logo.rows, logo.cols, logo.rows);

定义了 ROI 之后,我们可以创建一个新的 mat,将 ROI 应用到这个新的 mat 上,它可以作为常规的 cv::Mat 实例进行操作。ROI 是一个 cv::Mat 对象,它指向与其父图像相同的数据缓冲区,并具有指定 ROI 坐标的标头。插入 logo 的方式如下:

// 定义图像感兴趣区域位于图像右下角
cv::Mat imageROI(image, myRoi);
// 插入 logo
logo.copyTo(imageROI)

在以上代码中,image 是目标图像,logologo 图像,编译并执行代码可以得到以下结果:

F7.png

定义 ROI 的一种方法是使用 cv::Rect 实例,它通过指定左上角的位置(构造函数的前两个参数)和矩形的大小(即宽度和高度,使用后两个参数指定)来描述一个矩形区域。在示例代码中,我们使用图像的大小和 logo 大小令 logo 覆盖图像右下角的位置。需要注意的是,ROI 应该始终完全处于父图像内。

ROI 也可以使用行和列范围来描述,范围是从开始索引到结束索引(不包括两者)的连续序列,cv::Range 结构可以用于表示这个概念。因此,可以使用两个范围定义 ROI,在以上示例中的 ROI 也可以等效地定义如下:

// 也可以使用 cv::Range 定义感兴趣区域
imageROI= image(cv::Range(image.rows-logo.rows,image.rows),
                cv::Range(image.cols-logo.cols,image.cols));

在以上代码中,cv ::Matoperator() 函数返回另一个 cv::Mat 实例,然后可以在后续调用中使用该实例。ROI 的任何变换都会影响相应区域的原始图像,因为图像和 ROI 共享相同的图像数据。由于 ROI 的定义不需要数据的复制,因此无论 ROI 的大小如何,它都会在恒定的时间内执行。

如果要定义由图像的某些行组成的 ROI,可以使用以下代码:

cv::Mat imageROI = image.rowRange(start, end);

同样,对于由某些图像列组成的 ROI,可以使用以下代码:

cv::Mat imageROI = image.colRange(start, end);