在Python中学习OpenCV - ROI(region of interest)
一、核心原理
1.1 什么是ROI
ROI (Region of Interest) 即感兴趣区域,是图像中我们关注并需要单独处理的特定区域。在OpenCV中,ROI提取本质上是NumPy数组切片操作。
1.2 原理机制
- OpenCV读取的图像以NumPy数组形式存储,维度为
(height, width, channels) - 提取ROI通过数组切片
[y1:y2, x1:x2]实现 - 切片操作返回的是原图的引用(视图),而非副本,修改ROI会影响原图
二、基础操作步骤
步骤1:读取图像
python
import cv2
import numpy as np
# 读取图像
img = cv2.imread('image.jpg')
# 检查是否成功读取
if img is None:
print("图像读取失败")
步骤2:定义ROI坐标
python
# 定义矩形区域 (x, y, width, height)
x, y, w, h = 100, 100, 200, 150
步骤3:提取ROI
python
# 使用NumPy切片提取ROI
# 注意:OpenCV中坐标顺序是 [y:y+h, x:x+w]
roi = img[y:y+h, x:x+w]
三、代码示例
3.1 基础矩形ROI提取
python
import cv2
import numpy as np
#读取图片
img = cv2.imread("roi.jpg")
if img is None:
print("图片读取失败,请检查图片路径")
exit()
#2.转换为HSV颜色空间(更适合颜色分割)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 3.定义黄色足球的HSV范围
lower_yellow = np.array([20,100,100])
upper_yellow = np.array([40,255,255])
#4.生成掩码(只保留黄色区域)
mask = cv2.inRange(hsv,lower_yellow,upper_yellow)
# 5.形态学操作(去除噪点)
kernel = np.ones((5,5),np.uint8)
#高级形态学操作
mask = cv2.morphologyEx(mask,cv2.MORPH_CLOSE,kernel)
mask = cv2.morphologyEx(mask,cv2.MORPH_OPEN,kernel)
# 6.查找轮廓
contour,_ = cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
#7.筛选足球轮廓
football_roi = []
for cnt in contour:
area = cv2.contourArea(cnt)
if area > 200: #过滤小噪点
x,y,w,h = cv2.boundingRect(cnt)
if 0.8 < w/h < 1.2:
football_roi.append((x,y,w,h))
# 在原图上画出ROI矩形
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
#8.提取每个足球的ROI区域
for i ,(x,y,w,h) in enumerate(football_roi):
roi = img[y:y+h,x:x+w] #截取ROI
cv2.imshow(f"Football Roi {i+1}",roi)
cv2.imwrite(f"Football_{i + 1}.jpg", roi) # 保存ROI图片
#9.显示结果
cv2.imshow("Original Image with ROI",img)
cv2.imshow("Mask",mask)
cv2.waitKey(0)
cv2.destroyAllWindows()
代码运行效果:

3.2 交互式ROI选择(鼠标操作)
python
import cv2
import numpy as np
class ROISelector:
def __init__(self):
self.start_point = None
self.end_point = None
self.drawing = False
self.img = None
self.img_copy = None
def mouse_callback(self, event, x, y, flags, param):
"""鼠标回调函数"""
if event == cv2.EVENT_LBUTTONDOWN:
# 按下左键,开始绘制
self.drawing = True
self.start_point = (x, y)
self.img_copy = self.img.copy()
elif event == cv2.EVENT_MOUSEMOVE and self.drawing:
# 鼠标移动,实时绘制矩形
temp_img = self.img_copy.copy()
cv2.rectangle(temp_img, self.start_point, (x, y), (0, 255, 0), 2)
cv2.imshow('Select ROI', temp_img)
elif event == cv2.EVENT_LBUTTONUP:
# 释放左键,结束绘制
self.drawing = False
self.end_point = (x, y)
# 计算ROI坐标(确保左上角和右下角正确)
x1, y1 = self.start_point
x2, y2 = self.end_point
# 标准化坐标
x_min, x_max = min(x1, x2), max(x1, x2)
y_min, y_max = min(y1, y2), max(y1, y2)
# 提取并显示ROI
roi = self.img[y_min:y_max, x_min:x_max]
if roi.size > 0:
cv2.imshow('Selected ROI', roi)
cv2.imwrite('saved_roi.jpg', roi)
print(f"ROI已保存: 位置({x_min},{y_min}), 尺寸({x_max - x_min},{y_max - y_min})")
def run(self, image_path=None):
"""运行ROI选择器"""
if image_path:
self.img = cv2.imread(image_path)
else:
# 创建测试图像
self.img = np.random.randint(0, 255, (600, 800, 3), dtype=np.uint8)
cv2.namedWindow('Select ROI')
cv2.setMouseCallback('Select ROI', self.mouse_callback)
print("操作说明:")
print("- 按住左键拖动选择ROI区域")
print("- 按 'q' 退出程序")
print("- 按 'r' 重置图像")
while True:
cv2.imshow('Select ROI', self.img)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
elif key == ord('r'):
self.img = cv2.imread(image_path) if image_path else \
np.random.randint(0, 255, (600, 800, 3), dtype=np.uint8)
cv2.destroyAllWindows()
# 使用示例
selector = ROISelector()
selector.run("roi.jpg") # 或 selector.run('your_image.jpg')
代码运行效果:

好了,关于OpenCV中ROI的简单介绍就到这里了。