在Python中学习OpenCV - ROI(region of interest)

在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的简单介绍就到这里了。

相关推荐
T0uken2 小时前
【Python】docxnote:优雅的 Word 批注
开发语言·python·word
B站计算机毕业设计之家2 小时前
计算机毕业设计源码:Python图书数据智能采集与可视化大屏 当当网 Django框架 爬虫 Pandas 可视化 大数据 大模型 书籍(建议收藏)✅
爬虫·python·机器学习·信息可视化·django·pandas·课程设计
维度攻城狮2 小时前
AI 工具加持:ComfyUI 节点开发极速上手
人工智能·python·comfyui·工作流·节点图
Shine_1804182 小时前
ClaudeCode启动报错
python
桃气媛媛2 小时前
python推导式
python
福运常在2 小时前
股票数据API(14)股票近年增发数据
java·python·maven
Zhansiqi10 小时前
day42部分题目
python
小王不爱笑13210 小时前
IO 模型
开发语言·python
kishu_iOS&AI10 小时前
Conda 简要说明与常用指令
python·安全·conda