Program/OPEN_CV

[Open CV] OpenCV-Python 기초 사용법 _ 마우스 이벤트 처리하기

사막여유 2022. 5. 2. 23:25
728x90

 

OpenCV에서 일반적으로 띄우는 window 창에서는 마우스 이벤트를 사용할 수 있는데이는 우리가 마우수를 사용해서 어떤 동작을하게될때 보통은 무시가되는데setMouseCalllback 함수를 사용하여 그 동작을 돌려받아 다른 기능을 할수 있다.

 

그래서 콜백함수를 등록한 뒤 사용할 수 있는데

seMouseCallBack ( windowName, onMouse, param = None ) 의 인자를 갖고있다.

windowName은 마우스 이벤트를 실행 할 윈도우창의 이름이고

onMouse는 콜백함수의 이름을 지정해줄 수 있는 인자이다. 그리고 마지막에 있는

param 인자는 콜백함수에 전달할 데이터를 의미힌다.

 

여기서 onMouse 이벤트 처리함수의 형식을 따라서 만들어줘야하는데

onMouse ( event, x, y, flags, param ) 의 인자를 갖고있다.

event 라는 것인 마우스 이벤트의 종류를 나타내는데 아래와같은 종류를 사용할 수 있다.

 

 

그리고 x,y의 인자는 해당 마우스의 좌표를 의미한다.

 * 모니터 전체에 대한 좌표가 아닌 내가 띄운 창의 상대좌표 ( 픽셀 좌표 ) 를 의미한다.

 

flag는 마우스 이벤트 발생시 키보드 또는 마우스의 상태를 나타내는게 이게 무슨 말이냐면

예를 들면 마우스를 움직일때 컨트롤키 또는 쉬프트키등의 키보드를 함께 동작하게 되는 것을 지정해줄 수 있다.

 

 

위 flag는 event와 다르게 1,2,4,8,16,32의 값으로 구성되어있는데 이는 비트단위와 관련있다고 볼 수 있다.

위같이 비트단위를 사용하는 이유는 

예를들어 Ctrl와 왼쪽마우스클릭을 동시에 사용하는 경우를 대비하여 위와같이 만들어 놓은 것이다.

그래서 이 flag값을 그냥 비교하는게 아니고

논리연산자를 사용하여 값을 비교하는 것을 이후 코드에서 볼 수 있다.

 

마지막으로 param 은 이전 setMouseCallBack 에서 param의 인자값을 그대로 받아오게 된다.

 

아래에는 ones라고 하는 numpy 함수를 이용해서 1로 채워져있는 컬러 영상을 생성하고

255로 픽셀을 채워주는 함수를 사용하여 img라는 흰 컬러영상을 만든 뒤 waitkey로 대기시킨다.

 * setMouseCallback 함수는 이미지가 show되어있는 상태에서 호출 해야한다.

 

그 전에 on_mouse라는 변수를 생성해줘야하는데 가장 처음 

on_mouse라는 변수를 define 해준다.

 

그리고 event 의 LBUTTONDOWN 인자 LBUTTONUP 인지 MOVE인지를 값을 받아

처리해줄수 있는데 아래와 같이 만들어볼 수 있다.

 

 

 

그런데 위와같이 EVENT_MOUSEMOVE 이벤트를 사용하게 되면 마우스를 움직일때마다 print 되게되어 불편함이 있는데

그래서 이는 flag의 인자를 사용하여 마우스의 어떤 버튼이 눌려있는지 아니면 키보드의 어떠한 버튼이 눌려져있는지를 

함께 보고 처리할 수 있다.

    elif(event == cv2.EVENT_MOUSEMOVE):
        if flags == cv2.EVENT_FLAG_LBUTTON:
            print('event_move:{},{}'.format(x,y))

따라서 위와같이 왼쪽 마우스가 눌려져 있을때만 PRINT 하도록 할 수 있는데 이렇게 코딩하면 다른 키보드나 마우스의 입력이 들어왔을때 인식하지 못하기때문에 

위에 적었었던 것처럼 == 이 아닌 &의 비트연산자를 사용해야 한다.

 

그리고 이를 이용하여 그림을 그릴 수 있다.

픽셀에 점을 찍는 형식으로도 사용할 수 있고 cv2.circle을 사용하여 그려줄 수도 있다.

    elif(event == cv2.EVENT_MOUSEMOVE):
        if flags & cv2.EVENT_FLAG_LBUTTON:
            #print('event_move:{},{}'.format(x,y))
            cv2.circle(img, (x,y), 5, (0,0,255), -1)
            cv2.imshow('image',img)

위와같이 코드를 작성하고 실제로 그림을 그려보면

 

위와같은 이미지가 생성되는데 이는 마우스 이벤트가 실시간으로 처리하지 못하기때문에 발생되는 현상이다.

            cv2.line(img,(oldx,oldy),(x,y),(0,0,255),5)
            cv2.imshow('image',img)
            oldx, oldy = x, y

그래서 위와같이 시작점과 끝점의 직선을 긋는 방식으로 많이 사용한다.

( oldx , oldy 는 MouseLftDown 이벤트에서 생성해준다. )

 

cv2.LINE_AA

 

 

 

 

 

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.

https://bit.ly/3L3avNW

 

패스트캠퍼스 [직장인 실무교육]

프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.

fastcampus.co.kr

 

728x90