MJPEG vs YUYV vs H.264: USB 카메라 포맷 선택 가이드

대상: 리눅스(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 부하대표 사용처
YUYVRaw YUV 데이터❌ 무압축높음낮음저해상도, 저지연 필요
MJPEGJPEG 프레임들의 연속✅ 프레임 단위 압축중간중간일반 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 카메라MJPGUSB 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가 가장 실용적인 선택입니다.

댓글 남기기