4.3 KiB
4.3 KiB
Face SDK Web 服务
把 Android Face SDK 的人脸贴图渲染逻辑迁移到 Python Web 服务:上传一张人物图 + 效果 ID, 返回叠加渲染后的 PNG。CPU 实现(OpenCV 仿射 warp + alpha 混合),不依赖 GPU。
渲染原理(与 Android SDK 一致)
input image ──► MediaPipe FaceLandmarker ──► 478 normalized landmarks
│
▼
face_picture_3dmax.obj (468 顶点+UV / 852 三角形)
每个 obj 顶点 i 的画面位置 = landmarks[INDEX_MAP[i]]
│
▼
每个三角形:
src = obj UV × effect 贴图尺寸 (在 512×512 effect 里)
dst = landmarks 像素位置 (在 input image 里)
cv2.getAffineTransform → cv2.warpAffine → alpha 混合
│
▼
output PNG(同原图尺寸)
INDEX_MAP[468] 同步自 vulkan/hardcode_data.h::indexMap,UV 的 V 翻转与
vulkan/FaceApp.cpp::LoadOBJ 行为一致。
目录结构
python/
├── server/
│ ├── main.py FastAPI 入口(/health /effects /render)
│ ├── face_renderer.py 渲染核心
│ ├── mesh.py OBJ 解析
│ ├── index_map.py OBJ vertex → MediaPipe landmark 映射
│ ├── assets/
│ │ ├── face_picture_3dmax.obj ← 来自 app/src/main/assets
│ │ └── face_landmarker.task ← 可选;不放则自动回退到 app/src/main/assets/
│ └── effects/
│ └── 1.png 512×512 RGBA 效果贴图,文件名是效果 ID(1-99)
└── requirements.txt
一次性安装
需要 Python 3.10–3.12(mediapipe 当前不支持 3.13)。
# Windows PowerShell(或 cmd)
cd D:\face_sdk\python
python -m venv venv
.\venv\Scripts\Activate.ps1 # cmd 用 .\venv\Scripts\activate.bat
pip install --upgrade pip
pip install -r requirements.txt
# Linux / macOS
cd /path/to/face_sdk/python
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
启动服务
cd D:\face_sdk\python
.\venv\Scripts\Activate.ps1
uvicorn server.main:app --host 0.0.0.0 --port 8000
启动日志看到 Application startup complete. 即就绪。
API
GET /health
{"ok": true}
GET /effects
返回当前 server/effects/ 下存在的效果 ID(按 <id>.png 文件名提取,1–99):
{"effects": [1]}
POST /render
- form-data:
image: 文件(jpeg / png / webp,≤ 20MB)effect_id: 整数(1–99,必须在/effects列表内)
- 成功:
200,Content-Type: image/png,body 是 PNG 字节 - 没检测到人脸:
400 {"error":"no_face"} - effect_id 不存在:
404 - 参数错误(图非法 / 太大 / id 越界):
400
curl 示例
curl -X POST http://localhost:8000/render \
-F image=@/path/to/photo.jpg \
-F effect_id=1 \
--output result.png
Python 示例
import requests
files = {"image": open("photo.jpg", "rb")}
data = {"effect_id": 1}
r = requests.post("http://localhost:8000/render", files=files, data=data)
r.raise_for_status()
open("result.png", "wb").write(r.content)
添加新效果
把一张 512×512 的 RGBA PNG 放到 python/server/effects/<id>.png(<id> 是 1–99 的整数)。
服务下次响应 /effects 时会自动列出;首次被请求时按需载入并缓存内存。
PNG 必须有 alpha 通道——透明区域不会盖到原图上。
已知限制
- 纯 2D 仿射 warp,与 Android SDK 行为一致:人脸侧面角度大时贴图会拉伸。
- MediaPipe FaceLandmarker 每次
detect()不保证多线程并发安全,服务用锁串行化。 单进程同步部署够用;要更高并发请用多 worker 或前置队列。 - 单张 4K 图渲染约 100–300ms(852 三角形 ×
cv2.warpAffine);如需更快可改成cv2.remap一次性贴整脸,但需要更多代码。