滑鼠繪圖
1、目标
捕獲滑鼠事件
OpenCV函數:cv2.setMouseCallback()

2、知道滑鼠在哪兒
OpenCV中,我們需要建立一個滑鼠的回調函數來擷取滑鼠目前的位置、目前的事件如左鍵按下/左鍵釋放或是右鍵單擊等等,然後執行相應的功能。
使用cv2.setMouseCallback()來建立滑鼠的回調函數,比如我們在左鍵單擊的時候,列印出目前滑鼠的位置:
import cv2
import numpy as np
# 滑鼠的回調函數
def mouse_event(event, x, y, flags, param):
# 通過event判斷具體是什麼事件,這裡是左鍵按下
if event == cv2.EVENT_LBUTTONDOWN:
print((x, y))
img = np.zeros((512, 512, 3), np.uint8)
cv2.namedWindow('image')
# 定義滑鼠的回調函數
cv2.setMouseCallback('image', mouse_event)
while(True):
cv2.imshow('image', img)
# 按下ESC鍵退出
if cv2.waitKey(20) == 27:
break
上面的代碼先定義滑鼠的回調函數mouse_event(),然後在回調函數中判斷是否是左鍵單擊事件EVENT_LBUTTONDOWN,是的話就列印出坐标。需要注意的是,回調函數的參數格式是固定的,不要随意更改。
那除了左鍵單擊之外,還有哪些事件呢?可以用下面的代碼列印出來:
# 擷取所有的事件
events = [i for i in dir(cv2) if 'EVENT' in i]
print(events)
3、綜合執行個體
現在我們來實作一個綜合的例子,這個執行個體會幫助你了解圖像互動的一些思想:
在圖像上用滑鼠畫圖,可以畫圓或矩形,按m鍵在兩種模式下切換。左鍵按下時開始畫圖,移動到哪兒畫到哪兒,左鍵釋放時結束畫圖。聽上去很複雜,是嗎?一步步來看:
用滑鼠畫圖:需要定義滑鼠的回調函數mouse_event
畫圓或矩形:需要定義一個畫圖的模式mode
左鍵單擊、移動、釋放:需要捕獲三個不同的事件
開始畫圖,結束畫圖:需要定義一個畫圖的标記位drawing
好,開始coding吧:
import cv2
import numpy as np
drawing = False # 是否開始畫圖
mode = True # True:畫矩形,False:畫圓
start = (-1, -1)
def mouse_event(event, x, y, flags, param):
global start, drawing, mode
# 左鍵按下:開始畫圖
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
start = (x, y)
# 滑鼠移動,畫圖
elif event == cv2.EVENT_MOUSEMOVE:
if drawing:
if mode:
cv2.rectangle(img, start, (x, y), (0, 255, 0), 1)
else:
cv2.circle(img, (x, y), 5, (0, 0, 255), -1)
# 左鍵釋放:結束畫圖
elif event == cv2.EVENT_LBUTTONUP:
drawing = False
if mode:
cv2.rectangle(img, start, (x, y), (0, 255, 0), 1)
else:
cv2.circle(img, (x, y), 5, (0, 0, 255), -1)
img = np.zeros((512, 512, 3), np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image', mouse_event)
while(True):
cv2.imshow('image', img)
# 按下m切換模式
if cv2.waitKey(1) == ord('m'):
mode = not mode
elif cv2.waitKey(1) == 27:
break
效果應該如下圖所示:
4、小結
要用滑鼠繪圖,需要用cv2.setMouseCallback()定義回調函數,然後在回調函數中根據不同的event事件,執行不同的功能。
練習
1.(選做)實作用滑鼠畫矩形,跟執行個體差不多,但隻實時畫一個,類似下面動圖:
2.(選做)做一個在白色面闆上繪圖的簡單程式,可用滑動條調整顔色和筆刷大小。
引用
本節源碼
http://t.cn/EJ3P9fmMouse as a Paint-Brush
http://t.cn/EJ3veYt