Opencv鼠标事件+界面交互之绘制矩形多边形选取感兴趣区域ROI

2023-03-27 16:27:20

1.Opencv鼠标事件

import cv2

d=[i for i in dir(cv2) if 'EVENT' in i]
print(d)

'EVENT_FLAG_ALTKEY':代表拖拽事件。按住alt键不放
'EVENT_FLAG_CTRLKEY'按住ctrl键不放
'EVENT_FLAG_LBUTTON'按住左键拖拽
'EVENT_FLAG_MBUTTON'中键拖拽
'EVENT_FLAG_RBUTTON'右键拖拽
'EVENT_FLAG_SHIFTKEY'按住shift不放
'EVENT_LBUTTONDBLCLK'event鼠标事件。左键双击
'EVENT_LBUTTONDOWN'按下左键
'EVENT_LBUTTONUP'释放左键
 'EVENT_MBUTTONDBLCLK' 中键双击
 'EVENT_MBUTTONDOWN'中键点击
 'EVENT_MBUTTONUP'中键放开
 'EVENT_MOUSEHWHEEL'
 'EVENT_MOUSEMOVE'滑动
 'EVENT_MOUSEWHEEL',
 'EVENT_RBUTTONDBLCLK',右键双击
 'EVENT_RBUTTONDOWN',右键点击
 'EVENT_RBUTTONUP'右键释放

回调函数使用:

cv2.setMousecallback(const string& winname, MouseCallback onMouse, void* userdata=0)

winname:窗口的名字 
onMouse:鼠标响应函数,回调函数。指定窗口里每次鼠标时间发生的时候,被调用的函数指针。 这个函数的原型应该为void on_Mouse(int event, int x, int y, int flags, void* param);
userdate:传给回调函数的参数 

响应函数使用:

void on_Mouse(int event, int x, int y, int flags, void* param);
event是 CV_EVENT_*变量之一
x和y是鼠标指针在图像坐标系的坐标(不是窗口坐标系) 
flags是CV_EVENT_FLAG的组合, param是用户定义的传递到setMouseCallback函数调用的参数。

2.绘制矩形ROI

2.1方法一

import cv2

global img
global point1, point2

#鼠标响应函数
def Rectangular_box(event, x, y, flags, param):
    global img, point1, point2
    img2 = img.copy()
    if event == cv2.EVENT_LBUTTONDOWN:  # 左键点击
        point1 = (x, y)
        cv2.circle(img2, point1, 10, (0, 255, 0), 5)
        cv2.imshow('img', img2)
    elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON):  # 按住左键拖曳
        cv2.rectangle(img2, point1, (x, y), (255, 0, 0), 5)
        cv2.imshow('img', img2)
    elif event == cv2.EVENT_LBUTTONUP:  # 左键释放
        point2 = (x, y)
        cv2.rectangle(img2, point1, point2, (0, 255, 255), 4)
        cv2.imshow('img', img2)
        min_x = min(point1[0], point2[0])
        min_y = min(point1[1], point2[1])
        width = abs(point1[0] - point2[0])
        height = abs(point1[1] - point2[1])
        cut_img = img[min_y:min_y + height, min_x:min_x + width]
        #cv2.imwrite('baocun.jpg', cut_img)
        cv2.imshow('result',cut_img
def main():
    global img
    img = cv2.imread('yangmi.jpg')
    img=cv2.resize(img,None,fx=0.4,fy=0.4)
    cv2.namedWindow('image')
    cv2.setMouseCallback('image', Rectangular_box)
    cv2.imshow('image', img)
    cv2.waitKey(0)
if __name__ == '__main__':
    main()

2.2方法二

import cv2
import imutils
 
img = cv2.imread("./test_image.jpg")
img = imutils.resize(img, width=500)
 
roi = cv2.selectROI(windowName="roi", img=img, showCrosshair=True, fromCenter=False)
x, y, w, h = roi
 
cv2.rectangle(img=img, pt1=(x, y), pt2=(x + w, y + h), color=(0, 0, 255), thickness=2)
cv2.imshow("roi", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

3.绘制多边形ROI

多边形ROI,主要利用鼠标交互进行绘制:

  1. 单击左键,选择多边形的点;
  2. 单击右键,删除最近一次选择的点;
  3. 单击中键,确定ROI区域并可视化。
  4. 按”S“键,将多边形ROI区域的点保存到本地”config.pkl"文件中。
import cv2
import imutils
import numpy as np
import joblib
 
pts = []  # 用于存放点
 
 
# 统一的:mouse callback function
def draw_roi(event, x, y, flags, param):
    img2 = img.copy()
 
    if event == cv2.EVENT_LBUTTONDOWN:  # 左键点击,选择点
        pts.append((x, y))  
 
    if event == cv2.EVENT_RBUTTONDOWN:  # 右键点击,取消最近一次选择的点
        pts.pop()  
 
    if event == cv2.EVENT_MBUTTONDOWN:  # 中键绘制轮廓
        mask = np.zeros(img.shape, np.uint8)
        points = np.array(pts, np.int32)
        points = points.reshape((-1, 1, 2))
        # 画多边形
        mask = cv2.polylines(mask, [points], True, (255, 255, 255), 2)
        mask2 = cv2.fillPoly(mask.copy(), [points], (255, 255, 255))  # 用于求 ROI
        mask3 = cv2.fillPoly(mask.copy(), [points], (0, 255, 0))  # 用于 显示在桌面的图像
 
        show_image = cv2.addWeighted(src1=img, alpha=0.8, src2=mask3, beta=0.2, gamma=0)
 
        cv2.imshow("mask", mask2)
        cv2.imshow("show_img", show_image)
 
        ROI = cv2.bitwise_and(mask2, img)
        cv2.imshow("ROI", ROI)
        cv2.waitKey(0)
 
    if len(pts) > 0:
        # 将pts中的最后一点画出来
        cv2.circle(img2, pts[-1], 3, (0, 0, 255), -1)
 
    if len(pts) > 1:
        # 画线
        for i in range(len(pts) - 1):
            cv2.circle(img2, pts[i], 5, (0, 0, 255), -1)  # x ,y 为鼠标点击地方的坐标
            cv2.line(img=img2, pt1=pts[i], pt2=pts[i + 1], color=(255, 0, 0), thickness=2)
 
    cv2.imshow('image', img2)
 
 
# 创建图像与窗口并将窗口与回调函数绑定
img = cv2.imread("./test_image.jpg")
img = imutils.resize(img, width=500)
cv2.namedWindow('image')
cv2.setMouseCallback('image', draw_roi)
print("[INFO] 单击左键:选择点,单击右键:删除上一次选择的点,单击中键:确定ROI区域")
print("[INFO] 按‘S’确定选择区域并保存")
print("[INFO] 按 ESC 退出")
 
while True:
    key = cv2.waitKey(1) & 0xFF
    if key == 27:
        break
    if key == ord("s"):
        saved_data = {
            "ROI": pts
        }
        joblib.dump(value=saved_data, filename="config.pkl")
        print("[INFO] ROI坐标已保存到本地.")
        break
cv2.destroyAllWindows()

在这里插入图片描述

参考:
1.使用鼠标在图像上绘制矩形框或者多边形框
2.OpenCV-Python选择ROI(矩形和多边形)

  • 作者:明月醉窗台
  • 原文链接:https://blog.csdn.net/yohnyang/article/details/125455083
    更新时间:2023-03-27 16:27:20