15장. 비디오 처리와 실시간 영상처리
동영상 처리 한눈에 고르기
요리책의 맨 뒤에는 "이럴 때는 이 요리"라는 찾아보기 표가 있습니다. 동영상 처리도 하고 싶은 일에 따라 고를 도구가 정해져 있습니다. 이 장에서 본 도구를 하고 싶은 일별로 한데 모읍니다.
그림의 네 묶음이 이 장의 본문 절에 하나씩 맞습니다. 왼쪽 두 묶음은 어떤 동영상 처리에나 들어가는 바탕이고, 오른쪽 두 묶음은 목적에 따라 골라 씁니다.
하고 싶은 일과 도구
| 하고 싶은 일 | 도구 | 꼭 챙길 것 |
|---|---|---|
| 동영상 열기 | cv2.VideoCapture(이름) | isOpened() 확인, 다 쓰면 release() |
| 정보 보기 | cap.get(cv2.CAP_PROP_FRAME_COUNT) 등 | 실수로 오므로 int(...) |
| 한 장씩 읽기 | ok, frame = cap.read() | ok 가 False 면 끝 |
| 특정 장으로 가기 | cap.set(cv2.CAP_PROP_POS_FRAMES, 번호) | 코덱에 따라 근처 장이 나올 수 있다 |
| 저장하기 | cv2.VideoWriter(이름, fourcc, fps, (가로, 세로), isColor) | 크기·컬러가 맞아야 쓰인다 |
| 움직임(빠르게) | cv2.absdiff(지금, 앞) → 이진화 | 테두리만 잡히고 멈추면 사라진다 |
| 움직임(통째로) | 중앙값 배경 또는 MOG2 | MOG2 는 처음 몇 장이 지저분하다 |
| 실시간 확인 | time.perf_counter() 로 한 장 처리 시간 | 1000 ÷ FPS ms 안에 끝나야 한다 |
| 웹캠 | cv2.VideoCapture(0), cv2.waitKey(1) | q 로 끝내기, release() |
여러 동영상에 같은 처리를 할 때는 "한 장씩 읽어 함수에 넘기는" 틀을 함수로 만들어 두면 편합니다.
import cv2
def each_frame(path, step=1):
"""동영상을 열어 step 장마다 (번호, 프레임)을 하나씩 내준다. 다 읽으면 저절로 닫는다."""
cap = cv2.VideoCapture(path)
no = 0
try:
while True:
ok, frame = cap.read()
if not ok:
break
if no % step == 0:
yield no, frame # yield: 값을 하나 내주고 다음 요청까지 멈춰 기다린다
no += 1
finally:
cap.release() # 중간에 그만둬도 꼭 닫는다
for no, frame in each_frame("ch15_yard.mp4", step=20):
print(no, frame.shape) # 결과: 0, 20, 40 번 프레임의 모양주의할 점
- 동영상 처리는 결국 "사진 처리 × 장 수"입니다. 한 장에서 먼저 결과를 확인하고, 그다음 반복에 넣습니다.
- 결과 동영상은 웹 교안이나 보고서에 바로 싣기 어렵습니다. 대표 프레임 몇 장을 격자 그림으로 모아 보여 주는 방법을 이 장의 실습과 프로젝트에서 씁니다.