You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python OpenCV绘制自定义ROI并生成二进制掩码?

实现自由绘制ROI并生成二进制掩码(类似Matlab drawfreehand + createMask)

解决思路

  • 通过OpenCV的鼠标回调函数捕捉交互事件,记录自由绘制的坐标点序列
  • 绘制完成后,以记录的坐标点为轮廓,在空白画布上填充生成二进制掩码
  • 支持掩码保存、绘制重置、叠加效果预览等功能

完整代码实现

import cv2
import numpy as np

# 全局变量,控制绘制状态与坐标点
drawing = False
points = []
img = None
img_copy = None

def draw_freehand(event, x, y, flags, param):
    """鼠标回调函数,处理绘制逻辑"""
    global drawing, points, img
    if event == cv2.EVENT_LBUTTONDOWN:
        # 按下左键开始绘制,初始化点列表
        drawing = True
        points = [(x, y)]
    elif event == cv2.EVENT_MOUSEMOVE and drawing:
        # 拖动鼠标时记录点并绘制连线
        points.append((x, y))
        cv2.line(img, points[-2], points[-1], (0, 255, 0), 2)
    elif event == cv2.EVENT_LBUTTONUP:
        # 释放左键结束绘制,闭合最后一段线
        drawing = False
        points.append((x, y))
        cv2.line(img, points[-2], points[-1], (0, 255, 0), 2)

if __name__ == "__main__":
    # 替换为你的图像路径
    img_path = "your_image.jpg"
    img = cv2.imread(img_path)
    if img is None:
        print("无法读取图像,请检查路径是否正确")
        exit()
    img_copy = img.copy()

    cv2.namedWindow("Draw ROI")
    cv2.setMouseCallback("Draw ROI", draw_freehand)

    print("操作说明:")
    print("- 按住鼠标左键拖动绘制ROI")
    print("- 按s键保存掩码并显示掩码、叠加效果")
    print("- 按r键重置绘制")
    print("- 按q键退出程序")

    while True:
        cv2.imshow("Draw ROI", img)
        key = cv2.waitKey(1) & 0xFF
        
        if key == ord('s'):
            if len(points) > 2:
                # 创建与原图同尺寸的空白掩码(单通道)
                mask = np.zeros_like(img[:, :, 0], dtype=np.uint8)
                # 将坐标点转换为OpenCV要求的格式
                pts = np.array(points, np.int32).reshape((-1, 1, 2))
                # 填充轮廓生成白色掩码(255为白色,0为黑色)
                cv2.fillPoly(mask, [pts], 255)
                # 保存掩码到本地
                cv2.imwrite("roi_mask.png", mask)
                print("掩码已保存为roi_mask.png")
                # 显示掩码和掩码叠加后的图像
                cv2.imshow("ROI Mask", mask)
                masked_img = cv2.bitwise_and(img_copy, img_copy, mask=mask)
                cv2.imshow("Masked Image", masked_img)
            else:
                print("绘制的轮廓点过少,请重新绘制完整的ROI")
        elif key == ord('r'):
            # 重置图像和点列表
            img = img_copy.copy()
            points = []
        elif key == ord('q'):
            break

    cv2.destroyAllWindows()

关键说明

  • 绘制时按住鼠标左键拖动,松开左键结束绘制,会自动闭合轮廓
  • 按s键生成并保存二进制掩码,同时显示掩码和掩码与原图的叠加效果
  • 掩码是单通道的8位图像,白色区域(255)为选中的ROI,黑色区域(0)为背景
  • 按r键可以重置画布,重新绘制ROI

内容的提问来源于stack exchange,提问作者H Tai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 15:28:20