美文网首页
217. 鼠标交互获取多边形区域

217. 鼠标交互获取多边形区域

作者: 大龙10 | 来源:发表于2025-12-26 07:16 被阅读0次

12. 绘制图像索引

一、鼠标交互获取多边形区域

  • 函数 cv.selectROI 可以通过鼠标在图像上选择感兴趣的矩形区域(ROI,region of interest)。
    如果要通过鼠标在图像上选择感兴趣的多边形区域,可以利用鼠标交互来绘制。
  • 函数 cv.polylines() 用来绘制多边形曲线或多段线。
  • 函数 cv.fillPoly() 用来绘制一个或多个填充的多边形区域。

cv.polylines(img, pts, isClosed, color[, thickness=1, lineType=LINE_8, shift=0]) → img
cv.fillPoly(img, pts, color[, lineType=LINE_8, shift=0, offset=Point()]) → img

参数说明:

  • img:输入输出图像,允许单通道灰度图像或多通道彩色图像
  • pts:多边形顶点坐标, 二维 Numpy 数组的列表
  • isClosed: 闭合标志,True 表示闭合多边形,False 表示多边形不闭合

特别注意多边形顶点坐标 pts 的格式:

  • pts 是一个列表,列表中的元素是二维 Numpy 数组,每个元素表示一组顶点坐标。
  • 二维 Numpy 数组的形状为 (m,2),每行表示多边形的一个顶点的坐标 (xi,yi),数据格式应为整型。
    points1 = np.array([[200,100], [295,169], [259,281], [141,281], [105,169]], np.int)
    points2 = np.array([[200,400], [259,581], [105,469], [295,469], [141,581]])

  • points1、points2 是形状为 (m,2) 的二维 Numpy 数组。
    对于函数 cv.polylines 与 cv.fillPoly,不能直接把二维 Numpy 数组 points1 或 points2作为函数参数,而要将其作为列表的元素,如: [points1]、[points2] 或 [points1, points2]。

二、例程

  • A4.9:鼠标交互获取多边形区域(ROI)
    函数 cv.selectROI 可以通过鼠标在图像上选择感兴趣的矩形区域(ROI,region of interest)。
    如果要通过鼠标在图像上选择感兴趣的多边形区域,可以利用鼠标交互来绘制。
import cv2
import numpy as np
from matplotlib import pyplot as plt

# A4.9 鼠标交互获取多边形区域
def mouseHandler(event, x, y, flags, param):  # 鼠标交互 (左键选点右键完成)
    global drawing
    setpoint = (x, y)
    if event == cv2.EVENT_LBUTTONDOWN:  # 鼠标左键点击事件
        drawing = True  # 开启绘图状态
        pts.append(setpoint)  # 选择多边形顶点
        print("选择顶点 {}:{}".format(len(pts), setpoint))
    elif event == cv2.EVENT_RBUTTONDOWN:  # 鼠标右键点击事件
        drawing = False  # 结束绘图状态
        print("结束绘制。\n ROI 顶点坐标:")
        print(pts)

# 鼠标交互绘制多边形 ROI
img = cv2.imread(r"E:/OpenCV/bgra.png")  # 读取彩色图像(BGR)

# 鼠标交互 ROI
print("单击鼠标左键:选择 ROI 顶点")
print("单击鼠标右键:结束 ROI 选择")
print("按 ESC 退出")
pts = []  # ROI 顶点坐标向量
drawing = True  # 开启绘图状态
cv2.namedWindow('origin')  # 创建图像窗口
cv2.setMouseCallback('origin', mouseHandler)  # 窗口与回调函数绑定
while True:
    imgCopy = img.copy()
    if len(pts) > 0:
        cv2.circle(imgCopy, pts[-1], 5, (0,0,255), -1)  # 绘制最近一个顶点
        if len(pts) > 1:
            for i in range(len(pts)-1):
                cv2.circle(imgCopy, pts[i], 5, (0,0,255), -1)  # 绘制顶点
                cv2.line(imgCopy, pts[i], pts[i+1], (255,0,0), 2)  # 绘制边界线段
        if drawing==False:
            cv2.line(imgCopy, pts[0], pts[-1], (255,0,0), 2)  # 完成最后一段线段
    cv2.imshow('origin', imgCopy)
    key = 0xFF & cv2.waitKey(1)  # 按 ESC 退出
    if key == 27:  # Esc 退出
        break
cv2.destroyAllWindows()  # 图像窗口

points = np.array(pts, np.int)  # ROI 多边形顶点坐标集
cv2.polylines(img, [points], True, (255,255,255), 2)  # 在 img 绘制 ROI 多边形
mask = np.zeros(img.shape[:2], np.uint8)  # 黑色掩模,单通道
cv2.fillPoly(mask, [points], (255,255,255))  # 多边形 ROI 为白色窗口
imgROI = cv2.bitwise_and(img, img, mask=mask)  # 按位与,从 img 中提取 ROI

plt.figure(figsize=(9, 6))
plt.subplot(131), plt.title("origin image"), plt.axis('off')
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(132), plt.title("ROI mask"), plt.axis('off')
plt.imshow(mask, cmap='gray')
plt.subplot(133), plt.title("ROI cropped"), plt.axis('off')
plt.imshow(cv2.cvtColor(imgROI, cv2.COLOR_BGR2RGB))
plt.tight_layout()
plt.show()

三、资料

youcans_的博客:
https://blog.csdn.net/youcans/article/details/125490992

相关文章

网友评论

      本文标题:217. 鼠标交互获取多边形区域

      本文链接:https://www.haomeiwen.com/subject/mctacstx.html