Files
hair/docs/iface3_implementation.md
2026-07-18 15:30:31 +08:00

7.1 KiB
Raw Permalink Blame History

接口3 B端生发 — 实现文档

文档日期:2026-07-18


一、接口概述

接口3 是 B端(医生/操作端)生发接口。医生在用户照片上手动用马克笔画出发际线后,只需上传这一张划线图,系统自动检测划线 → 生成遮罩 → 送 ComfyUI 生发,返回「植发3个月」效果图。

与接口2 的核心区别

特性 接口2C端生发) 接口3B端生发)
输入 原始照片 划线图(含手绘线)
发际线来源 系统按发型模板自动生成 医生手绘标注
发型类型 ellipse/flower/heart/straight/wave custom(自定义)
中间步骤 extract_context + swapHair + ComfyUI重绘 划线检测 + 遮罩 + ComfyUI生发
是否调 change_hair 是(女性流程)
ComfyUI 工作流 0716add-hair-api.json(重绘) add_hair.json(生发)
典型耗时 ~11s ~6-8s

二、接口定义

路由

POST /api/v1/hair/grow-b

入参

参数 类型 必填 说明
marked_image_file UploadFile 三选一 划线图片文件(JPG/PNG
marked_image_url str 三选一 划线图片 URL
marked_image_base64 str 三选一 划线图片 base64
use_mask bool 否(默认True 是否自动检测划线并建遮罩。False时跳过检测,直接送划线图
prompt str ComfyUI 提示词,默认"补充遮罩区域的头发,加一点美颜"

返回

{
  "code": 0,
  "message": "success",
  "data": {
    "hair_growth_image_base64": "iVBORw0KGgo...(生发图 JPG base64",
    "hairline_type": "custom"
  }
}

错误码:

  • 1001: 无法识别人像 / 未检测到发际线划线
  • 1007: 处理失败
  • 1008: 图片格式不支持

三、完整调用链

POST /api/v1/hair/grow-b
│
├─ app.py hair_grow_b()                          [app.py:929]
│   ├─ resolve_image_bytes() → marked_raw       解析图片(file/url/base64三选一)
│   ├─ cv2.imdecode → marked_bgr                解码为 BGR
│   └─ run_in_threadpool(generate_grow_b, ...)
│
├─ service.py generate_grow_b(marked_bgr, use_mask, prompt)  [service.py:381]
│   │
│   ├─ 步骤1:人脸检测 + 头发分割(仅 use_mask=True 时)
│   │   ├─ get_landmarker().detect(rgb)          MediaPipe 478点人脸检测
│   │   │   → landmarks(无人脸返回 no_face
│   │   ├─ get_parser().parse(rgb)               SegFormer 面部分割(CPU ~0.9s
│   │   │   → parse_mapint label map
│   │   │
│   ├─ 步骤2:手绘发际线检测(仅 use_mask=True 时)
│   │   ├─ detect_marker_hairline(marked_bgr, landmarks, parse_map)
│   │   │   │                                   [marker_detect.py:41]
│   │   │   ├─ forehead_upper_region(landmarks)  额头上部 ROI
│   │   │   ├─ head_silhouette(parse_map)         头部轮廓 ROI
│   │   │   ├─ _blackhat(gray)                    黑帽变换(响应比邻域暗的细结构)
│   │   │   ├─ _snap_anchor(bh, 左鬓角21)         左锚点吸附
│   │   │   ├─ _snap_anchor(bh, 右鬓角251)        右锚点吸附
│   │   │   ├─ route_through_array(cost, 左, 右)  Dijkstra最小代价路径
│   │   │   └→ path (N,2) row,col(拒识返回 None → no_line
│   │   │
│   │   ├─ path_to_curve_mask(path)              路径→曲线maskuint8 0/255
│   │   └─ mask_from_curve(curve_mask, landmarks, parse_map)
│   │       │                                   [mask.py]
│   │       ├─ _above_curve_region(curve_mask)    曲线以上区域
│   │       ├─ cv2.morphologyEx(闭运算)           填洞
│   │       ├─ 最大连通域
│   │       └─ 高斯羽化                            → mask (uint8 0-255)
│   │
│   ├─ 步骤3:合成 RGBA PNG
│   │   ├─ compose_comfy_rgba(marked_bgr, mask)  RGB=原图,alpha=255×(1-mask)
│   │   └─ PNG 编码                               → rgba_png_bytes
│   │
│   └─ 步骤4ComfyUI 生发
│       └─ comfyui.run(rgba_png_bytes, prompt)   [comfyui.py:87]
│           ├─ 上传图片到 ComfyUI /upload/image
│           ├─ 加载工作流 add_hair.json
│           ├─ 替换节点26输入图 + 节点6随机seed + 节点60提示词
│           ├─ POST /prompt 提交工作流
│           ├─ 轮询 /history/{prompt_id}(间隔0.2s
│           └─ GET /view 取回输出 PNG              → grown_png
│
└─ 返回 {"grown_png": bytes, "status": "ok"}

四、用到的模型和外部服务

模型/服务 用途 位置 设备
FaceLandmarker (MediaPipe) 478点人脸检测 hairline/face_landmarks.py CPU
FaceParser (SegFormer) 面部分割(hair/skin/... hairline/face_parsing.py CPU (5090不兼容cu121)
ComfyUI (Flux-2) 生发图生成 hairline/comfyui.py → :8188 GPU

注意:接口3 不调用 change_hair 服务(:8801),不需要 swapHair。这是它与接口2女性流程的关键区别。


五、核心算法:手绘发际线检测

5.1 为什么不用简单阈值?

手绘马克笔线条的灰度值与皮肤阴影、抬头纹等重叠,全局阈值无法区分。采用黑帽变换 + Dijkstra最小路径方案。

5.2 黑帽变换(Black Hat

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (k, k))
bh = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, kernel)

黑帽 = 闭运算 − 原图,响应"比局部邻域暗的细结构"(即马克笔线条),对抬头纹/眉毛/发丝鲁棒。

5.3 Dijkstra 最小代价路径

  1. ROI 限定:额头上部 ∩ 头部轮廓(排除背景)
  2. 锚点:左鬓角(21) / 右鬓角(251) MediaPipe 关键点
  3. 代价图cost = (bh.max() - bh) + 1.0ROI外设 1e6
  4. 路径route_through_array(cost, 左锚, 右锚) — skimage 的 Dijkstra 实现

5.4 拒识机制

路径平均黑帽响应 < 8.0 → 判定"未画线",返回 no_line


六、与接口1、接口2 的对比

维度 接口1 接口2 接口3
功能 四庭七眼测量 C端生发(5种发际线) B端生发(手绘线)
路由 /api/v1/face/measure /api/v1/hair/grow /api/v1/hair/grow-b
输入 正面照 正面照 划线图
MediaPipe
SegFormer
change_hair (女性)
ComfyUI Flux-2重绘) Flux-2生发)
典型耗时 ~2s ~11s ~6-8s
ComfyUI工作流 0716add-hair-api.json add_hair.json

七、测试