Files
face_sdk/python/README.md
T
2026-05-05 21:44:42 +08:00

147 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.103.12mediapipe 当前不支持 3.13)。
```powershell
# 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
```
```bash
# 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
```
---
## 启动服务
```powershell
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`
```json
{"ok": true}
```
### `GET /effects`
返回当前 `server/effects/` 下存在的效果 ID(按 `<id>.png` 文件名提取,199):
```json
{"effects": [1]}
```
### `POST /render`
- form-data
- `image`: 文件(jpeg / png / webp,≤ 20MB
- `effect_id`: 整数(199,必须在 `/effects` 列表内)
- 成功:`200``Content-Type: image/png`body 是 PNG 字节
- 没检测到人脸:`400 {"error":"no_face"}`
- effect_id 不存在:`404`
- 参数错误(图非法 / 太大 / id 越界):`400`
#### curl 示例
```bash
curl -X POST http://localhost:8000/render \
-F image=@/path/to/photo.jpg \
-F effect_id=1 \
--output result.png
```
#### Python 示例
```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>` 是 199 的整数)。
服务下次响应 `/effects` 时会自动列出;首次被请求时按需载入并缓存内存。
PNG 必须有 alpha 通道——透明区域不会盖到原图上。
---
## 已知限制
- 纯 2D 仿射 warp,与 Android SDK 行为一致:人脸侧面角度大时贴图会拉伸。
- MediaPipe FaceLandmarker 每次 `detect()` 不保证多线程并发安全,服务用锁串行化。
单进程同步部署够用;要更高并发请用多 worker 或前置队列。
- 单张 4K 图渲染约 100300ms852 三角形 × `cv2.warpAffine`);如需更快可改成
`cv2.remap` 一次性贴整脸,但需要更多代码。