Skip to content

About

gRPC-based AI server for real-time face detection and selective anonymization.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

 

History

176 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

InnoLive AI Face Processor

실시간 영상의 얼굴과 차량 번호판을 세그멘테이션·추적하고, 세션별 whitelist에 등록된 인물의 얼굴만 제외해 서버에서 모자이크 JPEG를 반환하는 gRPC AI 서버입니다.

YOLO26n-seg가 얼굴·번호판 mask를 만들고 BoT-SORT가 object track을 유지합니다. face track만 YuNet + AdaFace로 whitelist와 비교하며, number_plate와 확인되지 않은 얼굴은 서버에서 fail-closed 방식으로 보호됩니다.

핵심 기능

  • Mask-level 비식별화: bbox가 아닌 instance mask 단위로 얼굴·번호판 영역을 정밀하게 합성
  • 안정적인 실시간 추적: stream별 BoT-SORT와 1-frame mask hold로 탐지 공백 완화
  • 선택적 모자이크: 세션별 AdaFace whitelist와 track cache를 이용해 등록 인물만 제외
  • Fail-closed 처리: 인식·합성·전송 실패 시 원본 frame으로 되돌아가지 않음
  • 환경별 가속: YOLO는 TensorRT FP16 또는 PyTorch CUDA/MPS/CPU runtime 자동 선택
  • Streaming backpressure: client W5 window, serialized inference, bounded AdaFace·mosaic lane

아키텍처

flowchart LR
    Client["클라이언트<br/>JPEG frame"] -->|gRPC 양방향 stream| Decode["검증 · decode"]
    Decode --> Detect["YOLO26n-seg<br/>얼굴·번호판 mask 탐지"]
    Detect --> Track["BoT-SORT<br/>object track 유지"]
    Track --> Type{"class"}
    Type -->|number_plate| Mosaic["mask 기반 모자이크"]
    Type -->|face| Match{"AdaFace whitelist<br/>일치 여부"}
    Match -->|일치| Keep["얼굴 유지"]
    Match -->|불일치 · 판단 실패| Mosaic
    Keep --> Output["처리 JPEG + metadata"]
    Mosaic --> Output

    Enroll["등록 이미지"] --> Align["YuNet landmark<br/>OpenCV 전처리"]
    Align --> Embed["AdaFace embedding"]
    Embed --> Whitelist[("세션별 whitelist<br/>메모리 저장")]
    Whitelist -.-> Match
Loading

운영 진입점은 bidirectional streaming gRPC 서버인 ai_processor_server.py입니다. App client는 gRPC를 직접 호출하고, 브라우저 demo만 server.py의 WebSocket gateway를 경유합니다. Gateway는 protocol만 변환하며 모델을 별도로 로드하지 않습니다.

기술 스택

  • 데이터 구축 · 외부 학습 pipeline
    • WIDER FACE bbox dataset
    • CVAT 기반 annotation 검수·가공
    • SAM 3.1을 이용한 bbox → segmentation mask 변환
    • 데이터 구축·학습 pipeline은 외부에서 관리하며, 이 저장소는 serving checkpoint와 runtime을 다룹니다.
  • 객체 탐지 · 추적
    • YOLO26n-seg: 640px, face·number_plate 2-class instance segmentation
    • BoT-SORT: stream-local multi-object tracking과 temporal mask hold
  • 얼굴 인식 · 정렬
    • AdaFace ViT-Base KP-RPE, WebFace12M: 512차원 face embedding과 cosine matching
    • YuNet ONNX + OpenCV: 5-point landmark 검출과 112×112 face preprocessing
  • 추론 · 영상 처리
    • TensorRT FP16: Linux x86_64 NVIDIA GPU 배포
    • PyTorch: CUDA, Apple Silicon MPS, CPU fallback
    • OpenCV · NumPy: image validation, mask 합성, Gaussian blur, JPEG encoding
    • ONNX: YuNet artifact와 TensorRT export pipeline의 model format
  • 서빙 · 검증
    • Python 3.12+ · grpc.aio · Protocol Buffers
    • FastAPI · Uvicorn · WebSocket: browser demo와 테스트 endpoint
    • aiortc · WebRTC: 독립 FHD TensorRT 얼굴 합성 실험의 저지연 미디어 경로
    • Ruff · unittest · Node.js test · transport benchmark

빠른 실행

1. 환경 구성

python3 -m venv .venv
.venv/bin/pip install -r requirements.txt

models/best.pt만으로 face/number_plate segmentation과 보호 모자이크를 실행할 수 있습니다. Whitelist 기능에 필요한 AdaFace와 YuNet artifact는 models/README.md의 안내에 따라 준비합니다. Artifact가 없으면 서버는 모든 얼굴과 번호판을 계속 보호하고 whitelist 등록 요청만 거부합니다.

2. gRPC 서버 실행

.venv/bin/python ai_processor_server.py

기본 endpoint는 127.0.0.1:50051입니다. auto 모드는 지원 환경에서 TensorRT engine 파일이 있으면 TensorRT를 선택하고, 그 외에는 PyTorch의 MPS → CUDA → CPU 순서로 device를 선택합니다. TensorRT를 선택한 뒤 검증에 실패하면 PyTorch로 fallback하지 않고 시작을 중단합니다.

CPU 실행을 강제하려면 다음 command를 사용합니다.

.venv/bin/python ai_processor_server.py --backend pytorch --device cpu

3. 브라우저 demo 실행

gRPC 서버를 실행한 상태에서 새 terminal을 엽니다.

.venv/bin/python server.py --grpc-target 127.0.0.1:50051

브라우저에서 http://127.0.0.1:8001을 열면 camera stream과 whitelist 등록 흐름을 확인할 수 있습니다. 이미지 단건 추론 시각화에서 이미지를 업로드하면 원본, gateway가 gRPC로 전달한 실제 resize 입력, bbox와 mask_polygon 윤곽선이 표시된 결과를 함께 확인할 수 있습니다.

NVIDIA TensorRT

TensorRT engine과 검증 manifest는 Git에 포함하지 않습니다. 실제 배포 대상인 Linux x86_64 NVIDIA 장비에서 저장소의 models/best.pt로 매번 생성합니다. 이렇게 해야 GPU와 TensorRT version이 다른 환경의 engine을 잘못 재사용하지 않습니다.

.venv/bin/pip install -r requirements-export.txt
.venv/bin/python -m scripts.export_tensorrt --device 0 --force
.venv/bin/python ai_processor_server.py --backend tensorrt --device 0

Export 단계가 best_b1.engine과 best_b1.engine.json을 생성하고, runtime은 local manifest의 serving profile·engine/checkpoint hash와 TensorRT version을 검증합니다. 두 파일은 배포 호스트에서만 유지되며 기존 engine을 교체할 때는 --force를 사용합니다.

FHD TensorRT 얼굴 합성 실험

experiments/trt_swap_client는 기존 gRPC 비식별화 서버와 분리된 얼굴 합성 실험 서버입니다. 카메라의 1920×1080 프레임을 WebRTC로 받고 YOLO26-seg TensorRT FP16으로 얼굴/번호판 mask를 검출한 뒤, 얼굴 mask가 기본 5,625px²(약 75×75) 이상인 얼굴에 InSwapper 128 TensorRT FP32를 적용합니다. 그보다 작은 얼굴과 번호판, 합성 실패 영역은 Gaussian blur로 보호합니다.

실시간 경로는 WebRTC 카메라 track → 최신 프레임 mailbox → TensorRT 처리 worker → WebRTC 반환 track입니다. mailbox는 프레임 하나만 유지하므로 새 프레임이 오면 아직 처리하지 않은 오래된 프레임을 대체합니다. 별도 RTP 송출 clock은 완료된 최신 결과를 전달하고, 다음 합성이 끝날 때까지는 직전 결과를 반복 송출합니다. 따라서 화면 송출 FPS와 새 얼굴 합성이 완료되는 FPS는 서로 다를 수 있습니다. WebRTC 연결 실패 시 JPEG/WebSocket 경로로 fallback합니다.

BoT-SORT는 stream별로 유지하며 WebRTC 경로에서 GMC(카메라 움직임 보정)를 끕니다. 입력 해상도가 바뀌어도 sparse optical flow pyramid 크기 불일치가 발생하지 않도록 하기 위한 설정입니다. 브라우저 통계에는 client_render_fps, 입력/출력 해상도, 연결 상태가 나오며, WebRTC data channel의 처리 통계에는 detector_batch_ms, swap_ms, swap_alignment_ms, swap_generator_ms, generator의 prepare/forward/paste 시간, total_ms가 포함됩니다.

Linux NVIDIA GPU에서 전용 의존성과 엔진을 준비합니다. TensorRT 엔진은 runtime/GPU 환경에 결합되므로 대상 장비에서 생성해야 합니다. InSwapper는 FP16에서 출력 차이가 확인되어 FP32를 사용합니다.

python -m pip install -r requirements-trt-swap-client.txt
python -m experiments.trt_swap_client.export_detector \
  --checkpoint models/best.pt --output models/best_swap_b4.engine \
  --max-batch 4 --workspace 4 --device 0 --force
python -m experiments.trt_swap_client.export_swapper \
  --onnx models/face_swap/inswapper_128.onnx \
  --output models/face_swap/inswapper_128_trt11_fp32.engine \
  --workspace 2 --precision fp32 --force

models/face_swap/inswapper_128.onnx와 ~/Documents/input.png를 준비한 뒤 저장소 루트에서 실행합니다. run.sh의 기본 port는 8088이며 인자 또는 PORT로 변경할 수 있습니다.

./run.sh
./run.sh 9090
PORT=9090 SOURCE_IMAGE=~/Documents/input.png ./run.sh

브라우저에서 http://SERVER_IP:8088을 엽니다. WebRTC는 UDP 연결이 필요합니다. NAT/방화벽으로 직접 연결할 수 없는 환경은 TURN을 구성하고, signaling과 ICE 후보를 교환할 수 있도록 서버와 네트워크를 설정해야 합니다.

API 요약

  • ProcessVideo: JPEG frame과 처리된 JPEG·object metadata를 주고받는 bidirectional stream
  • AddWhitelist · DeleteWhitelist · GetWhitelistStatus: 세션별 face exemplar 관리
  • CreateSession · ListSessions · DeleteSession: in-memory session lifecycle 관리
  • Python client: grpc_client.VideoProcessorClient

모자이크 강도 실시간 설정 (MosaicConfig)

VIDEO_OUTPUT_MODE_MOSAIC_JPEG 스트림에서 VideoChunk.mosaic_config로 프레임 단위로 모자이크 강도를 지정할 수 있습니다. 지정하지 않으면 서버 기본값 (blur_radius 24, pixel_size 2)을 사용하고, 스트림이 열린 상태에서도 다음 프레임부터 원하는 값으로 바꿀 수 있습니다. 설정은 해당 ProcessVideo 콜(스트림)에만 적용되며 다른 세션이나 다른 스트림에는 전파되지 않습니다.

필드 타입 범위 의미
blur_radius double (0, 64] 가우시안 블러 반경(px). 클수록 더 흐림
pixel_size uint32 1..8 모자이크 블록 크기(px). 1은 픽셀화 비활성(순수 블러)

두 필드 모두 optional이라 한쪽만 지정할 수 있으며 unset 필드는 서버 기본값을 사용합니다. 범위를 벗어나면 해당 프레임만 MOSAIC_CONFIG_INVALID 에러를 받고 스트림은 유지됩니다(에러 응답에는 픽셀이 포함되지 않습니다). Python client에서는 VideoFrame(mosaic=MosaicConfig(blur_radius=..., pixel_size=...))으로 전달합니다.

브라우저 demo gateway는 POST /api/infer-image?session_id=...에 JPEG·PNG·WebP를 raw body로 받습니다. 입력은 long edge 640 이하로 resize한 뒤 gRPC ProcessVideo에 전달하며, 응답에는 동일한 model input JPEG, box/mask overlay JPEG, object metadata가 포함됩니다.

등록 이미지는 저장하지 않고 정규화된 AdaFace embedding만 메모리에 유지합니다. 자세한 message field와 RPC 계약은 protos/ai_processor.proto를 참고합니다.

gRPC 서버 자체에는 인증이 없습니다. 외부 공개 시 private network 또는 authenticated proxy 뒤에서 사용해야 합니다.

experimental metadata 프리셋 합성

메인 gRPC 파이프라인은 기본 Gaussian blur(pixel_size=1)를 사용합니다. VideoChunk.anonymization_mode에 FACE_ANONYMIZATION_MODE_FACE_SWAP을 명시한 경우에만 metadata 기반 프리셋 매칭과 InSwapper-128 합성을 실행합니다. 동일 BoT-SORT 트랙의 identity를 유지하고 metadata와 표정·안경 variant를 트랙별 30프레임마다 갱신합니다. 프리셋 누락·합성 실패는 blur로 처리합니다. 기본 catalog에는 synthetic_faces의 40명·560개 variant가 연결되어 있으며 원본 ID 0..4를 serving slot 1..5로 대응합니다. 이미지 assets는 배포 시 importer로 설치합니다. FACE_ANONYMIZATION_MODE_FACE_METADATA로 속성과 매칭만 확인할 수도 있습니다.

# 새 호스트에 프리셋 설치; 현재 개발 호스트에는 설치 완료
.venv/bin/python scripts/import_face_presets.py --source /path/to/synthetic_faces

# 서버 실행 후 명시적으로 experimental 합성 요청
.venv/bin/python scripts/face_preset_client.py --camera 0 --mode face_swap

프리셋 manifest, 모델 준비, 배포 서버 테스트와 모델 제약은 상세 실행 문서를 참고합니다. Go 서버의 요청 필드와 값별 동작은 Go 연동 가이드, 모델 다운로드와 프리셋 설치는 모델 준비 가이드를 참고합니다.

검증

.venv/bin/pip install -r requirements-test.txt
.venv/bin/ruff check .
.venv/bin/ruff format --check .
.venv/bin/python -m unittest discover -s tests
node tests/test_web.mjs

CPU-safe smoke test

GPU가 사용 중인 개발 환경에서는 모델 runtime server를 새로 띄우지 않고 아래 검증만 실행합니다. 이 스모크 스위트는 runtime·gRPC transport의 test double을 사용해 GPU server를 시작하지 않습니다. 실제 model artifact를 이용한 성능 측정은 배포 GPU에서만 수행하세요.

.venv/bin/ruff check .
.venv/bin/ruff format --check .
.venv/bin/python -m unittest discover -s tests
node tests/test_web.mjs

배포 GPU용 scripts/benchmark_grpc.py는 30 FPS, server p95 33.3 ms 이하와 W5 ordering을 acceptance target으로 검사합니다. 이는 보장된 성능 수치가 아니므로 실제 sequential validation video와 배포 환경에서 다시 측정해야 합니다.

프로젝트 구조

.
├── ai_processor_server.py   # AI gRPC server와 session lifecycle
├── grpc_client.py           # bounded async Python client
├── server.py                # browser ↔ gRPC demo gateway
├── run.sh                   # 독립 TensorRT 얼굴 합성 실험 실행기
├── service/
│   ├── runtime.py           # YOLO 및 TensorRT/PyTorch backend 선택
│   ├── tracking.py          # stream-local BoT-SORT
│   ├── adaface_*.py         # AdaFace backbone과 YuNet runtime
│   ├── recognition.py       # session whitelist와 track decision cache
│   ├── frame.py             # bounded image validation/decode
│   ├── visualization.py     # 단건 추론 box/mask overlay JPEG
│   ├── mosaic.py            # mask union, blur, JPEG 합성
│   └── protocol.py          # browser WebSocket binary codec
├── protos/                  # gRPC schema와 generated Python stubs
├── models/                  # checkpoint와 runtime artifact 안내
├── config/                  # BoT-SORT 설정
├── scripts/                 # TensorRT export와 acceptance benchmark
├── experiments/trt_swap_client/ # FHD WebRTC/TensorRT 얼굴 합성 실험
├── tests/                   # Python·Node 회귀 테스트
├── web/                     # browser demo client

코드 경계

기능을 추가하거나 내부를 정리할 때에는 다음 경계를 유지합니다. 이렇게 하면 transport와 모델 runtime을 독립적으로 테스트할 수 있고, 보호 정책이 UI 구현에 섞이지 않습니다.

영역 책임 의존하면 안 되는 영역
service/frame.py, service/protocol.py 입력 크기·형식 검증과 browser binary codec 모델·세션 상태
service/runtime.py, service/tracking.py detector 실행, stream-local track과 mask 안정화 HTTP/WebSocket
service/recognition.py, service/mosaic.py whitelist 판단과 fail-closed 픽셀 보호 gRPC/FastAPI 객체
ai_processor_server.py protobuf 변환, lifecycle, bounded execution lane browser protocol
grpc_client.py, server.py 각각 app client와 browser demo transport adapter model 직접 로딩

공개 API·protobuf 계약을 바꾸지 않는 정리는 해당 계층 안의 private helper로 제한하고, 경계가 바뀌는 변경은 protocol test와 transport test를 함께 갱신합니다.

라이선스

별도 표시된 제3자 구성요소를 제외하고, 이 저장소에서 자체 작성한 source code는 GNU Affero General Public License v3.0 only로 배포합니다. Ultralytics runtime과 YOLO 학습 checkpoint도 upstream의 기본 AGPL-3.0 조건을 따릅니다. 수정본을 network service로 운영할 때에는 AGPL v3 제13조에 따라 원격 사용자에게 해당 version의 Corresponding Source를 받을 수 있는 방법을 제공해야 합니다.

모델과 학습 데이터의 권리는 source code 라이선스와 별도로 확인해야 합니다. 특히 models/best.pt는 WIDER FACE 기반 학습 이력이 있으므로, 이 저장소의 AGPL 표시는 해당 checkpoint의 상업적 이용 가능성을 보증하지 않습니다. 상업 배포 전에는 WIDER FACE 관련 권리를 별도로 검토하거나, 용도가 명확히 허용된 데이터로 다시 학습한 checkpoint로 교체해야 합니다. Ultralytics, WIDER FACE, SAM 3.1, AdaFace, YuNet 관련 범위와 고지는 THIRD_PARTY_NOTICES.md를 참고하세요.

About

gRPC-based AI server for real-time face detection and selective anonymization.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages