なんでやろうとおもったの?
矩形をクリックして取得する等はすでにあるライブラリでできたけど、
クリック位置が欲しいタイミングがあったので先にMouseイベントを取得できるようにした。
ただ、UIとWebカメラの組み合わせのベストプラクティスかはわからないのでなんとも言えない。
やったこと
Webカメラから画像を取り込む。
毎フレーム画面にマウスでクリックしている間に動いた範囲に青い円を書く。
Mouse as a Paint-Brush — OpenCV 3.0.0-dev documentation
whitecat-student.hatenablog.com
こちらを参考にさせていただいてやってみた。
コード
import cv2 class mouseParam: def __init__(self, input_img_name): #マウス入力用のパラメータ self.mouseEvent = {"x":None, "y":None, "event":None, "flags":None} #マウス入力の設定 cv2.setMouseCallback(input_img_name, self.__CallBackFunc, None) #コールバック関数 def __CallBackFunc(self, eventType, x, y, flags, userdata): self.mouseEvent["x"] = x self.mouseEvent["y"] = y self.mouseEvent["event"] = eventType self.mouseEvent["flags"] = flags #マウス入力用のパラメータを返すための関数 def getData(self): return self.mouseEvent #マウスイベントを返す関数 def getEvent(self): return self.mouseEvent["event"] #マウスフラグを返す関数 def getFlags(self): return self.mouseEvent["flags"] #xとyの座標を返す関数 def getPos(self): return (self.mouseEvent["x"], self.mouseEvent["y"]) cap = cv2.VideoCapture(0) click_points = [] draw = False #コールバックの設定 window_name = "main window" while True: # VideoCaptureから1フレーム読み込む ret, frame = cap.read() # スクリーンショットを撮りたい関係で1/4サイズに縮小 frame = cv2.resize(frame, (int(frame.shape[1]/2), int(frame.shape[0]/2))) # 描画する [cv2.circle(frame, point, 20, (255,0,0), thickness=1, lineType=cv2.LINE_8, shift=0) for point in click_points] cv2.imshow(window_name, frame) # 描画結果の中でマウスの状態を取得する mouseData = mouseParam(window_name) # キー入力を1ms待って、k が27(ESC)だったらBreakする k = cv2.waitKey(1) if k == 27: break #左クリックがあったら表示 if mouseData.getEvent() == cv2.EVENT_LBUTTONDOWN: # 左ボタンを押下したとき draw = True click_points.append(mouseData.getPos()) if mouseData.getEvent() == cv2.EVENT_LBUTTONUP: # 左ボタンを上げたとき draw = False if mouseData.getEvent() == cv2.EVENT_MOUSEMOVE and draw: # マウスが動いた時 print(mouseData.getPos()) if draw: click_points.append(mouseData.getPos()) cap.release() cv2.destroyAllWindows()
できました
やってみてどうだった?
どう考えてもシーケンシャルに入ってくる動画に対してはベストプラクティスじゃないことまではわかった。
非同期的にやるべきだし、静止画を前提とされているようにも感じたし、その用途では使いやすそう。