Python과 OpenCV – 4 : 마우스 이벤트

원문은 https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_gui/py_mouse_handling/py_mouse_handling.html 입니다.

이미지 처리를 위해 OpenCV에서는 자체적인 마우스 이벤트 체계를 가지고 있습니다. 마우스 이벤트는 cv2.setMouseCallback 함수를 통해 마우스 이벤트를 처리할 Window에 등록됩니다. 먼저 간단한 예를 통해 살펴보겠습니다.

import cv2
import numpy as np

def draw_circle(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDBLCLK:
        cv2.circle(img,(x,y),100,(255,0,0),-1)

img = np.zeros((512,512,3), np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)

while(1):
    cv2.imshow('image',img)
    if cv2.waitKey(20) & 0xFF == 27:
        break

cv2.destroyAllWindows()

위의 프로그램은 Window 위에서 마우스 버튼을 더블클릭하면 해당 지점에서 파란색 큰 원을 그립니다.

좀더 복잡한 예제를 살펴보겠습니다.

import cv2
import numpy as np

drawing = False
mode = True
ix, iy = -1, -1

def draw_circle(event,x,y,flags,param):
    global ix, iy, drawing, mode

    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        ix, iy = x, y

    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing == True:
            if mode == True:
                cv2.rectangle(img, (ix,iy), (x,y), (0,255,0), -1)
            else:
                cv2.circle(img, (x,y), 5, (0,0,255), -1)

    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        if mode == True:
            cv2.rectangle(img, (ix,iy), (x,y), (0,255,0), -1)
        else:
            cv2.circle(img, (x,y), 5, (0,0,255), -1)

img = np.zeros((512,512,3), np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image', draw_circle)

while(1):
    cv2.imshow('image', img)
    k = cv2.waitKey(1) & 0xFF
    if k == ord('m'):
        mode = not mode
    elif k == 27:
        break

cv2.destroyAllWindows()

위의 프로그램은 마우스 드래그를 이용해 사각형과 원을 그릴 수 있는데, m 키를 눌러 그리고자 하는 원과 사각형을 결정할 수 있습니다.

Python과 OpenCV – 3 : 코드로 이미지에 도형 그리기

참조한 글은 https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_gui/py_drawing_functions/py_drawing_functions.html 입니다.

이미지는 사진이나 동영상을 통해 얻을 수도 있지만 코드를 통해서도 생성할 수 있습니다. 아래의 코드는 512×512 크기의 3개의 채널로 되어 있으며 채널의 구성 데이터 타입은 unit8입니다.

import numpy as np
import cv2

img = np.zeros((512,512,3), np.uint8)

이 이미지 위에 다양한 도형을 그리는 코드를 정리해 볼텐데요. 먼저 두점으로 구성된 선분을 그리는 코드입니다.

cv2.line(img, (0,0), (512,512), (255,0,0), 5)

위의 코드는 좌표(0,0)에서 좌표(512,512)로 구성된 선분을 색상은 (B,G,R) 순서인 (255,0,0)인 파란색으로 굵기는 5pixel로 그립니다. 다음 코드는 사각형을 그리는 코드입니다.

cv2.rectangle(img, (384,0), (510,128), (0,255,0), 3)

위의 코드는 좌상단 (384,0)과 우하단 (510,128)인 지사각형을 초록색(0,255,0)으로 3Pixel 굵기로 그립니다. 다음은 원을 그리는 코드입니다.(

cv2.circle(img, (447,63), 63, (0,0,255), -1)

위의 코드는 중심점 (447,63)이고 반지름은 63인 원을 빨간색(0,0,255)으로 하여 굵기속성은 -1로 함으로써 도형을 채움형태로 그리는 코드입니다. 다음은 타원을 그리는 코드입니다.

cv2.ellipse(img, (256,256), (100,50), 45,0,180,(0,0,255),-1)

위의 코드는 중심점이 (256,256)이고 가로 반지름과 세로 반지름을 각각 (100,50)이며, 45도 시계방향으로 회전하고 시작각 0도 종료각 180도인 타원을 빨간색(0,0,255)로 채워진(-1) 타원을 그리는 코드입니다. 다음은 폴리라인을 그리는 코드입니다.

pts = np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)
pts = pts.reshape((-1,1,2))
cv2.polylines(img, [pts], True, (0,255,255))

위의 코드는 총 4개의 좌표로 구성된 pts를 이용해 색상은 BRG값이 각각 (0,255,255)로 하여 폴리곤을 그리는 코드인데.. cv2.polylines의 3번째를 True로 지정하여 폐합(시작점과 끝점을 연결)하도록 그립니다. 마지막으로 문자를 그리는 코드입니다.

font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, 'OpenCV', (10,500), font, 4, (255,255,255), 2)

위치 (10,500)에 OpenCV라는 문자열을 폰트 크기 4로 하여 백색(255,255,255)로 하여 굵기는 2로 그리는 코드입니다.

지금까지 그린 이미지를 화면에 표시하기 위해 아래의 코드를 덧붙입니다.

cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()