본문 바로가기
강의 (Lecture)/OpenCV 마스터 with Python (초급)

OpenCV + Python 마우스 및 키보드 이벤트 처리와 트랙바 활용하기

by codingwalks 2024. 9. 28.
728x90
반응형

안녕하세요. 코딩산책입니다.

이벤트 처리는 사용자와 프로그램 간의 상호작용을 가능하게 해주는 중요한 요소입니다. OpenCV에서도 이러한 이벤트 처리 기능을 통해 이미지와 비디오를 보다 직관적으로 조작할 수 있습니다. 마우스 클릭이나 키보드 입력을 감지하여 특정 동작을 수행하게 하거나, 트랙바를 통해 동적으로 값을 변경하여 프레임을 제어하는 등의 작업이 가능합니다. 특히 동영상 재생 시, 트랙바를 사용해 원하는 프레임으로 바로 이동하는 기능은 비디오 편집 프로그램이나 분석 도구에 유용하게 쓰일 수 있습니다.

이 글에서는 Python과 OpenCV를 사용해 마우스 및 키보드 이벤트를 처리하고, 트랙바를 활용하여 동영상 프레임을 이동하는 방법을 살펴보겠습니다.

 

1. 마우스 이벤트 처리

OpenCV에서는 setMouseCallback() 콜백(Callback) 함수를 사용하여 창에 발생하는 마우스 이벤트를 처리할 수 있습니다. 또한, 함수의 파라미터로 param에 매개 변수를 전달하면 전달된 변수를 사용하여 추가적인 작업이 가능합니다. 마우스 이벤트에는 다양한 이벤트가 있으며, 그중 자주 사용되는 이벤트는 다음과 같습니다.

자주 사용되는 이벤트

cv2.EVENT_LBUTTONDOWN 왼쪽 마우스 버튼이 눌릴 때 발생
cv2.EVENT_RBUTTONDOWN 오른쪽 마우스 버튼이 눌릴 때 발생
cv2.EVENT_MOUSEMOVE 마우스 커서가 창 안에서 움직일 때 발생

자주 사용되는 플래그

cv2.EVENT_FLAG_LBUTTON 마우스 왼쪽 버튼이 눌린 상태
cv2.EVENT_FLAG_RBUTTON 마우스 오른쪽 버튼이 눌린 상태
cv2.EVENT_FLAG_MBUTTON 마우스 가운데 버튼이 눌린 상태
cv2.EVENT_FLAG_CTRLKEY Ctrl 키가 눌린 상태
cv2.EVENT_FLAG_SHIFTKEY Shift 키가 눌린 상태
cv2.EVENT_FLAG_ALTKEY Alt 키가 눌린 상태

키보드 이벤트 처리 예제 코드

import cv2
import numpy as np

# Mouse event handler function
def mouse_event(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
    	print(f"Left button clicked at ({x}, {y})")
    	if flags & cv2.EVENT_FLAG_SHIFTKEY:
        	cv2.rectangle(param, (x-5,y-5), (x+5,y+5), (0,0,255), 2)
        else:
        	cv2.circle(param, (x,y), 5, (0,0,255), 2)
    elif event == cv2.EVENT_RBUTTONDOWN:
        print(f"Right button clicked at ({x}, {y})")
        cv2.circle(param, (x, y), 5, (0, 0, 0), 2)
    elif event == cv2.EVENT_MOUSEMOVE:
        print(f"Mouse moved at ({x}, {y})")
        cv2.circle(param, (x, y), 1, (0, 255, 0), 2)

# Create a blank image
img = 255 * np.ones((300, 300, 3), dtype=np.uint8)
    
# Create an empty window
cv2.namedWindow('Mouse Event Window')

# Setting the mouse callback function
cv2.setMouseCallback('Mouse Event Window', mouse_event, img)

while True:    
    cv2.imshow('Mouse Event Window', img)
    # Exit with ESC key
    if cv2.waitKey(1) & 0xFF == 27:
        break

cv2.destroyAllWindows()

Mouse Event Example

 

사용 가능한 추가적인 마우스 이벤트

cv2.EVENT_LBUTTONUP 왼쪽 마우스 버튼을 뗄 때 발생
cv2.EVENT_RBUTTONUP 오른쪽 마우스 버튼을 뗄 때 발생
cv2.EVENT_LBUTTONDBLCLK 왼쪽 마우스 버튼을 더블 클릭할 때 발생
cv2.EVENT_RBUTTONDBLCLK 오른쪽 마우스 버튼을 더블 클릭할 때 발생
cv2.EVENT_MBUTTONDOWN 가운데(휠) 마우스 버튼이 눌릴 때 발생
cv2.EVENT_MBUTTONUP 가운데 마우스 버튼이 떼어질 때 발생
cv2.EVENT_MBUTTONDBLCLK 가운데 마우스 버튼이 더블 클릭될 때 발생
cv2.EVENT_MOUSEWHEEL 마우스 휠을 위로 굴릴 때 발생 (전방향)
cv2.EVENT_MOUSEHWHEEL 마우스 휠을 좌우로 움직일 때 발생 (수평 방향)

이러한 추가적인 마우스 이벤트를 통해 사용자는 보다 다양한 마우스 입력을 감지하고 처리할 수 있습니다. 예를 들어 더블 클릭을 사용하여 특정 기능을 빠르게 실행하거나, 마우스 휠을 통해 줌 기능을 구현할 수 있습니다.

모든 마우스 이벤트를 처리하는 예제 코드

import cv2
import numpy as np

# A function that handles all mouse events
def mouse_event(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        print(f"Left button down at ({x}, {y})")
    elif event == cv2.EVENT_LBUTTONUP:
        print(f"Left button released at ({x}, {y})")
    elif event == cv2.EVENT_RBUTTONDOWN:
        print(f"Right button down at ({x}, {y})")
    elif event == cv2.EVENT_RBUTTONUP:
        print(f"Right button released at ({x}, {y})")
    elif event == cv2.EVENT_LBUTTONDBLCLK:
        print(f"Left button double clicked at ({x}, {y})")
    elif event == cv2.EVENT_RBUTTONDBLCLK:
        print(f"Right button double clicked at ({x}, {y})")
    elif event == cv2.EVENT_MBUTTONDOWN:
        print(f"Middle button down at ({x}, {y})")
    elif event == cv2.EVENT_MBUTTONUP:
        print(f"Middle button released at ({x}, {y})")
    elif event == cv2.EVENT_MBUTTONDBLCLK:
        print(f"Middle button double clicked at ({x}, {y})")
    elif event == cv2.EVENT_MOUSEMOVE:
        print(f"Mouse moved to ({x}, {y})")
    elif event == cv2.EVENT_MOUSEWHEEL:
        print(f"Mouse wheel scrolled vertically at ({x}, {y})")
    elif event == cv2.EVENT_MOUSEHWHEEL:
        print(f"Mouse horizontal wheel scrolled at ({x}, {y})")

# Create an empty window
cv2.namedWindow('Mouse Event Window')

# Setting the mouse callback function
cv2.setMouseCallback('Mouse Event Window', mouse_event)

while True:
    # Display a blank image in the window
    img = 255 * np.ones((300, 300, 3), dtype=np.uint8)
    cv2.imshow('Mouse Event Window', img)

    # Exit with ESC key
    if cv2.waitKey(1) & 0xFF == 27:
        break

cv2.destroyAllWindows()

 

2. 키보드 이벤트 처리

OpenCV에서는 waitKey() 함수를 사용하여 키보드 이벤트를 처리할 수 있습니다. 특정 키를 눌렀을 때 발생하는 동작을 지정할 수 있습니다. 일반적으로 ord() 함수를 사용하여 특정 문자의 ASCII 값을 비교합니다.

키보드 이벤트 처리 예제 코드

import cv2
import numpy as np

cv2.namedWindow('Keyboard Event Window')

while True:
    img = 255 * np.ones((300, 300, 3), dtype=np.uint8)
    cv2.imshow('Keyboard Event Window', img)

    key = cv2.waitKey(1) & 0xFF
    if key == ord('q'):
        print("Key 'q' pressed - Exiting")
        break
    elif key == ord('s'):
        print("Key 's' pressed - Saving image")
        cv2.imwrite('saved_image.jpg', img)
        
cv2.destroyAllWindows()

 

3. 트랙바 활용

트랙바는 OpenCV에서 슬라이더를 만들고 이를 통해 변수 값을 동적으로 조절할 수 있는 도구입니다. 트랙바는 createTrackbar() 함수를 사용하여 생성합니다. 이를 통해 사용자 입력에 따라 실시간으로 변수 값을 변경할 수 있습니다.

트랙바 생성 시 중요한 인수:

트랙바 이름
트랙바가 속할 창 이름
최소값, 최대값 설정
트랙바 위치 변경 시 호출될 콜백 함수

 

트랙바 예제 코드 (단순 슬라이더)

import cv2
import numpy as np

# Trackbar callback function
def on_trackbar(val):
    print(f"Trackbar value: {val}")

cv2.namedWindow('Trackbar Window')

# Create trackbar (name, window name, initial value, maximum value, callback function)
cv2.createTrackbar('Slider', 'Trackbar Window', 0, 100, on_trackbar)

while True:
    img = 255 * np.ones((300, 300, 3), dtype=np.uint8)
    cv2.imshow('Trackbar Window', img)

    if cv2.waitKey(1) & 0xFF == 27:
        break

cv2.destroyAllWindows()

 

4. 트랙바로 비디오 프레임 이동 제어하기

트랙바를 활용하여 비디오 파일에서 특정 프레임으로 이동할 수 있는 기능을 구현할 수 있습니다. 이는 비디오 재생을 보다 쉽게 제어할 수 있게 해 줍니다.

비디오 파일을 트랙바로 제어하는 예제 코드

import cv2

# Trackbar callback function (frame change)
def on_trackbar(val):
    global cap
    cap.set(cv2.CAP_PROP_POS_FRAMES, val)

# Load video file
cap = cv2.VideoCapture('resources/TownCentreXVID.mp4')

# Check if the video file is opened
if not cap.isOpened():
    print("Error: Unable to open video file")
    exit()

# Total number of frames
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

# Create a window and set up the trackbar
cv2.namedWindow('Video Control')
cv2.createTrackbar('Frame', 'Video Control', 0, total_frames - 1, on_trackbar)

while True:
    ret, frame = cap.read()
    
    # End when end of video file is reached
    if not ret:
        break
    
    # Set current trackbar position
    current_frame = int(cap.get(cv2.CAP_PROP_POS_FRAMES))
    cv2.setTrackbarPos('Frame', 'Video Control', current_frame)

    # Frame display
    cv2.imshow('Video Control', frame)
    
    # Exit with ESC key
    if cv2.waitKey(1) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

Video Frame Trackbar

 

5. 결론

OpenCV에서 마우스 이벤트, 키보드 이벤트, 트랙바를 활용하는 방법을 알아보았습니다. 이러한 이벤트 처리 및 인터페이스를 사용하면 이미지 및 비디오를 보다 상호작용적으로 제어할 수 있습니다. 특히 트랙바를 통해 비디오 프레임을 제어하는 기능은 실용적이며, 다양한 애플리케이션에 적용할 수 있습니다. 이 예제를 통해 OpenCV의 이벤트 처리 및 사용자 인터페이스 구현에 대한 이해를 높일 수 있기를 바랍니다.

 

해당 포스트가 유용하셨다면 하단의 좋아요와 구독하기 부탁드립니다. ^^

Buy me a coffee

 

[Codingwalks]에게 송금하기 - AQR

[Codingwalks]에게 송금하기 - AQR

aq.gy

728x90
반응형