ペイントツールとしてのマウス¶
目的¶
- OpenCVのマウスイベントの操作方法を学びます.
- 以下の関数の使い方を学びます : cv2.setMouseCallback()
簡単なデモ¶
このチュートリアルでは,マウスイベントを管理することでウィンドウ上のダブルクリックした位置に円を描画するアプリケーションを作成します.
まずはじめにマウスイベントが発生する度に呼び出すマウスコールバック関数を作成します.マウスイベントはマウスに関するイベントであれば何でもよく,例えば左ボタンの押し上げ,ダブルクリックなどです.マウスコールバック関数は,マウスイベントが起きた時のマウスカーソルの座標(x,y)を与えます.マウスのイベント情報と位置情報から好きな処理をできます.使用可能な全てのイベントを列挙するには,以下のコードをPythonのターミナルから実行してください.:
>>> import cv2
>>> events = [i for i in dir(cv2) if 'EVENT' in i]
>>> print events
マウスコールバック関数の定義は特殊な形式ですが,どのようなシステムでも共通のもので, 関数の挙動のみが異なります.このチュートリアルではダブルクリックしたウィンドウの位置に円を描くというものです.以下のコードを読んでみてください.コメントを読めば十分分かる内容です:
import cv2
import numpy as np
# mouse callback function
def draw_circle(event,x,y,flags,param):
if event == cv2.EVENT_LBUTTONDBLCLK:
cv2.circle(img,(x,y),100,(255,0,0),-1)
# Create a black image, a window and bind the function to window
img = np.zeros((512,512,3), np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)
while(1):
cv2.imshow('image',img)
if cv2.waitKey(20) & 0xFF == 27:
break
cv2.destroyAllWindows()
発展デモ¶
次の発展デモではよりよいアプリケーションを作成します.ペイントアプリケーションで実装されているような描画機能として,マウスのドラッグに合わせて長方形もしくは円(選択したモードによって切り替え)を描画します.ここでのマウスコールバック関数は長方形を描く部分と円を描く部分の2パートにわかれます.このチュートリアルは今後物体追跡や画像の領域分割のようにユーザの入力が必要なアプリケーションを作る時に役立ちます.
import cv2
import numpy as np
drawing = False # true if mouse is pressed
mode = True # if True, draw rectangle. Press 'm' to toggle to curve
ix,iy = -1,-1
# mouse callback function
def draw_circle(event,x,y,flags,param):
global ix,iy,drawing,mode
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
ix,iy = x,y
elif event == cv2.EVENT_MOUSEMOVE:
if drawing == True:
if mode == True:
cv2.rectangle(img,(ix,iy),(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 == True:
cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
else:
cv2.circle(img,(x,y),5,(0,0,255),-1)
次に,作成したマウスコールバック関数をOpenCVのウィンドウに関連付けます.描画するオブジェクトを切り替えるために,メインループの中で’‘m’を押すとモードを切り替えるようにします.
img = np.zeros((512,512,3), np.uint8)
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 == 27:
break
cv2.destroyAllWindows()
補足資料¶
課題¶
- 発展デモの例を変更し,塗りつぶした長方形を描画するようにしてください.