Files
hair/docs/实现说明.md
T
xslandClaude Opus 4.8 76f7c06905 review+docs: 接口4 回收到网关、对齐错误码、合并文档为一份实现说明
代码 review 后的清理:
- 接口4 由网关本机实现,worker app.py 的 /face/features 回退 Mock(保持 worker 无外网依赖);
  worker requirements 标注 volcengine 改为网关侧;移除 worker 的接口4 测试(随实现挪到网关)
- 网关接口4 业务错误 HTTP 状态统一改 200(与其余接口/worker 约定一致,原为400/503)
- 接口文档:gender 非法码 1004(原误写1008);修正指向已删文档的链接

文档合并:把各接口技术方案/开发任务书/系统架构/网关任务书 合并成 docs/实现说明.md(简要总览),
删除原 7 份分散文档,README 收敛为索引(实现说明/接口文档/需求/OFFLINE_ASSETS)。

pytest 44 全绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 20:58:33 +08:00

7.0 KiB
Raw Blame History

旷视五接口 — 实现说明(总)

把原先分散的「各接口技术方案 + 开发任务书 + 系统架构 + 网关任务书」合并成这一份简要总览。 对外 API 契约以 接口文档.md 为唯一权威;原始需求见 旷视具体需求.md 离线模型清单见 ../OFFLINE_ASSETS.md


1. 架构

两台机器、一个仓库:

客户端 ──HTTPS──> 外网网关(gateway/)  ──HTTP(X-Internal-Token)──> worker(GPU 机, app.py)
                     │ 薄代理 + 落盘改URL                          │ 跑算法(本地模型/ComfyUI)
                     └ 接口4 本机直接调豆包(不转发)                 └ 接口1/2/3/5
  • workerapp.py + face_analysis/ + hairline/):跑真正的算法,纯本地、无外网依赖。 对 /api/* 校验 X-Internal-Token(密码在 worker_config.jsonaccept_passwords); /health 模型就绪才返回 200。监听 8187./start.sh 控制开关,./run_worker.sh 热重载)。
  • 网关gateway/):薄反向代理,健康检查/派发/鉴权/把 worker 的 *_base64 落盘改成 *_url。 唯一例外是接口4 在网关本机直接实现(调外网豆包,不转发 worker)。
  • 图片三选一:所有接口图片入参 image_file/image_url/image_base64 严格三选一(接口3 是 marked_image_*)。
  • 响应信封{code, message, request_id, data};业务错误用 codeHTTP 一律 200)。

base64 → URL 映射(网关落盘改写,递归进数组、可空保留 null)

接口 worker 字段(内部) 对外字段
1 annotated_image_base64 annotated_image_url
2 results[].image_base64 / results[].grown_image_base64(可空) results[].image_url / results[].grown_image_url
3 hair_growth_image_base64(可空) hair_growth_image_url
5 hairline_images[].image_base64 hairline_images[].image_url
4 (网关本机产出,无图片字段,features 为 JSON 字符串)

实现建议:递归遍历 data,凡 key 以 _base64 结尾就落盘改 _url,自动覆盖嵌套/新增字段。

错误码

1001 无法识别人像 1002 分辨率过低 1003 非正面 1004 gender 必填/非法(接口2/5)| 1006 >1MB 1007 图片参数错误(0或多个)/未预期异常 | 1008 格式不支持。


2. 五个接口实现简述

接口1 四庭七眼测量 /api/v1/face/measureworker

  • 做什么:正面照 → 四庭(顶/上/中/下庭) + 七眼(眼宽/脸宽/间距) 的 cm 与占比、5 个关键点坐标、一张透明底标注 PNG。
  • 怎么实现face_analysis/):MediaPipe Face Mesh 468+虹膜点 → solvePnP 姿态校验(非正面 1003) → 虹膜直径法定标(px→cm) → 眉心以下实测眉心以上用 BiSeNet 头发分割取真实发际线/头顶(方案B), 失败回退比例推算(方案A,hairline_source 透出)。标注图 numpy 向量化渐变线 + 思源黑体。返回 annotated_image_base64
  • 门槛可配:MIN_SHORT_SIDE/MIN_LONG_SIDE(默认600/800)、姿态阈值 FRONTAL_*_THR(默认30°)。

接口2 C端生发 /api/v1/hair/growworker)—— 预览 + 生发图

  • 做什么:正面照 + gender(必填) → 该性别全部发际线(female5/male4) 各一组:预览图(发际线叠在照片上) + 生发后图(植发3个月效果)。
  • 怎么实现hairline/):移植 head3d——MediaPipe(Tasks) + SegFormer 分割 + 17 锚点射线检测 → 502 点 mesh, 按 face_ext.obj 的 UV 把发际线贴图渲染到额头(预览)。生发:黑贴图渲染遮罩 → 调本机 ComfyUI 8182add_hair.json(Flux-2) 出图。关键坑obj 是重排序,需 INDEX_MAP_468 把 MP 序→OBJ 序。 同步、一次 N 张(~18s)。返回 results[].image_base64 + grown_image_base64

接口3 B端生发 /api/v1/hair/grow-bworker)—— 马克笔发际线

  • 做什么:医生用马克笔在额头画好发际线,只传这一张划线图 → 检测线 → 生发图。输出 hair_growth_image_url + hairline_type="custom"
  • 怎么实现:检测算法源自 headmark——黑帽响应图 + 鬓角锚点(MediaPipe 21/251) + Dijkstra 最小路径(scikit-image), 比全局阈值鲁棒;路径平均响应过低→拒识(1001)。检测路径建遮罩,划线图原样送 ComfyUI(提示词清除黑线)。

接口4 用户特征 /api/v1/face/features网关本机

  • 做什么:照片 → 几十项面部特征(脸型/眉形/肤色/三庭五眼/四季色彩季型/量感/基因风格/性别…)。data.features 是 JSON 字符串。
  • 怎么实现gateway/,逻辑参考 worker face_features.py / /home/xsl/fuyan):调火山方舟 豆包视觉模型 doubao-seed-1-6-vision(OpenAI 兼容,base64 data URI 喂图),解析 JSON + 映射 6 个英文优先字段并保留全部中文。 无人脸→1001。唯一调外网的接口:网关需可达 ark.cn-beijing.volces.comAPI Key 走网关配置(不入 git)。

接口5 发际线PNG生成 /api/v1/hairline/generateworker

  • 做什么:照片 + gender(必填) → N 张发际线叠加图(同接口2预览) + 最佳(order1)发际线曲线的面部中间点坐标。
  • 怎么实现:复用接口2 的 502 点渲染管线,输出 N 张叠图 + best_hairline_center_point(眉心 x × 该处发际线 y)。无生发。

3. 部署 / 环境要点

workerGPU 机)

  • Python 3.12(系统 3.13 无 mediapipe/torch wheel);venv 在 ./venv,依赖 requirements.txt
  • numpy<2(1.26.4)scikit-image==0.24.0别升 0.25+,会顶 numpy≥2 顶崩 mediapipe)。
  • ⚠️ 本机 RTX 5090(sm_120)pinned torch 2.2.2(cu121) 只到 sm_90 → GPU 算子报 "no kernel image" 代码已自动回退 CPUBiSeNet/SegFormer CPU 推理可用)。要用 5090 GPU 需换 torch cu128(≥2.7)。
  • 模型权重/字体见 ../OFFLINE_ASSETS.mdBiSeNet/SegFormer/face_landmarker.task 本地。
  • 生发接口依赖本机 ComfyUI(8182)Flux-2,它自带支持 5090 的 torch);worker 只调其 HTTP API,不跑 Flux。
  • worker_config.json(不入 git)accept_passwords(鉴权) + 鉴权头 X-Internal-Token

网关机

  • 很轻:FastAPI/uvicorn/httpx + 接口4 的 volcengine-python-sdk[ark](或直接 httpx 调,OpenAI 兼容)。
  • 不装 torch/mediapipe/opencv。配置 gateway/config.json(不入 git)workers 列表、shared_passwordark 的 api_key/base_url/model、public_base_url、超时(生发接口慢,request_timeout_seconds 调大 ≥120s)。
  • 托管 /static/annotations/(落盘的图),定期清理。

维护:本文为简要总览;字段以 接口文档.md 为准。各接口更细的算法推导可查 git 历史中已合并的旧技术方案文档。