第一步:按性别把发际线类型贴图渲染到照片,输出 N 张发际线叠加预览图。 - hairline/render.py: 解析 face_ext.obj(502 UV + 64 ribbon扩展面) + OpenCV 逐三角 仿射 warp 渲染器;关键修复——face_ext.obj 是 OBJ序,用 INDEX_MAP_468 把 MP序 502点重排成 OBJ序后再投影,否则 ribbon 会错贴到中脸 - hairline/service.py: FaceLandmarker+SegFormer 单例 + 性别贴图映射(扫描去空格) + generate_previews 管线(female5/male4) - 集成点修复: face_landmarks DEFAULT_MODEL_PATH 改 hairline/models/; constants HF_FACE_PARSER_MODEL 改本地路径(离线) - app.py: /api/v1/hair/grow 接真实实现,gender 必填(非法→1004),返回 results[].image_base64(不落盘),校验/鉴权同接口1;lifespan 预热接口2单例; 补 logging.basicConfig - 依赖: transformers==4.45.2;SegFormer 权重走 hf-mirror 下载(见 OFFLINE_ASSETS) - 测试: tests/test_hairline.py(mesh/重排/贴图映射) + test_api 接口2用例,31 全绿 注:SegFormer 受 5090/torch 限制走 CPU(~2.5s/张),换 cu128 可 SEG_DEVICE=cuda。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4.3 KiB
4.3 KiB
离线资产清单(内网部署用)
已入库文件(git clone 后自动到位)
以下文件体积适中,已直接提交进 git,clone 仓库即可:
| 文件 | 路径 | 大小 | 用途 |
|---|---|---|---|
| BiSeNet 主权重 | face_analysis/weights/79999_iter.pth |
~53MB | 人脸解析分割(接口1方案B,取真实发际线/头顶) |
| resnet18 骨干 | face_analysis/weights/resnet18-5c106cde.pth |
~45MB | BiSeNet 骨干网络 |
| 中文字体 | face_analysis/fonts/NotoSansCJKsc-Regular.otf |
~16MB | 标注图中文渲染 |
| MediaPipe 模型 | hairline/models/face_landmarker.task |
~3.7MB | 468点人脸关键点检测(接口2) |
需手动下载文件(体积过大,不入 git)
SegFormer 人脸分割模型(接口2必需)
| 文件 | 路径 | 大小 |
|---|---|---|
| model.safetensors | hairline/models/face-parsing/model.safetensors |
338,580,732 B (~323MB) |
下载命令(国内用 hf-mirror 镜像,快很多):
# 国内镜像(推荐)
curl -L -o hairline/models/face-parsing/model.safetensors \
"https://hf-mirror.com/jonathandinu/face-parsing/resolve/main/model.safetensors"
# 官方源
# curl -L -o hairline/models/face-parsing/model.safetensors \
# "https://huggingface.co/jonathandinu/face-parsing/resolve/main/model.safetensors"
sha256 校验:
c2bec795a8c243db71bd95be538fd62559003566466c71237e45c99b920f4b62 hairline/models/face-parsing/model.safetensors
sha256sum hairline/models/face-parsing/model.safetensors
sha256 校验(已入库文件)
468e13ca13a9b43cc0881a9f99083a430e9c0a38abd935431d1c28ee94b26567 face_analysis/weights/79999_iter.pth
5c106cde386e87d4033832f2996f5493238eda96ccf559d1d62760c4de0613f8 face_analysis/weights/resnet18-5c106cde.pth
2c76254f6fc379fddfce0a7e84fb5385bb135d3e399294f6eeb6680d0365b74b face_analysis/fonts/NotoSansCJKsc-Regular.otf
sha256sum -c <<'EOF'
468e13ca13a9b43cc0881a9f99083a430e9c0a38abd935431d1c28ee94b26567 face_analysis/weights/79999_iter.pth
5c106cde386e87d4033832f2996f5493238eda96ccf559d1d62760c4de0613f8 face_analysis/weights/resnet18-5c106cde.pth
2c76254f6fc379fddfce0a7e84fb5385bb135d3e399294f6eeb6680d0365b74b face_analysis/fonts/NotoSansCJKsc-Regular.otf
EOF
resnet18 文件名内嵌的
5c106cde即其官方 sha256 前 8 位(torchvision 命名惯例),与上表一致 = 官方权重无误。
⚠️ resnet18 骨干的离线处理(重要)
BiSeNet 初始化时会调用 torch.utils.model_zoo / torchvision 联网下载 resnet18 骨干,内网会失败报错。两种解法任选其一:
- 放进 torch 缓存目录(推荐,零改代码):
(Windows 路径:
mkdir -p ~/.cache/torch/hub/checkpoints/ cp face_analysis/weights/resnet18-5c106cde.pth ~/.cache/torch/hub/checkpoints/%USERPROFILE%\.cache\torch\hub\checkpoints\) - 改 BiSeNet 代码,把骨干加载改成从
face_analysis/weights/resnet18-5c106cde.pth本地读取(load_state_dict(torch.load(本地路径)),并去掉联网下载分支)。
下载来源(联网环境重建用)
79999_iter.pth https://huggingface.co/ManyOtherFunctions/face-parse-bisent/resolve/main/79999_iter.pth
resnet18-5c106cde.pth https://download.pytorch.org/models/resnet18-5c106cde.pth
NotoSansCJKsc-Regular.otf https://github.com/notofonts/noto-cjk/raw/main/Sans/OTF/SimplifiedChinese/NotoSansCJKsc-Regular.otf
model.safetensors https://huggingface.co/jonathandinu/face-parsing/resolve/main/model.safetensors
还差什么(pip 依赖)
模型已就位,但内网机还需要 Python 依赖的离线 wheel 包,否则 pip install 在内网无法联网安装。这部分与目标机的操作系统、Python 版本、CUDA 版本强相关,需确认后单独打包:
- worker(GPU 机):
mediapipe/opencv-python/numpy<2/Pillow/torch+torchvision的 CUDA 版(按 GPU 的 CUDA 版本选 cu118/cu121 等)/transformers(接口2 SegFormer)+ FastAPI/uvicorn 全家桶。 - 网关机:很轻,只需 FastAPI/uvicorn/httpx 等代理依赖,不需要 torch/mediapipe。
架构已拆分(见
docs/系统架构-网关与高性能后端.md):算法依赖只装在 worker,网关保持轻量。
创建日期:2026-06-14 | 配套:技术方案 v2.0 / 任务书 v1.3