15장. 비디오 처리와 실시간 영상처리
동영상 파일 읽기
DVD 플레이어로 영화를 볼 때는 디스크를 넣고, 잘 들어갔는지 화면을 보고, 재생 단추를 누르고, 다 보면 디스크를 꺼냅니다. OpenCV 로 동영상을 읽는 순서도 같습니다. 재생기를 만들어 파일을 열고, 열렸는지 확인하고, 한 장씩 읽고, 다 읽으면 닫습니다.
그림의 네 단계가 cv2.VideoCapture, isOpened(), read(), release() 에 하나씩 맞습니다. 여기서 DVD 플레이어가 VideoCapture 이고, 재생 단추를 한 번 누를 때마다 한 장이 나오는 것이 read() 입니다. 비유와 다른 점은 read() 가 자동으로 넘어가지 않는다는 것입니다. 부를 때마다 한 장씩만 꺼내 줍니다.
read() 가 돌려주는 두 값
read() 는 (ok, frame) 두 값을 돌려줍니다. ok 는 읽기에 성공했는지(True/False), frame 은 BGR 그림(NumPy 배열)입니다. 마지막 프레임을 지나면 ok 가 False, frame 이 None 이 됩니다. 그래서 "ok 가 False 면 멈춘다"가 읽기 반복의 끝내는 조건입니다.
| 속성 이름 | 뜻 | 컨베이어 동영상 |
|---|---|---|
cv2.CAP_PROP_FRAME_COUNT | 전체 프레임 수 | 80.0 |
cv2.CAP_PROP_FPS | 1초에 몇 장 | 10.0 |
cv2.CAP_PROP_FRAME_WIDTH | 가로 칸 수 | 320.0 |
cv2.CAP_PROP_FRAME_HEIGHT | 세로 칸 수 | 240.0 |
cv2.CAP_PROP_POS_FRAMES | 다음에 읽을 프레임 번호(position, 위치) | 처음에는 0.0 |
import cv2
# VideoCapture(파일 이름): 동영상을 여는 재생기를 만든다
cap = cv2.VideoCapture("ch15_conveyor.mp4")
print("열렸나:", cap.isOpened()) # 결과: True
# get(속성): 값이 실수로 오므로 장 수와 칸 수는 int 로 바꾼다
print("프레임 수:", int(cap.get(cv2.CAP_PROP_FRAME_COUNT))) # 결과: 80
print("FPS:", cap.get(cv2.CAP_PROP_FPS)) # 결과: 10.0
ok, frame = cap.read() # 첫 프레임 한 장
print(ok, frame.shape) # 결과: True (240, 320, 3)
cap.release() # 다 쓰면 닫는다주의할 점
- 없는 파일을 열어도
VideoCapture는 오류를 내지 않습니다.isOpened()가 False 일 뿐입니다. 2장에서 본cv2.imread가None을 돌려주던 것과 같은 성질이라 꼭 확인합니다. - 한글이 든 절대 경로는 동영상도 열리지 않습니다. 사진과 마찬가지로
data폴더를 작업 폴더로 두고 상대 경로로 엽니다. CAP_PROP_FRAME_COUNT는 파일에 적힌 값을 읽은 것이라, 파일 형식에 따라 실제로 읽히는 장 수와 조금 다를 수 있습니다. 정확히 세려면 끝까지 읽으며 셉니다.