OpenCV 동영상과 웹캠
실습 준비
pip install opencv-python pillow
- 실습 동영상:
자전거.mp4를 현재 폴더에 준비
from pathlib import Path
import cv2 as cv
from yeom import to_pil
동영상은 프레임의 연속
동영상은 시간 순서대로 저장된 이미지 프레임의 연속.
frame 0 → frame 1 → frame 2 → ···
- 프레임(frame): 동영상을 구성하는 이미지 한 장
- FPS(frames per second): 1초 동안 재생되는 프레임 수
- 해상도: 각 프레임의 가로·세로 픽셀 수
- 코덱(codec): 프레임을 압축하고 해제하는 방식
- 컨테이너(container): 영상과 부가 정보를 담는 파일 형식
동영상 파일 열기
video_path = Path("자전거.mp4")
video = cv.VideoCapture(str(video_path))
VideoCapture: 동영상 파일, 이미지 시퀀스, 카메라에서 프레임을 읽는 공통 인터페이스.
동영상 정보 확인
fps = video.get(cv.CAP_PROP_FPS)
frame_count = int(video.get(cv.CAP_PROP_FRAME_COUNT))
frame_width = int(video.get(cv.CAP_PROP_FRAME_WIDTH))
frame_height = int(video.get(cv.CAP_PROP_FRAME_HEIGHT))
{
"FPS": fps,
"프레임 수": frame_count,
"프레임 크기": (frame_width, frame_height),
}
속성값은 동영상 코덱과 운영체제의 비디오 백엔드에 따라 일부 제공되지 않거나 근사값일 수 있음.
프레임 한 장 읽기
ret, frame = video.read()
ret: 프레임을 성공적으로 읽었는지 나타내는 불리언 값frame: BGR 순서의 NumPy 이미지 배열- 동영상 끝에 도달하거나 프레임을 읽지 못하면
ret은False
if not ret:
raise RuntimeError("첫 프레임을 읽지 못했습니다.")
frame.shape
to_pil(frame)
video.release()
release(): 파일이나 카메라 장치 해제.
동영상 재생
동영상 파일을 다시 열고 프레임을 한 장씩 읽어 데스크톱 창에 표시.
video = cv.VideoCapture(str(video_path))
fps = video.get(cv.CAP_PROP_FPS)
delay = max(1, round(1000 / fps)) if fps > 0 else 33 # FPS를 읽지 못하면 약 30 FPS 사용
try:
while video.isOpened():
ret, frame = video.read()
if not ret:
break
cv.imshow("video", frame)
key = cv.waitKey(delay) & 0xFF # 하위 8비트 키 코드만 사용
if key == ord("q"):
break
finally:
video.release()
cv.destroyAllWindows()
delay: 다음 프레임을 표시하기 전 기다릴 밀리초q: 반복 재생 중단try–finally: 오류나 중단이 발생해도 장치와 창을 해제
GUI를 사용할 수 없는 원격 노트북에서는 한 프레임씩 to_pil(frame)로 확인하거나 별도의 노트북용 동영상 표시 기능을 사용.
동영상 파일 저장
VideoWriter: 프레임 배열을 순서대로 인코딩하여 동영상 파일로 저장.
reader = cv.VideoCapture(str(video_path))
if not reader.isOpened():
raise FileNotFoundError(f"동영상을 열 수 없습니다: {video_path}")
fps = reader.get(cv.CAP_PROP_FPS)
width = int(reader.get(cv.CAP_PROP_FRAME_WIDTH))
height = int(reader.get(cv.CAP_PROP_FRAME_HEIGHT))
fourcc = cv.VideoWriter_fourcc(*"mp4v") # MP4 예제 코덱
writer = cv.VideoWriter(
"자전거_복사본.mp4",
fourcc,
fps,
(width, height),
)
if not writer.isOpened():
reader.release()
raise RuntimeError("동영상 저장 장치를 열지 못했습니다.")
try:
while True:
ret, frame = reader.read()
if not ret:
break
writer.write(frame)
finally:
reader.release()
writer.release()
fourcc: 사용할 코덱을 나타내는 네 문자 코드fps: 출력 동영상의 재생 속도(width, height): 저장할 모든 프레임의 크기writer.write(frame): BGR 프레임을 출력 동영상에 추가
사용 가능한 코덱은 운영체제와 OpenCV 설치 환경에 따라 다름. VideoWriter는 영상 프레임을 저장하며 원본의 오디오 트랙은 복사하지 않음.
웹캠에서 한 프레임 읽기
동영상 파일 경로 대신 카메라 장치 번호를 전달. 일반적으로 0은 기본 카메라.
camera = cv.VideoCapture(0) # 기본 카메라 장치
if not camera.isOpened():
raise RuntimeError("카메라를 열 수 없습니다.")
원하는 프레임 크기를 요청한 뒤 실제로 적용된 값을 확인. 카메라가 지원하지 않는 크기라면 가장 가까운 값이 사용될 수 있음.
camera.set(cv.CAP_PROP_FRAME_WIDTH, 640) # VGA 가로 크기 요청
camera.set(cv.CAP_PROP_FRAME_HEIGHT, 480) # VGA 세로 크기 요청
actual_width = int(camera.get(cv.CAP_PROP_FRAME_WIDTH))
actual_height = int(camera.get(cv.CAP_PROP_FRAME_HEIGHT))
actual_width, actual_height
try:
ret, webcam_frame = camera.read()
if not ret:
raise RuntimeError("웹캠 프레임을 읽지 못했습니다.")
finally:
camera.release()
to_pil(webcam_frame)
웹캠 접근에는 로컬 실행 환경과 운영체제의 카메라 권한이 필요.
웹캠 영상 표시
camera = cv.VideoCapture(0) # 기본 카메라 장치
if not camera.isOpened():
raise RuntimeError("카메라를 열 수 없습니다.")
try:
while True:
ret, frame = camera.read()
if not ret:
break
cv.imshow("webcam", frame)
key = cv.waitKey(1) & 0xFF # 하위 8비트 키 코드만 사용
if key == ord("q"):
break
finally:
camera.release()
cv.destroyAllWindows()
cv.waitKey(1): 잠깐 키 입력을 확인하면서 화면 갱신. 원격 서버나 일반적인 Colab 환경에서는 로컬 웹캠과 데스크톱 창을 같은 방식으로 사용할 수 없음.