在 OpenCV 中,ROI 是 Region of Interest(感兴趣区域)的缩写。

简单来说,ROI 就是从图像中切出来的“一块”。在处理图像时,我们往往不需要处理整张图片(比如处理人脸时不需要管背景里的树),通过提取 ROI,我们可以只关注重点区域,从而大幅提升处理速度和算法精度。

结合最新的 OpenCV 开发实践,我为你整理了 ROI 的核心操作指南:

📐 基础操作:矩形 ROI

这是最常用、最高效的方式。在 Python 中,OpenCV 图像本质上是 NumPy 数组,因此我们直接使用数组切片来提取 ROI。

关键口诀:先行后列,即 [y, x] 或 [高, 宽]

python

import cv2

# 1. 读取图像
img = cv2.imread('example.jpg')

# 2. 提取 ROI
# 语法:img[y1:y2, x1:x2]
# 含义:从第 y1 行到 y2 行,从第 x1 列到 x2 列
roi = img[100:300, 200:400]  # 提取坐标 (200,100) 到 (400,300) 的矩形区域

# 3. 显示 ROI
cv2.imshow('ROI', roi)
cv2.waitKey(0)

常见应用场景:

  • 复制粘贴:将 ROI 复制到图像的其他位置(如 img[500:700, 200:400] = roi)。
  • 局部处理:只对 ROI 进行模糊、边缘检测等操作,节省计算资源。

🎭 进阶操作:不规则 ROI (圆形、多边形)

如果你想提取圆形、椭圆或任意多边形区域,简单的切片就不够用了。这时需要用到 Mask(掩膜) 技术。

核心逻辑: 创建一个与原图同尺寸的“黑白图”(Mask),白色代表保留,黑色代表舍弃,然后通过按位与运算提取。

python

import cv2
import numpy as np

img = cv2.imread('example.jpg')
h, w = img.shape[:2]

# --- 场景 A:圆形 ROI ---
# 1. 创建全黑 Mask
mask = np.zeros((h, w), dtype=np.uint8)
# 2. 在 Mask 上画一个白色的圆
cv2.circle(mask, (w//2, h//2), 100, (255), -1) # 圆心在中间,半径100
# 3. 提取 ROI
circular_roi = cv2.bitwise_and(img, img, mask=mask)

# --- 场景 B:多边形 ROI (任意形状) ---
# 1. 创建全黑 Mask
mask_poly = np.zeros((h, w), dtype=np.uint8)
# 2. 定义多边形顶点
pts = np.array([[100,100], [200,100], [200,200], [100,250]], np.int32)
pts = pts.reshape((-1, 1, 2))
# 3. 填充白色多边形
cv2.fillPoly(mask_poly, [pts], (255))
# 4. 提取 ROI
poly_roi = cv2.bitwise_and(img, img, mask=mask_poly)

cv2.imshow('Circular ROI', circular_roi)
cv2.imshow('Polygon ROI', poly_roi)
cv2.waitKey(0)

🖱️ 交互式选择 ROI

如果你在写调试工具,不想每次都手动去量坐标,可以使用 OpenCV 自带的交互函数。

  • cv2.selectROI:弹出一个窗口,让你用鼠标框选区域,返回 (x, y, w, h)

python

img = cv2.imread('example.jpg')
# 按下空格键确认选择,按 ESC 取消
x, y, w, h = cv2.selectROI("Select ROI", img, False)

# 根据返回值裁剪
roi = img[y:y+h, x:x+w]
cv2.imshow("Selected ROI", roi)
cv2.waitKey(0)

⚡ 为什么要用 ROI?(性能对比)

使用 ROI 不仅仅是为了裁剪图片,更是为了性能优化。在视频处理或高分辨率图像分析中,差异巨大。

假设我们要对一张 1920×1080 的图片做高斯模糊:

表格

处理方式 处理区域大小 耗时 (估算) 说明
全图处理 1920 × 1080 ~450ms 计算量大,浪费资源处理背景
ROI 处理 200 × 200 ~30ms 速度提升 90% 以上,只算核心区域

💡 避坑指南

  1. 坐标顺序:再次强调,NumPy 切片是 img[y:y+h, x:x+w],也就是 img[行范围, 列范围]。很多初学者写成 img[x, y] 会导致报错或截取到错误的长条区域。
  2. 越界问题:切片的坐标不能超出图像的实际宽高,否则会报错 IndexError
  3. 引用与拷贝
    • roi = img[0:100, 0:100] 得到的是视图(引用),修改 roi 会直接改变原图 img
    • 如果你希望修改 ROI 而不影响原图,必须使用 .copy(),例如 roi = img[0:100, 0:100].copy()

掌握 ROI 是 OpenCV 入门的第一步,也是从“处理整图”进阶到“精准视觉分析”的关键。

Logo

更多推荐