白猫学生のブログ

自分の趣味をひたすら投稿するブログ

OpenCVで表示した画像にマウスクリックした場所を取得する方法 (Python)

前回,C++OpenCVを用いて表示されている画像のマウスクリックした場所を取得するプログラムを作成したのですが,Pythonでも必要だったため作成しました.
グローバル変数を用いるともっと簡単になったのかも知れませんが,あんまりグローバル変数を利用したくなかったのと(特に理由はない)前回作成したプログラムと似たような動作を行ってほしいため無理やりまとめました.
動作は入力画像を表示して,左クリックをした場所を取得するだけのプログラムです.


Pythonで構造体ってどうすればいいんだ?」って思って結局ディクショナリ型を使用しました.(誰か最適解を教えてください)
ただディクショナリ型だけだとどうしても1つのオブジェクトにまとめきれなかったので,結局クラスも用いました.
そうするならディクショナリ型を使用する必要はない気がしますが,変更するのも面倒なのでそのままにしてあります.

ライブラリはOpenCV3.0を用いましたが,2.4以降であれば同様のプログラムで動作すると思います.
Pythonは2.7.12を使用しています.

サンプルプログラムではネットから適当に拾ってきた「lena.jpg」を用いております.

# -*- coding: utf-8 -*-

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の座標を返す関数
    def getX(self):
        return self.mouseEvent["x"]  

    #yの座標を返す関数
    def getY(self):
        return self.mouseEvent["y"]  

    #xとyの座標を返す関数
    def getPos(self):
        return (self.mouseEvent["x"], self.mouseEvent["y"])
        

if __name__ == "__main__":
    #入力画像
    read = cv2.imread("lena.jpg")
    
    #表示するWindow名
    window_name = "input window"
    
    #画像の表示
    cv2.imshow(window_name, read)
    
    #コールバックの設定
    mouseData = mouseParam(window_name)
    
    while 1:
        cv2.waitKey(20)
        #左クリックがあったら表示
        if mouseData.getEvent() == cv2.EVENT_LBUTTONDOWN:
            print(mouseData.getPos())
        #右クリックがあったら終了
        elif mouseData.getEvent() == cv2.EVENT_RBUTTONDOWN:
            break;
            
    cv2.destroyAllWindows()            
    print("Finished")

マウスイベントの種類は以下の通りです.

  • EVENT_MOUSEMOVE
  • EVENT_LBUTTONDOWN
  • EVENT_RBUTTONDOWN
  • EVENT_MBUTTONDOWN
  • EVENT_LBUTTONUP
  • EVENT_RBUTTONUP
  • EVENT_MBUTTONUP
  • EVENT_LBUTTONDBLCLK
  • EVENT_RBUTTONDBLCLK
  • EVENT_MBUTTONDBLCLK

フラグの種類は以下の通りです.これは,マウスイベントが発生したときの状態を表しています.

  • EVENT_FLAG_LBUTTON
  • EVENT_FLAG_RBUTTON
  • EVENT_FLAG_MBUTTON
  • EVENT_FLAG_CTRLKEY
  • EVENT_FLAG_SHIFTKEY
  • EVENT_FLAG_ALTKEY

ちなみに,C++バージョンはこちら
whitecat-student.hatenablog.com