Python/파이썬 OpenCV 공부

[파이썬 OpenCV] 마우스를 이용해 그리기 - cv2.setMouseCallback

AI 꿈나무 2020. 9. 27. 12:24
반응형

황선규 박사님의 OpenCV 강의를 공부하면서 정리하였습니다.

 


마우스 이벤트 처리하기

 마우스 이벤트 처리하는 방법을 알아보고 마우스를 이용해 그림을 그려보도록 하겠습니다.

 

1. 마우스 이벤트 콜백함수 등록함수 - cv2.setMouseCallback

 마우스 이벤트가 입력되면 사전에 작성한 함수를 불러와서 작동시킵니다.

 

[함수 설명]

cv2.setMouseCallback(windowName, onMouse, param=None) -> None

 

• windowName: 마우스 이벤트 처리를 수행할 창 이름

• onMouse: 마우스 이벤트 처리를 위한 콜백 함수 이름. 

• param: 콜백 함수에 전달할 데이터

 

[예시 코드]

# 윈도우 창
cv2.namedWindow('image')

# 마우스 입력, namedWIndow or imshow가 실행되어 창이 떠있는 상태에서만 사용가능
# 마우스 이벤트가 발생하면 on_mouse 함수 실행
cv2.setMouseCallback('image', on_mouse, img)

 

2. 마우스 이벤트 콜백함수 - onMouse

 마우스 입력 값에 따라 어떤 동작을 실행할 것인지 지정하는 함수입니다.

 지정해둔 함수를 cv2.setMouseCallback함수로 등록해서 사용할 수 있습니다.

 

[함수 설명]

onMouse(event, x, y, flags, param) -> None

 

• event: 마우스 이벤트 종류. cv2.EVENT_로 시작하는 상수.

• x: 마우스 이벤트가 발생한 x 좌표

• y: 마우스 이벤트가 발생한 y 좌표

• flags: 마우스 이벤트 발생 시 상태. cv2.EVENT_FLAG_로 시작하는 상수

• param: cv2.setMouseCallback() 함수에서 설정한 데이터

 

[예시 코드]

def on_mouse(event, x, y, flags, param):
    # event는 마우스 동작 상수값, 클릭, 이동 등등
    # x, y는 내가 띄운 창을 기준으로 좌측 상단점이 0,0이 됌
    # flags는 마우스 이벤트가 발생할 때 키보드 또는 마우스 상태를 의미, Shif+마우스 등 설정가능
    # param은 영상이룻도 있도 전달하고 싶은 데이타, 안쓰더라도 넣어줘야함

    global oldx, oldy 함수 밖에 있는 oldx, oldy 불러옴

    if event == cv2.EVENT_LBUTTONDOWN: # 왼쪽 클릭시 실행
        oldx, oldy = x, y # 마우스가 눌렀을 때 좌표 저장, 띄워진 영상에서의 좌측 상단 기준
        print('EVENT_LBUTTONDOWN: %d, %d' % (x, y)) # 좌표 출력

    elif event == cv2.EVENT_LBUTTONUP: # 마우스 클릭하고 뗏을때 발생
        print('EVENT_LBUTTONUP: %d, %d' % (x, y)) # 좌표 출력

    elif event == cv2.EVENT_MOUSEMOVE: # 마우스가 움직일 때 발생
        if flags & cv2.EVENT_FLAG_LBUTTON: # ==를 쓰면 다른 키도 입력되었을 때 작동안하므로 &(and) 사용
            # cv2.circle(img, (x, y), 5, (0, 255, 0), -1) # 단점이 빠르게 움직이면 끊김

            # circle은 끊기므로 line 이용
            # 마우스 클릭한 좌표에서 시작해서 마우스 좌표까지 그림
            cv2.line(img, (oldx, oldy), (x, y), (0, 0, 255), 4, cv2.LINE_AA)
            cv2.imshow('image', img)
            oldx, oldy = x, y # 그림을 그리고 또 좌표 저장

 

 이처럼 마우스를 이용해 그림을 그릴 수 있는 함수를 만들었습니다.

 함수 이름은 onMouse가 아니어도 됩니다.

 

3. 마우스 이벤트 처리 함수의 event, flags 인자

 onMouse에 입력값은 event, flags 인자에 대해 알아보겠습니다.

 

 

 

4. 마우스를 이용해 그리기

 앞에서 열거한 코드들을 조합하여 마우스를 이용해 그림을 그려보겠습니다.

 

[코드]

import sys
import numpy as np
import cv2


oldx = oldy = -1 # 좌표 기본값 설정

# 내가 만든 마우스 함수를 실행시켜줘


def on_mouse(event, x, y, flags, param):
    # event는 마우스 동작 상수값, 클릭, 이동 등등
    # x, y는 내가 띄운 창을 기준으로 좌측 상단점이 0,0이 됌
    # flags는 마우스 이벤트가 발생할 때 키보드 또는 마우스 상태를 의미, Shif+마우스 등 설정가능
    # param은 영상이룻도 있도 전달하고 싶은 데이타, 안쓰더라도 넣어줘야함

    global oldx, oldy # 밖에 있는 oldx, oldy 불러옴

    if event == cv2.EVENT_LBUTTONDOWN: # 왼쪽이 눌러지면 실행
        oldx, oldy = x, y # 마우스가 눌렀을 때 좌표 저장, 띄워진 영상에서의 좌측 상단 기준
        print('EVENT_LBUTTONDOWN: %d, %d' % (x, y)) # 좌표 출력

    elif event == cv2.EVENT_LBUTTONUP: # 마우스 뗏을때 발생
        print('EVENT_LBUTTONUP: %d, %d' % (x, y)) # 좌표 출력

    elif event == cv2.EVENT_MOUSEMOVE: # 마우스가 움직일 때 발생
        if flags & cv2.EVENT_FLAG_LBUTTON: # ==를 쓰면 다른 키도 입력되었을 때 작동안하므로 &(and) 사용
            # cv2.circle(img, (x, y), 5, (0, 255, 0), -1) # 단점이 빠르게 움직이면 끊김

            # circle은 끊기므로 line 이용
            # 마우스 클릭한 좌표에서 시작해서 마우스 좌표까지 그림
            cv2.line(img, (oldx, oldy), (x, y), (0, 0, 255), 4, cv2.LINE_AA)
            cv2.imshow('image', img)
            oldx, oldy = x, y # 그림을 그리고 또 좌표 저장


# 흰색 컬러 영상 생성
img = np.ones((480, 640, 3), dtype=np.uint8) * 255

# 윈도우 창
cv2.namedWindow('image')

# 마우스 입력, namedWIndow or imshow가 실행되어 창이 떠있는 상태에서만 사용가능
# 마우스 이벤트가 발생하면 on_mouse 함수 실행
cv2.setMouseCallback('image', on_mouse, img)


# 영상 출력
cv2.imshow('image', img)
cv2.waitKey()

cv2.destroyAllWindows()

 

[결과]

 

출력된 좌표값

 

반응형