카메라/웹캠 개요
OpenCV의 VideoCapture 클래스를 사용하여 카메라나 웹캠에서 실시간으로 영상을 캡처하고 처리할 수 있습니다.
주요 사용 사례:
- 실시간 비디오 스트리밍
- 실시간 이미지 필터링 및 효과 적용
- 객체 추적 및 감지
- 얼굴 인식 및 포즈 추정
- 모션 감지
- AR(증강현실) 애플리케이션
1. 기본 카메라 캡처
1.1 웹캠 열기 및 프레임 읽기
import cv2
# 카메라 열기 (0은 기본 카메라, 1은 두 번째 카메라)
cap = cv2.VideoCapture(0)
# 카메라가 제대로 열렸는지 확인
if not cap.isOpened():
print("카메라를 열 수 없습니다")
exit()
while True:
# 프레임 읽기
# ret: 프레임 읽기 성공 여부 (True/False)
# frame: 읽은 프레임 (numpy 배열)
ret, frame = cap.read()
if not ret:
print("프레임을 읽을 수 없습니다")
break
# 프레임 표시
cv2.imshow('Camera', frame)
# 키 입력 처리
# cv2.waitKey(1): 1밀리초 동안 키 입력 대기 (0이면 무한 대기)
# & 0xFF: 비트 마스킹으로 하위 8비트만 추출 (64비트 시스템 호환성)
# ord('q'): 'q' 문자의 ASCII 코드 값 (113)
# 'q' 키를 누르면 루프 종료
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 리소스 해제
cap.release()
cv2.destroyAllWindows()
1.2 카메라 속성 설정
import cv2
cap = cv2.VideoCapture(0)
# 카메라 속성 설정
# 너비 설정
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
# 높이 설정
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
# FPS 설정
cap.set(cv2.CAP_PROP_FPS, 30)
# 밝기 설정 (0-100)
cap.set(cv2.CAP_PROP_BRIGHTNESS, 50)
# 대비 설정
cap.set(cv2.CAP_PROP_CONTRAST, 50)
# 설정된 속성 확인
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = cap.get(cv2.CAP_PROP_FPS)
print(f"해상도: {int(width)}x{int(height)}, FPS: {fps}")
주요 카메라 속성:
cv2.CAP_PROP_FRAME_WIDTH: 프레임 너비cv2.CAP_PROP_FRAME_HEIGHT: 프레임 높이cv2.CAP_PROP_FPS: 초당 프레임 수cv2.CAP_PROP_BRIGHTNESS: 밝기cv2.CAP_PROP_CONTRAST: 대비cv2.CAP_PROP_SATURATION: 채도cv2.CAP_PROP_GAIN: 영상 밝기 증폭률 (받은 빛을 뻥튀기)cv2.CAP_PROP_EXPOSURE: 노출 (빛을 받는 시간을 늘림)
2. 실시간 이미지 처리
2.1 그레이스케일 변환
import cv2
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
# 그레이스케일 변환
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 원본과 그레이스케일 동시 표시
cv2.imshow('Original', frame)
cv2.imshow('Grayscale', gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
2.2 실시간 필터링
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
# 가우시안 블러
blurred = cv2.GaussianBlur(frame, (15, 15), 0)
# 엣지 검출
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 100, 200)
# 결과 표시
cv2.imshow('Original', frame)
cv2.imshow('Blurred', blurred)
cv2.imshow('Edges', edges)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
2.3 실시간 색상 필터링
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
# HSV 색공간으로 변환
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# 빨간색 범위 정의 (BGR이 아닌 HSV)
lower_red = np.array([0, 50, 50])
upper_red = np.array([10, 255, 255])
lower_red2 = np.array([170, 50, 50])
upper_red2 = np.array([180, 255, 255])
# 빨간색 마스크 생성
mask1 = cv2.inRange(hsv, lower_red, upper_red)
mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
mask = mask1 + mask2
# 마스크 적용
result = cv2.bitwise_and(frame, frame, mask=mask)
cv2.imshow('Original', frame)
cv2.imshow('Red Filter', result)
cv2.imshow('Mask', mask)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
3. 프레임 저장 및 재생
3.1 비디오 파일로 저장
import cv2
cap = cv2.VideoCapture(0)
# 비디오 코덱 및 Writer 설정
fourcc = cv2.VideoWriter_fourcc(*'XVID') # 또는 'mp4v', 'X264'
out = cv2.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
while True:
ret, frame = cap.read()
if not ret:
break
# 프레임 저장
out.write(frame)
cv2.imshow('Recording', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 리소스 해제
cap.release()
out.release()
cv2.destroyAllWindows()
3.2 스크린샷 저장
import cv2
import datetime
cap = cv2.VideoCapture(0)
frame_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
cv2.imshow('Camera', frame)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
elif key == ord('s'): # 's' 키를 누르면 스크린샷 저장
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f'screenshot_{timestamp}.jpg'
cv2.imwrite(filename, frame)
print(f"스크린샷 저장: {filename}")
frame_count += 1
cap.release()
cv2.destroyAllWindows()
4. 성능 최적화
4.1 프레임 크기 조정으로 성능 향상
import cv2
cap = cv2.VideoCapture(0)
# 작은 해상도로 설정 (처리 속도 향상)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
while True:
ret, frame = cap.read()
if not ret:
break
# 프레임 크기 조정 (더 작게)
small_frame = cv2.resize(frame, (320, 240))
# 작은 프레임에서 처리 (더 빠름)
gray = cv2.cvtColor(small_frame, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 100, 200)
# 결과를 원본 크기로 확대하여 표시
edges_large = cv2.resize(edges, (640, 480))
cv2.imshow('Original', frame)
cv2.imshow('Edges', edges_large)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
4.2 FPS 측정 및 표시
import cv2
import time
cap = cv2.VideoCapture(0)
prev_time = 0
fps = 0
while True:
ret, frame = cap.read()
if not ret:
break
# FPS 계산
current_time = time.time()
fps = 1 / (current_time - prev_time) if prev_time > 0 else 0
prev_time = current_time
# FPS 텍스트 표시
fps_text = f'FPS: {fps:.2f}'
cv2.putText(frame, fps_text, (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.imshow('Camera', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
4.3 스레드를 사용한 비동기 처리
import cv2
import threading
import queue
class VideoCaptureThread:
def __init__(self, src=0):
self.cap = cv2.VideoCapture(src)
self.q = queue.Queue()
self.running = True
# 캡처 스레드 시작
self.thread = threading.Thread(target=self._reader)
self.thread.daemon = True
self.thread.start()
def _reader(self):
while self.running:
ret, frame = self.cap.read()
if not ret:
break
if not self.q.empty():
try:
self.q.get_nowait()
except queue.Empty:
pass
self.q.put((ret, frame))
def read(self):
return self.q.get()
def release(self):
self.running = False
self.thread.join()
self.cap.release()
# 사용 예시
cap = VideoCaptureThread(0)
while True:
ret, frame = cap.read()
if not ret:
break
# 이미지 처리
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('Camera', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
5. 실전 예제
5.1 실시간 얼굴 감지 (Haar Cascade)
import cv2
# 얼굴 감지 모델 로드
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
# 그레이스케일 변환
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 얼굴 감지
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
# 감지된 얼굴에 사각형 그리기
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)
cv2.putText(frame, 'Face', (x, y-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.9, (255, 0, 0), 2)
cv2.imshow('Face Detection', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
5.2 실시간 모션 감지
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
# 배경 추출기 생성
fgbg = cv2.createBackgroundSubtractorMOG2()
while True:
ret, frame = cap.read()
if not ret:
break
# 배경 제거 (움직이는 객체만 추출)
fgmask = fgbg.apply(frame)
# 노이즈 제거
kernel = np.ones((5, 5), np.uint8)
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_CLOSE, kernel)
# 컨투어 찾기
contours, _ = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 움직이는 객체에 사각형 그리기
for contour in contours:
area = cv2.contourArea(contour)
if area > 500: # 작은 노이즈 제거
x, y, w, h = cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
cv2.imshow('Original', frame)
cv2.imshow('Motion', fgmask)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
6. 문제 해결
프레임 지연 문제 해결
import cv2
cap = cv2.VideoCapture(0)
# 버퍼 크기 제한 (지연 방지)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
while True:
ret, frame = cap.read()
if not ret:
break
# 처리 시간이 오래 걸리는 작업은 최소화
# 예: 작은 해상도로 처리
small = cv2.resize(frame, (320, 240))
# ... 처리 ...
cv2.imshow('Camera', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
주요 팁
- 성능 최적화: 처리할 프레임 크기를 줄이면 성능이 향상됩니다
- 버퍼 관리:
CAP_PROP_BUFFERSIZE를 1로 설정하여 지연을 줄일 수 있습니다 - 리소스 해제: 항상
cap.release()와cv2.destroyAllWindows()를 호출하세요 - 에러 처리:
ret값을 항상 확인하여 프레임 읽기 성공 여부를 체크하세요 - 키 입력:
cv2.waitKey(1)은 1밀리초 대기하며, 0으로 설정하면 무한 대기합니다