Files
hair/docs/接口文档.md
T
xsl 752630e4f5 feat: ComfyUI 默认提示词统一改为「填充遮罩区域的头发,人物增加一点磨皮」
- app.py 各接口 Form 默认值与说明、hairline/service.py _REDRAW_PROMPT、
  hairline/redraw.py _DEFAULT_PROMPT、face_analysis/hairline_grow.py 兜底值
- add_hair.json / 0716add-hair-api.json / 0716add-hair.json / hair_repaint.json
  工作流节点60内置文本
- static 测试页、local_test、benchmark 脚本、接口文档同步
注意:新提示词首次请求会因 CLIP 缓存失效变慢一次,之后恢复
2026-09-16 00:27:33 +08:00

38 KiB
Raw Blame History

旷视五个接口 — 接口文档(输入 / 输出定义)

本文档依据《旷视具体需求.docx》整理,描述各接口的输入与输出。 文中标记为 【待确认】 的内容为需求文档中尚未明确、需与对方对齐的点。

当前为第一版 Mock 服务:所有接口已上线,但不做真实算法计算,统一返回下文「响应示例」中的默认值;所有图片字段均返回示例图 https://hair.xiangsilian.com/static/sample.jpg。真实逻辑后续接入。


服务地址与接口路径

  • Base URL:https://hair.xiangsilian.com
  • 在线接口文档(Swagger):https://hair.xiangsilian.com/docs
接口 方法 路径
1 四庭七眼测量 POST /api/v1/face/measure
6 四庭七眼测量 v2 POST /api/v1/face/measure-v2
2 C 端生发 POST /api/v1/hair/grow
3 B 端生发 POST /api/v1/hair/grow-b
4 用户特征 POST /api/v1/face/features
5 发际线 PNG 生成 POST /api/v1/hairline/generate

通用约定

以下约定适用于全部 5 个接口(最终以联调为准)。

请求

项目 约定
协议 HTTPS
请求方式 POST
图片传参方式 三选一,三种都支持:① multipart/form-data 上传文件、② 图片 URL、③ base64 字符串
字符编码 UTF-8
坐标基准 所有返回的坐标均以原图像素为基准(原点为图片左上角,x 向右、y 向下)

图片传参字段(三者严格互斥,必须且只能传其一;传了 0 个或 ≥2 个均报错):

参数 类型 说明
image_file file 上传文件(multipart/form-data)
image_url string 图片 URL
image_base64 string 图片 base64 字符串,需带前缀,如 data:image/png;base64,xxxx

图片输入要求(接口 1/2/3/4/5 通用)

项目 要求
图片类型 用户正面照(人像)
人脸数量 默认仅支持单人;若检测到 2 或 3 张人脸(即多人),报错并提示客户端
单文件大小 ≤ 1 MB
最低分辨率 720 × 1024
最大分辨率 2160 × 3840
格式 目前仅支持 JPG / PNG

统一响应结构

{
  "code": 0,
  "message": "success",
  "request_id": "唯一请求标识",
  "data": { }
}
字段 类型 说明
code int 0 表示成功,非 0 表示失败
message string 结果描述 / 错误原因
request_id string 请求追踪 ID
data object 业务数据,结构见各接口

通用错误码(识别失败时返回,见需求文档)

code message 说明
1001 无法识别人像 图片中未检测到人脸
1002 人像分辨率过低 低于最低分辨率要求
1003 角度问题,非正面照 非正面 / 角度过大
1004 gender 必填/非法 接口2/5 的 gender 缺失或非 male/female
1005 检测到多张人脸 默认仅支持单人,检测到 2 人或以上时返回
1006 文件超出大小限制 单文件超过 1 MB
1007 图片参数错误 file / url / base64 未传,或同时传了多个(三者严格互斥)
1008 图片格式不支持 非 JPG / PNG
1009 未授权 缺少或错误的 X-Internal-Token(/api/* 路径鉴权)

接口 1:四庭七眼测量标注接口

说明:输入用户照片,输出一张标注好四庭七眼数据的 PNG 图片(不包含人物本体,仅标注图层),同时返回四庭、七眼的比例与厘米数值。

请求:POST /api/v1/face/measure

输入

图片参数见「通用约定 → 图片传参字段」(image_file / image_url / image_base64 三选一)。本接口无其他专属参数。

输出(data)

字段 类型 说明
annotated_image_url string 标注好数据的 PNG 图片(仅标注图层,不含人物)
face_total_height_cm number 全脸总高度(cm)
four_courts object 四庭数据,见下表
seven_eyes object 七眼数据,见下表
landmarks object 关键分界点坐标(头顶 / 发际线 / 眉心 / 鼻翼下缘 / 下巴尖),原图像素坐标
left_position object MediaPipe 21 号关键点坐标(左脸定位点),原图像素:{ "x": int, "y": int }
right_position object MediaPipe 251 号关键点坐标(右脸定位点,与 21 号镜像),原图像素:{ "x": int, "y": int }

four_courts(四庭,自上而下):

字段 类型 说明
top_court_cm number 顶庭长度(cm),示例:约占全脸高度 22%
upper_court_cm number 上庭长度(cm),约占 25%
middle_court_cm number 中庭长度(cm),约占 28%
lower_court_cm number 下庭长度(cm),约占 25%
ratios object 各庭占全脸高度的百分比

seven_eyes(七眼,横向):

字段 类型 说明
eye_width_cm number 单眼宽度(cm)
face_width_cm number 脸宽(cm)
inter_eye_distance_cm number 两眼间距(cm)
ratios object 七眼各段占脸宽的比例
eye1 number | null 从左到右第 1 段宽度(cm):人头最左 → 左脸颊(左耳外侧段)。该侧耳朵不可见时为 null
eye2 number 从左到右第 2 段宽度(cm):左脸颊 → 左眼外角
eye3 number 从左到右第 3 段宽度(cm):左眼外角 → 左眼内角(左眼宽度)
eye4 number 从左到右第 4 段宽度(cm):左眼内角 → 右眼内角(两眼间距)
eye5 number 从左到右第 5 段宽度(cm):右眼内角 → 右眼外角(右眼宽度)
eye6 number 从左到右第 6 段宽度(cm):右眼外角 → 右脸颊
eye7 number | null 从左到右第 7 段宽度(cm):右脸颊 → 人头最右(右耳外侧段)。该侧耳朵不可见时为 null

eye1~eye7 为从左到右共 7 段宽度,与标注图竖线一一对应。最左/最右端线取自耳朵分割外缘;某侧耳朵被头发或侧脸遮挡(不可见)时该侧端线省略,对应 eye1 或 eye7 为 null(键始终保留),实际有效段为 5 或 6 段。eye3/eye5 为左右眼宽、eye4 为两眼间距,与 eye_width_cm / inter_eye_distance_cm 语义一致。

标注图片(UI)规范

项目 要求
颜色 字体及所有线/箭头 #FFFFFF 100%,透明底
尺寸 字号/线宽/虚线/箭头按图片短边自适应缩放(非固定 pt)
横线 5 条分界线(头顶/发际线/眉心/鼻翼下缘/下巴尖),两端渐变消失并略超出最外侧竖线;线名在线右上方
竖线 人头最左 + 七眼 6 点 + 人头最右(最外两条取自头发分割轮廓),两端渐变消失并略超出头顶/下巴
数值排布 四庭数值(名 + 数值两行,不带 cm)统一在图片左侧呈现;七眼段宽上下穿插展示;底部统一标「单位cm」
线样式 段宽/庭高用虚线 + 实心三角双箭头标示(箭头尖端落在虚线两端)

响应示例(当前 Mock 返回值)

{
  "code": 0,
  "message": "success",
  "request_id": "mock-request-id",
  "data": {
    "annotated_image_url": "https://hair.xiangsilian.com/static/sample.jpg",
    "face_total_height_cm": 13.76,
    "four_courts": {
      "top_court_cm": 3.44,
      "upper_court_cm": 3.44,
      "middle_court_cm": 3.44,
      "lower_court_cm": 3.44,
      "ratios": { "top_court": 0.25, "upper_court": 0.25, "middle_court": 0.25, "lower_court": 0.25 }
    },
    "seven_eyes": {
      "eye_width_cm": 3.44,
      "face_width_cm": 24.08,
      "inter_eye_distance_cm": 3.44,
      "ratios": { "eye_width": 0.143, "inter_eye_distance": 0.143 },
      "eye1": 3.44, "eye2": 3.44, "eye3": 3.44, "eye4": 3.44,
      "eye5": 3.44, "eye6": 3.44, "eye7": 3.44
    },
    "landmarks": {
      "hair_top": { "x": 540, "y": 120 },
      "hairline": { "x": 540, "y": 430 },
      "brow_center": { "x": 540, "y": 740 },
      "nose_bottom": { "x": 540, "y": 1050 },
      "chin_tip": { "x": 540, "y": 1360 }
    }
  }
}

接口 6:四庭七眼测量 v2 接口

说明:基于接口 1的变体。与接口 1 的差异:

  • 去顶庭:不画头顶横线、不返回顶庭数据。four_courts 仅含上/中/下庭,landmarks 无 hair_top,face_total_height_cm 为三庭之和(不含顶庭)。
  • 竖线范围:纵向竖线从发际线画到下巴尖(接口 1 为头顶→下巴尖)。
  • 不画人头最左/最右端线:仅画七眼 6 点(左脸颊/左眼外角/左眼内角/右眼内角/右眼外角/右脸颊)共 5 段标尺,不取头发轮廓的头部端线(接口 1 会多出最左/最右 2 条头部端线、共 7 段)。
  • 其余(实心三角箭头、虚线样式、字体、单位cm、七眼数据)与接口 1 一致。

请求:POST /api/v1/face/measure-v2

输入

与接口 1 完全相同。图片参数见「通用约定 → 图片传参字段」(image_file / image_url / image_base64 三选一)。本接口无其他专属参数。

输出(data)

字段 类型 说明
annotated_image_url string 标注图层 PNG URL(透明底,仅标注线/文字,不含人物)
face_total_height_cm number 面部总高度(cm)= 上庭 + 中庭 + 下庭(不含顶庭)
four_courts object 三庭数据(上/中/下庭,各含 cm 与 ratio;无顶庭)
seven_eyes object 七眼数据(眼宽/脸宽/两眼间距 cm + 占比 ratios + eye2~eye6 共 5 段宽度)
landmarks object 四个关键点像素坐标(发际线/眉心/鼻翼下缘/下巴尖)
left_position object MediaPipe 21 号关键点坐标(左脸定位点),原图像素:{ "x": int, "y": int }
right_position object MediaPipe 251 号关键点坐标(右脸定位点,与 21 号镜像),原图像素:{ "x": int, "y": int }

接口6 是三庭五眼:four_courts/landmarks 不含顶庭与头顶点(无 top_court_cm/hair_top);seven_eyes 只含 eye2~eye6(左脸颊/左眼/两眼间距/右眼/右脸颊,5 段),无 eye1/eye7(耳外段需头发轮廓端线,仅接口1 有)。

响应示例

{
  "code": 0,
  "message": "success",
  "request_id": "mock-request-id",
  "data": {
    "annotated_image_url": "https://hair.xiangsilian.com/static/sample.jpg",
    "face_total_height_cm": 10.32,
    "four_courts": {
      "upper_court_cm": 3.44, "middle_court_cm": 3.44, "lower_court_cm": 3.44,
      "ratios": { "upper_court": 0.333, "middle_court": 0.333, "lower_court": 0.333 }
    },
    "seven_eyes": {
      "eye_width_cm": 3.44, "face_width_cm": 24.08, "inter_eye_distance_cm": 3.44,
      "ratios": { "eye_width": 0.143, "inter_eye_distance": 0.143 },
      "eye2": 3.0, "eye3": 3.44, "eye4": 3.44, "eye5": 3.44, "eye6": 3.0
    },
    "landmarks": {
      "hairline": { "x": 540, "y": 430 },
      "brow_center": { "x": 540, "y": 740 },
      "nose_bottom": { "x": 540, "y": 1050 },
      "chin_tip": { "x": 540, "y": 1360 }
    }
  }
}

接口 2:C 端生发接口

说明:输入用户正面照 + 性别 + 发型序号(可多选),按指定发际线类型渲染发际线曲线透明 PNG + 生发图。

每个方案返回两张图:image_url=「发际线曲线透明 PNG(仅白色曲线,透明底,需叠加原图显示)」;grown_image_url= 经 ComfyUI/Flux 的「植发 3 个月生发后图片」(完整人像照片)。两者均已实现,实现简述见 实现说明.md。

请求:POST /api/v1/hair/grow

输入

图片参数见「通用约定 → 图片传参字段」。专属参数:

参数 类型 必填 说明
gender string 是 性别:male / female。决定使用的发际线贴图集合
hair_style string 是 发型序号,逗号分隔多选(如 1,2,3),最多不超过该性别的预设数。female:1=ellipse, 2=flower, 3=heart, 4=straight, 5=wave, 6=bigflower, 7=clasicalflower;male:1=ellipse, 2=inverse_arc, 3=m, 4=straight, 5=heart, 6=Softpetal, 7=wave。越界/非法返回 1007
beauty_enabled bool 否 生发图是否带美颜效果,默认 false(当前阶段不生效)
use_mask bool 否 是否启用 inpaint 遮罩,默认 true。false 时用干净原图生成(空遮罩、不烧模板黑线),供测试对比。仅对原生发(male / female 6/7)管线生效
prompt string 否 ComfyUI 提示词,默认「填充遮罩区域的头发,人物增加一点磨皮」,会替换工作流节点 60 的文本。所有分支生效(male / female 6/7 原生生发,female 1..5 换发型后的发际线带重绘;不进 change_hair)。注:非默认提示词会使 ComfyUI 的 CLIP 条件缓存失效,换词后首次请求明显变慢(实测 45s vs 命中缓存 8s),相同提示词的后续请求恢复正常
flux_model string 否 Flux 模型文件名(如 flux-2-klein-9b-Q5_K_M.gguf)。缺省用工作流默认(9B-Q4_K_M);.gguf 自动切 UnetLoaderGGUF 并同步配套 qwen CLIP
redraw_max_side int 否 female 1..5 重绘管线送模型前的长边上限像素。缺省=服务端默认(REDRAW_MAX_SIDE,当前 1024);0=不缩图(原图直送,更慢)

输出(data)

results:发际线方案数组,数量 = 所选发型数。每个元素:

字段 类型 说明
image_url string 发际线曲线透明 PNG URL(仅白色发际线曲线,透明底,不含人物,需前端叠加原图显示)
grown_image_url string 生发后图片 URL(ComfyUI/Flux「植发 3 个月」效果图,完整人像照片)
hairline_type string 发际线类型 key:ellipse/flower/heart/straight/wave/bigflower/clasicalflower(female),ellipse/m/straight/inverse_arc/heart/Softpetal/wave(male)
order int 排序序号(当前阶段固定 1..N,按贴图顺序,暂不计算合适度)

⚠️ 生发图由本机 ComfyUI(Flux-2,端口 8188)生成,一次请求生成指定发型的 1 张、同步返回; female 1..5 的生发图另依赖 change_hair 换发型服务(:8801)。 worker 侧返回 image_base64 / grown_image_base64, 网关落盘后改写为上表的 image_url / grown_image_url。

💡 image_url 为透明底 PNG,前端需用绝对定位叠加到原图上显示(参考测试页的 .img-stack 叠加结构)。

响应示例

{
  "code": 0,
  "message": "success",
  "request_id": "mock-request-id",
  "data": {
    "results": [
      { "image_url": "https://hair.xiangsilian.com/static/annotations/uuid1.png", "grown_image_url": "https://hair.xiangsilian.com/static/annotations/grown1.png", "hairline_type": "ellipse", "order": 1 },
      { "image_url": "https://hair.xiangsilian.com/static/annotations/uuid2.png", "grown_image_url": "https://hair.xiangsilian.com/static/annotations/grown2.png", "hairline_type": "flower", "order": 2 }
    ]
  }
}

识别失败时返回通用错误码(1001 / 1002 / 1003 等)。gender 缺失或非法值返回 1004;本接口已改为必填入参,不再自动判别性别。


接口 3:B 端生发接口

说明:医生/操作端在用户照片上用马克笔标注目标发际线后,只需上传这一张划线图。系统检测划线 → 据此生成生发后图片。

请求:POST /api/v1/hair/grow-b

输入

划线图片支持「文件 / URL / base64」三选一(字段:marked_image_file / marked_image_url / marked_image_base64)。 不需要原始照片(划线图本身就是用户照片 + 手绘线)。

参数 类型 必填 说明
marked_image_* file / string 是 已用马克笔标注发际线的图片,三选一
use_mask bool 否 是否画发际线,默认 true。false 时跳过划线检测、直接送划线图,模型仅凭手绘黑线生发,供测试对比
prompt string 否 ComfyUI 提示词,默认「补充遮罩区域的头发,加一点美颜」,会替换工作流节点 60 的文本

输出(data)

字段 类型 说明
hair_growth_image_url string 生发后图片(检测划线 → ComfyUI/Flux「植发 3 个月」效果)。worker 返回 hair_growth_image_base64
hairline_type string 发际线形,手绘为定制,固定 "custom"

未检测到划线(或无人脸)返回 1001。

响应示例

{
  "code": 0,
  "message": "success",
  "request_id": "mock-request-id",
  "data": {
    "hair_growth_image_url": "https://hair.xiangsilian.com/static/annotations/grown.png",
    "hairline_type": "custom"
  }
}

接口 4:用户特征接口

说明:输入用户照片,由火山方舟 豆包视觉模型(doubao-seed-1-6-vision)分析,输出一大批面部特征。

请求:POST /api/v1/face/features

输入

图片参数见「通用约定 → 图片传参字段」。本接口无其他专属参数。

输出(data)

data.features 是一个 JSON 字符串(不是对象,客户端 JSON.parse() 后用),仅含以下 6 个英文字段:

字段 说明
face_shape 脸形(脸型)
eyebrow_shape 眉形
facial_age 面部年龄(区间字符串,如"18-25岁")
dynamic_static_type 动静类型(静态型/动态型)
gender 性别(男/女)
gene_style 基因风格(如"自然型")

无人脸返回 1001(据 doubao「图片是否有人脸」判定)。⚠️ 本接口是唯一调外网云模型的接口, worker 需可访问 ark.cn-beijing.volces.com;API Key 走 worker 配置/环境变量。

响应示例

{
  "code": 0,
  "message": "success",
  "request_id": "mock-request-id",
  "data": {
    "features": "{\"face_shape\":\"鹅蛋脸\",\"eyebrow_shape\":\"平眉\",\"facial_age\":\"18-25岁\",\"dynamic_static_type\":\"静态型\",\"gender\":\"女\",\"gene_style\":\"少年型\"}"
  }
}

features 为字符串形式的 JSON,固定上述 6 个字段。


接口 5:发际线 PNG 生成接口

说明:入参同接口2(先选性别、再多选发型)。对每个选中发型返回 middle / high / low 三档发际线叠图与生发图,并返回「最合适发际线」的面部中间点坐标。

请求:POST /api/v1/hairline/generate

输入

图片参数见「通用约定 → 图片传参字段」。专属参数:

参数 类型 必填 说明
gender string 是 性别:male / female。决定发型集合(female 7 / male 7)。缺失/非法返回 1004
hair_style string 是 发型序号,逗号分隔多选(如 1,2,3),决定返回哪些发际线类型。female:1=ellipse, 2=flower, 3=heart, 4=straight, 5=wave, 6=bigflower, 7=clasicalflower;male:1=ellipse, 2=inverse_arc, 3=m, 4=straight, 5=heart, 6=Softpetal, 7=wave。缺失/越界/非法返回 1007
use_mask bool 否 生发是否启用 inpaint 遮罩,默认 true。false 时用干净原图生成(空遮罩、不烧模板黑线),供测试对比
prompt string 否 ComfyUI 提示词,默认「补充遮罩区域的头发,加一点美颜」,会替换工作流节点 60 的文本
generate_grow_image bool 否 是否生成生发效果图(ComfyUI 生发,全流程最耗时),默认 true。传 false 时跳过生发,各发型 grown_image_* 恒为 null,仅返回三档发际线叠图与中心点,可大幅降低耗时

⚠️ 三档叠图分别用 hairline_texture / hairline_texture_high / hairline_texture_low 三套同名贴图;生发黑模板固定取自 hairline_texture_black/(middle 档),即生发目标固定压到 middle 档,每个发型仅 1 张生发图。

输出(data)

字段 类型 说明
hairline_images object[] 选中发型列表,数量 = 所选发型数,元素见下表
best_hairline_center_point object | null 首个选中发型的 middle 档发际线曲线「面部中间点」坐标,原图像素:{ "x": number, "y": number }
high_hairline_center_point object | null 同上,high 档发际线中点(发际线偏高)
low_hairline_center_point object | null 同上,low 档发际线中点(发际线偏低)
face_measure object | null 复用接口1的四庭七眼测量数值(不含标注图)。独立流程,测量失败(无人脸/非正面/分割失败)时为 null,不影响发际线主结果。字段结构见下表

hairline_images 元素:

字段 类型 说明
hairline_type string 发际线类型 key:ellipse/flower/heart/straight/wave/bigflower/clasicalflower(female),ellipse/m/straight/inverse_arc/heart/Softpetal/wave(male)
image_middle_url string middle 档发际线曲线透明 PNG URL(仅曲线,透明底,不含人物,需叠加原图显示)
image_high_url string high 档发际线曲线透明 PNG URL(同上,high 档曲线)
image_low_url string low 档发际线曲线透明 PNG URL(同上,low 档曲线)
grown_image_url string | null 生发后图片 URL(ComfyUI「植发」效果图,完整人像照片,生发失败或 generate_grow_image=false 时为 null)
order int 发型序号(= 传入的 hair_style 值)

worker 侧返回 image_middle_base64 / image_high_base64 / image_low_base64 / grown_image_base64,网关落盘后改写为上表对应的 *_url。

💡 三档 image_*_url 为透明底 PNG,前端需用绝对定位叠加到原图上显示(参考测试页的 .img-stack 叠加结构)。grown_image_url 是完整人像照片,直接显示即可。

face_measure 元素(与接口1的 data 同构,不含 annotated_image_* 标注图字段):

字段 类型 说明
face_total_height_cm number 全脸总高度(cm)= 四庭之和
four_courts object 四庭数据(顶/上/中/下庭 cm + 占比 ratios),结构同接口1
seven_eyes object 七眼数据(眼宽/脸宽/两眼间距 cm + 占比 ratios + eye1~eye7 从左到右 7 段宽度),结构同接口1
landmarks object 5 个纵向关键点像素坐标(hair_top/hairline/brow_center/nose_bottom/chin_tip),结构同接口1
hairline_source string 发际线来源:segmentation(真实分割)/ estimated(比例估算)/ corrected(发际线贴近头顶、分割不可靠,已按 0.95×中庭反推修正)
head_pose object 头部姿态角度(yaw/pitch/roll,单位:度)
left_position object MediaPipe 21 号关键点坐标(左脸定位点),原图像素:{ "x": int, "y": int }
right_position object MediaPipe 251 号关键点坐标(右脸定位点,与 21 号镜像),原图像素:{ "x": int, "y": int }

eye1~eye7 为从左到右共 7 段宽度,eye1=左耳外段、eye7=右耳外段,某侧耳朵不可见时对应段为 null。详见接口1说明。

响应示例(当前 Mock 返回值)

{
  "code": 0,
  "message": "success",
  "request_id": "mock-request-id",
  "data": {
    "hairline_images": [
      {
        "hairline_type": "ellipse",
        "image_middle_url": "https://hair.xiangsilian.com/static/annotations/mid1.png",
        "image_high_url": "https://hair.xiangsilian.com/static/annotations/high1.png",
        "image_low_url": "https://hair.xiangsilian.com/static/annotations/low1.png",
        "grown_image_url": "https://hair.xiangsilian.com/static/annotations/grown1.png",
        "order": 1
      },
      {
        "hairline_type": "heart",
        "image_middle_url": "https://hair.xiangsilian.com/static/annotations/mid3.png",
        "image_high_url": "https://hair.xiangsilian.com/static/annotations/high3.png",
        "image_low_url": "https://hair.xiangsilian.com/static/annotations/low3.png",
        "grown_image_base64": null,
        "order": 3
      }
    ],
    "best_hairline_center_point": { "x": 540, "y": 430 },
    "high_hairline_center_point": { "x": 540, "y": 380 },
    "low_hairline_center_point": { "x": 540, "y": 480 },
    "face_measure": {
      "face_total_height_cm": 26.76,
      "four_courts": {
        "top_court_cm": 5.77, "upper_court_cm": 5.93,
        "middle_court_cm": 7.62, "lower_court_cm": 7.44,
        "ratios": { "top_court": 0.216, "upper_court": 0.222,
                    "middle_court": 0.285, "lower_court": 0.278 }
      },
      "seven_eyes": {
        "eye_width_cm": 2.76, "face_width_cm": 15.08,
        "inter_eye_distance_cm": 3.9,
        "ratios": { "eye_width": 0.183, "inter_eye_distance": 0.259 },
        "eye1": null, "eye2": 3.0, "eye3": 2.76, "eye4": 3.9,
        "eye5": 2.76, "eye6": 3.0, "eye7": null
      },
      "landmarks": {
        "hair_top": { "x": 504, "y": 103 },
        "hairline": { "x": 504, "y": 228 },
        "brow_center": { "x": 504, "y": 357 },
        "nose_bottom": { "x": 505, "y": 522 },
        "chin_tip": { "x": 506, "y": 683 }
      },
      "hairline_source": "segmentation",
      "head_pose": { "yaw": -1.39, "pitch": 2.49, "roll": -0.06 }
    }
  }
}

说明:生发失败的元素中,网关不改写 null 值,故字段名保持为 grown_image_base64: null(有值时才改写为 grown_image_url),与接口2生发失败项一致。


接口 9:头发遮罩生成接口

说明:输入一张含人头的照片,生成头发遮罩,并返回每一步的可视化图(供对比调试)。

请求:POST /api/v1/head/mask

输入

图片参数见「通用约定 → 图片传参字段」。专属参数:

参数 类型 必填 说明
erode_cm float 否 外缘朝中心(鼻梁 151 点)内缩的距离(厘米),默认 1.2

处理流程

  1. MediaPipe 关键点 → 底部分割线(关键点 21,68,104,69,108,151,337,299,333,298,251 的连线,21 水平延伸到最左、251 延伸到最右)。
  2. 分割线以上为「上半区」。
  3. 头发分割(BiSeNet 与 SegFormer 两套);从每列最顶端头发向下填充到分割线,得到含额头的闭合区域(头发+额头,不割断)。
  4. 外缘朝中心点 151 内缩 erode_cm(虹膜标定换算像素)、底线不动 → 最终遮罩。

输出(data)

字段 类型 说明
px_per_cm float 虹膜标定出的像素/厘米
erode_cm / erode_px float / int 内缩距离(厘米 / 像素)
image_size object {width, height} 原图尺寸
steps_common object landmarks_baseline_*(关键点/分割线)、upper_region_*(上半区)
bisenet / segformer object 两套分割模型各自的结果:hair_mask_*(原始头发分割)、closed_region_*(含额头闭合区域)、final_overlay_*(最终遮罩叠加可视化)、mask_*(最终遮罩 PNG)及 hair_pixels/closed_pixels/mask_pixels 像素计数

worker 返回 *_base64(data URI),经网关改写为 *_url。


接口 10:头部外缘膨胀带遮罩接口

说明:先和接口9 一样得到内缩后的基准遮罩,再沿头部外缘生成一条膨胀带遮罩。

请求:POST /api/v1/head/band

输入

参数 类型 必填 说明
erode_cm float 否 基准遮罩外缘朝 151 内缩距离(厘米,同接口9),默认 1.2
dilate_cm float 否 外轮廓线膨胀后带子总宽(厘米),默认 2.0

处理流程

  1. 取基准遮罩的外轮廓线,去掉贴着底部分割线的那一段(只留头发/头部外缘弧线)。
  2. 把外轮廓线膨胀成带子(总宽 dilate_cm;半径=总宽/2,虹膜标定换算像素)。
  3. 裁到分割线以上(不越过底线)。

输出(data)

结构同接口9,但每组结果为 base_mask_*(基准遮罩)/ contour_*(外轮廓线)/ band_overlay_*(带子叠加可视化)/ mask_*(最终带状遮罩)及 base_pixels/band_pixels 计数,另有 dilate_cm/dilate_radius_px。


接口 11:发际线生发接口(不含重绘)

说明:输入一张发际线较高 / 头发稀少的正脸图 + 发际线类型 ID,输出同一个人、同一发型、按该类型压低发际线后的图片,并返回每一步可视化。重绘版见接口12。

请求:POST /api/v1/hairline/grow

输入

参数 类型 必填 说明
hairline_id string 是 发际线类型 ID(= change_hair hair_id):chang_tuoyuan / chang_huaban / chang_xinxing / chang_zhixian / chang_bolang
gen_backend string 否 生成后端:swaphair(换发型 LoRA,默认)|hairgrow(区域生发 inpaint)
hairgrow_strength float 否 区域生发强度(仅 hairgrow 后端),默认 0.75
is_hr bool 否 高清模式(换发型输出 1152×1536,否则 576×768),默认 false
seg_model string 否 头发分割模型:bisenet | segformer(默认)
erode_cm float 否 baseline 参考内缩距离(厘米),默认 0.6
hairline_push_cm float 否 发际线外推距离(厘米,往头发方向推进),默认 1.0
hairline_edge string 否 发际线提取方式:column(默认)|contour
swap_mode string 否 换发型取图模式:ext_mask(默认,把接口9 遮罩传给 webui 精确重绘)|as_is(用内部遮罩,贴回时再裁)
edge_erode_px int 否 贴图前遮罩内缩像素(防边缘露皮/光晕),默认 3
denoising_strength float 否 换发型 webui 重绘强度(越大生发越激进),默认 0.6
mb_levels int 否 多频段金字塔层数(2~6),默认 5
blend_method string 否 接缝融合:multiband(默认)|seamless(泊松)|two_stage(泊松→多频段)|feather(高斯羽化)|alpha_gradient(距离渐变)
color_match bool 否 融合前 Reinhard 颜色迁移消除整体色差,默认 true
color_match_strength float 否 颜色迁移强度(0~1),默认 1.0
mb_feather_px int 否 多频段最细层掩码轻羽化像素,默认 1
transition_band_px int 否 keep-region 过渡带边距(-1=自动按层数 2^n),默认 -1
inpainting_fill int 否 change_hair 服务端重绘填充:0=保留原图 | 1=噪声(默认)| 2=纯色 | 3=潜变量噪声
mask_blur int 否 change_hair 服务端遮罩边缘模糊像素,默认 11
mask_dilate_scale float 否 change_hair 服务端遮罩膨胀缩放(<1 收缩防越界),默认 1.0

输出(data)

steps:input(原图)/ baseline(底部分割线)/ hair_mask(头发分割)/ mask_overlay(遮罩叠加)/ mask(遮罩)/ swap_raw(换发型原始输出)/ alpha(融合权重)/ final(最终结果)各步图(*_base64,经网关改写为 *_url),另有 timings_ms 分步耗时。

⚠️ swaphair 后端依赖 change_hair(:8801)在跑;hairgrow 后端依赖 ComfyUI(:8188)。


接口 12:发际线带重绘接口

说明:接口11 的下游重绘阶段——内部先跑接口11 核心管线拿 ④ 接缝融合最终图(final),再取发际线重绘带(外推 band_lo_mult×push ~ band_hi_mult×push 之间、经 baseline 截断只留上部的带状区域)作遮罩,用 Flux-2(ComfyUI,reference-latent 保色重绘) 重绘。

同时产出两版结果:

  • redraw_full:ComfyUI 整帧输出(全脸美颜 + 全脸重绘)。
  • redraw_band:加发只在发际线带内、band 外保留 final 结构并按 beauty_alpha 融入全脸美颜。

请求:POST /api/v1/hairline/grow_v2

输入

接口11 的全部参数(见上表)再叠加:

参数 类型 必填 说明
comfyui_prompt string 否 Flux-2 重绘提示词,缺省「填充遮罩区域的头发,人物增加一点磨皮」
beauty_alpha float 否 redraw_band 版 band 外的全脸美颜融入强度(0=band 外纯用 final,1≈整帧版),默认 0.6
band_lo_mult float 否 重绘带外推倍率下限(相对 hairline_push_cm),默认 0.5
band_hi_mult float 否 重绘带外推倍率上限(相对 hairline_push_cm),默认 1.5

输出(data)

steps:input / final(重绘输入基底)/ redraw_band_overlay(重绘带可视化)/ redraw_full(A 整帧)/ redraw_band(B 局部+美颜)/ redraw_c(兼容旧字段,=redraw_full);重绘异常在 redraw.c_error 报告。

精简变体(生产推荐)

路径 说明
POST /api/v1/hairline/grow_v2_final 仅需图片 + hairline_id,其余参数固化为调优默认值(push=0.8cm / two_stage / color_match=关 等),最终取整帧重绘 redraw_full
POST /api/v1/hairline/grow_v2_final_v2 参数同上,最终取 B 局部加发+全脸美颜 redraw_band

⚠️ 依赖 ComfyUI(:8188)与 change_hair(:8801)均在跑。接口2 女性 1..5 的生发图即复用 grow_v2_final 管线。


接口 99:人脸特殊点检测接口

说明:输入一张人脸照片,返回一组固定编号 MediaPipe Face Mesh 关键点的像素坐标,外加 5 个发际线特殊点(射线与头发分割发际线的交点)。生产路径:网关本机实现(纯 CPU,不转发 worker,同接口4 模式);worker 侧保留同路径接口供测试页直连。

请求:POST /api/v1/face/special-points

输入

图片参数见「通用约定 → 图片传参字段」,无专属参数。要求单人正面照(非正面返回 1003)。

输出(data)

points:字段名 = <组英文名>_<点ID>,值为原图像素坐标 {x, y}(int);发际线点不可得(秃顶/分割失败)时为 null。

组 字段前缀 点 ID
眉毛 eyebrow 107 66 105 63 70 336 296 334 293 300
眼睛 eye 189 222 224 113 226 413 442 444 342 446
嘴 mouth 0 37 40 67 91 84 17 405 375 409 269
中线鼻 nose_midline 9 168 197 5 4 194 278 48 437 217
面颊 cheek 101 117 123 187 205 50 330 346 352 280 425
边线 face_edge 162 234 58 136 149 152 378 365 288 401 366 389 251

发际线特殊点(沿关键点 a→b 方向射线步进,首次进入 BiSeNet 头发 mask 处为交点;双射线取中点,仅一条命中返回该点):

字段 计算
hair_line_center 151→10 方向交点
hair_line_right mid(108→109 交点A, 69→67 交点B)
hair_line_right_right mid(104→103 交点A, 68→54 交点B)
hair_line_left mid(337→338 交点A, 299→297 交点B)
hair_line_left_left mid(333→332 交点A, 298→284 交点B)

另有 image_size(宽高)与 hairline_source(segmentation=发际线点已算出 / unavailable=分割不可用,发际线点为 null)。


汇总:输入输出一览

接口 路径 输入 主要输出
1 四庭七眼测量 /api/v1/face/measure 用户照片 标注 PNG(无人物)+ 四庭/七眼厘米数值与坐标
6 四庭七眼测量 v2 /api/v1/face/measure-v2 用户照片 同接口1,去顶庭变体
2 C 端生发 /api/v1/hair/grow 用户照片 + gender + hair_style(多选) 每发型预览 PNG + 生发图(female 1..5=换发型+重绘,其余=原生生发)
7 C 端生发 v2 /api/v1/hair/grow-v2 同接口2 同接口2(add_hair2 工作流,已弃用隐藏)
3 B 端生发 /api/v1/hair/grow-b 划线图片 检测到的发际线 + 生发后图片
4 用户特征 /api/v1/face/features 用户照片 6 个用户特征字段(脸形/眉形/年龄/动静/性别/基因风格),网关本机实现
5 发际线 PNG /api/v1/hairline/generate 用户照片 + gender + hair_style(多选) 每个选中发型 middle/high/low 三档发际线叠图 + 生发图 + 最合适发际线面部中间点坐标
9 头发遮罩 /api/v1/head/mask 用户照片 头发遮罩 + 分步可视化(BiSeNet/SegFormer 双路)
10 外缘膨胀带 /api/v1/head/band 用户照片 头部外缘带状遮罩 + 分步可视化
11 发际线生发 /api/v1/hairline/grow 用户照片 + hairline_id 压低发际线图 + 全步骤可视化(不含重绘)
12 发际线带重绘 /api/v1/hairline/grow_v2 同接口11 + 重绘带参数 final 基底 + Flux-2 保色重绘(整帧/局部两版);精简版 grow_v2_final[_v2] 仅需图片+hairline_id
99 人脸特殊点 /api/v1/face/special-points 用户照片 60 个固定编号关键点 + 5 个发际线特殊点像素坐标 JSON(网关本机实现,同接口4)

另有 worker 本机工具路由(不在对外契约内):/api/swapHair/v1、/hairColor/v2(CORS 代理 change_hair)、/api/v1/redraw(直接 ComfyUI 重绘)、/api/v1/debug/*。


已确认结论

  • 图片传参:文件 / URL / base64 三种都支持,严格互斥(必须且只能传一个,base64 需带 data:image/...;base64, 前缀)。
  • 默认单人;检测到 2~3 人报错提示客户端;单文件 ≤ 1 MB;格式仅 JPG / PNG。
  • 所有坐标基准:原图像素。
  • 接口 2:提供「美颜」开关 beauty_enabled。
  • 接口 3:仅传划线图(marked_image_* 三选一),需返回发际线类型(custom)。
  • 接口 4:data 返回一个 JSON 字符串,字段不固定,可随时调整。
  • 接口 5:发际线 PNG 数量 N 不固定,需按合适度排序。
  • 英文字段命名由本文档约定(见各接口表格)。

待与需求方确认的问题清单

  1. 接口 1 标注图片设计稿(见下方说明)。