OpenCV图像裁剪与 ROI 操作

发布于:2025-08-11 ⋅ 阅读:(17) ⋅ 点赞:(0)

    在图像处理领域,ROI(Region of Interest)区域感兴趣操作是非常基础而重要的一环。无论是进行目标检测、图像分割,还是简单的图像处理,都离不开对图像某一区域的选取与处理。本文将结合 OpenCV 的 C++ 接口,详细介绍如何实现图像的裁剪与 ROI 操作。

    ROI(Region of Interest)表示“感兴趣区域”,是图像中你想要单独处理的一部分。例如,一张 1920×1080 的图像中,我们只想处理中间 300×300 的区域,这个区域就称为 ROI。在 OpenCV 中,ROI 通常通过设置图像的矩形区域来实现。

 

设置 ROI 区域并裁剪图像

// 定义一个矩形区域 ROI,位置(100, 100),大小(200×150)
cv::Rect roi(100, 100, 200, 150);

// 使用 ROI 对图像进行裁剪
cv::Mat cropped = img(roi);

cv::imshow("裁剪后的图像", cropped);
    

    以上代码实现了从大图像(img)中提取一个局部区域(ROI)图像cropped。

  • cv::Rect(x, y, width, height) 表示从 (x, y) 点开始,宽为 width,高为 height。
  • img(roi) 返回的是对原始图像的一块“视图”,不复制数据,我们称作为浅拷贝。

ROI 的复制与修改

因为 ROI 是视图,所以对其修改会影响原图。如果你不想修改原图,应当使用 .clone() 方法。

// clone 后成为一块新内存区域
cv::Mat roi_copy = cropped.clone();

// 在 ROI 上画一个绿色矩形
cv::rectangle(cropped, cv::Point(0, 0), cv::Point(199, 149), cv::Scalar(0, 255, 0), 2);

cv::imshow("在 ROI 上画矩形(影响原图)", img);
cv::imshow("ROI 拷贝(不受影响)", roi_copy);
    

以上代码中,clone函数返回新的内存数据区域,因此称作深拷贝。我们在cropped上绘制一个矩形区域,由于cropped是img的浅拷贝,img数据上同样也会绘制一个矩形。

 

用 ROI 做遮罩处理

// 创建一个遮罩
cv::Mat mask = cv::Mat::zeros(img.size(), CV_8UC1);
mask(roi).setTo(255);  // 设置 ROI 区域为白色

// 提取 ROI 区域内容
cv::Mat result;
img.copyTo(result, mask);  // 使用遮罩复制内容

cv::imshow("遮罩提取 ROI", result);
    

以上代码生成了一个mask遮罩,对于mask矩阵中的非零区域被视作有效区域,因此函数copyTo仅拷贝mask中非零区域所对应的img像素。

 

在 ROI 上应用图像处理(如模糊)

cv::Mat blurred;
cv::GaussianBlur(img(roi), blurred, cv::Size(15, 15), 0);

// 将模糊图像复制回原图对应 ROI
blurred.copyTo(img(roi));

cv::imshow("对 ROI 模糊处理后的图像", img);
    

在OpenCV中,很多函数可以传入一个ROI区域。因此我们在对图像局部区域进行操作时,可以不需要重新生成新的局部图像即可完成。但是注意一些特殊的函数可能不支持ROI区域操作,如cv::Mat::reshape(),cv::medianBlur()等。

 

完整代码

int main() {

	cv::Mat img = cv::imread("lena.png");
	if (img.empty()) {
		std::cerr << "无法读取图像!" << std::endl;
		return -1;
	}

	// 定义 ROI 区域,这是一个200*150的区域,左上角坐标为(100,100)
	// cropped定义了一个 ROI 矩阵,但和img使用相同的数据区域
	cv::Rect roi(100, 100, 200, 150);
	cv::Mat cropped = img(roi);
	cv::imwrite("1_cropped.png", cropped);

	// 在 ROI 上画框
	cv::rectangle(cropped, cv::Point(0, 0), cv::Point(199, 149), cv::Scalar(0, 255, 0), 2);
	cv::imwrite("2_rect.png", cropped);

	// ROI 的拷贝
	// 使用cv::Mat::clone函数进行深拷贝,roi_copy有单独的数据内存
	cv::Mat roi_copy = cropped.clone();
	cv::imwrite("3_roi_copy.png", roi_copy);

	// 遮罩提取
	// 生成一个mask遮罩,在roi区域内为255,其他区域为0
	cv::Mat mask = cv::Mat::zeros(img.size(), CV_8UC1);
	mask(roi).setTo(255);
	cv::imwrite("4_mask.png", mask);

	// 使用mask遮罩拷贝数据,此时仅将img图像中mask遮罩对应的数据拷贝到result中
	// 注意:copyTo也是深拷贝,并且该函数支持mask操作
	cv::Mat result;
	img.copyTo(result, mask);
	cv::imwrite("5_result.png", result);

	// 仅对 ROI 模糊处理
	// OpenCV中大多数函数支持基于ROI的操作,但有部分函数确不支持(需要特别留意)
	cv::Mat blurred;
	cv::blur(img(roi), blurred, cv::Size(15, 15));
	cv::imwrite("6_blurred.png", blurred);


	// 将模糊后图像拷贝到原图指定 ROI 上,copyTo支持 ROI 输入
	blurred.copyTo(img(roi));
	cv::imwrite("7_img.png", img);

	return 0;
}

对局部区域进行平滑操作

 


网站公告

今日签到

点亮在社区的每一天
去签到