이번 시간에는 opencv 에서의 키보드,마우스 이벤트에 다뤄 보겠습니다.
1. 키보드 이벤트
● 키보드 입력 대기
cv2.waitKey(delay=None) -> retval
delau 매개변수에서 ms(밀리세컨즈) 단위 시간은 (1초=1000)입니다.
delay <= 0 이면 무한대기인데요.
별도의 값을 입력하지 않으면 default 인 None으로 입력이 되는데 이는 무한대기를 의미합니다.
특정키 입력은 ord() 함수를 활용합니다.
'q' 를 누르면 영상의 밝기가 반전되도록 해보는 예제를 진행해보겠습니다.
위의 원본 이미지를 grayscale 한 다음에 반전을 시켜보겠습니다.
grayscale 이미지의 ~ 표시를 붙여주면 반전이 됩니다.
이를 활용한 위의 결과를 보여주는 코드는 아래와 같습니다.
import os
import cv2
path = os.path.join('my_images', '고양이.jpg')
img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
cv2.namedWindow('image1', cv2.WINDOW_NORMAL)
cv2.imshow('image1', img)
cv2.moveWindow('image1', 200, 200)
cv2.resizeWindow('iamge1', 700, 900)
while True:
key = cv2.waitKey()
if key == ord('q'):
img = ~img
cv2.imshow('image1', img)
elif key == 27:
break
cv2.destroyAllWindows()
두 번째 예제는 컬러 영상을 입력 받고 이를 w 버튼을 눌러서 BRG 영상을 RGB 로 바꾸고, 다시 w 를 누르면 RGB 를 BRG 으로 바꾸는 예제를 작성해보겠습니다.
코드는 아래와 같습니다.
import os
import cv2
path = os.path.join('my_images', '고양이.jpg')
img = cv2.imread(path)
cv2.imshow('image1', img)
while True:
key = cv2.waitKey()
if key == ord('w'):
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
cv2.imshow('image1', img)
elif key == 27:
break
cv2.destroyAllWindows()
2. 마우스 이벤트
마우스 이벤트는 키보드 이벤트보다는 조금(?) 복잡합니다.
setMouseCallback 함수를 사용하여 특정 윈도우를 위한 콜백함수를 지정해주면 마우스 이벤트가 발생할 때마다 콜백함수가 호출됩니다. 이 말이 조금 어렵게 느껴지시는 분들이 있을까 비유를 하자면, 보통 저희가 파이썬으로 어떤 문제를 해결하려는 기능이 들어간 함수를 def main(*kwargs)처럼 만든 다음 마지막에
f __name__=="__main"__
def main(*kwargs)
으로 불러서 사용하는거와 같은 느낌으로 이해하시면 됩니다. (느낌만을 얘기한건데, 음 저 비유 자체를 이해하는 사람이라면 콜백함수 호출해서 사용한다는 말 자체도 이해를 당연히 하겠네요...;;;)
● 마우스 콜백함수 등록 함수
cv2.setMouseCallback(windowName, mouse_fn, param=None)
windowName : 마우스 이벤트를 실행할 윈도우 이름
onMouse
- 마우스 이벤트 처리를 위한 콜백 함수
마우스 이벤트 콜백함수는 아래 형식을 따릅니다.
mouse(event, x, y , flags, param)
- param: 콜백 함수에 전달할 데이터
● 마우스 콜백함수
mouse(event, x, y, flags, param)
event: 마우스 이벤트 type
x, y : 마우스 이벤트가 발생한 x, y 좌표
flag: 마우스 이벤트 발생시 상태
param: 콜백 함수에 전달할 데이터
※ 이벤트 타입 리스트
MouseEventTypes | value | 설명 |
cv2.EVENT_MOUSEMOVE | 0 | 마우스가 창 위에서 움직이는 경우 |
cv2.EVENT_LBUTTONDOWN | 1 | 마우스 왼쪽 버튼이 눌려지는 경우 |
cv2.EVENT_RBUTTONDOWN | 2 | 마우스 오른쪽 버튼이 눌려지는 경우 |
cv2.EVENT_MBUTTONDOWN | 3 | 마우스 가운데 버튼이 눌려지는 경우 |
cv2.EVENT_LBUTTONUP | 4 | 마우스 왼쪽 버튼이 떼어지는 경우 |
cv2.EVENT_RBUTTONUP | 5 | 마우스 오른쪽 버튼이 떼어지는 경우 |
cv2.EVENT_MBUTTONUP | 6 | 마우스 가운데 버튼이 떼어지는 경우 |
cv2.EVENT_LBUTTONDBLCLK | 7 | 마우스 왼쪽 버튼을 더블클릭하는 경우 |
cv2.EVENT_RBUTTONDBLCLK | 8 | 마우스 오른쪽 버튼을 더블클릭하는 경우 |
cv2.EVENT_MBUTTONDBLCLK | 9 | 마우스 가운데 버튼을 더블클릭 하는 경우 |
cv2.EVENT_MOUSEWHEEL | 10 | 마우스 휠을 앞뒤로 돌리는 경우 |
※ 이벤트 Flag 타입 리스트
MouseEventFlags | value | 설명 |
cv2.EVENT_FLAG_LBUTTON | 1 | 마우스 왼쪽 버튼이 눌려져 있음 |
cv2.EVENT_FLAG_RBUTTON | 2 | 마우스 오른쪽 버튼이 눌려져 있음 |
cv2.EVENT_FLAG_MBUTTON | 2 | 마우스 가운데 버튼이 눌려져 있음 |
cv2.EVENT_FLAG_CTRLKEY | 8 | CTRL 키가 눌려져 있음 |
cv2.EVENT_FLAG_SHIFTKEY | 16 | SHIFT 키가 눌려져 있음 |
cv2.EVENT_FLAG_ALTKEY | 32 | ALT 키가 눌려져 있음 |
자, 이제 이를 활용하여 영상을 마우스로 드레그한 영역을 grayscale 로 변환해주는 새로운 윈도우에 띄우는 프로그램을 만들어보겠습니다. 우선, 결과를 먼저 보겠습니다.
좌측의 원본 이미지에서 마우스로 드래그하면 우측에 새로운 윈도우 창이 나오면서 해당 부분만 grayscale 로 바꿔주는 걸 확인할 수 있습니다.
'''영상을 마우스로 드레그한 영역을 grayscale 로 변환하여 새로운 윈도우에 띄우는 프로그램 개발'''
import os
import cv2
# 마우스 왼쪽 버튼 상태 체크를 위한 변수
mouse_is_pressing = False
# 최초로 마우스 왼쪽 버튼 누른 위치를 저장하기 위해 사용
start_x, start_y = -1, -1
def mouse_callback(event, x, y, flags, param):
global mouse_is_pressing, start_x, start_y
img_result = img_color.copy()
# 마우스 왼쪽 버튼 누를 시 발생 이벤트
if event == cv2.EVENT_LBUTTONDOWN:
mouse_is_pressing = True
start_x, start_y = x, y
cv2.circle(img_result, (x, y), 10, (0, 0, 255), -1)
cv2.imshow('img_color', img_result)
# 마우스 이동시 발생하는 이벤트
elif event == cv2.EVENT_MOUSEMOVE:
if mouse_is_pressing:
# 마우스 이동하는 조건인 true 동안 rectangle 그리기
cv2.rectangle(img_result, (start_x, start_y),
(x, y), (0, 0, 255), -1)
cv2.imshow('img_color', img_result)
# 마우스 왼쪽 버튼에서 손을 떼면 발생하는 이벤트
elif event == cv2.EVENT_LBUTTONUP:
mouse_is_pressing = False
# min, max가 들어가는 이유는 클릭을 한 뒤에 마우스의 이동방향이 상하좌우 아무 방향으로든 향할 수 있다. 이 때, grayscale 이 적용되는 일부 픽셀을 선택하고 추출해서 변수화.
img_cat = img_color[min(start_y, y):max(start_y, y), min(start_x, x): max(start_x, x)]
img_cat = cv2.cvtColor(img_cat, cv2.COLOR_BGR2GRAY)
img_cat = cv2.cvtColor(img_cat, cv2.COLOR_GRAY2BGR)
img_result[min(start_y, y):max(start_y, y), min(start_x, x): max(start_x, x)] = img_cat
# 그림에 대한 세가지 객체가 존재합니다. img_color(원본), img_result(원본에서 일부 픽셀에 grayscale 적용되어 변한 사본), img_cat (gray scale 적용된 일부 픽셀)
cv2.imshow('img_result', img_result)
cv2.imshow('img_cat', img_cat)
path = os.path.join('my_images', '고양이.jpg')
img_color = cv2.imread(path)
# 최초의 영상
cv2.imshow('img_color', img_color)
cv2.setMouseCallback('img_color', mouse_callback)
cv2.waitKey()
cv2.destroyAllWindows()
위 코드를 실행하면 앞에 나온 보여준 이미지 2개만 나오지 않고, 3개가 나오는데 이는 공부하시는 분의 이해를 돕고자 그렇게 바꿨습니다. 잠시 위 코드 실행 결과를 보여주면,
마우스 클릭과 드래그 할때는 좌측의 원본 'img_color' 이미지에 원과 직사각형이 그려지고 마우스 왼쪽 버튼에서 손을 떼면 가운데 이미지와 오른쪽 이미지가 생성됩니다.
img_color 가 윈도우에서 바로 변하게 하려면 왼쪽버튼에서 손을 떼는 조건문이 있는 부분에서 imshow 부분을 바꿔주면 됩니다.
'머신러닝,딥러닝 > opencv' 카테고리의 다른 글
opencv 입문하기 6편 트랙바, 산술 연산 (0) | 2020.07.26 |
---|---|
opencv 입문하기 5편 마우스 이벤트(2) (0) | 2020.07.26 |
opencv 입문하기 3편 영상생성,추출, 그리기 함수 (0) | 2020.07.21 |
opencv 입문하기 2편 - 이미지 객체 속성 , 픽셀값 변경 (0) | 2020.07.20 |
opencv 입문하기 1편 - 이미지 reading (0) | 2020.07.20 |