An open API service indexing awesome lists of open source software.

https://github.com/pathcosmos/jeju_masking

4K 영상 자동 마스킹 도구 - YOLO12x + TensorRT + GPU 가속 (사람/번호판 마스킹, NVDEC/NVENC, 멀티스레딩, 2-Pass 모드)
https://github.com/pathcosmos/jeju_masking

Last synced: 21 days ago
JSON representation

4K 영상 자동 마스킹 도구 - YOLO12x + TensorRT + GPU 가속 (사람/번호판 마스킹, NVDEC/NVENC, 멀티스레딩, 2-Pass 모드)

Awesome Lists containing this project

README

          

# Video Privacy Masking Tool

4K 영상에서 얼굴과 차량 번호판을 자동으로 감지하고 마스킹하는 도구입니다.
NVIDIA CUDA / Apple Silicon MPS GPU 가속, 멀티스레딩, 트래킹 보간 등 다양한 최적화 기법을 적용하여 고해상도 영상도 효율적으로 처리합니다.

## 주요 기능

- **사람 전체 마스킹**: YOLO12x 모델로 사람 감지 후 전신 마스킹 (얼굴만이 아닌 전체)
- **차량 번호판 마스킹**: 차량 감지 + 번호판 영역 추정 마스킹
- **적응형 색보정**: 장면별 자동 분석 + 시네마틱 필터 적용 (선택적)
- **배치 처리 시스템**: 여러 영상 동시 처리 + 자동 큐 관리
- **TensorRT 가속**: YOLO 모델을 TensorRT 엔진으로 변환하여 최대 성능 (기본 활성화)
- **GPU 블러**: OpenCV CUDA 가우시안 블러 (CPU 대비 13배 빠름)
- **GPU 색보정**: OpenCV CUDA 기반 색보정 가속
- **NVDEC 하드웨어 디코딩**: GPU에서 직접 영상 디코딩
- **NVENC 하드웨어 인코딩**: RTX GPU에서 H.264/HEVC 하드웨어 인코딩
- **FP16 반정밀도 추론**: NVIDIA GPU에서 메모리 절약 및 속도 향상
- **MPS GPU 가속**: Apple Silicon에서 Metal Performance Shaders 활용
- **멀티스레딩 파이프라인**: 읽기/처리/쓰기 분리로 성능 향상
- **프레임 스킵 + 트래킹 보간**: ByteTrack/BoT-SORT로 추적, 중간 프레임 보간
- **해상도 다운스케일 감지**: 감지는 축소 해상도, 출력은 원본 해상도 유지

## 파일 구조

```
jeju_masking/
├── mask_video.py # CLI 인터페이스 (권장 진입점)
├── video_masker.py # 핵심 마스킹 클래스 (VideoMasker, VideoMaskerOptimized)
├── adaptive_color_grade.py # 적응형 색보정 모듈 (ColorGrader 클래스)
├── batch_masking.py # 배치 처리 큐 시스템
├── masking_utils.py # 공용 유틸리티 (로거, 시간 파싱 등)
├── encoding_utils.py # 인코딩 유틸리티 (NVENC 설정, 시스템 최적화)
├── two_pass.py # 2-Pass 모드 함수
├── high_performance.py # 고성능 모드 함수
├── models/ # 감지 모델 (자동 다운로드)
├── movs/ # 입출력 영상 폴더
│ └── 4k_420_10bit/ # 4K 10bit 영상 폴더
│ ├── day/ # 주간 영상
│ │ └── masking/ # 마스킹 출력 폴더
│ └── night/ # 야간 영상
│ └── masking/ # 마스킹 출력 폴더
├── SETUP.md # 환경 설정 가이드
└── README.md # 이 파일
```

---

## 설치

### 1. 시스템 의존성

#### macOS (Apple Silicon)

```bash
# ffmpeg 설치 (HEVC 인코딩용)
brew install ffmpeg
```

#### Ubuntu/Linux (NVIDIA GPU)

```bash
# ffmpeg 및 빌드 도구 설치
sudo apt update
sudo apt install -y ffmpeg build-essential cmake git pkg-config
```

### 2. Python 환경 설정

#### 기본 설치 (pip OpenCV - CUDA 없음)

```bash
# uv 설치 (없는 경우)
curl -LsSf https://astral.sh/uv/install.sh | sh

# 가상환경 생성
uv venv --python 3.12

# 가상환경 활성화
source .venv/bin/activate

# 패키지 설치
uv pip install ultralytics opencv-contrib-python numpy lap pyyaml torch torchvision
```

#### NVIDIA GPU 최적화 설치 (OpenCV CUDA 빌드)

NVIDIA GPU에서 OpenCV DNN CUDA 백엔드를 사용하려면 OpenCV를 소스에서 빌드해야 합니다.
pip로 설치되는 opencv-python 패키지는 CUDA 지원이 포함되어 있지 않습니다.

자세한 빌드 가이드는 아래 [OpenCV CUDA 빌드 가이드](#opencv-cuda-빌드-가이드-nvidia-gpu) 섹션을 참조하세요.

---

## 빠른 시작 (Quick Start)

### 1. 최초 실행 전 TensorRT 엔진 준비 (선택사항)

최초 실행 시 TensorRT 엔진이 자동 생성되지만, 사전에 생성하면 시간을 절약할 수 있습니다.

```bash
source .venv/bin/activate

# TensorRT 엔진 생성 (약 2-5분 소요)
yolo export model=yolo12x.pt format=engine half=True device=0
```

### 2. 기본 실행

```bash
# 영상 마스킹 (사람 + 번호판)
python mask_video.py input.mp4 --hevc
```

### 3. 출력 확인

```bash
# 출력 파일: input_masked.mp4 (기본 경로)
ls -la input_masked.mp4
```

---

## 사용법

### 기본 실행

```bash
source .venv/bin/activate
python mask_video.py input.mp4
```

### 처리 모드 선택

| 모드 | 옵션 | 특징 | 권장 사용 |
|------|------|------|-----------|
| **최적화 모드** | (기본) | 1-Pass, 멀티스레딩 파이프라인 | 일반 처리 |
| **고성능 모드** | `--high-performance` | 1-Pass, 배치 GPU 추론 + NVENC | RTX GPU 최대 활용 |
| **2-Pass 모드** | `--2pass` | Pass1(분석) + Pass2(인코딩) 분리 | JSON 재작업, 대용량 처리 |
| **간단 모드** | `--simple` | 최적화 없음, 기본 설정 | CPU 환경, 빠른 테스트 |

### 옵션 전체 목록

#### 입출력 옵션

| 옵션 | 설명 | 기본값 |
|------|------|--------|
| `input` | 입력 비디오 파일 (필수) | - |
| `-o, --output` | 출력 파일 경로 | `{input}_masked.mp4` |
| `--start` | 시작 시간 (예: `23:00`, `1:30:00`) | 처음부터 |
| `--end` | 종료 시간 (예: `28:00`) | 끝까지 |
| `--hevc` | HEVC(H.265) 인코딩 사용 | 비활성화 |

#### 마스킹 옵션

| 옵션 | 설명 | 기본값 |
|------|------|--------|
| `--no-persons` | 사람 마스킹 비활성화 | - |
| `--no-plates` | 번호판 마스킹 비활성화 | - |
| `--mask-type` | `blur` 또는 `mosaic` | `blur` |
| `--blur-strength` | 블러 강도 (홀수 값, GPU는 31 이하) | `31` |
| `--mosaic-size` | 모자이크 블록 크기 | `15` |

#### 색보정 옵션 (적응형 필터)

| 옵션 | 설명 | 기본값 |
|------|------|--------|
| `--color-grade` | 적응형 색보정 활성화 | 비활성화 |
| `--cg-interval` | 분석 주기 (프레임 단위) | `1000` |
| `--cg-smooth` | 부드러운 전환 윈도우 (프레임 단위) | `300` |

#### 감지 파라미터

| 옵션 | 설명 | 기본값 |
|------|------|--------|
| `--person-conf` | 사람 감지 신뢰도 임계값 | `0.4` |
| `--vehicle-conf` | 차량 감지 신뢰도 임계값 | `0.3` |
| `--person-expand` | 사람 영역 확장 비율 | `0.2` |
| `--plate-expand` | 번호판 영역 확장 비율 | `0.5` |
| `--max-mask-ratio` | 프레임 대비 최대 마스킹 비율 | `0.4` |

#### 2-Pass 모드 옵션

| 옵션 | 설명 | 기본값 |
|------|------|--------|
| `--2pass` | 2-Pass 모드 활성화 (분석→인코딩 분리) | 비활성화 |
| `--analyze-only` | Pass 1만 실행: 마스크 좌표를 JSON으로 저장 | - |
| `--encode-only` | Pass 2만 실행: JSON 마스크 데이터로 인코딩 | - |
| `--mask-json` | 마스크 JSON 파일 경로 (`--encode-only`와 함께) | - |
| `--keep-json` | 2-Pass 완료 후 JSON 파일 유지 | 삭제 |

#### 성능 최적화 옵션

| 옵션 | 설명 | 기본값 |
|------|------|--------|
| `--device` | 연산 디바이스 (`auto`, `mps`, `cuda`, `cpu`) | `auto` |
| `--yolo-model` | YOLO 모델 (`yolov8n`~`yolov8x`, `yolo11n`~`yolo11x`, `yolo12n`~`yolo12x`) | `yolo12x` |
| `--tensorrt` | TensorRT 가속 (.engine 파일 필요) | **활성화** |
| `--no-tensorrt` | TensorRT 비활성화 (PyTorch 모델 사용) | - |
| `--fp16` | FP16 반정밀도 추론 (NVIDIA GPU 전용) | 비활성화 |
| `--nvdec` | NVDEC GPU 디코딩 | **활성화** |
| `--no-nvdec` | NVDEC 비활성화 (CPU 디코딩) | - |
| `--detect-interval` | 감지 수행 프레임 간격 (1=매 프레임, -1=자동) | `-1` |
| `--detect-scale` | 감지용 해상도 스케일 (0.5 = 50%, -1=자동) | `-1` |
| `--batch-size` | 배치 추론 크기 (-1=자동) | `-1` |
| `--queue-size` | 프레임 큐 크기 (-1=자동, 병렬처리 시 64 권장) | `-1` |
| `--high-performance` | 고성능 모드: FFmpeg 파이프라인 + 배치 GPU 추론 | 비활성화 |
| `--no-auto` | 자동 최적화 비활성화 | - |

#### 트래킹 파라미터

| 옵션 | 설명 | 기본값 |
|------|------|--------|
| `--tracker` | 트래커 종류 (`bytetrack`, `botsort`) | `bytetrack` |
| `--track-buffer` | 트래킹 버퍼 크기 (손실 허용 프레임) | `30` |
| `--match-thresh` | 트래킹 매칭 임계값 | `0.8` |
| `--iou-thresh` | IoU 임계값 | `0.5` |

#### 로깅 옵션

| 옵션 | 설명 | 기본값 |
|------|------|--------|
| `--log` | 로그 파일 경로 | 자동 생성 |
| `--verbose, -v` | 상세 로그 출력 | 비활성화 |

---

## 사용 예시

### 기본 마스킹

```bash
# 전체 영상 마스킹 (사람 + 번호판 블러)
python mask_video.py video.mp4

# 특정 구간만 처리 (23분~28분)
python mask_video.py video.mp4 --start 23:00 --end 28:00

# HEVC 인코딩 (RTX GPU에서 NVENC 자동 사용)
python mask_video.py video.mp4 --hevc
```

### 고성능 모드 (RTX GPU 권장)

```bash
# 1-Pass 고성능 모드: 배치 GPU 추론 + NVENC 인코딩
# RTX 4070 SUPER 기준 4K 60fps에서 ~48 fps 달성
python mask_video.py video.mp4 --high-performance --hevc

# FP16 반정밀도 추론 (메모리 절약, 속도 향상)
python mask_video.py video.mp4 --high-performance --fp16 --hevc
```

### 2-Pass 모드 (GPU 최대 활용, 재작업 가능)

```bash
# 2-Pass 모드: Pass1(분석) → Pass2(인코딩) 순차 실행
python mask_video.py video.mp4 --2pass --hevc

# JSON 파일 유지 (재인코딩 가능)
python mask_video.py video.mp4 --2pass --hevc --keep-json
```

### 2-Pass 분리 실행 (일괄 처리)

```bash
# 여러 영상을 분석만 먼저 실행 (GPU 100% YOLO 추론)
python mask_video.py video1.mp4 --analyze-only
python mask_video.py video2.mp4 --analyze-only
python mask_video.py video3.mp4 --analyze-only

# 분석 완료 후 순차 인코딩 (GPU 100% NVENC)
python mask_video.py video1.mp4 --encode-only --mask-json video1_masks.json --hevc
python mask_video.py video2.mp4 --encode-only --mask-json video2_masks.json --hevc
python mask_video.py video3.mp4 --encode-only --mask-json video3_masks.json --hevc
```

### 적응형 색보정 + 마스킹

```bash
# 마스킹 + 시네마틱 색보정 (기본 설정)
python mask_video.py video.mp4 --color-grade --hevc

# 색보정 분석 주기 조정 (500프레임마다 분석)
python mask_video.py video.mp4 --color-grade --cg-interval 500 --hevc

# 색보정 전환 부드럽게 (600프레임 윈도우)
python mask_video.py video.mp4 --color-grade --cg-smooth 600 --hevc
```

### 배치 처리 (여러 영상 자동 큐)

```bash
# 기본 배치 처리 (2개 동시 처리)
python batch_masking.py /path/to/video/folder

# 동시 처리 개수 지정
python batch_masking.py /path/to/video/folder --workers 3

# 색보정 비활성화
python batch_masking.py /path/to/video/folder --no-color-grade

# 출력 경로 지정
python batch_masking.py /path/to/input --output-dir /path/to/output

# 작업 미리보기 (실제 실행 안 함)
python batch_masking.py /path/to/video/folder --dry-run
```

### 번호판/사람 선택 마스킹

```bash
# 번호판만 마스킹 (사람 제외)
python mask_video.py video.mp4 --no-persons

# 사람만 마스킹 (번호판 제외)
python mask_video.py video.mp4 --no-plates

# 모자이크 처리
python mask_video.py video.mp4 --mask-type mosaic --mosaic-size 20
```

### 정확도 vs 속도 조절

```bash
# 매 프레임 감지 (정확도 최대, 속도 느림)
python mask_video.py video.mp4 --detect-interval 1

# 5프레임마다 감지 (속도 최대, 정확도 감소)
python mask_video.py video.mp4 --detect-interval 5 --detect-scale 0.25
```

### 트래킹 조정

```bash
# 긴 트래킹 버퍼 (객체가 일시적으로 사라져도 추적 유지)
python mask_video.py video.mp4 --track-buffer 60
```

### 실시간 로그 모니터링

```bash
# 상세 로그 + 파일 저장
python mask_video.py video.mp4 -v --log masking.log

# 별도 터미널에서 실시간 확인
tail -f masking.log
```

---

## 적응형 색보정 (Adaptive Color Grading)

### 개요

적응형 색보정은 영상의 장면별 특성을 분석하여 자동으로 시네마틱 필터를 적용합니다.
일반적인 LUT(Look-Up Table) 방식과 달리, 각 장면의 밝기와 채도를 분석하여
최적의 보정값을 실시간으로 계산합니다.

### 작동 원리

```
┌─────────────────────────────────────────────────────────────┐
│ 1. 분석 단계 (프레임 0, 1000, 2000, ...) │
│ │
│ 프레임 → [밝기 분석] → [채도 분석] → 보정 파라미터 계산 │
│ (HSV V채널) (HSV S채널) │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ 2. 보간 단계 (중간 프레임) │
│ │
│ 키프레임 A ─── [선형 보간] ─── 키프레임 B │
│ (프레임 0) (프레임 500) (프레임 1000) │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ 3. 스무딩 단계 (이동평균) │
│ │
│ [보간된 값] → [이동평균 필터] → 최종 보정 파라미터 │
│ (윈도우: 300 프레임) │
└─────────────────────────────────────────────────────────────┘
```

### C 스타일 필터 특성

기본 적용되는 "C 스타일"은 시네마틱한 느낌을 연출합니다:

| 파라미터 | 값 | 설명 |
|----------|----|----- |
| 목표 밝기 | 115 | 약간 밝은 톤 |
| 목표 채도 | 130 | 생생한 색감 |
| 대비 | 1.15 | 살짝 강조된 대비 |
| 따뜻함 | 15 | 오렌지/골드 톤 |
| 하이라이트 보호 | 0.8 | 과노출 방지 |

### GPU 가속

OpenCV CUDA가 사용 가능한 경우 GPU에서 색보정을 처리합니다:

```python
# GPU 사용 여부 자동 감지
# cv2.cuda.getCudaEnabledDeviceCount() > 0 이면 GPU 사용

# GPU 색보정 파이프라인:
# 1. cv2.cuda_GpuMat.upload() - CPU → GPU 전송
# 2. cv2.cuda.cvtColor() - 색공간 변환
# 3. cv2.cuda.split/merge() - 채널 분리/병합
# 4. cv2.cuda_GpuMat.download() - GPU → CPU 전송
```

### 파라미터 조정 가이드

| 상황 | 권장 설정 |
|------|-----------|
| **급격한 장면 변화** | `--cg-interval 500` (더 자주 분석) |
| **일정한 조명** | `--cg-interval 2000` (분석 빈도 감소) |
| **부드러운 전환** | `--cg-smooth 600` (큰 윈도우) |
| **빠른 반응** | `--cg-smooth 100` (작은 윈도우) |

---

## 배치 처리 시스템

### 개요

`batch_masking.py`는 여러 영상을 자동으로 처리하는 큐 시스템입니다.
지정된 수의 영상을 동시에 처리하고, 하나가 완료되면 다음 파일을 자동으로 시작합니다.

### 사용법

```bash
# 기본 사용 (2개 동시 처리, 색보정 활성화)
python batch_masking.py /path/to/videos

# 옵션
python batch_masking.py /path/to/videos \
--output-dir /path/to/output \ # 출력 경로
--workers 3 \ # 동시 처리 개수
--no-color-grade \ # 색보정 비활성화
--log-dir /path/to/logs \ # 로그 경로
--dry-run # 미리보기
```

### 로그 구조

```
masking/logs/
├── batch_20260112_010317.log # 마스터 로그 (전체 진행)
├── 01-111_4k_420_10bit.log # 개별 로그 (파일별 상세)
├── 01-222_4k_420_10bit.log
└── ...
```

### 마스터 로그 예시

```
[2026-01-12 01:03:17] ==================================================
[2026-01-12 01:03:17] 배치 마스킹 작업 시작
[2026-01-12 01:03:17] 총 파일: 10개, 동시 처리: 2개
[2026-01-12 01:03:17] ==================================================
[2026-01-12 01:03:17] ▶ 시작: 01-111_4k_420_10bit.mp4
[2026-01-12 01:03:17] ▶ 시작: 01-222_4k_420_10bit.mp4
[2026-01-12 02:15:30] ✓ 완료: 01-222_4k_420_10bit.mp4 (1시간 12분 13초)
[2026-01-12 02:15:30] 진행: 1/10 완료, 9개 남음
[2026-01-12 02:15:30] ▶ 시작: 01-333_4k_420_10bit.mp4
```

### 권장 동시 처리 수

| 시스템 RAM | GPU VRAM | 권장 workers |
|-----------|----------|--------------|
| 16GB | 8GB | 1 |
| 32GB | 12GB | **2** |
| 64GB | 12GB+ | 3-4 |

---

## 권장 파라미터 설정

### 시나리오별 권장 설정

#### 🎯 일반 사용 (품질 우선)

```bash
# 기본 설정 - 대부분의 경우 충분
python mask_video.py video.mp4 --hevc

# 자동 최적화가 적용됨:
# - yolo12x TensorRT 모델
# - GPU 블러 (blur-strength 31)
# - NVDEC 디코딩 + NVENC 인코딩
# - 시스템 RAM/VRAM 기반 자동 배치 크기
```

#### ⚡ 최대 속도 (처리량 우선)

```bash
# 고성능 모드 + FP16
python mask_video.py video.mp4 --high-performance --fp16 --hevc

# 또는 배치 크기 수동 지정
python mask_video.py video.mp4 --batch-size 32 --detect-interval 2 --hevc
```

#### 🎬 여러 영상 동시 처리 (병렬 처리)

```bash
# 3개 영상 동시 처리 (RAM 32GB 기준)
python mask_video.py video1.mp4 --queue-size 64 --hevc -o out1.mp4 &
python mask_video.py video2.mp4 --queue-size 64 --hevc -o out2.mp4 &
python mask_video.py video3.mp4 --queue-size 64 --hevc -o out3.mp4 &
wait
```

#### 🎨 마스킹 + 색보정 통합 처리

```bash
# 단일 영상: 마스킹 + 시네마틱 색보정
python mask_video.py video.mp4 --color-grade --hevc

# 배치 처리: 폴더 내 모든 영상 자동 처리
python batch_masking.py ./videos --workers 2
```

#### 🔬 정확도 최대 (느리지만 정밀)

```bash
# 매 프레임 감지 + 큰 모델
python mask_video.py video.mp4 --detect-interval 1 --yolo-model yolo12x --hevc
```

#### 💾 낮은 RAM 환경 (16GB 이하)

```bash
# 큐 크기 줄이기
python mask_video.py video.mp4 --queue-size 32 --batch-size 8 --hevc
```

### 기본 파라미터 값 요약

| 파라미터 | 기본값 | 설명 | 조정 시점 |
|----------|--------|------|-----------|
| `--yolo-model` | `yolo12x` | YOLO 모델 | 속도 필요시 `yolo11x` |
| `--tensorrt` | `True` | TensorRT 가속 | 호환 문제시 `--no-tensorrt` |
| `--fp16` | `False` | FP16 추론 | NVIDIA GPU에서 `--fp16` 권장 |
| `--nvdec` | `True` | GPU 디코딩 | CPU 디코딩 필요시 `--no-nvdec` |
| `--detect-interval` | `-1` (자동) | 감지 주기 | 정확도 필요시 `1`, 속도 필요시 `3-5` |
| `--detect-scale` | `-1` (자동) | 감지 해상도 | 속도 필요시 `0.5` |
| `--batch-size` | `-1` (자동) | 배치 크기 | VRAM 부족시 `8-16` |
| `--queue-size` | `-1` (자동) | 프레임 큐 | 병렬 처리시 `64`, RAM 부족시 `32` |
| `--blur-strength` | `31` | 블러 강도 | GPU는 31 이하 권장 |
| `--person-conf` | `0.4` | 사람 감지 신뢰도 | 놓침 많으면 `0.3`, 오탐 많으면 `0.5` |
| `--vehicle-conf` | `0.3` | 차량 감지 신뢰도 | 놓침 많으면 `0.2`, 오탐 많으면 `0.4` |
| `--person-expand` | `0.2` | 사람 영역 확장 | 마스킹 부족시 `0.3` |
| `--plate-expand` | `0.5` | 번호판 영역 확장 | 마스킹 부족시 `0.6-0.7` |
| `--track-buffer` | `60` | 트래킹 버퍼 | 끊김 많으면 `90-120` |

### 자동 최적화 (-1 = auto)

`-1` 값은 시스템 사양에 따라 자동 설정됩니다:

| 항목 | 자동 계산 기준 |
|------|---------------|
| `detect-interval` | VRAM 12GB 이상: 1, 미만: 2 |
| `detect-scale` | 4K 영상: 0.5, FHD: 1.0 |
| `batch-size` | VRAM의 70% 기준 계산 |
| `queue-size` | RAM의 25% 기준, 최대 512 |

---

## 성능 참고

### 테스트 환경

- **GPU**: NVIDIA RTX 4070 SUPER (12GB VRAM)
- **CPU**: Intel i5-13400 (10코어, 16스레드)
- **RAM**: 32GB DDR5
- **입력**: 4K 60fps HEVC 10bit 영상 (3840x2160)

### 처리 모드별 성능 비교 (yolo12x TensorRT)

| 모드 | 속도 (fps) | 특징 | 권장 사용 |
|------|------------|------|-----------|
| **최적화 모드** (기본) | ~32 fps | yolo12x TRT + GPU 블러 + NVENC | **일반 권장** |
| **고성능 모드** (`--high-performance`) | ~48 fps | 배치 GPU 추론 + 파이프라인 | 빠른 처리 |
| **2-Pass 모드** (`--2pass`) | ~22 fps + ~20 fps | 분석/인코딩 분리 | JSON 재작업 |

### YOLO 모델별 성능 비교

| 모델 | TensorRT | 정확도 | 속도 (fps) | 권장 |
|------|----------|--------|------------|------|
| **yolo12x** | ✅ | 최고 | ~32 fps | **기본값** |
| **yolo11x** | ✅ | 매우 높음 | ~33 fps | 대안 |
| **yolov8x** | ✅ | 높음 | ~35 fps | 속도 중시 |
| **yolov8n** | ✅ | 낮음 | ~45 fps | 테스트용 |

### 병렬 처리 (여러 영상 동시 처리)

여러 영상을 동시에 처리하여 총 처리량을 높일 수 있습니다.

#### 병렬 처리 설정

| 설정 | RAM 사용 | 개별 속도 | 총 처리량 | 권장 |
|------|----------|-----------|-----------|------|
| 단일 (기본) | ~10GB | 28 fps | 28 fps | 일반 |
| **3개 병렬** (`--queue-size 64`) | ~23GB | 19-23 fps | **~63 fps** | **권장** |

#### 병렬 처리 사용법

```bash
# 3개 영상 동시 처리 (--queue-size 64 필수!)
python mask_video.py video1.mp4 --queue-size 64 --hevc -o out1.mp4 &
python mask_video.py video2.mp4 --queue-size 64 --hevc -o out2.mp4 &
python mask_video.py video3.mp4 --queue-size 64 --hevc -o out3.mp4 &
wait # 모든 프로세스 완료 대기
```

#### 병렬 처리 핵심 포인트

- **`--queue-size 64` 필수**: 기본값(512)은 프레임 버퍼가 커서 RAM 부족 발생
- **RAM 32GB 기준 최대 3개**: 프로세스당 ~8GB RAM 사용
- **총 처리량 2배 이상**: 단일 28fps → 병렬 63fps (2.25배)
- **GPU/VRAM 여유**: GPU 17%, VRAM 4.5GB/12GB (병목 아님)

#### 권장 병렬 수 (RAM 기준)

| 시스템 RAM | 권장 병렬 수 | `--queue-size` |
|-----------|-------------|----------------|
| 16GB | 1개 | 기본값 |
| 32GB | **3개** | 64 |
| 64GB | 5-6개 | 64 |

### 2-Pass 모드 상세

| Pass | 동작 | GPU 사용 | 출력 |
|------|------|----------|------|
| **Pass 1** (분석) | YOLO 배치 추론 | GPU 100% 추론 | JSON 마스크 파일 |
| **Pass 2** (인코딩) | 마스크 적용 + NVENC | GPU 100% 인코딩 | 마스킹된 영상 |

### NVENC 인코딩 최적화

시스템 사양에 따라 자동으로 최적화된 NVENC 설정이 적용됩니다:

| 항목 | RTX 4070 SUPER (12GB) | RTX 3060 (8GB) | GTX 1660 (6GB) |
|------|----------------------|----------------|----------------|
| 프리셋 | p4 (quality) | p3 (balanced) | p2 (fast) |
| Lookahead | 32 프레임 | 24 프레임 | 16 프레임 |
| B-프레임 | 4 | 3 | 2 |
| Surfaces | 16 | 12 | 8 |
| FP16 추론 | 활성화 | 활성화 | 비활성화 |

### 감지 통계 예시 (1분 4K 영상)

- 처리 프레임: 3,596
- 감지된 사람: 0
- 감지된 번호판: 19,021

---

## 2-Pass 모드 상세

### 작동 원리

2-Pass 모드는 GPU 자원을 최대한 활용하기 위해 분석과 인코딩을 분리합니다:

```
┌─────────────────────────────────────────────────────────────┐
│ Pass 1: 분석 (GPU 100% YOLO 추론) │
│ │
│ 비디오 → [디코더] → [YOLO 배치 추론] → JSON 마스크 파일 │
│ (사람/번호판 감지) │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ Pass 2: 인코딩 (GPU 100% NVENC) │
│ │
│ 비디오 + JSON → [마스크 적용] → [NVENC 인코딩] → 출력 영상 │
└─────────────────────────────────────────────────────────────┘
```

### JSON 마스크 형식

```json
{
"metadata": {
"version": "1.0",
"input": "video.mp4",
"width": 3840,
"height": 2160,
"fps": 59.94,
"total_frames": 3596,
"start_frame": 0,
"end_frame": 3596,
"created": "2026-01-04T12:51:53"
},
"stats": {
"total_persons": 0,
"total_plates": 19021
},
"frames": {
"0": {
"persons": [],
"plates": [[1520, 1080, 1680, 1140]]
},
"1": {
"persons": [],
"plates": [[1522, 1082, 1682, 1142], [2100, 1500, 2200, 1550]]
}
}
}
```

### 사용 시나리오

| 시나리오 | 명령어 | 설명 |
|----------|--------|------|
| 일반 처리 | `--2pass` | Pass1 + Pass2 순차 실행, JSON 자동 삭제 |
| 재작업 대비 | `--2pass --keep-json` | JSON 파일 유지 |
| 일괄 분석 | `--analyze-only` | 여러 영상 분석만 먼저 실행 |
| 일괄 인코딩 | `--encode-only --mask-json file.json` | 분석된 영상 순차 인코딩 |
| 파라미터 변경 | `--encode-only --mask-json file.json --mask-type mosaic` | 동일 분석 결과로 다른 마스킹 |

---

## 모델 정보

| 모델 | 용도 | 소스 | 비고 |
|------|------|------|------|
| **YOLO12x** | 사람/차량 감지 | Ultralytics | **기본값**, 최신 모델 |
| YOLO11x | 사람/차량 감지 | Ultralytics | 높은 정확도 |
| YOLOv8x | 사람/차량 감지 | Ultralytics | 안정적 |
| YOLOv8n | 사람/차량 감지 | Ultralytics | 속도 우선 |
| ByteTrack | 객체 추적 | Ultralytics 내장 | **기본값** |
| BoT-SORT | 객체 추적 | Ultralytics 내장 | 대안 |

### TensorRT 엔진 생성 (상세 가이드)

TensorRT 엔진은 YOLO 모델을 GPU에 최적화하여 추론 속도를 2-3배 향상시킵니다.
**최초 실행 시 자동 생성**되지만, 사전에 수동 생성하면 첫 실행 시간을 절약할 수 있습니다.

> ⚠️ **주의**: `.engine` 파일은 **시스템 종속적**입니다. GPU, CUDA, TensorRT 버전이 다른 시스템에서는 재생성해야 합니다.

#### 방법 1: YOLO CLI (권장)

```bash
# 기본 FP16 엔진 생성 (권장)
yolo export model=yolo12x.pt format=engine half=True device=0

# 특정 배치 크기로 생성 (배치 추론용)
yolo export model=yolo12x.pt format=engine half=True device=0 batch=32

# 동적 배치 크기 엔진 (유연성 필요 시)
yolo export model=yolo12x.pt format=engine half=True device=0 dynamic=True
```

#### 방법 2: trtexec (고급 설정)

ONNX 모델을 거쳐 TensorRT 엔진을 세밀하게 제어할 수 있습니다.

```bash
# Step 1: PyTorch → ONNX 변환
yolo export model=yolo12x.pt format=onnx half=True simplify=True opset=17

# Step 2: ONNX → TensorRT 엔진 변환
trtexec --onnx=yolo12x.onnx \
--saveEngine=yolo12x.engine \
--fp16 \
--workspace=4096 \
--verbose

# 고정 배치 크기 (최적 성능)
trtexec --onnx=yolo12x.onnx \
--saveEngine=yolo12x_b32.engine \
--fp16 \
--shapes=images:32x3x640x640 \
--workspace=4096

# 동적 배치 크기 (유연성)
trtexec --onnx=yolo12x.onnx \
--saveEngine=yolo12x_dynamic.engine \
--fp16 \
--minShapes=images:1x3x640x640 \
--optShapes=images:16x3x640x640 \
--maxShapes=images:64x3x640x640 \
--workspace=4096
```

#### 주요 trtexec 옵션

| 옵션 | 설명 | 권장값 |
|------|------|--------|
| `--fp16` | FP16 반정밀도 (속도 2배, 정확도 유지) | **필수** |
| `--workspace` | 빌드 시 GPU 메모리 (MB) | 4096 |
| `--shapes` | 고정 입력 크기 (batch×channels×height×width) | 32x3x640x640 |
| `--minShapes/optShapes/maxShapes` | 동적 배치 범위 | 1/16/64 |
| `--best` | INT8 양자화 (캘리브레이션 필요) | 선택적 |

#### 배치 크기별 엔진 파일 관리

```bash
# 여러 배치 크기 엔진 사전 생성
for bs in 16 24 32 48 64; do
yolo export model=yolo12x.pt format=engine half=True device=0 batch=$bs
mv yolo12x.engine yolo12x_b${bs}.engine
done
```

#### 엔진 파일 위치

생성된 `.engine` 파일은 모델 파일과 같은 디렉토리에 저장됩니다:
- 자동 생성: `~/.cache/ultralytics/` 또는 현재 디렉토리
- 수동 지정: `--yolo-model /path/to/yolo12x.engine`

> 💡 **팁**: Git에 `.engine` 파일을 포함하지 마세요 (`.gitignore`에 추가)

---

## 변경 이력

### v3.4 - 2026-01-12 (현재)

**적응형 색보정 시스템 추가**
- **장면별 자동 분석**: 지정된 프레임 간격(기본 1000프레임)마다 밝기/채도 분석
- **시네마틱 필터 적용**: 따뜻한 톤, 대비 향상, 채도 조절 (C 스타일)
- **부드러운 전환**: 장면 변화 시 급격한 필터 변화 방지 (보간 + 이동평균)
- **GPU 가속**: OpenCV CUDA 기반 색보정으로 CPU 대비 빠른 처리
- **마스킹 통합**: 읽기 → 색보정 → 마스킹 → 인코딩 단일 패스로 효율적 처리

**배치 처리 큐 시스템 (`batch_masking.py`)**
- **동시 처리 지원**: 최대 N개 영상 병렬 처리 (기본 2개)
- **자동 큐 관리**: 하나 완료 시 다음 파일 자동 시작
- **상세 로그 시스템**:
- 마스터 로그: 전체 진행 상황 기록
- 개별 로그: 파일별 상세 처리 로그 (`logs/파일명.log`)
- **색보정 통합**: `--color-grade` 옵션 기본 활성화
- **에러 핸들링**: TensorRT 배치 호환 문제로 PyTorch 모델 사용 (`--no-tensorrt`)

**파일 조직화**
- 영상 밝기 기반 day/night 폴더 자동 분류
- 각 폴더별 masking 출력 디렉토리 구조

**새로운 CLI 옵션**
- `--color-grade`: 적응형 색보정 활성화
- `--cg-interval`: 분석 주기 (프레임 단위, 기본 1000)
- `--cg-smooth`: 부드러운 전환 윈도우 (프레임 단위, 기본 300)

**신규 파일**
- `adaptive_color_grade.py`: 적응형 색보정 모듈
- `ColorGrader` 클래스: 마스킹 파이프라인 통합용
- `TargetStyle`: 목표 스타일 파라미터 (C 스타일 기본)
- `CorrectionParams`: 프레임별 보정 파라미터
- GPU/CPU 자동 선택 (`apply_correction_gpu`, `apply_correction`)
- `batch_masking.py`: 배치 처리 큐 시스템

### v3.3 - 2026-01-05

**문서 개선**
- TensorRT 엔진 제작 가이드 강화 (YOLO CLI, trtexec)
- 권장 파라미터 설정 섹션 추가
- 빠른 시작 가이드 추가

### v3.2 - 2026-01-04

**YOLO 모델 업그레이드**
- **기본 모델 변경**: yolov8n → **yolo12x** (최신 고정확도 모델)
- **TensorRT 기본 활성화**: `--tensorrt` 옵션 기본값 True
- **지원 모델 확장**: YOLO11 시리즈 (yolo11n~yolo11x), YOLO12 시리즈 (yolo12n~yolo12x) 추가

**GPU 최적화**
- **GPU 블러**: OpenCV CUDA 가우시안 블러 적용 (CPU 대비 13배 빠름)
- 커널 크기 31 이하에서 GPU 사용, 초과 시 CPU 폴백
- 블러 필터 캐시로 재생성 오버헤드 제거
- **기본 블러 강도**: 51 → 31 (GPU 최적화)
- **NVDEC 기본 활성화**: `--nvdec` 옵션 기본값 True

**마스킹 영역 확장**
- **사람 영역 확장**: `person_expand` 0.1 → 0.2 (여유있게 마스킹)
- **번호판 영역 확장**: `plate_expand` 0.3 → 0.5 (여유있게 마스킹)

**버그 수정**
- **VRAM 감지 임계값 수정**: 12GB → 11.5GB (12282 MiB / 1024 = 11.99GB 문제 해결)
- **인코딩 크래시 수정**: FrameWriter 스레드 동기화 문제 해결
- `daemon=True` → `daemon=False` 변경
- `finished` Event 추가로 완료 대기
- `wait_finished()` 메서드로 안전한 종료 보장
- VideoCapture/Writer 안전한 해제

**병렬 처리 지원**
- **`--queue-size` 옵션 추가**: 프레임 큐 크기 조절로 RAM 최적화
- **3개 동시 처리 가능**: `--queue-size 64`로 RAM 사용량 감소
- **총 처리량 2.25배 향상**: 단일 28fps → 병렬 63fps

**성능 (RTX 4070 SUPER, 4K 60fps)**
- 단일 처리: yolo12x TensorRT ~32 fps
- **병렬 처리 (3개)**: 총 ~63 fps (개별 19-23 fps)
- 15분 영상: 41.5분 (단일) → ~18분 (병렬 3개 추정)

### v3.1 - 2026-01-04

**코드 모듈화**
- **파일 분리**: 대규모 단일 파일을 기능별 모듈로 분리
- `encoding_utils.py`: 시스템 정보 수집, NVENC 설정, FFmpeg 명령어 빌더
- `two_pass.py`: 2-Pass 모드 함수 (`analyze_video`, `encode_with_masks`, `process_video_2pass`)
- `high_performance.py`: 고성능 모드 함수 (`process_video_high_performance`)
- `masking_utils.py`: 공용 유틸리티 (로거 설정, 시간 파싱)
- **CLI 통합**: `mask_video.py`를 단일 진입점으로 통합
- 기존 `mask_video_optimized.py`, `mask_video_advanced.py` 기능 포함

**2-Pass 멀티스레딩**
- **Pass 1 멀티스레딩**: `decoder_thread` + `analyzer_thread` 비동기 처리
- **Pass 2 멀티스레딩**: `decoder_thread` + `masker_thread` + `encoder_thread` 파이프라인
- **성능 개선**: 2-Pass 총 시간 6.7분 → 5.5분 (18% 향상)

### v3.0 - 2026-01-04

**NVENC 인코딩 최적화**
- **최적화된 NVENC 설정**: `build_nvenc_command()` 함수 추가
- `rc-lookahead`: 프레임 미리보기로 품질 향상 (최대 32프레임)
- `spatial-aq`: 공간 적응형 양자화 (디테일 보존)
- `temporal-aq`: 시간 적응형 양자화 (움직임 품질)
- `surfaces`: 동시 인코딩 표면 (처리량 증가)
- `b_ref_mode`: B-프레임 참조 (압축 효율)
- **시스템 자동 최적화**: `get_optimal_settings()` 함수 개선
- CPU 코어/스레드 기반 FFmpeg 스레드 수 자동 설정
- RAM 용량 기반 큐 크기 자동 조정
- VRAM 용량 기반 배치 크기 자동 계산
- GPU 아키텍처 기반 FP16/프리셋 자동 선택

**2-Pass 모드 추가**
- **Pass 1 (분석)**: GPU 100% YOLO 추론, 마스크 좌표를 JSON으로 저장
- 프레임별 마스크 바운딩 박스 저장
- 사람/번호판 감지 통계 포함
- 메타데이터 (해상도, FPS, 총 프레임 수) 저장
- **Pass 2 (인코딩)**: GPU 100% NVENC 인코딩, JSON 마스크 적용
- JSON 마스크 데이터 로드
- 프레임별 마스크 적용 + NVENC 하드웨어 인코딩
- **분리 실행 지원**: `--analyze-only`, `--encode-only`, `--mask-json` 옵션
- 여러 영상 일괄 분석 후 순차 인코딩 가능
- JSON 파일 유지로 재인코딩 지원 (`--keep-json`)

**고성능 모드 개선**
- **멀티스레딩 파이프라인**: 디코딩, 추론, 인코딩 비동기 처리
- `decoder_thread`: 비동기 프레임 읽기
- `processor_thread`: 배치 GPU 추론 + 마스킹
- `encoder_thread`: NVENC 순서 보장 인코딩
- **RTX 4070 SUPER 기준**: 4K 60fps에서 ~48 fps 달성

### v2.4.1 - 2026-01-03

**버그 수정**
- **FP16 추론 오류 수정**: `yolo_half` 변수 초기화 시 잘못된 변수 참조 수정
- 이전: `self.yolo_half = use_fp16 and self.device == 'cuda'` (파라미터 `use_fp16`은 `None`일 수 있음)
- 수정: `self.yolo_half = self.use_fp16 and self.device == 'cuda'` (인스턴스 변수 사용)
- 증상: `unsupported operand type(s) for &=: 'NoneType' and 'bool'` 오류로 배치 처리 실패
- 영향: 모든 프레임에서 마스킹이 적용되지 않고 원본 프레임만 인코딩됨

### v2.4 - 2026-01-03

**NVIDIA CUDA 최적화**
- **OpenCV DNN CUDA 백엔드 지원**: 얼굴 감지를 GPU에서 처리
- `check_opencv_cuda_support()`: OpenCV CUDA/cuDNN 지원 여부 확인
- `FaceDetectorDNN` 클래스에 CUDA 백엔드 자동 선택 로직 추가
- CUDA 사용 불가 시 자동으로 CPU fallback
- **시스템 하드웨어 자동 감지**: `get_system_info()` 함수 추가
- CPU 모델, 코어/스레드 수, 최대 클럭
- RAM 총량 및 사용 가능량
- GPU 모델, VRAM, CUDA 버전, 아키텍처 감지
- **하드웨어 기반 자동 최적화**: `optimize_settings_for_hardware()` 함수
- CPU 스레드 수 기반 워커 수 자동 조정 (threads // 2)
- RAM 기반 프레임 큐 크기 계산
- VRAM 기반 배치 크기 자동 계산 (VRAM 70% 활용)
- 12GB+ VRAM: detect_interval=1 (매 프레임 감지 가능)
- **GPU 메모리 최적화**:
- cuDNN benchmark 모드 활성화
- TF32 연산 활성화 (Ampere+)
- 주기적 GPU 캐시 정리
- **NVENC 하드웨어 인코딩**: RTX GPU에서 hevc_nvenc 자동 사용
- NVENC 실패 시 libx265 소프트웨어 인코딩 fallback

**Python 환경 변경**
- Python 3.11 → 3.12로 업그레이드 (OpenCV CUDA 빌드 호환성)
- NumPy 2.x → 1.26.4로 다운그레이드 (OpenCV 바인딩 호환성)

### v2.1 - 2026-01-02

**버그 수정**
- **차량 감지 버그 수정**: `detect_batch()`에서 `predict()` 대신 `track()` 사용
- 이전: 배치 추론 시 `track_id`가 None이 되어 차량 감지 수가 항상 0
- 수정: 프레임별 `track()` 호출로 트래킹 ID 유지
- **폴백 ID 생성**: `track_id`가 None인 경우 `_get_next_vehicle_id()`로 고유 ID 할당
- **배치 결과 초기화**: `batch_detections` 리스트 사전 초기화로 인덱스 오류 방지

**개선**
- 실시간 로그 출력을 위한 `FlushStreamHandler` 추가
- 진행률 로그 포맷 개선 (fps, 남은 시간, 감지 수 표시)

### v2.0 - 2026-01-02

**성능 최적화 (mask_video_optimized.py 신규 생성)**
- **MPS GPU 가속**: Apple Silicon에서 Metal Performance Shaders 활용
- `get_optimal_device()` 함수로 자동 감지
- YOLO `track()` 호출 시 `device` 파라미터 전달
- **멀티스레딩 파이프라인**:
- `FrameReader`: 별도 스레드에서 프레임 읽기
- `FrameWriter`: 별도 스레드에서 프레임 쓰기
- Queue 기반 비동기 처리
- **프레임 스킵 + 트래킹 보간**:
- `--detect-interval` 옵션으로 감지 주기 설정
- `TrackingInterpolator` 클래스로 중간 프레임 위치 예측
- 속도 기반 선형 보간으로 부드러운 마스킹
- **해상도 다운스케일 감지**:
- `--detect-scale` 옵션으로 감지용 해상도 축소
- 출력은 원본 해상도 유지
- **배치 추론**:
- `--batch-size` 옵션으로 동시 처리 프레임 수 설정
- `detect_batch()` 메서드로 여러 프레임 동시 처리
- **확장된 트래킹 파라미터**:
- `--tracker`: bytetrack 또는 botsort 선택
- `--track-buffer`: 트래킹 버퍼 크기
- `--match-thresh`: 매칭 임계값
- `--iou-thresh`: IoU 임계값
- `create_custom_tracker_config()`: 커스텀 YAML 설정 생성

### v1.0 - 초기 버전

**기본 기능 (mask_video_advanced.py)**
- OpenCV DNN 기반 얼굴 감지
- YOLOv8n 기반 차량 감지
- 기본 ByteTrack 트래킹
- 블러/모자이크 마스킹
- 시작/종료 시간 구간 설정
- HEVC 인코딩 옵션

---

## 문제 해결

### MPS 사용 불가

```
RuntimeError: MPS backend out of memory
```

해결: 배치 크기 줄이기
```bash
python mask_video_optimized.py video.mp4 --batch-size 2
```

### 감지 누락이 많은 경우

해결: 감지 간격 줄이기 + 신뢰도 낮추기
```bash
python mask_video_optimized.py video.mp4 --detect-interval 1 --face-conf 0.3 --vehicle-conf 0.2
```

### 트래킹이 자주 끊기는 경우

해결: 트래킹 버퍼 늘리기 + 매칭 임계값 낮추기
```bash
python mask_video_optimized.py video.mp4 --track-buffer 60 --match-thresh 0.6
```

### 처리 속도가 너무 느린 경우

해결: 감지 간격 늘리기 + 해상도 낮추기
```bash
python mask_video_optimized.py video.mp4 --detect-interval 5 --detect-scale 0.25
```

### NVENC/NVDEC 하드웨어 가속 실패

NVIDIA 하드웨어 인코더/디코더는 **지원하는 픽셀 포맷이 제한적**입니다.

#### 지원 포맷

| 포맷 | NVDEC | NVENC | 비고 |
|------|-------|-------|------|
| **8bit 4:2:0** (yuv420p) | ✅ | ✅ | 가장 호환성 좋음 |
| **10bit 4:2:0** (p010le) | ✅ | ✅ | HDR/고품질 권장 |
| 8bit 4:2:2 (yuv422p) | ❌ | ❌ | 미지원 |
| **10bit 4:2:2** (yuv422p10le) | ❌ | ❌ | 미지원 |
| 8bit 4:4:4 (yuv444p) | ❌ | ⚠️ | 일부 GPU만 지원 |

#### 증상

```
[hevc_nvenc @ 0x...] No capable devices found
```
또는
```
Error initializing output stream -- Hardware does not support this format
```

#### 해결: 입력 영상을 4:2:0으로 변환

```bash
# 10bit 4:2:2 → 10bit 4:2:0 변환 (NVENC 사용)
ffmpeg -i input_422.mp4 -c:v hevc_nvenc -preset p4 -pix_fmt p010le -c:a copy output_420.mp4

# 소프트웨어 인코더로 변환 (더 호환성 높음)
ffmpeg -i input_422.mp4 -c:v libx265 -pix_fmt yuv420p10le -crf 18 -c:a copy output_420.mp4

# 8bit로 변환 (파일 크기 작음)
ffmpeg -i input_422.mp4 -c:v hevc_nvenc -preset p4 -pix_fmt yuv420p -c:a copy output_420_8bit.mp4
```

#### 입력 영상 포맷 확인

```bash
# 픽셀 포맷 확인
ffprobe -v error -select_streams v:0 -show_entries stream=pix_fmt -of default=nw=1 input.mp4

# 상세 정보 확인
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,pix_fmt,color_space,color_transfer -of default=nw=1 input.mp4
```

#### 일괄 변환 스크립트

```bash
#!/bin/bash
# convert_to_420.sh - 4:2:2 영상을 4:2:0으로 일괄 변환

for f in *.mp4; do
pix_fmt=$(ffprobe -v error -select_streams v:0 -show_entries stream=pix_fmt -of csv=p=0 "$f")
if [[ "$pix_fmt" == *"422"* ]]; then
echo "Converting $f ($pix_fmt → p010le)"
ffmpeg -y -i "$f" -c:v hevc_nvenc -preset p4 -pix_fmt p010le -c:a copy "${f%.mp4}_420.mp4"
fi
done
```

> 💡 **팁**: 원본이 10bit 4:2:2인 경우, 10bit 4:2:0 (p010le)으로 변환하면 색상 정보 손실을 최소화할 수 있습니다.

---

## TODO (개선 필요 사항)

### 1. 자동차 번호판 위치 탐지 정확도 개선

- **현재 문제**: 차량마다 번호판 위치가 상이하여 정확한 탐지가 어려움
- **원인 추정**: YOLOv8n은 차량 전체를 감지하며, 번호판 영역은 차량 바운딩 박스 하단 일부로 추정
- **개선 방향**:
- 번호판 전용 감지 모델 도입 (예: 번호판 특화 YOLO 모델)
- 차량 종류별 번호판 위치 비율 학습
- OCR 기반 번호판 텍스트 영역 감지

### 2. 화면 전체 마스킹 오류 수정

- **현재 문제**: 특정 프레임 또는 연속된 프레임에서 화면 전체가 마스킹되는 현상 발생
- **원인 추정**:
- 트래킹 보간 시 비정상적으로 큰 바운딩 박스 생성
- 감지 결과의 좌표값 오류
- 스케일 변환 시 좌표 계산 오류
- **개선 방향**:
- 바운딩 박스 크기 상한선 설정 (화면 대비 비율 제한)
- 이상치 감지 및 필터링 로직 추가
- 프레임 간 바운딩 박스 크기 급변 감지

### 3. 사람 얼굴 감지 및 마스킹 개선

- **현재 문제**: 얼굴 인식 및 마스킹 기능이 부족함
- **원인 추정**:
- OpenCV DNN SSD 모델의 한계 (정면 얼굴 위주, 원거리/측면 감지 약함)
- 4K 영상에서 작은 얼굴 감지 어려움
- **개선 방향**:
- 사람 객체 전체 감지 후 전신 마스킹 옵션 추가
- 더 강력한 얼굴 감지 모델 도입 (RetinaFace, YOLO-Face 등)
- 사람 감지 + 얼굴 감지 2단계 파이프라인 구성
- `--mask-person` 옵션으로 사람 전체 마스킹 선택 가능하도록

### 4. NVIDIA GPU 최적화 세팅 (v2.4에서 일부 완료)

- **완료된 항목** (v2.4):
- ✅ OpenCV DNN CUDA 백엔드 지원 (얼굴 감지 GPU 가속)
- ✅ 시스템 하드웨어 자동 감지 및 최적화
- ✅ VRAM 기반 배치 크기 자동 계산
- ✅ cuDNN benchmark 모드, TF32 활성화
- ✅ NVENC 하드웨어 인코딩 지원
- ✅ FP16 추론 (half=True)
- **추가 개선 필요**:
- TensorRT 변환을 통한 추론 속도 향상
- 멀티 GPU 지원 (대용량 영상 병렬 처리)
- CUDA 스트림을 활용한 비동기 처리
- Docker 이미지 제공 (CUDA 환경 포함)

---

## OpenCV CUDA 빌드 가이드 (NVIDIA GPU)

pip로 설치되는 `opencv-python` 패키지는 CUDA 지원이 포함되어 있지 않습니다.
OpenCV DNN CUDA 백엔드를 사용하려면 소스에서 직접 빌드해야 합니다.

### 테스트 환경

| 항목 | 버전 |
|------|------|
| OS | Ubuntu 24.04 LTS |
| GPU | NVIDIA RTX 4070 Super (12GB VRAM) |
| CUDA | 12.0 |
| cuDNN | 9.17.1 |
| Python | 3.12.3 |
| OpenCV | 4.10.0 |
| GCC | 12 (CUDA 12.0 호환) |

### 1. 빌드 의존성 설치

```bash
sudo apt update
sudo apt install -y \
build-essential cmake git pkg-config \
libjpeg-dev libpng-dev libtiff-dev \
libavcodec-dev libavformat-dev libswscale-dev \
libv4l-dev libxvidcore-dev libx264-dev \
libgtk-3-dev libatlas-base-dev gfortran \
python3.12-dev python3-numpy \
libtbb-dev libdc1394-dev \
gcc-12 g++-12
```

> **중요**: CUDA 12.0은 GCC 12 이하만 지원합니다. Ubuntu 24.04는 기본 GCC 13+를 사용하므로 gcc-12를 별도 설치해야 합니다.

### 2. OpenCV 소스 다운로드

```bash
cd /tmp
git clone --depth 1 --branch 4.10.0 https://github.com/opencv/opencv.git
git clone --depth 1 --branch 4.10.0 https://github.com/opencv/opencv_contrib.git
```

### 3. CMake 설정 및 빌드

```bash
mkdir -p /tmp/opencv_build && cd /tmp/opencv_build

# GCC 12 지정 (CUDA 12.0 호환성)
export CC=/usr/bin/gcc-12
export CXX=/usr/bin/g++-12

# GPU 아키텍처 확인 (예: RTX 4070 = 8.9)
# https://developer.nvidia.com/cuda-gpus 참조

cmake \
-D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=/tmp/opencv_contrib/modules \
-D CMAKE_C_COMPILER=/usr/bin/gcc-12 \
-D CMAKE_CXX_COMPILER=/usr/bin/g++-12 \
-D WITH_CUDA=ON \
-D WITH_CUDNN=ON \
-D OPENCV_DNN_CUDA=ON \
-D ENABLE_FAST_MATH=ON \
-D CUDA_FAST_MATH=ON \
-D CUDA_ARCH_BIN=8.9 \
-D WITH_CUBLAS=ON \
-D WITH_TBB=ON \
-D WITH_V4L=ON \
-D BUILD_opencv_python3=ON \
-D PYTHON3_EXECUTABLE=/usr/bin/python3.12 \
-D BUILD_EXAMPLES=OFF \
-D BUILD_TESTS=OFF \
-D BUILD_PERF_TESTS=OFF \
/tmp/opencv

# 빌드 (CPU 코어 수에 맞게 -j 옵션 조정)
make -j16

# 설치
sudo make install
sudo ldconfig
```

#### GPU 아키텍처 (CUDA_ARCH_BIN) 참조

| GPU 시리즈 | 아키텍처 | CUDA_ARCH_BIN |
|-----------|----------|---------------|
| RTX 40xx (Ada Lovelace) | sm_89 | 8.9 |
| RTX 30xx (Ampere) | sm_86 | 8.6 |
| RTX 20xx (Turing) | sm_75 | 7.5 |
| GTX 10xx (Pascal) | sm_61 | 6.1 |

### 4. Python 가상환경 설정

```bash
cd /path/to/jeju_masking

# Python 3.12로 가상환경 생성 (OpenCV 빌드 버전과 일치)
uv venv --python python3.12
source .venv/bin/activate

# 필수 패키지 설치 (opencv 제외)
uv pip install ultralytics torch torchvision numpy lap pyyaml

# pip opencv 제거 (의존성으로 설치된 경우)
uv pip uninstall opencv-python opencv-python-headless opencv-contrib-python 2>/dev/null || true

# 시스템 OpenCV CUDA를 venv에 심링크
SITE_PACKAGES=$(.venv/bin/python -c "import site; print(site.getsitepackages()[0])")
ln -sf /usr/local/lib/python3.12/dist-packages/cv2 $SITE_PACKAGES/cv2

# NumPy 다운그레이드 (OpenCV 바인딩 호환성)
uv pip install "numpy<2"
```

### 5. 설치 확인

```bash
.venv/bin/python -c "
import cv2
print('OpenCV version:', cv2.__version__)
print('CUDA devices:', cv2.cuda.getCudaEnabledDeviceCount())

# CUDA 빌드 정보 확인
build = cv2.getBuildInformation()
for line in build.split('\n'):
if 'CUDA' in line or 'cuDNN' in line:
print(line)
"
```

예상 출력:
```
OpenCV version: 4.10.0
CUDA devices: 1
NVIDIA CUDA: YES (ver 12.0, CUFFT CUBLAS FAST_MATH)
NVIDIA GPU arch: 89
cuDNN: YES (ver 9.17.1)
```

### 6. 문제 해결

#### GCC 버전 오류

```
error: #error -- unsupported GNU version! gcc versions later than 12 are not supported!
```

해결: CMake에서 GCC 12 명시적 지정
```bash
export CC=/usr/bin/gcc-12
export CXX=/usr/bin/g++-12
cmake -D CMAKE_C_COMPILER=/usr/bin/gcc-12 -D CMAKE_CXX_COMPILER=/usr/bin/g++-12 ...
```

#### NumPy 버전 오류

```
A module that was compiled using NumPy 1.x cannot be run in NumPy 2.x
```

해결: NumPy 다운그레이드
```bash
uv pip install "numpy<2"
```

#### Python 버전 불일치

OpenCV는 빌드 시 지정한 Python 버전의 바인딩만 생성합니다.
venv Python 버전이 빌드 시 사용한 버전과 일치해야 합니다.

```bash
# 빌드 시 Python 3.12 사용한 경우
uv venv --python python3.12
```

---

## 라이선스

이 프로젝트는 개인 프라이버시 보호를 위한 목적으로 제작되었습니다.

### 사용된 오픈소스

- [Ultralytics YOLOv8](https://github.com/ultralytics/ultralytics) - AGPL-3.0
- [OpenCV](https://opencv.org/) - Apache 2.0
- [ByteTrack](https://github.com/ifzhang/ByteTrack) - MIT