接口5:改为多选发型 + 每发型返回 middle/high/low 三档叠图(去掉 hairline_level 入参)

- 去掉 hairline_level 入参;middle/high/low 三档都返回
- 入参改为同接口2:gender + hair_style(逗号分隔多选,必填),缺失/越界返回 1007
- 每个选中发型返回 image_{middle,high,low}_base64 三档叠图 + grown_image_base64 生发图,
  按发型分组;order = 发型序号,含 hairline_type
- 生发黑模板仍固定 middle(hairline_texture_black/),每发型 1 张生发图
- best_hairline_center_point 取首个选中发型的 middle 档
- 同步更新测试页(三档并排展示)、integration.html、stub_worker、接口文档/实现说明、test_api

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
xsl
2026-07-10 00:19:08 +08:00
co-authored by Claude Opus 4.8
parent 864d7f969a
commit f8e30ad32e
8 changed files with 161 additions and 120 deletions
+32 -14
View File
@@ -373,7 +373,7 @@
## 接口 5:发际线 PNG 生成接口
**说明**输入用户照片,返回 N 张用户发际线的 PNG 图片,并返回「最合适发际线」的面部中间点坐标。可选地对指定发际线类型**同步生发**(同接口2)
**说明**入参同接口2(先选性别、再多选发型)。对每个选中发型返回 `middle` / `high` / `low` **三档**发际线叠图与**生发图**,并返回「最合适发际线」的面部中间点坐标
**请求**`POST /api/v1/hairline/generate`
@@ -383,28 +383,32 @@
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| gender | string | **是** | 性别:`male` / `female`。决定返回的发际线集合(female 5 / male 4 |
| hairline_level | string | 否 | 发际线贴图档位:`middle`(默认)/ `high` / `low`,选用不同高度档位的发际线贴图(仅影响发际线叠图)。非法返回 `1004` |
| hair_style | string | 否 | 生发发型序号,**逗号分隔多选**(如 `1,2,3`)。**留空则只返回发际线叠图、不生发**。female1=ellipse, 2=flower, 3=heart, 4=straight, 5=wavemale1=ellipse, 2=inverse_arc, 3=m, 4=straight。越界/非法返回 `1007` |
| gender | string | **是** | 性别:`male` / `female`。决定发型集合(female 5 / male 4。缺失/非法返回 `1004` |
| hair_style | string | **是** | 发型序号,**逗号分隔多选**(如 `1,2,3`),决定返回哪些发际线类型。female1=ellipse, 2=flower, 3=heart, 4=straight, 5=wavemale1=ellipse, 2=inverse_arc, 3=m, 4=straight。缺失/越界/非法返回 `1007` |
| use_mask | bool | 否 | 生发是否启用 inpaint 遮罩,默认 `true``false` 时用干净原图生成(空遮罩、不烧模板黑线),供测试对比 |
| prompt | string | 否 | ComfyUI 提示词,默认「补充遮罩区域的头发」,会替换工作流节点 60 的文本 |
> ⚠️ 生发的黑模板固定取自 `hairline_texture_black/`middle 档),与 `hairline_level` 无关:即 `high`/`low` 档下发际线叠图用对应档位贴图,但生发目标压到 middle 档。
> ⚠️ 三档叠图分别用 `hairline_texture` / `hairline_texture_high` / `hairline_texture_low` 三套同名贴图;**生发黑模板固定取自 `hairline_texture_black/`middle 档)**,即生发目标固定压到 middle 档,每个发型仅 1 张生发图
### 输出(data
| 字段 | 类型 | 说明 |
|------|------|------|
| hairline_images | object[] | N 张发际线叠加图(发际线曲线叠在用户照片上,同接口2预览),**数量 = 该性别发际线数**,本期按贴图顺序,元素见下表 |
| best_hairline_center_point | object | 最佳(order=1发际线曲线「面部中间点」坐标,原图像素:`{ "x": number, "y": number }` |
| hairline_images | object[] | **选中发型**列表,**数量 = 所选发型数**,元素见下表 |
| best_hairline_center_point | object | **首个选中发型**的 middle 档发际线曲线「面部中间点」坐标,原图像素:`{ "x": number, "y": number }` |
`hairline_images` 元素:
| 字段 | 类型 | 说明 |
|------|------|------|
| image_url | string | 发际线叠加图 URLworker 返回 `image_base64`,网关落盘后改写为 url |
| grown_image_url | string \| null | **生发后图片** URL(ComfyUI「植发」效果图)。仅当该项 `order``hair_style` 中时有值,否则为 `null`worker 返回 `grown_image_base64`,网关落盘后改写为 url |
| order | int | 排序序号(本期固定 `1..N`,暂不计算合适度) |
| hairline_type | string | 发际线类型 key`ellipse`/`flower`/`heart`/`straight`/`wave`female),`ellipse`/`m`/`straight`/`inverse_arc`male |
| image_middle_url | string | middle 档发际线叠加图 URL |
| image_high_url | string | high 档发际线叠加图 URL |
| image_low_url | string | low 档发际线叠加图 URL |
| grown_image_url | string \| null | **生发后图片** URL(ComfyUI「植发」效果图,生发失败时为 `null` |
| order | int | 发型序号(= 传入的 hair_style 值) |
> worker 侧返回 `image_middle_base64` / `image_high_base64` / `image_low_base64` / `grown_image_base64`,网关落盘后改写为上表对应的 `*_url`。
### 响应示例(当前 Mock 返回值)
@@ -415,15 +419,29 @@
"request_id": "mock-request-id",
"data": {
"hairline_images": [
{ "image_url": "https://hair.xiangsilian.com/static/annotations/uuid1.png", "grown_image_url": "https://hair.xiangsilian.com/static/annotations/grown1.png", "order": 1 },
{ "image_url": "https://hair.xiangsilian.com/static/annotations/uuid2.png", "grown_image_base64": null, "order": 2 }
{
"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 }
}
}
```
> 说明:生发的元素中,网关不改写 `null` 值,故字段名保持为 `grown_image_base64: null`(有值时才改写为 `grown_image_url`),与接口2生发失败项一致。
> 说明:生发失败的元素中,网关不改写 `null` 值,故字段名保持为 `grown_image_base64: null`(有值时才改写为 `grown_image_url`),与接口2生发失败项一致。
---
@@ -489,7 +507,7 @@
| 2 C 端生发 | 用户照片 | 生发后图片 + 指定发际线预览(单/多张) |
| 3 B 端生发 | 划线图片 | 最合适发际线图片 + 生发后图片 |
| 4 用户特征 | 用户照片 | 6 个用户特征字段(脸形/眉形/年龄/动静/性别/基因风格) |
| 5 发际线 PNG | 用户照片 + gender+ hairline_level 档位 / hair_style 生发 | N 张发际线 PNG(可含生发图+ 最合适发际线面部中间点坐标 |
| 5 发际线 PNG | 用户照片 + gender + hair_style(多选 | 每个选中发型 middle/high/low 三档发际线叠图 + 生发图 + 最合适发际线面部中间点坐标 |
| 7 C 端生发 v2 | 用户照片 + gender + hair_style | 同接口2,使用 add_hair2.json 工作流 |
---