如何用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
相关产品推荐
相关产品推荐

