inswapper (InsightFace face swap) → OpenVINO 16 / 8 / 4 bit
把 haofanwang/inswapper / InsightFace inswapper_128
的整條換臉流程轉成 OpenVINO IR,並用 NNCF 量化成 16-bit / 8-bit / 4-bit。
推論時不需要 PyTorch / onnxruntime,只要 openvino + opencv + numpy。
⚠️ 授權與使用範圍(請先讀)
inswapper_128、ArcFace、RetinaFace 都是 InsightFace 訓練並發佈的模型, 依其官方授權僅限非商業研究用途(non-commercial research use only)。 本 repo 只做格式轉換與量化測試,請勿用於冒充他人、散布謠言或任何未經當事人同意的用途; 商用請先取得 InsightFace 官方授權。
這條流程用到三個模型
| 網路 | 用途 | 原始 ONNX |
|---|---|---|
retinaface_10g |
人臉偵測 + 5 點關鍵點 | 16.9 MB |
arcface_w600k_r50 |
人臉辨識,輸出 512 維 embedding | 174.4 MB |
inswapper_128 |
換臉本體(target 128×128 + source 512 維 embedding → 換好的臉) | 554.3 MB |
三者都已轉成 OpenVIR,各有 fp16 / int8 / int4 三種版本(int4-mixed 只有 swapper 版本)。
模型清單(models/)
| 檔案 | 精度 | 大小 (xml+bin) |
|---|---|---|
inswapper_fp16.* |
16-bit FP16 | 276.9 MB |
inswapper_int8.* |
8-bit W8A8(NNCF PTQ + SmoothQuant) | 139.1 MB |
inswapper_int4.* |
4-bit u4 權重(NNCF LWC) |
69.7 MB |
inswapper_int4_mixed.* |
4-bit/8-bit 混合(75% 權重為 4-bit) | 91.7 MB |
retinaface_fp16.* / _int8.* / _int4.* |
偵測 | 8.7 / 4.6 / 2.5 MB |
arcface_fp16.* / _int8.* / _int4.* |
辨識 | 87.5 / 44.2 / 22.3 MB |
inswapper_emap.npy |
512×512 的 embedding 投影矩陣(原模型最後一個 initializer) | 1.0 MB |
快速開始(單一 py 檔)
pip install openvino opencv-python numpy huggingface_hub
git clone https://huggingface.co/HelloSun/inswapper
cd inswapper
python inswapper_ov.py -s input/source_face_nasa_astronaut.jpg \
-t input/target_photo_nasa_astronaut.jpg \
-o result.jpg -m int8
模型會在第一次執行時自動從本 repo 下載並快取到 ~/.cache/inswapper_openvino
(可用 INSWAPPER_OV_CACHE 改路徑;也可下載後用 --model-dir models 指定本機資料夾)。
# 最小可運作範例
import cv2
from inswapper_ov import FaceSwapperOpenVINO
swapper = FaceSwapperOpenVINO(precision='int8') # fp16 / int8 / int4 / int4-mixed
out = swapper.swap('source.jpg', 'target.jpg', out='result.jpg')
命令列選項
| 選項 | 說明 |
|---|---|
-s, --source |
提供臉孔的來源圖 |
-t, --target |
要被換臉的目標圖 |
-o, --output |
輸出路徑(預設 result.jpg) |
-m, --model |
fp16(16-bit) / int8(8-bit) / int4(4-bit) / int4-mixed |
-d, --device |
CPU / GPU / NPU / AUTO |
--all-faces |
目標圖中每一張臉都換 |
--face-index N |
只換第 N 張臉(依置信度排序,預設 0 = 最大張) |
--det-size W H |
偵測輸入尺寸,預設 640 640 |
--model-dir |
使用本機 models/ 資料夾,不連網 |
--num-threads |
CPU 執行緒數 |
Python API
from inswapper_ov import FaceSwapperOpenVINO
sw = FaceSwapperOpenVINO(precision='int4-mixed', device='CPU', det_size=(640, 640))
bboxes, kpss = sw.detect(img_bgr) # 偵測
emb, kps = sw.embedding(img_bgr) # 512 維 embedding(ArcFace)
out = sw.swap('src.jpg', 'tgt.jpg', all_faces=True)
實測結果(16 / 8 / 4 bit)
素材為 NASA 公有領域太空人肖像照片(見 samples/README.md),
以 ONNX Runtime FP32(完全相同的預處理與貼回程式碼)為參考基準:
| 精度 | swapper 大小 | 臉部 PSNR ↑ | 臉部 SSIM ↑ | 全圖 PSNR ↑ | embedding cos ↑ | 單次換臉 ↑ |
|---|---|---|---|---|---|---|
| ONNX Runtime FP32(參考) | 554.3 MB | – | – | – | 1.000 | 8.08 s |
| fp16 (16-bit) | 276.9 MB | 56.29 dB | 0.9994 | 71.02 dB | 1.000 | 0.47 s |
| int8 (8-bit) | 139.1 MB | 19.28 dB | 0.556 | 37.09 dB | 0.979 | 0.09 s |
| int4-mixed (4-bit 主體) | 91.7 MB | 17.28 dB | 0.672 | 37.70 dB | 0.947 | 0.40 s |
| int4 (純 4-bit) | 69.7 MB | 14.79 dB | 0.532 | 32.29 dB | 0.947 | 0.43 s |
(測試機:Xeon Platinum 8559C 16 vCPU、OpenVINO 2026.4.1、1280×1024 照片、單張臉。)
怎麼選
- fp16(16-bit):與原模型幾乎一模一樣(56 dB),又快 17×,大多數情況請用這個。
- int8(8-bit):CPU 上最快(0.09 s),模型只有原版 1/4;臉部會有細微雜訊, 但辨識度完全沒問題。注意:校準資料一定要用真實人臉(見下方匯出說明), 用隨機雜訊校準會讓 ArcFace embedding 偏移到 cosine 0.78(會換到錯的人)。
- int4-mixed(4-bit 主體):視覺品質比純 4-bit 好很多,幾乎達到 int8 的水準, 模型 91.7 MB(FP32 的 1/6)。要在 4-bit 路線上兼顧品質就用這個。
- int4(純 4-bit):最小(69.7 MB),但 swapper 是類 GAN 網路, 4-bit 誤差會讓膚色嚴重偏色(見 montage 右下),不建議實際使用。
INT4 在 CPU 上不會比 INT8 快(0.43 s vs 0.09 s):CPU plugin 會在 runtime 把
u4權重 解壓回 FP32/FP16 再計算。INT4 的收益是模型體積,不是速度。
Intel GPU / NPU
python inswapper_ov.py -s src.jpg -t tgt.jpg -o out.jpg -m int8 -d GPU
這三個 IR 都是標準 OpenVINO IR,不綁 plugin,CPU / GPU / NPU / AUTO / HETERO 都能跑。
GPU 上推薦 int8(plugin 對 INT8 卷積最佳化)與 fp16;
int4 在 GPU 上也不會有 4-bit 卷積加速,權重同樣是 runtime 解壓。
要產生針對 GPU plugin 調校的 INT8 模型:
python export_openvino_inswapper.py --onnx-dir onnx --target-device gpu \
--models inswapper --precisions int8 --calib-dir calib
本 repo 的數據是在沒有 GPU 的機器上量測的(
available_devices = ['CPU']), GPU 的說明依 OpenVINO plugin 能力整理,非本機實測。
從原始 ONNX 重新轉換/量化
# 1) 先取得三個 ONNX(見 README 的來源)
# 2) 用真實人臉照片產生 NNCF 校準張量(強烈建議,否則 INT8 embedding 會偏移)
python make_calib_data.py --images "input/*.jpg" --samples 24 --out-dir calib
# 3) 轉換 + 量化(fp16 / int8 / int4 一次產出)
python export_openvino_inswapper.py --onnx-dir onnx --out-dir models --calib-dir calib
# 只做純 4-bit 或混合精度 4/8-bit
python export_openvino_inswapper.py --onnx-dir onnx --out-dir models \
--models inswapper --precisions int4 --int4-ratio 0.75
轉換管線裡處理了三個「不處理就會出包」的點:
- NNCF 的
compress_weights(mode='int4_*')預設只壓 MatMul,卷積會靜默退回 INT8 →enable_int4_for_convolutions()擴充_get_ratio_defining_params,讓 Conv 也用 4-bit。 swapper 裡的Gemm會自動被壓,Conv則需要這個 patch。 - NNCF 的 CPU hardware config 只允許 8/16-bit 權重 →
enable_int4_weights_in_cpu_hw_config()把q4_w加進 Convolution/MatMul 的 qspace,才會產生真正的u4常數。 (--target-device gpu時 NNCF 本身就允許 4-bit,不需 patch。) openvino.convert_model()預設把權重壓成 FP16(舊版 Model Converter 的行為) →convert_onnx_fp32()以compress_to_fp16=False轉換,量化才從真正的 FP32 出發。
另外,emap(embedding 投影矩陣)在推論時需要,但它是 ONNX 最後一個 initializer,
已匯出成 models/inswapper_emap.npy,執行期就不必安裝 onnx 了。
重新產生 samples/
python make_sample.py --onnx-dir onnx --models-dir models --out-dir samples
疑難排解
| 症狀 | 原因 / 解決 |
|---|---|
| 換錯人 / 換到奇怪的人 | ArcFace 精度太低或校準資料是隨機雜訊;用 --model-dir 指定本機 IR,並用 int8 以上 |
| 臉部出現彩色斑塊 | 用了純 int4,改用 int4-mixed 或 int8 / fp16 |
No face detected |
把 --det-size 調大(例如 1024 1024),或換張臉比較大的圖 |
| 想對影片換臉 | 逐影格呼叫 sw.swap(...),參考下方「影片」範例 |
| OpenVINO 對 FP32 graph 預設 bf16 | inswapper_ov.py 已固定 INFERENCE_PRECISION_HINT=f32;自己呼叫 ov.Core().compile_model 時記得傳入 |
影片換臉(逐影格)
import cv2
from inswapper_ov import FaceSwapperOpenVINO
sw = FaceSwapperOpenVINO(precision='int8')
cap, out = cv2.VideoCapture('in.mp4'), cv2.VideoWriter('out.mp4', cv2.VideoWriter_fourcc(*'mp4v'), 25, (1920, 1080))
while True:
ok, frame = cap.read()
if not ok: break
out.write(sw.swap('src.jpg', frame, verbose=False))
out.release()
來源與授權
| 項目 | 來源 | 授權 |
|---|---|---|
| 換臉程式 | haofanwang/inswapper | Apache-2.0 |
inswapper_128 |
deepinsight/insightface | 非商業研究用途 |
arcface_w600k_r50、retinaface_10g |
InsightFace(buffalo_l 系列) | 非商業研究用途 |
| 量化 | OpenVINO NNCF | Apache-2.0 |
| 測試照片 | NASA Johnson Space Center(公有領域) | Public Domain |
inswapper_ov.py / 匯出腳本 / 本說明 |
本專案 | Apache-2.0 |
本 repo 的 inswapper_ov.py 內含從 InsightFace 移植的 estimate_norm / RetinaFace 後處理 /
換臉貼回(paste_back)邏輯,以確保 OpenVINO 版本與原版逐像素一致。
