Files
hair/docs/接口文档.md
T
xslandClaude Opus 4.8 bf76923591 refactor(接口3): 简化为只需划线图一张,去掉 original + best_hairline
按需求方意见——B端只需上传一张已画好发际线的图,用不着原图:
- 入参去掉 original_image_*,只保留 marked_image_*(三选一)
- 输出去掉 best_hairline_image_url,只返回 hair_growth_image_url + hairline_type
- ComfyUI 输入图改用 marked 划线图原样(add_hair.json 本就是"画了线的照片",
  提示词清除黑线);检测路径只用于建遮罩,不再重画干净线/不需对齐原图
- service.generate_grow_b 签名改 (marked_bgr) 单参
- 同步文档:接口文档/接口3技术方案/网关映射表(去掉接口3 best_hairline 行)
- 测试更新:grow-b 只传 marked,断言无 best_hairline 字段,44全绿

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 10:28:13 +08:00

385 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 旷视五个接口 — 接口文档(输入 / 输出定义)
> 本文档依据《旷视具体需求.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` |
| 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 |
### 统一响应结构
```json
{
"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 | 性别标签判断异常 | 男女标签无法判定 **【待确认】** 是否作为错误 |
| 1005 | 检测到多张人脸 | 默认仅支持单人,检测到 2 人或以上时返回 |
| 1006 | 文件超出大小限制 | 单文件超过 1 MB |
| 1007 | 图片参数错误 | file / url / base64 未传,或同时传了多个(三者严格互斥) |
| 1008 | 图片格式不支持 | 非 JPG / PNG |
---
## 接口 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 | 关键分界点坐标(头顶 / 发际线 / 眉心 / 鼻翼下缘 / 下巴尖),原图像素坐标 |
`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 | 七眼各段占脸宽的比例 |
### 标注图片(UI)规范
| 项目 | 要求 |
|------|------|
| 字体及线颜色 | `#FFFFFF` 100% |
| 数值排布 | 四庭数值统一在图片**左侧**呈现;七眼间距**上下穿插**展示 |
| 字体 | PingFangSC-Regular,字号 10pt |
| 线宽 | 横线、竖线、虚线均为 1pt |
| 线样式 | 横线、竖线渐变消失;虚线两侧呈现箭头 |
> **【待确认】** 标注图片需提供设计稿后才能最终确定样式。
### 响应示例(当前 Mock 返回值)
```json
{
"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 }
},
"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 }
}
}
}
```
---
## 接口 2C 端生发接口
**说明**:输入用户正面照 + 性别,按性别对应的发际线类型,逐张把建议发际线渲染到照片上,输出多张方案。
> **每个方案返回两张图**`image_url`=「原照片 + 发际线曲线叠加的**预览图**」;`grown_image_url`=
> 经 ComfyUI/Flux 的「植发 3 个月**生发后图片**」。两者均已实现,见 [`接口2-C端生发-技术实现方案.md`](接口2-C端生发-技术实现方案.md)。
**请求**`POST /api/v1/hair/grow`
### 输入
图片参数见「通用约定 → 图片传参字段」。专属参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| gender | string | **是** | 性别:`male` / `female`。决定使用的发际线贴图集合 |
| beauty_enabled | bool | 否 | 生发图是否带美颜效果,默认 false(当前阶段不生效) |
### 输出(data
`results`:发际线方案数组,**数量 = 该性别的发际线类型数**(`female` 5 个 / `male` 4 个)。每个元素:
| 字段 | 类型 | 说明 |
|------|------|------|
| image_url | string | 方案**预览图** URL(发际线曲线叠加图) |
| grown_image_url | string | **生发后图片** URLComfyUI/Flux「植发 3 个月」效果图) |
| hairline_type | string | 发际线类型 key`ellipse`/`flower`/`heart`/`straight`/`wave`female),`ellipse`/`m`/`straight`/`inverse_arc`male |
| order | int | 排序序号(当前阶段固定 `1..N`,按贴图顺序,暂不计算合适度) |
> ⚠️ 生发图由本机 ComfyUIFlux-2,端口 8182)生成,**一次请求生成全部 N 张、同步返回**,
> 单请求耗时可达数分钟,调用方超时需放大。worker 侧返回 `image_base64` / `grown_image_base64`
> 网关落盘后改写为上表的 `image_url` / `grown_image_url`。
### 响应示例
```json
{
"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` 缺失或非法值返回参数错误(1008);本接口已改为必填入参,不再自动判别性别(1004 不再使用)。
---
## 接口 3B 端生发接口
**说明**:医生/操作端在用户照片上用马克笔标注目标发际线后,**只需上传这一张划线图**。系统检测划线 →
据此生成生发后图片。
**请求**`POST /api/v1/hair/grow-b`
### 输入
划线图片支持「文件 / URL / base64」三选一(字段:`marked_image_file` / `marked_image_url` / `marked_image_base64`)。
**不需要原始照片**(划线图本身就是用户照片 + 手绘线)。
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| marked_image_* | file / string | 是 | 已用马克笔标注发际线的图片,三选一 |
### 输出(data
| 字段 | 类型 | 说明 |
|------|------|------|
| hair_growth_image_url | string | **生发后图片**(检测划线 → ComfyUI/Flux「植发 3 个月」效果)。worker 返回 `hair_growth_image_base64` |
| hairline_type | string | 发际线形,手绘为定制,固定 `"custom"` |
> 未检测到划线(或无人脸)返回 **1001**。
### 响应示例
```json
{
"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:用户特征接口
**说明**:输入用户照片,输出 N 个用户特征字段。
**请求**`POST /api/v1/face/features`
### 输入
图片参数见「通用约定 → 图片传参字段」。本接口无其他专属参数。
### 输出(data
`data` 直接返回一个 **JSON 字符串**`features`),其内部字段不固定、可随时调整,由业务方约定。当前优先返回的字段如下(仅作示例,最终以实际返回为准):
| 字段 | 类型 | 说明 |
|------|------|------|
| face_shape | string | 脸形 |
| eyebrow_shape | string | 眉形 |
| facial_age | int | 面部年龄 |
| dynamic_static_type | string | 动静类型 |
| gender | string | 性别 |
| gene_style | object | 面部特征对应面部标签的「基因风格」 |
### 响应示例(当前 Mock 返回值)
```json
{
"code": 0,
"message": "success",
"request_id": "mock-request-id",
"data": {
"features": "{\"face_shape\": \"鹅蛋脸\", \"eyebrow_shape\": \"柳叶眉\", \"facial_age\": 26, \"dynamic_static_type\": \"静态\", \"gender\": \"女\", \"gene_style\": {\"label\": \"面部特征标签\", \"style\": \"基因风格示例\"}}"
}
}
```
> `features` 为字符串形式的 JSON,字段后续可随时增删,不固定。
---
## 接口 5:发际线 PNG 生成接口
**说明**:输入用户照片,返回 N 张用户发际线的 PNG 图片,并返回「最合适发际线」的面部中间点坐标。
**请求**`POST /api/v1/hairline/generate`
### 输入
图片参数见「通用约定 → 图片传参字段」。专属参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| gender | string | **是** | 性别:`male` / `female`。决定返回的发际线集合(female 5 / male 4 |
### 输出(data
| 字段 | 类型 | 说明 |
|------|------|------|
| hairline_images | object[] | N 张发际线叠加图(发际线曲线叠在用户照片上,同接口2预览),**数量 = 该性别发际线数**,本期按贴图顺序,元素见下表 |
| best_hairline_center_point | object | 最佳(order=1)发际线曲线的「面部中间点」坐标,原图像素:`{ "x": number, "y": number }` |
`hairline_images` 元素:
| 字段 | 类型 | 说明 |
|------|------|------|
| image_url | string | 发际线叠加图 URLworker 返回 `image_base64`,网关落盘后改写为 url |
| order | int | 排序序号(本期固定 `1..N`,暂不计算合适度) |
### 响应示例(当前 Mock 返回值)
```json
{
"code": 0,
"message": "success",
"request_id": "mock-request-id",
"data": {
"hairline_images": [
{ "image_url": "https://hair.xiangsilian.com/static/sample.jpg", "order": 1 },
{ "image_url": "https://hair.xiangsilian.com/static/sample.jpg", "order": 2 }
],
"best_hairline_center_point": { "x": 540, "y": 430 }
}
}
```
---
## 汇总:输入输出一览
| 接口 | 输入 | 主要输出 |
|------|------|----------|
| 1 四庭七眼测量 | 用户照片 | 标注 PNG(无人物)+ 四庭/七眼厘米数值与坐标 |
| 2 C 端生发 | 用户照片 | 生发后图片 + 多张发际线(带类型与排序) |
| 3 B 端生发 | 划线图片 | 最合适发际线图片 + 生发后图片 |
| 4 用户特征 | 用户照片 | N 个用户特征字段(脸形/眉形/年龄/动静/性别/基因风格…) |
| 5 发际线 PNG | 用户照片 | N 张发际线 PNG + 最合适发际线面部中间点坐标 |
---
## 已确认结论
- 图片传参:**文件 / URL / base64 三种都支持,严格互斥**(必须且只能传一个,base64 需带 `data:image/...;base64,` 前缀)。
- 默认单人;检测到 2~3 人报错提示客户端;单文件 **≤ 1 MB**;格式仅 **JPG / PNG**
- 所有坐标基准:**原图像素**。
- 接口 2:提供「美颜」开关 `beauty_enabled`
- 接口 3:需同时上传原图,需返回发际线类型。
- 接口 4`data` 返回**一个 JSON 字符串**,字段不固定,可随时调整。
- 接口 5:发际线 PNG 数量 **N 不固定**,需按合适度**排序**。
- 英文字段命名由本文档约定(见各接口表格)。
## 待与需求方确认的问题清单
1. 接口 1 标注图片设计稿(见下方说明)。