点赞 + 关注 + 收藏 = 学会了

在使用 OpenCV 进行图像处理时,有时需要与图像进行交互,例如选择感兴趣区域(ROI)、标注关键点、调整参数、获取图片指定位置的颜色值等。OpenCV 提供了鼠标事件支持,可以在图像窗口中通过鼠标实现丰富的交互功能。

推荐 《OpenCV专栏》

用到的方法是 cv2.setMouseCallback(window_name, on_mouse, param=None),用这个方法监听鼠标在指定窗口里做了什么。

  • window_name:需要绑定鼠标事件的窗口名称。
  • on_mouse:回调函数。在这个函数里可以知道用户用鼠标做了什么操作。
  • param:传递给回调函数的额外参数,可以不传。也可以传你需要的内容,比如传递图像数据到回调函数中,让回调函数可以访问或修改图像。

其中,回调函数(on_mouse)需要按照以下形式定义:

def on_mouse(event, x, y, flags, param):
    # event: 当前的鼠标事件类型。
    # x, y: 鼠标事件发生时的坐标。
    # flags: 事件相关的附加信息(按下键盘时的修饰键状态,比如按下shift健的同时鼠标在图片上有操作)。
    # param: 通过 setMouseCallback 传递的额外参数。

OpenCV 提供了多种鼠标事件(event),以下是常见类型:

枚举值数字值描述
cv2.EVENT_MOUSEMOVE0鼠标移动
cv2.EVENT_LBUTTONDOWN1鼠标左键按下
cv2.EVENT_RBUTTONDOWN2鼠标右键按下
cv2.EVENT_MBUTTONDOWN3鼠标中键按下
cv2.EVENT_LBUTTONUP4鼠标左键释放
cv2.EVENT_RBUTTONUP5鼠标右键释放
cv2.EVENT_MBUTTONUP6鼠标中键释放
cv2.EVENT_LBUTTONDBLCLK7鼠标左键双击
cv2.EVENT_RBUTTONDBLCLK8鼠标右键双击
cv2.EVENT_MBUTTONDBLCLK9鼠标中键双击
cv2.EVENT_MOUSEWHEEL10滚轮正向滚动(滚轮事件,向上滚动)
cv2.EVENT_MOUSEHWHEEL11滚轮横向滚动(滚轮事件,水平滚动)

可以通过这些值判断用户做了什么操作。

举个例子,创建一个 400x400 的黑色背景图片,然后监听鼠标在这个图片上做过什么操作。

01_compressed.gif

import cv2
import numpy as np

# 鼠标回调事件
def mouse_callback(event, x, y, flags, param):
    print(f"事件:{event} | 坐标:x{x}, y{y} | 组合键:{flags} | 额外参数: {param}")

# 创建 400x400 黑色背景图片
img = np.zeros((400, 400, 3), dtype=np.uint8)

# 展示图片
cv2.imshow("ImgWindow",  img)

# 监听 ImgWindow 窗口的鼠标事件
cv2.setMouseCallback("ImgWindow", mouse_callback)

cv2.waitKey()
cv2.destroyAllWindows()

最后的一个参数 param 有什么用呢?

如果需要通过鼠标对图像做一些操作,比如框选、标记等操作,可以将图片传入鼠标回调函数里,在里面对图片进行绘制。

举个例子,当检测到鼠标在图像上点击了左键,就在图像对应的位置标记一个红点。

02.gif

import cv2
import numpy as np

# 鼠标回调事件
def mouse_callback(event, x, y, flags, param):
    # 左键按下时绘制一个点
    if event == cv2.EVENT_LBUTTONDOWN:
        img = param  # 从 param 参数获取图像
        cv2.circle(img, (x, y), 5, (0, 0, 255), -1)

# 创建 400x400 黑色背景图片
img = np.zeros((400, 400, 3), dtype=np.uint8)

# 展示图片
cv2.imshow("ImgWindow",  img)

# 监听 ImgWindow 窗口的鼠标事件
cv2.setMouseCallback("ImgWindow", mouse_callback, param=img)

while True:
    cv2.imshow("ImgWindow", img)
    if cv2.waitKey(1) & 0xFF == 27:  # 按 ESC 键退出
        break
cv2.destroyAllWindows()

点赞 + 关注 + 收藏 = 学会了


德育处主任
170 声望16 粉丝