侦测鼠标事件
使用 OpenCV 建立视窗后,除了打开图片进行预览,也可透过视窗侦测鼠标的事件,进一步利用鼠标和图像互动,这篇教学会介绍如何侦测鼠标事件,以及取得鼠标事件后进行的简单应用 ( 标记、取得颜色...等 )。
快速导览:
因为程序中的 OpenCV 会需要使用镜头或 GPU,所以请使用本机环境 ( 参考:使用 Python 虚拟环境 ) 或使用 Anaconda Jupyter 进行实作 ( 参考:使用 Anaconda ) ,并安装 OpenCV 函数库 ( 参考:OpenCV 函数库 )。
侦测鼠标事件
使用 cv2.setMouseCallback 方法,可以侦测指定视窗下的鼠标事件,侦测事件后会透过一个特定的函数处理相关事件参数,每次发生鼠标事件时会回传四个参数,第一个是 event,第二个是 x 座标,第三个是 y 座标,第四个是 flag,下方的程序码执行后,用鼠标在视窗上滑动以及点击,后台就会看见印出对应的数值。
import cv2
img = cv2.imread('meme.jpg')
def show_xy(event,x,y,flags,userdata):
print(event,x,y,flags)
# 印出相關參數的數值,userdata 可透過 setMouseCallback 第三個參數垂遞給函式
cv2.imshow('oxxostudio', img)
cv2.setMouseCallback('oxxostudio', show_xy) # 設定偵測事件的函式與視窗
cv2.waitKey(0) # 按下任意鍵停止
cv2.destroyAllWindows()
鼠标 event 与 flag 列表
当鼠标在指定视窗中滑动进行某些行为,都会触发一些事件,相关事件列表如下:
| 代号 | 事件 | 说明 |
|---|---|---|
| 0 | cv2.EVENT_MOUSEMOVE | 滑动 |
| 1 | cv2.EVENT_LBUTTONDOWN | 左键点击 |
| 2 | cv2.EVENT_RBUTTONDOWN | 右键点击 |
| 3 | cv2.EVENT_MBUTTONDOWN | 中键点击 |
| 4 | cv2.EVENT_LBUTTONUP | 左键放开 |
| 5 | cv2.EVENT_RBUTTONUP | 右键放开 |
| 6 | cv2.EVENT_MBUTTONUP | 中键放开 |
| 7 | cv2.EVENT_LBUTTONDBLCLK | 左键双击 |
| 8 | cv2.EVENT_RBUTTONDBLCLK | 右键双击 |
| 9 | cv2.EVENT_MBUTTONDBLCLK | 中键双击 |
除了事件,鼠标的行为也会触发一些 flag,相关 flag 列表如下:
| 代号 | flag | 说明 |
|---|---|---|
| 1 | cv2.EVENT_FLAG_LBUTTON | 左键拖曳 |
| 2 | cv2.EVENT_FLAG_RBUTTON | 右键拖曳 |
| 4 | cv2.EVENT_FLAG_MBUTTON | 中键拖曳 |
| 8~15 | cv2.EVENT_FLAG_CTRLKEY | 按 Ctrl 不放事件 |
| 16~31 | cv2.EVENT_FLAG_SHIFTKEY | 按 Shift 不放事件 |
| 32~39 | cv2.EVENT_FLAG_ALTKEY | 按 Alt 不放事件 |
透过鼠标点击,取得像素的颜色
下方的程序码,会使用一个黑色圆框标记鼠标的位置,当点击鼠标时,会印出该位置像素的颜色。
import cv2
img = cv2.imread('meme.jpg')
def show_xy(event,x,y,flags,param):
if event == 0:
img2 = img.copy() # 當滑鼠移動時,複製原本的圖片
cv2.circle(img2, (x,y), 10, (0,0,0), 1) # 繪製黑色空心圓
cv2.imshow('oxxostudio', img2) # 顯示繪製後的影像
if event == 1:
color = img[y,x] # 當滑鼠點擊時
print(color) # 印出顏色
cv2.imshow('oxxostudio', img)
cv2.setMouseCallback('oxxostudio', show_xy)
cv2.waitKey(0)
cv2.destroyAllWindows()
透过鼠标点击,绘制多边形
下方的程序码,会在点击鼠标时绘制一个实心圆形,并记录该点击时的座标,当座标数量大于 1 时,会透过两个座标绘制直线。
import cv2
img = cv2.imread('meme.jpg')
dots = [] # 記錄座標的空串列
def show_xy(event,x,y,flags,param):
if event == 1:
dots.append([x, y]) # 記錄座標
cv2.circle(img, (x, y), 10, (0,0,255), -1) # 在點擊的位置,繪製圓形
num = len(dots) # 目前有幾個座標
if num > 1: # 如果有兩個點以上
x1 = dots[num-2][0]
y1 = dots[num-2][1]
x2 = dots[num-1][0]
y2 = dots[num-1][1]
cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2) # 取得最後的兩個座標,繪製直線
cv2.imshow('oxxostudio', img)
cv2.imshow('oxxostudio', img)
cv2.setMouseCallback('oxxostudio', show_xy)
cv2.waitKey(0)
cv2.destroyAllWindows()
微信扫码关注
抖音扫码关注