目标
• 學習使用 OpenCV 處理滑鼠事件
• 你将要學習的函數是:cv2.setMouseCallback()
滑鼠事件 :cv2.setMouseCallback()
cv2_EVENT_MOUSEMOVE 0 滑動
cv2_EVENT_LBUTTONDOWN 1 左鍵點選
cv2_EVENT_RBUTTONDOWN 2 右鍵點選
cv2_EVENT_MBUTTONDOWN 3 中間點選
cv2_EVENT_LBUTTONUP 4 左鍵釋放
cv2_EVENT_RBUTTONUP 5 右鍵釋放
cv2_EVENT_MBUTTONUP 6 中間釋放
cv2_EVENT_LBUTTONDBLCLK 7 左鍵輕按兩下
cv2_EVENT_RBUTTONDBLCLK 8 右鍵輕按兩下
cv2_EVENT_MBUTTONDBLCLK 9 中間釋放
cv2_EVENT_FLAG_LBUTTON 1 左鍵拖拽
cv2_EVENT_FLAG_RBUTTON 2 右鍵拖拽
cv2_EVENT_FLAG_MBUTTON 4 中間拖拽
cv2_EVENT_FLAG_CTRLKEY 8 (8~15)按Ctrl不放事件
cv2_EVENT_FLAG_SHIFTKEY 16 (16~31)按Shift不放事件
cv2_EVENT_FLAG_ALTKEY 32 (32~39)按Alt不放事件(後面8-39還有待研究)
執行個體1 :輕按兩下左鍵畫圓圈
用到的EVENT為:cv2_EVENT_LBUTTONDBLCLK
所有的滑鼠事件回調函數都有一個統一的格式,他們所不同的地方僅僅是
被調用後的功能。我們的滑鼠事件回調函數隻用做一件事:在輕按兩下過的地方繪
制一個圓圈。下面是代碼,不懂的地方可以看看注釋。
import cv2
import numpy as np
import time
img=cv2.imread('PIC/000.jpg') #讀取圖檔作為背景
#定義畫圓事件,如果事件輕按兩下左鍵發生
#則以此時輕按兩下的點為原點畫一個半徑為100px BGR為(255,255,0)粗細為3px的圓圈
def draw_circle(event,x,y,flags,param):
if event==cv2.EVENT_LBUTTONDBLCLK:
cv2.circle(img,(x,y),100,(255,255,0),3)
# 建立圖像與視窗并将視窗與回調函數綁定
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)
while(1):
cv2.imshow('image',img)
if cv2.waitKey(100) == ord('q'): #等待100毫秒 重新整理一次顯示圖像
break
cv2.destroyAllWindows()
運作結果:

執行個體2
現在我們來建立一個更好的程式。這次我們的程式要完成的任務是根據我
們選擇的模式在拖動滑鼠時繪制矩形或者是圓圈(就像畫圖程式中一樣)。是以
我們的回調函數包含兩部分,一部分畫矩形,一部分畫圓圈。這是一個典型的
例子他可以幫助我們更好了解與建構人機互動式程式,比如物體跟蹤,圖像分
割等。
下面我們要把這個回調函數與 OpenCV 視窗綁定在一起。在主循環中我
們需要将鍵盤上的“m”鍵與模式轉換綁定在一起。
import cv2
import numpy as np
import time
img=cv2.imread('PIC/000.jpg')
# 當滑鼠按下時變為True
drawing=False
# 如果mode 為true 繪制矩形。按下'm' 變成繪制曲線。
mode=True
ix,iy=-1,-1
# 建立回調函數
def draw_circle(event,x,y,flags,param):
global ix,iy,drawing,mode
# 當按下左鍵是傳回起始位置坐标
if event==cv2.EVENT_LBUTTONDOWN:
drawing=True
ix,iy=x,y
# 當滑鼠左鍵按下并移動是繪制圖形。event 可以檢視移動,flag 檢視是否按下
elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:
if drawing==True:
if mode==True:
cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
else:
# 繪制圓圈,小圓點連在一起就成了線
cv2.circle(img,(x,y),3,(0,0,255),-1)
# 當滑鼠松開停止繪畫。
elif event==cv2.EVENT_LBUTTONUP:
drawing==False
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)
while(1):
cv2.imshow('image',img)
k=cv2.waitKey(1)&0xFF
if k==ord('m'):
mode=not mode
elif k==ord('q'):
break
運作結果:
全部代碼:
'''函數:cv2.setMouseCallback()'''
import cv2
import numpy as np
import time
img=cv2.imread('PIC/000.jpg')
def draw_circle(event,x,y,flags,param):
if event==cv2.EVENT_LBUTTONDBLCLK:
cv2.circle(img,(x,y),100,(255,255,0),3)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)
while(1):
cv2.imshow('image',img)
if cv2.waitKey(100) == ord('q'): #等待100毫秒 重新整理一次顯示圖像
break
cv2.destroyAllWindows()
# 當滑鼠按下時變為True
drawing=False
# 如果mode 為true 繪制矩形。按下'm' 變成繪制曲線。
mode=True
ix,iy=-1,-1
6
# 建立回調函數
def draw_circle(event,x,y,flags,param):
global ix,iy,drawing,mode
# 當按下左鍵是傳回起始位置坐标
if event==cv2.EVENT_LBUTTONDOWN:
drawing=True
ix,iy=x,y
# 當滑鼠左鍵按下并移動是繪制圖形。event 可以檢視移動,flag 檢視是否按下
elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:
if drawing==True:
if mode==True:
cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
else:
# 繪制圓圈,小圓點連在一起就成了線
cv2.circle(img,(x,y),3,(0,0,255),-1)
# 當滑鼠松開停止繪畫。
elif event==cv2.EVENT_LBUTTONUP:
drawing==False
img=cv2.imread('PIC/000.jpg')
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)
while(1):
cv2.imshow('image',img)
k=cv2.waitKey(1)&0xFF
if k==ord('m'):
mode=not mode
elif k==ord('q'):
break