save code

This commit is contained in:
xsl
2026-05-05 21:44:42 +08:00
parent f8b1e567c1
commit bd1b7e66c8
45 changed files with 2953 additions and 0 deletions
+146
View File
@@ -0,0 +1,146 @@
# 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` 一次性贴整脸,但需要更多代码。