15장. 비디오 처리와 실시간 영상처리
원하는 프레임 고르기
두 시간짜리 영화에서 한 장면만 다시 보고 싶으면 처음부터 다시 보지 않고 재생 막대를 그 자리로 끌어다 놓습니다. 영화 전체의 줄거리만 훑고 싶으면 10분마다 한 장면씩 건너뛰며 봅니다. 동영상에서 프레임을 고르는 법도 이 세 가지입니다.
왼쪽부터 처음부터 끝까지 차례로 읽기, CAP_PROP_POS_FRAMES 로 번호를 정해 건너뛰기, 차례로 읽되 N장마다 하나만 쓰기입니다. 여기서 재생 막대를 끌어다 놓는 일이 cap.set(cv2.CAP_PROP_POS_FRAMES, 번호) 이고, 10분마다 훑는 일이 "번호를 N 으로 나눈 나머지가 0 일 때만 쓰기"입니다.
세 가지 견주기
| 고르는 법 | 코드 | 쓰는 때 |
|---|---|---|
| 처음부터 차례로 | while 에서 read() 되풀이 | 모든 프레임을 처리할 때 |
| 번호로 건너뛰기 | cap.set(cv2.CAP_PROP_POS_FRAMES, 40) 뒤 read() | 특정 장면 한두 장만 볼 때 |
| N장마다 하나 | 차례로 읽고 if no % 10 == 0: 일 때만 처리 | 긴 동영상을 훑거나 처리량을 줄일 때 |
import cv2
cap = cv2.VideoCapture("ch15_conveyor.mp4")
# set(속성, 값): 다음에 읽을 프레임 번호를 40 으로 옮긴다
cap.set(cv2.CAP_PROP_POS_FRAMES, 40)
ok, frame = cap.read()
# 한 장을 읽었으므로 다음 번호는 41 이 된다
print("다음에 읽을 번호:", int(cap.get(cv2.CAP_PROP_POS_FRAMES))) # 결과: 41
# 처음으로 되돌려 20장마다 하나씩 번호를 모은다
cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
kept, no = [], 0
while True:
ok, frame = cap.read()
if not ok:
break
if no % 20 == 0: # 0, 20, 40, 60 번만 쓴다
kept.append(no)
no += 1
cap.release()
print("고른 프레임:", kept) # 결과: [0, 20, 40, 60]주의할 점
- 번호로 건너뛰는 일은 코덱에 따라 느리거나, 바로 그 장이 아닌 근처 장이 나올 수도 있습니다. 묶인 동영상은 몇 장마다 한 장만 통째로 저장하고 나머지는 "앞 장과 달라진 곳"만 저장하기 때문입니다. 정확한 장이 꼭 필요하면 차례로 읽으며 셉니다.
- 건너뛴 뒤에는
CAP_PROP_POS_FRAMES가 읽은 장의 다음 번호를 가리킵니다. 같은 장을 다시 보려면 번호를 다시 정합니다.