OpenCV-Python 演習
マウス入力を処理する†
ポイント†
- ウィンドウ上で以下のようなマウス操作を行うと,イベント(割り込み)が発生し,予め登録しておいたコールバック関数が呼出される.
- コールバック関数の定義
- マウス操作に関するイベントが発生したときに呼出されるコールバック関数を定義しておく.
def onMouse(event, x, y, flags, param):
- eventには,次の表のいずれかがセットされ,どのイベントが発生したかがわかる.
イベント | 発生するタイミング |
cv2.EVENT_MOUSEMOVE | マウスを移動したとき,またはボタンを離した直後 |
cv2.EVENT_LBUTTONDOWN | 左ボタンを押下したとき |
cv2.EVENT_RBUTTONDOWN | 右ボタンを押下したとき |
cv2.EVENT_MBUTTONDOWN | 中ボタンを押下したとき |
cv2.EVENT_LBUTTONUP | 左ボタンを離したとき |
cv2.EVENT_RBUTTONUP | 右ボタンを離したとき |
cv2.EVENT_MBUTTONUP | 中ボタンを離したとき |
cv2.EVENT_LBUTTONDBLCLK | 左ボタンがダブルクリックされたとき |
cv2.EVENT_RBUTTONDBLCLK | 右ボタンがダブルクリックされたとき |
cv2.EVENT_MBUTTONDBLCLK | 中ボタンがダブルクリックされたとき |
- x, yにはイベントが発生したときのマウスポインタの(ウィンドウに表示している画像上の)座標が入る.
- flagsには,次の表に示すフラグの論理和がセットされ,どのキーが同時に押されているかが分かる
フラグ名 | フラグが立つ条件 |
cv2.EVENT_FLAG_LBUTTON | CTRL,SHIFT,ALTいずれも押さずに,左ボタンを押下したとき |
cv2.EVENT_FLAG_RBUTTON | CTRL,SHIFT,ALTいずれも押さずに,右ボタンを押下したとき |
cv2.EVENT_FLAG_MBUTTON | CTRL,SHIFT,ALTいずれも押さずに,中ボタンを押下したとき |
cv2.EVENT_FLAG_CTRLKEY | CTRLを押して,ボタンを離したときと離した直後 |
cv2.EVENT_FLAG_SHIFTKEY | SHIFTを押して,ボタンを離したときと離した直後 |
cv2.EVENT_FLAG_ALTKEY | ALTを押して,ボタンを離したときと離した直後 |
- paramには,以下に説明するコールバック関数の登録時に設定した,値や構造体のポインタが入る.
- コールバック関数の第5引数(param)について
- コールバック関数内で処理した結果を外部に持ち出したいときなどに使用する.
- 辞書をコールバック関数の引数として渡すときの使用例
- 辞書は参照渡しとなるため,コールバック関数内での変更は,呼び出し元の辞書に反映される.
- コールバック関数の定義例
def onMouse(event, x, y, flags, param):
event_description = ""
if event == cv2.EVENT_MOUSEMOVE:
event_description += "MOUSE_MOVE"
elif event == cv2.EVENT_LBUTTONDOWN:
event_description += "LBUTTON_DOWN"
print("centerX: " + str(param["centerX"]) +
", centerY: " + str(param["centerY"]))
param["centerX"] = -1
param["centerY"] = -1
else:
pass
- メイン関数内での使用例
param = {"centerX": 10, "centerY": 20, "color": 0 }
cv2.setMouseCallback('img', onMouse, param)
サンプルコード†
'''
tutorial_008.py
ウィンドウ上のマウス入力を処理する
'''
import cv2
import numpy as np
img = np.zeros((480, 640, 3), np.uint8) # y座標, x座標, チャンネル
def onMouse(event, x, y, flags, param):
event_description = ""
if event == cv2.EVENT_MOUSEMOVE:
event_description += "MOUSE_MOVE"
elif event == cv2.EVENT_LBUTTONDOWN:
event_description += "LBUTTON_DOWN"
print("centerX: " + str(param["centerX"]) +
", centerY: " + str(param["centerY"]))
param["centerX"] = -1
param["centerY"] = -1
elif event == cv2.EVENT_RBUTTONDOWN:
event_description += "LBUTTON_DOWN"
elif event == cv2.EVENT_MBUTTONDOWN:
event_description += "MBUTTON_DOWN"
elif event == cv2.EVENT_LBUTTONUP:
event_description += "LBUTTON_UP"
elif event == cv2.EVENT_RBUTTONUP:
event_description += "RBUTTON_UP"
elif event == cv2.EVENT_MBUTTONUP:
event_description += "MBUTTON_UP"
elif event == cv2.EVENT_LBUTTONDBLCLK:
event_description += "LBUTTON_DBLCLK"
cv2.circle(img, (x, y), 100, (0, 0, 255), 3)
elif event == cv2.EVENT_RBUTTONDBLCLK:
event_description += "RBUTTON_DBLCLK"
elif event == cv2.EVENT_MBUTTONDBLCLK:
event_description += "MBUTTON_DBLCLK"
else:
event_description += ""
if flags & cv2.EVENT_FLAG_LBUTTON:
event_description += " + LBUTTON"
if flags & cv2.EVENT_FLAG_RBUTTON:
event_description += " + RBUTTON"
if flags & cv2.EVENT_FLAG_MBUTTON:
event_description += " + MBUTTON"
if flags & cv2.EVENT_FLAG_CTRLKEY:
event_description += " + CTRL"
if flags & cv2.EVENT_FLAG_SHIFTKEY:
event_description += " + SHIFT"
if flags & cv2.EVENT_FLAG_ALTKEY:
event_description += " + ALT"
print(event_description)
def tutorial_008():
# 画面全体を青色にする
img[:, :] = [255, 0, 0]
cv2.namedWindow("img", cv2.WINDOW_AUTOSIZE)
cv2.moveWindow("img", 100, 100)
param = {"centerX": 10, "centerY": 20, "color": 0}
cv2.setMouseCallback('img', onMouse, param)
while(True):
cv2.imshow('img', img)
key = cv2.waitKey(20) & 0xFF
if key == 0x1b or key == ord("q"):
break
elif key == ord("1"):
param["centerX"] = 100
param["centerY"] = 200
elif key == ord("0"):
param["centerX"] = 10
param["centerY"] = 20
elif key == ord("p"):
print("centerX: " + str(param["centerX"]) +
", centerY: " + str(param["centerY"]))
else:
pass
cv2.destroyAllWindows()
if __name__ == "__main__":
tutorial_008()
課題1 (exercise_008_01.py)†
- 簡単なペイントソフトを作成しなさい.
- 背景を黒とし,マウスの左キーを押しながらドラッグすることで,フリーハンドによる絵が描けるようにする.
- ドラッグ中は,マウスポインタの位置に適当な半径,適当な色の円を描くようにすることで実現可能である.
- マウスの左キーの状態(押されているか,押されていないか)を管理するグローバル変数(bool型など)を利用しなさい.
課題2 (exercise_008_02.py)†
- 簡単なドローロフトを作成しなさい.
- 左クリックした場所を起点とし,左ボタンを押している間は現在のマウスポインタの位置を終点とする,描画候補となる直線を動的に描くようにし,左ボタンを離したときに,線が確定するものとする.
OpenCV-Python 演習