대상: 리눅스(Ubuntu) 환경에서 USB 카메라를 다루며, 어떤 포맷을 선택해야 할지 고민하는 개발자
환경: Ubuntu 22.04 / OpenCV 4.x / ROS2 Humble
1. 문제/주제 요약
USB 카메라를 사용할 때 v4l2-ctl이나 cv2.VideoCapture를 통해 확인하면
보통 아래 세 가지 포맷을 볼 수 있습니다:
MJPG(Motion JPEG)YUYV(YUYV 4:2:2, Raw YUV)H264(H.264 / AVC 압축 포맷)
이 중 어떤 걸 써야 성능, 지연시간, 화질이 좋은지 고민될 때가 많습니다.
이 글에서는 세 포맷의 차이점과 선택 기준을 정리합니다.
2. 원인/배경 설명
USB 카메라가 출력하는 영상 포맷은 단순히 “색 표현 방식”만이 아니라
압축 여부 / CPU 부하 / 전송 대역폭 / 지연시간에 큰 영향을 줍니다.
| 포맷 | 특징 | 압축 여부 | 대역폭 | CPU 부하 | 대표 사용처 |
|---|---|---|---|---|---|
| YUYV | Raw YUV 데이터 | ❌ 무압축 | 높음 | 낮음 | 저해상도, 저지연 필요 |
| MJPEG | JPEG 프레임들의 연속 | ✅ 프레임 단위 압축 | 중간 | 중간 | 일반 USB 웹캠, OpenCV |
| H.264 | 고효율 영상 압축 (GOP 구조) | ✅✅ 고압축 | 낮음 | 높음 (디코딩 시) | 고해상도 스트리밍, 네트워크 카메라 |
3. 세부 비교
(1) YUYV (Raw YUV 4:2:2)
- 장점
- 압축이 없어 프레임 손실이 거의 없음
- 지연시간 최소화
- 영상 처리를 직접 할 때(예: OpenCV 필터, 딥러닝 입력) 좋음
- 단점
- 대역폭 소모 큼
(1920×1080 @30fps는 USB 2.0 한계 초과 가능) - 고해상도에서는 프레임 드롭 자주 발생
- 저장 시 용량 매우 큼
- 대역폭 소모 큼
- 추천 상황
- 저해상도(640×480 이하)에서 실시간 영상처리가 필요한 경우
- 예: ROS2 이미지 토픽 실시간 필터링, 로봇 비전 등
(2) MJPEG (Motion JPEG)
- 장점
- 각 프레임이 독립적인 JPEG 이미지 → 디코딩 단순
- 대역폭 절감 (YUYV 대비 3~5배 효율적)
- OpenCV, ROS 등에서 기본적으로 지원
- 단점
- 압축 artifacts 존재 (특히 움직임 많은 경우)
- 디코딩 시 CPU 부하 있음 (하지만 대부분 가벼움)
- 프레임간 압축이 없어서 H.264보단 비효율적
- 추천 상황
- 1080p 이상 고해상도 + 일반적인 USB 2.0 환경
- OpenCV로 영상 프레임을 읽어서 처리할 때 기본값으로 적합
- 예:
cv2.VideoCapture(0)+CAP_PROP_FOURCC = 'MJPG'
(3) H.264 (Advanced Video Coding)
- 장점
- 가장 높은 압축률 (대역폭 절감)
- 고해상도 스트리밍에 적합 (USB 3.0 이상)
- 일부 카메라는 하드웨어 인코더 내장 → CPU 부하 적음
- 단점
- 인코딩/디코딩 과정에서 지연시간 증가
- OpenCV에서 프레임 단위 디코딩 어려움
(GStreamer 필요) - 실시간 영상처리엔 부적합 (프레임 누락 가능)
- 추천 상황
- 네트워크 스트리밍, 영상 저장, 저대역폭 환경
- 예: IP 카메라, 녹화 전용 시스템
4. 실무 선택 가이드
| 목적 | 권장 포맷 | 이유 |
|---|---|---|
| 실시간 영상처리 (ROS2, AI, OpenCV) | MJPG → fallback YUYV | 적당한 대역폭과 프레임 안정성 |
| 저지연 제어용 카메라 (로봇, 산업용) | YUYV | 무압축으로 지연 최소화 |
| 스트리밍 / 저장 전용 | H.264 | 압축 효율 및 네트워크 대역 절약 |
| 고해상도 USB2.0 카메라 | MJPG | USB 2.0 대역폭 한계 극복 |
5. 확인 및 설정 예시
(1) 지원 포맷 확인
v4l2-ctl --list-formats-ext -d /dev/video0
출력 예시:
[0]: 'YUYV' (YUYV 4:2:2)
[1]: 'MJPG' (Motion-JPEG)
[2]: 'H264' (H.264, compressed)
(2) 특정 포맷으로 설정
# MJPG 1280x720 @ 30fps
v4l2-ctl -d /dev/video0 \
--set-fmt-video=width=1280,height=720,pixelformat=MJPG \
--set-parm=30
또는 OpenCV 코드로:
cap = cv2.VideoCapture(0, cv2.CAP_V4L2)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG'))
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
cap.set(cv2.CAP_PROP_FPS, 30)
6. 추가 팁 / 자주 하는 실수
- ⚠️
H264포맷을 OpenCV 기본 백엔드로 직접 열면cap.read()에서 오류 발생 가능
→ GStreamer 파이프라인을 이용해야 함:gst = "v4l2src device=/dev/video0 ! video/x-h264,framerate=30/1 ! avdec_h264 ! videoconvert ! appsink" cap = cv2.VideoCapture(gst, cv2.CAP_GSTREAMER) - ⚙️
MJPG는 USB 2.0 환경에서 가장 안정적인 선택
(YUYV는 720p 이상에서 프레임 드롭 발생 가능) - 🧠 ROS2에서
image_transport를 사용할 경우,compressed옵션은 MJPEG 기반으로 동작 → 전송 효율 높음
7. 정리
- YUYV: 무압축, 저지연, 고대역폭 — 실시간 제어용
- MJPG: 중간 압축, 범용적, OpenCV 친화적 — 기본 선택
- H.264: 고압축, 고효율, 스트리밍/저장용 — 비실시간 처리
👉 일반적인 개발 환경(USB 카메라 + OpenCV/ROS2)에서는
MJPG가 가장 실용적인 선택입니다.