본문 바로가기
CV(Computer Vision)

동영상 처리

by 코낄2 2024. 2. 9.

1. 동영상 처리하기

OpenCV(Open Source Computer Vision Library)를 사용하면 동영상 처리를 쉽게 할 수 있습니다. 동영상 처리는 주로 cv2.VideoCapture 클래스를 사용하여 카메라 또는 동영상 파일에서 프레임을 받아오고, 필요한 처리를 수행하는 과정을 포함합니다.

카메라 영상 입력

cap = cv2.VideoCapture(index)

# 카메라에 연결 여부 확인
if not cap.isOpened():
    print("카메라를 열 수 없습니다.")
else:
    print("카메라 연결 성공!")

여기서 index는 시스템의 기본 카메라는 0, 별도의 카메라를 열기 위해서는 해당 카메라의 고유 인덱스 값을 사용합니다.

cv2.VideoCapture.isOpened() : 카메라에 연결이 되었는지 여부를 확인합니다. True/False를 반환합니다.

width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

cv2.CAP_PROP_FRAME_WIDTH: 카메라로 읽어들인 영상의 가로 사이즈
cv2.CAP_PROP_FRAME_HEIGHT: 카메라로 읽어들인 영상의 세로 사이즈

 

cv2.VideoCapture.read() : 두가지의 값을 반환합니다.
    - ret: 영상이 정상적으로 리턴되었는지 여부(True, False)
    - frame: 영상(그레이스케일 영상 또는 컬러 영상)

import cv2
import sys

cap = cv2.VideoCapture(0)

if not cap.isOpened():
    print('카메라를 열 수 없습니다')
    sys.exit()
print('카메라 연결 성공!')

print('가로 사이즈: ', int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)))
print('세로 사이즈: ', int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))

while True:
    ret, frame = cap.read()
    if not ret:
        break
    cv2.imshow('frame',frame)
    if cv2.waitKey(1000) == 27:
        break
# cv2.waitKey(10) : 아무 값도 안쓰거나 0이면 키를 누를때까지 계속 멈춘 화면이 wait
                    # 1000 이 1초. 1초에 한장씩 넘어감.
                    # 27은 esc키. esc키를 누르면 break. 
cap.release()

cap.release() 함수는 OpenCV에서 사용한 자원을 해제하는 역할을 합니다. 이는 사용이 끝난 카메라나 동영상 파일에 대한 연결을 종료하고 사용한 메모리를 해제합니다. 이는 다른 프로그램이나 다른 부분에서 카메라나 동영상 파일을 사용할 수 있도록 하는 것과 메모리 누수(memory leak)를 방지하는 데 도움이 됩니다.

동영상 입력

동영상 파일을 입력으로 사용하려면 파일명을 지정하여 cv2.VideoCapture를 생성합니다.

cap = cv2.VideoCapture('filename.mp4')
cap1 = cv2.VideoCapture('./kitty.mp4')
cap2 = cv2.VideoCapture('./cita.mp4')

# 영상 파일 또는 카메라로부터 프레임 수를 읽어옴
frame_cnt1 = round(cap1.get(cv2.CAP_PROP_FRAME_COUNT))
frame_cnt2 = round(cap2.get(cv2.CAP_PROP_FRAME_COUNT))
print(frame_cnt1) // 375
print(frame_cnt2) // 230

# 카메라로부터 초당 프레임 수(FPS)를 읽어오는 것
fps1 = cap1.get(cv2.CAP_PROP_FPS)
fps2 = cap2.get(cv2.CAP_PROP_FPS)
print(fps1) // 30.0
print(fps2) // 23.97

동영상 출력

동영상을 파일로 출력하기 위해서는 cv2.VideoWriter를 사용합니다. 출력할 동영상 파일의 형식은 FourCC(Four Character Code)를 지정해야 합니다. FourCC 코드는 일반적으로 데이터 형식을 구분하는 4개의 고유 문자열로 이루어져 있습니다. AVI 파일의 영상 코덱을 구분하기 위해 사용합니다.

ex)   cv2.VideoWriter_fourcc(*'DIVX') // Divx로 압축
        cv2.VideoWriter_fourcc(*'XVID') // Xvid로 압축
         ...
        cv2.VideoWriter.fourcc(*'MP4V') // mp4로 압축

cap = cv2.VideoCapture(0)

w = round(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = round(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)

fourcc = cv2.VideoWriter.fourcc(*'DIVX')
out = cv2.VideoWriter('output.avi', fourcc, fps, (w,h))

while True:
    ret, frame = cap.read()
    if not ret:
        break
    out.write(frame)
    cv2.imshow('frame',frame)

    if cv2.waitKey(10) == 27:
        break

cap.release()

파일 저장

fourcc = cv2.VideoWriter.fourcc(*'DIVX')
out = cv2.VideoWriter('output.avi', fourcc, fps, (width, height), isColor)

fps는 초당 프레임 수이고, isColor는 컬러 영상 여부를 나타냅니다.

 

문제.
무료 동영상 사이트에서 동영상 2개를 다운받아 두 동영상을 연결하는 프로그램을 만들어보자
- 단, 두 동영상의 해상도가 같아야 함

cap1 = cv2.VideoCapture('./kitty.mp4')
cap2 = cv2.VideoCapture('./cita.mp4')

fourcc = cv2.VideoWriter.fourcc(*'DIVX')
out = cv2.VideoWriter('mix.avi', fourcc, fps1, (w, h))

for i in range(frame_cnt1):
    ret, frame = cap1.read()
    cv2.imshow('output', frame)
    out.write(frame)
    if cv2.waitKey(10) == 27:
        break

for i in range(frame_cnt2):
    ret, frame = cap2.read()
    cv2.imshow('output', frame)
    out.write(frame)
    if cv2.waitKey(10) == 27:
        break

cap1.release()
cap2.release()
out.release()

2. 키보드 이벤트

cv2.waitKey(delay)
cv2.waitKey(5000) # 5초 대기

# delay: 밀리초 단위 대기(0보다 작거나 같으면 무한정 기다림. 기본값은 0)

cv2.waitKey() 함수는 사용자가 키보드를 누르거나 마우스를 클릭할 때까지 대기하며, 그 이벤트가 발생하면 해당 이벤트에 대한 아스키 코드값을 반환합니다.

예를 들어:

  • ESC 키가 눌려지면 반환 값은 27이 됩니다.
  • ENTER 키가 눌려지면 반환 값은 13이 됩니다.
  • TAB 키가 눌려지면 반환 값은 9가 됩니다.
img = cv2.imread('./dog.bmp')
cv2.imshow('image', img)

while True:
    keyvalue = cv2.waitKey()
    if keyvalue == ord('i') or keyvalue == ord('I'):
        img = ~img
        cv2.imshow('image', img)
    elif keyvalue == 27:
        break

# ord()는 문자의 아스키 코드값을 반환하는 파이썬 내장 함수입니다.

위 코드는 키보드 i값을 누를 때마다 이미지 색상은 반전된다. esc(아스키코드 27)키를 누르면 종료된다.

2. 마우스 이벤트

cv2.setMouseCallback(윈도우이름, 콜백함수, 파라미터)
  • 윈도우이름: 마우스 이벤트를 처리할 윈도우 창의 이름
  • 콜백함수: 마우스 이벤트가 발생할 때 호출되는 함수
  • 파라미터: 콜백함수에 전달할 추가적인 정보 (선택 사항)
def 함수명(event, x, y, flags, param):
    pass
  • event: 이벤트 객체
  • x, y: 마우스 x, y 좌표
  • flags: 마우스 버튼이 눌리고 있는지 뗏는지 여부
  • param: 추가적인 정보가 전달되었다면 저장되는 변수
import cv2
import numpy as np

oldx = oldy = 0

def on_mouse(event, x, y, flags, param):
    global oldx, oldy
    if event == cv2.EVENT_LBUTTONDOWN:
        oldx, oldy = x, y
        print('왼쪽 버튼이 눌렸어요: %d, %d' % (x,y))
    elif event == cv2.EVENT_LBUTTONUP:
        print('왼쪽 버튼이 떼졌어요: %d, %d' % (x, y))
    elif event == cv2.EVENT_MOUSEMOVE:
        if flags & cv2.EVENT_FLAG_LBUTTON: # 마우스가 눌리고 있는 상태 & 왼쪽 버튼이 눌러져있는 상태
            cv2.line(img, (oldx,oldy), (x,y), (255,51,255), 3)
            cv2.imshow('img', img)
            oldx, oldy = x,y

img = np.ones((500,500,3), dtype=np.uint8) * 255
cv2.namedWindow('img')
cv2.setMouseCallback('img', on_mouse)
# 윈도우창 이름, 만들어야 할 함수명
cv2.imshow('img',img)
cv2.waitKey()

 

'CV(Computer Vision)' 카테고리의 다른 글

영상의 변환/ 적응형 이진화/ 유사도  (0) 2024.02.25
관심 영역/ 이진화  (0) 2024.02.18
이미지 처리 기법  (0) 2024.02.16
영상처리 기초 : 화소처리  (0) 2024.02.10
컴퓨터 비전과 OpenCV  (1) 2024.02.09