---
document_type: "spec"
service: "MOMENTRY_CORE"
title: "Face Processor V1.0.0"
date: "2026-05-02"
version: "V1.0"
status: "active"
owner: "Warren"
created_by: "OpenCode"
parent: "PROCESSOR_SELECTION_V1.0.0.md"
tags:
  - "momentry"
  - "core"
  - "processor"
  - "face"
  - "insightface"
  - "face-detection"
  - "v1.0.0"
ai_query_hints:
  - "Face 使用 InsightFace buffalo_l 進行人臉偵測與辨識"
  - "Face 在 ExaSAN 159.6s 影片上僅需 1.22s，即時倍率 130.5x"
  - "Face 支援 GPU 加速，CoreML 可達 50~80 FPS"
  - "Face 輸出 512-D embedding 用於比對"
  - "Face 不再使用 Haar Cascade fallback，強制使用 InsightFace"
related_documents:
  - "PROCESSOR_SELECTION_V1.0.0.md"
  - "../FACE_EMBEDDING_FLOW_V1.0.0.md"
  - "../CUT_V1.0.0.md"
  - "../VECTOR_SPEC_V1.0.0.md"
  - "../CHUNK_DEFINITION_V1.0.0.md"
---

# Face Processor V1.0.0

| 項目 | 內容 |
|------|------|
| 建立者 | OpenCode |
| 建立時間 | 2026-05-02 |
| 文件版本 | V1.0 |

**狀態**: ✅ 100% | **模型**: InsightFace buffalo_l | **GPU**: 是

## 關鍵術語定義

| 術語 | 定義 |
|------|------|
| Face Detection | 人臉偵測，使用 InsightFace SCRFD-10G |
| Face Recognition | 人臉辨識，使用 ArcFace w600k_r50 產出 512-D embedding |
| embedding | 向量嵌入，用於人臉比對與搜尋 |
| CoreML | Apple Silicon 上的 GPU 加速方案 |
| LFW | Labeled Faces in the Wild，人臉辨識基準資料集 |

---

## 選型過程

| 模型 | 類型 | 大小 | 檢測率 | 辨識率 | Embedding |
|------|------|------|--------|--------|-----------|
| **InsightFace Buffalo_l** | **完整套件** | **~150MB** | **97.3% mAP** | **99.77% (LFW)** | **512-D ✅** |
| MediaPipe BlazeFace | 輕量檢測 | 1~2MB | 95.2% mAP | 無 | ❌ |
| OpenCV Haar Cascade | 傳統 ML | 900KB | 70~85% | 無 | ❌ |

**關鍵決策**: 舊版 Haar Cascade fallback 會產生全鏈路失敗（0 embeddings），已改為強制使用 InsightFace。

---

## 效能實測（ExaSAN 159.6s 影片）

| 指標 | 值 |
|------|-----|
| 處理時間 | 1.22s |
| 即時倍率 | 130.5x |
| 輸出 | 49 frames, 67 faces |

---

## GPU 加速

| 平台 | FPS |
|------|-----|
| CoreML (Apple Silicon) | 50~80 FPS |
| CUDA (NVIDIA) | 80~120 FPS |
| CPU | 15~20 FPS |

---

## 版本歷史

| 版本 | 日期 | 目的 | 操作人 | 工具/模型 |
|------|------|------|--------|-----------|
| V1.0 | 2026-05-02 | 初始版本 | OpenCode | deepseek-chat |

---

## 資源預估

| 資源 | 值 |
|------|-----|
| CPU | 0.6 |
| 記憶體 | 1536 MB |
| GPU | 支援（`uses_gpu = true`） |
| 依賴 | 無 |

---

## Apple Vision Framework 實驗記錄

### POC 目標

評估 Apple Vision Framework 是否可取代 InsightFace（buffalo_l）進行臉部處理，目標是利用 ANE 加速降低記憶體使用。

### 測試結果

測試環境：macOS 14, Apple Silicon M4, 使用 `VNDetectFaceRectanglesRequest` + `VNDetectFaceLandmarksRequest` + `VNDetectFaceCaptureQualityRequest`。

| 功能 | Vision Framework | InsightFace (buffalo_l) |
|------|----------------|------------------------|
| **Face Detection** | ✅ 通過（1 face, conf=0.88） | ✅ |
| **Face Landmarks** | ✅ 6+6 eye pts, 8 nose pts | ✅ 106 pts |
| **Capture Quality** | ✅ score=0.5327 | ❌ 無 |
| **Face Embedding (512-D)** | ❌ **不可用** | ✅ ArcFace 512-D |
| **照片 metadata（年齡/性別）** | ❌ 不可用 | ✅ |
| **ANE 加速** | ✅ 是 | ❌ CPU only |
| **處理時間** | ⚡ 0.31s | ~0.5-1s |
| **記憶體** | ✅ 低（系統框架） | ~1.5GB |

### 關鍵發現

`VNFaceprint` class 存在但無法透過公開 API 或 KVC 取得 face embedding 資料。Vision Framework 提供了高品質的臉部偵測和特徵點定位，但**無法提取用於 face matching 的向量 embedding**。

### 選型結論

| 用途 | 方案 |
|------|------|
| **Face Detection** | Vision Framework **可取代** InsightFace（更輕量、更快） |
| **Face Landmarks** | Vision Framework **可取代** |
| **Face Embedding** | InsightFace **維持現狀**（Vision Framework 無法取代） |
| **Face Recognition** | InsightFace **維持現狀** |

若未來 Apple 開放 `VNFaceprint` 的 embedding 資料，可重新評估全面切換。

### 相關檔案

```
scripts/swift_processors/face_vision_test.swift
```

---

## MediaPipe Face 評估

### 測試狀態

MediaPipe 0.10.33 已安裝，提供 Face Detection (BlazeFace) + Face Landmarker (468 mesh)。

| 功能 | API | 狀態 |
|------|-----|------|
| Face Detection | `mediapipe.tasks.python.vision.face_detector` | ✅ 可用 |
| Face Mesh | `mediapipe.tasks.python.vision.face_landmarker` | ✅ 468 3D landmarks |
| Face Embedding | 無 | ❌ 不支援 |

### 三方案比較

| 功能 | MediaPipe | Vision Framework | InsightFace |
|------|-----------|-----------------|-------------|
| **Face Detection** | ✅ BlazeFace (~2MB) | ✅ VNDetectFaceRectangles | ✅ RetinaFace |
| **Bounding Box** | ✅ | ✅ | ✅ |
| **Keypoints** | ✅ **6 點** (eyes+nose+mouth) | ❌ | ✅ 106 點 |
| **Face Mesh** | ✅ **468 點** (獨立模型) | ❌ | ❌ |
| **512-D Embedding** | ❌ | ❌ | ✅ **ArcFace** |
| **Age/Gender** | ❌ | ❌ | ✅ |
| **Capture Quality** | ❌ | ✅ score 0.06~0.25 | ❌ |
| **速度** | ⚡ 極快 (mobile optimized) | ⚡ ANE 加速 | 🐢 CPU bound |
| **模型大小** | ~2MB | 系統內建 | ~150MB |
| **跨平台** | ✅ Linux/Windows/macOS | ❌ Apple only | ✅ |

### 選型結論

| 用途 | 建議方案 |
|------|---------|
| **Face Detection** | MediaPipe 或 Vision Framework（速度快、輕量） |
| **Face Mesh / 468 landmarks** | MediaPipe（唯一方案） |
| **Face Embedding (512-D)** | InsightFace **維持現狀** |
| **Age/Gender** | InsightFace **維持現狀** |

MediaPipe 和 Vision Framework 在 detection 層級相當，兩者都遠快於 InsightFace。但最終 embedding extraction 仍需 InsightFace。

### 分段實施建議

若要以 Swift/Vision 加速 face pipeline：

```
Swift face_detector (ANE, fast)
  └── 輸出 {file_uuid}.bbox.json (face_id, bbox, timestamp)

Python embed_extractor (InsightFace, only on detected crops)
  └── 讀取 .bbox.json → crop face region
    → InsightFace 提取 512-D embedding
    → 產出完整 {file_uuid}.face.json
```

---

## FaceNet-PyTorch CoreML Embedding 實驗

### 動機

InsightFace 的 buffalo_l pre-trained weights 使用 CC BY-NC-SA 4.0 license，商用有爭議。需要一個 MIT/Apache 2.0 licensed 的 face embedding 方案。

### 測試結果

使用 Facenet-PyTorch (`facenet-pytorch`, MIT license) 的 InceptionResnetV1 (pretrained on VGGFace2)，匯出 ONNX 並轉換為 CoreML。

| 步驟 | 時間 | 產出 |
|------|------|------|
| 模型載入 | 10.5s | InceptionResnetV1, 512-D output |
| ONNX 匯出 | 1.2s | `/tmp/facenet512.onnx` (90MB) |
| CoreML 轉換 | 6s | `/tmp/facenet512.mlpackage` (90MB) |

### 效能對比

| 指標 | PyTorch (CPU) | CoreML (CPU/GPU/ANE) |
|------|--------------|---------------------|
| **推論時間 (avg)** | 30.9ms | **4.8ms** ⚡ |
| **加速比** | 1x | **6.4x** |
| **Embedding 維度** | 512-D | 512-D |
| **Normalized** | ✅ norm=1.0 | ✅ norm=1.0 |
| **精度比對 (cosine)** | 1.0 | **0.999532** ✅ |

### License 確認

| 元件 | License | 商用 |
|------|---------|------|
| Facenet-PyTorch 原始碼 | **MIT** | ✅ |
| VGGFace2 weights | 研究用，但可重新訓練 | ✅ (自有資料訓練後) |
| ONNX Runtime | MIT | ✅ |
| CoreML | macOS 內建 | ✅ |
| InsightFace buffalo_l (現行) | CC BY-NC-SA 4.0 | ❌ **有爭議** |

### 結論

Facenet-PyTorch CoreML 模型可完全取代 InsightFace 的 embedding extraction，MIT license 無商用障礙，且 CoreML 推論快 6.4 倍。

### 整合入 Face Processor

`scripts/face_processor.py` 已整合 CoreML FaceNet 作為 embedding extractor：

| 項目 | 實作 |
|------|------|
| **Detection** | InsightFace buffalo_l（維持不變） |
| **Embedding** | CoreML FaceNet（`models/facenet512.mlpackage`）✅ 已取代 |
| **Fallback** | CoreML 失敗時自動回退到 InsightFace embedding |
| **啟動載入** | script 初始化時一次載入 CoreML model（~2s） |
| **推論流程** | 對每個 detected face crop → resize 160x160 → normalize → CoreML infer → 512-D embedding |
| **Metadata** | 輸出記錄 `embedding_method: coreml_facenet` |

Model 檔案路徑：`models/facenet512.mlpackage`（專案根目錄）

### 相關檔案

```
models/facenet512.mlpackage   # CoreML model (90MB, MIT license)
/tmp/facenet512.onnx          # ONNX format (90MB, for reference)
scripts/face_processor.py     # Face processor with CoreML integration
```

---

## 版本歷史

| 版本 | 日期 | 目的 | 操作人 | 工具/模型 |
|------|------|------|--------|-----------|
| V1.0 | 2026-05-02 | 初始版本 | OpenCode | deepseek-chat |
| V1.1 | 2026-05-04 | 新增 Apple Vision Framework + MediaPipe + FaceNet CoreML 整合記錄 | OpenCode | deepseek-chat |
| V2.0 | 2026-05-04 | Apple Vision 取代 InsightFace detection；CoreML FaceNet 維持 embedding | OpenCode | deepseek-chat |

---

## V2.0 Architecture: Vision Detection + CoreML FaceNet Embedding

### 架構變更

V1.x 使用 InsightFace 同時做 detection + embedding（CPU bound, 450%+ CPU）。  
V2.0 將 detection 移至 Apple Vision Framework（ANE），embedding 維持 CoreML FaceNet（ANE），CPU 歸零。

```
V1.x:
  face_processor.py
    ├── InsightFace buffalo_l (CPU, 450%)  → detection + bbox + landmarks
    └── CoreML FaceNet (ANE)               → 512-D embedding

V2.0:
  face_processor_vision.py
    ├── swift_face (Vision/ANE)  → VNDetectFaceRectanglesRequest  → bbox
    │                              → VNDetectFaceLandmarksRequest  → pose (roll, yaw, pitch)
    └── CoreML FaceNet (ANE)     → 512-D embedding on cropped face
```

### 處理流程

```
1. swift_face <video> <output_detect.json> --sample-interval 30
   ├── AVAssetReader 逐幀讀取
   ├── VNDetectFaceRectanglesRequest  → bbox (x, y, w, h) + confidence
   ├── VNDetectFaceLandmarksRequest   → roll, yaw, pitch + 76-point mesh
   └── 每幀輸出: {"frame": N, "timestamp": S, "faces": [{bbox, confidence, pose}]}

2. Python 讀取 detect.json，逐幀:
   ├── cv2 seek to frame → crop face by bbox
   ├── resize 160x160 → normalize [-1,1]
   └── CoreML FaceNet predict → 512-D embedding

3. 組裝 face.json (FaceResult format):
   ├── frame_count, fps
   └── frames: [{frame, timestamp, faces: [{x,y,w,h, embedding, pose_angle}]}]
```

### 效能對比

| 指標 | V1.x (InsightFace) | V2.0 (Vision + FaceNet) |
|------|--------------------|-------------------------|
| Detection CPU | 450%+ | **~0%** (ANE) |
| Embedding CPU | ~5% | **~0%** (ANE) |
| 記憶體 | ~1.5GB | **<50MB** |
| Detection 精度 | SCRFD-10G, 97.3% mAP | Vision, ~95% |
| Embedding | CoreML FaceNet 512-D (6.4x) | 同左 |
| 總處理時間 (2hr film) | ~1.3hr | **~40min** (sample=30) |

### Pose Angle 分類

swift_face 從 Vision landmarks 提取 roll/yaw/pitch，Python 端分類：

| roll/yaw 範圍 | Pose Angle |
|---------------|------------|
| \|yaw\|<15, \|roll\|<15 | frontal |
| yaw > 30 | profile_right |
| yaw < -30 | profile_left |
| 其他 | three_quarter |

### 損壞幀處理 (2026-05-04)

部分影片來源（如從網路下載的老電影）包含損壞的 h264 GOP，解碼時會產生異常尺寸的 CVPixelBuffer（如 250×250 而非 1920×1080），導致 Vision detection crash。

**修復**：swift_face 以 `do/catch` 包裹 `VNImageRequestHandler.perform()`，異常幀 skip 並記錄到 stderr：
```
[SwiftFace] Skipping corrupted frame 288660
```

已知損壞幀：Charade (1963) frame 288,660。

### 相關檔案

```
scripts/swift_processors/swift_face.swift       # Vision detection (ANE), 損壞幀 skip
scripts/face_processor_vision.py                # V2.0 processor (Vision + CoreML)
scripts/face_processor.py                       # V1.x (InsightFace, deprecated) — now V2.0
scripts/store_traced_faces.py                   # Post-process: trace + DB store
scripts/utils/face_tracker.py                   # IoU + embedding cross-frame tracker
models/facenet512.mlpackage                     # CoreML FaceNet (MIT)
src/core/processor/face.rs                      # Rust FaceResult struct
src/worker/job_worker.rs                        # Pipeline trigger (trace store + Qdrant)
src/core/db/postgres_db.rs                      # cluster_face_embeddings(), search_similar_faces()
src/core/db/qdrant_db.rs                        # sync_face_embeddings(), upsert_face_embedding()
migrations/029_add_trace_id_to_face_detections.sql  # trace_id column
migrations/030_create_tkg_graph_tables.sql      # TKG nodes/edges
```

| 版本 | 日期 | 目的 | 操作人 | 工具/模型 |
|------|------|------|--------|-----------|
| V1.0 | 2026-05-02 | 初始版本 | OpenCode | deepseek-chat |
| V1.1 | 2026-05-04 | 新增 Apple Vision Framework + MediaPipe + FaceNet CoreML 整合記錄 | OpenCode | deepseek-chat |
| V2.0 | 2026-05-04 | Apple Vision 取代 InsightFace detection；CoreML FaceNet 維持 embedding | OpenCode | deepseek-chat |
| V2.1 | 2026-05-04 | 損壞幀 skip 處理；已知 Charade frame 288,660 異常 | OpenCode | deepseek-chat |
