❗ 이 문서는 적용 이전(Scope A 가정) 의 계획 기록입니다. 2026-05-28 최종 적용은 Scope C (공개 구조체 멤버/파라미터명 까지 변경) 로 확장되었으며, →
pvMtcnn/pvMtcnnHandle→pvFaceDetector/pvFaceDetectorHandle→mtcnn_path/pcMtcnnDir→face_detector_path/pcFaceDetectorDirVAS 재컴파일 필수. 최신 적용 상태 문서는NZDeeplearningSDK_V7_onnx_preview/README.md참조.
SDK ONNX 대체 — 변경 전후 한눈 요약
기존 mxnet 기반 얼굴인식 → ONNX(SCRFD + 변환 MobileFaceNet)로 대체했을 때의 차이를 스냅샷으로 정리. 본 문서는 TensorRT 적용은 제외한 기본 CUDA FP32 기준. 통합 절차는 SDK_ONNX_REPLACEMENT_PLAN.md 참조.
아키텍처 그림
변경 전 (mxnet 기반)
VAS NZDeeplearningSDK_V7
├─ CSvrFrClient (FR 소켓 서버) ├─ InsightfaceCPU.lib (mxnet)
│ └─ insightface_cpu_* ─────────────────▶ │ ├─ insightface_cpu.cpp
├─ DetectThread (실시간 영상) │ └─ mxnet_mtcnn.cpp (1147줄, 3단계 MTCNN)
│ └─ *_insightface ────────────────────▶ ├─ InsightfaceLib.lib (mxnet GPU)
└─ ... ├─ NZDeeplearningSDK.lib
│
├─ mtcnn_model/{det1,det2,det3}-{symbol,params}
├─ feature_model/{model-symbol.json, model-0000.params}
├─ libmxnet.dll (~수십 MB + 종속)
├─ mxnet/, mxnet_cpu_1.6.0/, shared_libs/mxnet/
└─ (외 mxnet 의존)
변경 후 (ONNX 기반)
VAS (소스 무변경) NZDeeplearningSDK_V7
├─ CSvrFrClient ├─ InsightfaceCPU.lib (내부 ONNX)
│ └─ insightface_cpu_* ─────────────────▶ │ └─ insightface_cpu.cpp (ScrfdDetector + EmbeddingEngine)
├─ DetectThread ├─ InsightfaceLib.lib (내부 ONNX)
│ └─ *_insightface ────────────────────▶ ├─ NZDeeplearningSDK.lib
└─ ... │
├─ models/det_10g.onnx (SCRFD)
├─ models/feature_model_mxnet.onnx (변환본 128-d)
├─ onnxruntime.dll
├─ onnxruntime_providers_cuda.dll
├─ onnxruntime_providers_shared.dll
└─ shared_libs/onnx/
1. 파일/모델 변경
| 영역 | 변경 전 | 변경 후 | 비고 |
|---|---|---|---|
| 검출 모델 | mtcnn_model/det1+det2+det3-symbol.json + .params (4개) |
models/det_10g.onnx (1개) |
MTCNN 3단계 → SCRFD 단일 |
| 임베딩 모델 | feature_model/model-symbol.json + model-0000.params |
models/feature_model_mxnet.onnx |
mxnet→ONNX 무손실 변환 |
| MTCNN 코드 | InsightfaceCPU/src/mxnet_mtcnn.cpp (1147줄) |
빌드 제외/삭제 | SCRFD로 대체 |
InsightfaceLib/src/mxnet_mtcnn.cpp (1147줄) |
빌드 제외/삭제 | 동상 | |
| 추출 코드 | feature_extract.hpp (mxnet MXPred*) |
EmbeddingEngine.cpp (ONNX Runtime) |
|
| 신규 파일 | — | ScrfdDetector.h/.cpp, EmbeddingEngine.h/.cpp |
검증된 빌딩블록 |
| Lib 소스(변경) | insightface_cpu.cpp, InsightfaceLib.cpp, NZDeeplearning.cpp 내부에 mxnet 호출 |
같은 파일들, 내부만 ONNX 호출로 교체 (헤더 무변경) | 공개 API 무변경 |
| VAS 소스 | — | 수정 안 함 | drop-in |
2. 공개 API (시그니처)
| API 함수 | 시그니처 | 변경 |
|---|---|---|
insightface_cpu_init |
int(const char* mtcnnDir, const char* paramFile, const char* jsonFile, insightface_handle&) |
무변경 |
insightface_cpu_feature_extract(file) |
int(const char*, float*, insightface_handle&) |
무변경 |
insightface_cpu_feature_extract(data,len) |
int(char*, int, float*, insightface_handle&) |
무변경 |
insightface_cpu_identity |
float(float*, float*) — L2SQR distance 반환 |
무변경 (의미 동일) |
insightface_cpu_close |
int(insightface_handle&) |
무변경 |
init_insightface (2 overloads) |
void(facerecognition_handle_data&, ...) |
무변경 |
load_featuremap_insightface |
bool(int, float*, facerecognition_handle_data&) |
무변경 |
identity_insightface (YUV/face_image 2 overloads) |
void(facerecognition_info_container&, ...) |
무변경 |
feature_extract_insightface |
bool(facerecognition_info&, char*, facerecognition_handle_data&) |
무변경 |
close_insightface |
void(facerecognition_handle_data&) |
무변경 |
→ VAS는 같은 함수 시그니처로 호출하면 자동으로 내부 ONNX가 동작.
3. 구조체 (ABI)
| 구조체 / 상수 | 변경 |
|---|---|
insightface_handle { void* pvMtcnnHandle; void* pvFeatureExtractHandle; } |
무변경 (필드 의미 재배치만: ScrfdDetector* / EmbedderBox*) |
face_image { int w,h,c; float* data; } |
무변경 |
facerecognition_info { ...; float feature_map[128]; } |
무변경 (FACE_FETUREMAP=128) |
facerecognition_info_container { int count; ...candidates[32]; } |
무변경 |
facerecognition_handle_data |
무변경 (GPU mem 필드들은 GPU 경로에서 그대로 사용) |
NZMXnetDeviceType enum |
무변경 (ONNX 구현은 무시) |
→ ABI 보존 — VAS 무재빌드 가능.
4. 데이터 흐름
CPU 경로 (FR 소켓 서버)
변경 전: JPEG → imdecode(uint8 BGR) → MTCNN(mxnet 3단계) → align(112) → mxnet feature_model → 128-d
변경 후: JPEG → imdecode(uint8 BGR) → SCRFD(ONNX, box+5점) → align(112) → feature_model_mxnet.onnx → 128-d
───────────────── ─────────────────────────
MTCNN 3단계 → 단일 ONNX 세션 mxnet→ONNX 무손실 변환본
GPU 경로 (실시간 영상)
변경 전: YV12 → CUDA YV12→BGR(/255) → face_image_to_mat(*255) → MTCNN(mxnet) → align → mxnet feature_model → 128-d
변경 후: YV12 → CUDA YV12→BGR(/255) → face_image_to_mat(*255) → SCRFD(ONNX) → align → feature_model_mxnet.onnx → 128-d
───────────────────────────────────────────── ──────
CUDA 전처리 인프라 그대로 유지(YOLO 등과 공유) SCRFD가 MTCNN 대체
→ CUDA 측 코드 / face_image_to_mat 등 기존 전처리 파이프라인 그대로 유지.
5. 빌드 의존성
| 항목 | 변경 전 | 변경 후 |
|---|---|---|
| Include 경로 | $(SolutionDir)mxnet\cpp-package\include |
$(SolutionDir)shared_libs\onnx\include |
| Lib 경로 | $(SolutionDir)mxnet\lib |
$(SolutionDir)shared_libs\onnx\lib |
| 링크 라이브러리 | libmxnet.lib |
onnxruntime.lib + onnxruntime_providers_cuda.lib + _shared.lib |
| Lib 산출물 | InsightfaceCPU.lib / Lib.lib / NZDeeplearningSDK.lib (mxnet 의존) | 동일 .lib들, 내부만 ONNX 의존 |
| 빌드 툴체인 | v143 (VS2022) | v143 유지(본체) |
6. 런타임 DLL
| 변경 전 | 변경 후 |
|---|---|
libmxnet.dll (~수십 MB) |
onnxruntime.dll |
| 종속 mxnet/BLAS DLL들 | onnxruntime_providers_cuda.dll |
onnxruntime_providers_shared.dll |
|
| (CUDA Toolkit 12.5 DLL은 기존 그대로 — cudart, nvjpeg, nvml 등) |
→ libmxnet.dll 와 그 의존성 제거, onnxruntime*.dll 추가(이미 배포 검증됨).
7. 정확도/성능 (LFW 3200쌍, CUDA FP32)
| 지표 | mxnet 원본 | ONNX 변환 | 차이 |
|---|---|---|---|
| 검증 정확도 | 98.8054% | 98.8054% | 0.0%p |
| 평균 유사도(동일인) | 0.651846 | 0.651841 | 0.000005 |
| 평균 유사도(다른인) | 0.005651 | 0.005650 | 0.0000004 |
| 동일인 distance | 0.377647 | 0.377399 | 0.000248 |
| 다른인 distance | 2.173031 | 2.172828 | 0.000203 |
| 동일↔다른인 분리 마진 | 1.795384 | 1.795429 | 0.000045 |
| YV12 왕복 동일인 distance | 0.379356 | 0.379235 | 0.000121 |
→ 소수점 4자리까지 일치 — 패리티 무손실. 기존 갤러리·임계값 그대로.
8. 코드 복잡도
| 영역 | 변경 전 | 변경 후 |
|---|---|---|
| MTCNN 추론 | mxnet_mtcnn.cpp (1147줄) — 3단계, 스케일 피라미드, 동적 PNet predictor 재생성 | ScrfdDetector.cpp (~130줄) — 단일 세션, distance2bbox/kps, NMS |
| 임베딩 추론 | feature_extract.hpp — mxnet C Predict API(MXPredCreate/SetInput/Forward/...) | EmbeddingEngine.cpp — ONNX Runtime 래퍼 |
| 정렬 | similarTransform + warpAffine | ArcFace 5점 템플릿 + estimateAffinePartial2D + warpAffine (동일 패턴) |
| 합산(대략) | ~1500줄 (MTCNN + extract) | ~400줄 (SCRFD + Embedding) |
9. 운영 환경에서 보이는 변경
| 항목 | 영향 |
|---|---|
| 등록된 얼굴 갤러리 | 유지 — 같은 임베딩 공간, 재등록 불필요 |
인식 임계값 (m_params.distance) |
유지 — distance 의미 동일(L2SQR) |
| FR 클라이언트 응답 포맷 | 무변경 (feature_map 128 floats base64) |
| 모델 파일 배포 경로 | mtcnn_model/, feature_model/ → models/ |
| CUDA 의존성 | CUDA 12.5 그대로 |
| GPU 메모리 사용 | mxnet 대비 비슷하거나 약간 적음 |
| 첫 인식 응답 시간 | 비슷 (mxnet cuDNN autotune ↔ ONNX 세션 워밍업) |
| MTCNN 동적 shape 비용 | 제거 (스케일별 predictor 재생성 없어짐) |
10. 검증 시나리오 체크리스트
- [x] LFW 3200쌍 — mxnet vs ONNX 검증 정확도 동일 (98.81%)
- [x] LFW 3200쌍 — distance 패리티 (소수점 4자리)
- [x] 동일 인물 cross-image distance 유지
- [x] 다른 인물 distance 유지
- [x] YV12 왕복 견고성 — 동일인 distance 변화 +0.5% 미만
- [x] 다중 얼굴 컨테이너 —
NZFaceOnnx실시간 경로 - [x] 갤러리 매칭 —
load_featuremap_insightface→identity_insightface로 index 정확 매칭 - [x] 드롭인 API 패리티 —
insightface_cpu_*동일 시그니처·distance 의미 유지
11. 통합 작업 범위 (이번 문서 적용 시)
SDK 측 수정 대상:
- NZDeeplearningSDK_V7/InsightfaceCPU/insightface_cpu.cpp (내부 ONNX 교체)
- NZDeeplearningSDK_V7/InsightfaceLib/InsightfaceLib.cpp (내부 ONNX 교체)
- NZDeeplearningSDK_V7/NZDeeplearningSDK/NZDeeplearning.cpp (*_insightface 함수 내부 ONNX 교체)
- 각 .vcxproj (mxnet → ONNX 링크)
- 모델 배포 패키지 (mxnet 파일 → ONNX 파일)
SDK 측 무수정:
- 공개 헤더 (InsightfaceCPU.h, InsightfaceLib.h, NZDeeplearning.h)
- 구조체 (facerecognition_*, face_image, FACE_FETUREMAP)
- CUDA 전처리 (yuv420ToReuseDevThumbnail, face_image_to_mat 등)
- GPU 경로 데이터 흐름 (YV12 → CUDA → face_image_to_mat → align → embed)
VAS 측 무수정:
- 모든 소스 (CSvrFrClient.cpp, DetectThread.cpp, CFrHandle, ...)
- 빌드 설정
- 갤러리 데이터
12. 이번 범위에서 제외한 향후 확장
| 항목 | 효과 | 추가 작업 |
|---|---|---|
| TensorRT FP16 활성화 | ~1.8× 가속, 정확도 무손실 | 1줄 코드(또는 환경변수) |
| glint360k r100(512-d) 채택 | 정확도 +0.9%p (99.69%) | 구조체·갤러리 변경, 재등록 |
| SCRFD 검출 자체를 TRT로 | 검출 속도 추가 향상 | EmbeddingEngine 동일 패턴 적용 |
요약: mxnet 모델·코드·DLL 의존을 ONNX로 대체하되, 공개 API·구조체·VAS 소스·등록 갤러리·임계값을 전부 그대로 유지. 변경은 SDK 내부 구현 + 모델 파일 + 빌드 의존성에 한정되며, VAS 측은 lib만 교체하면 동작합니다.