feat: 拆分接口11/12,新增接口12 final / final v2 精简重绘端点
- 接口11 移除重绘,仅生成 final;接口12 (grow_v2) 负责发际线带 Flux-2 重绘 - 接口12 重绘带改为发际线外推 band_lo_mult~band_hi_mult 倍 push(默认 0.5~1.5),页面可调 - 接口12 同时产出 A 整帧重绘 与 B 局部加发+全脸美颜(beauty_alpha 可调) - 新增 grow_v2_final(整帧重绘)/ grow_v2_final_v2(B 局部+美颜)端点:仅需图片+发型 ID,其余用固化默认值(color_match 关闭) - 配套精简测试页 test_interface12_final.html / test_interface12_final_v2.html / test_interface12.html - 恢复接口11 调试页多频段与换发型可调参数、color_match 默认不勾选 - 删除旧脚本 batch_grow_v2.py / gen_report_hairline_v2.py / test_simple.html Co-authored-by: Cursor <cursoragent@cursor.com>
|
After Width: | Height: | Size: 304 KiB |
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"request_id": "mock-request-id",
|
||||
"data": {
|
||||
"hairline_id": "chang_zhixian",
|
||||
"gen_backend": "swaphair",
|
||||
"hairgrow_strength": 0.75,
|
||||
"is_hr": false,
|
||||
"seg_model": "segformer",
|
||||
"mask_type": "pushed",
|
||||
"erode_cm": 0.6,
|
||||
"swap_mode": "ext_mask",
|
||||
"blend_method": "multiband",
|
||||
"edge_erode_px": 3,
|
||||
"mb_levels": 5,
|
||||
"hairline_push_cm": 1.0,
|
||||
"hairline_edge": "column",
|
||||
"denoising_strength": 0.6,
|
||||
"color_match": true,
|
||||
"color_match_strength": 1.0,
|
||||
"mb_feather_px": 1,
|
||||
"transition_band_px": -1,
|
||||
"inpainting_fill": 1,
|
||||
"mask_blur": 11,
|
||||
"mask_dilate_scale": 1.0,
|
||||
"px_per_cm": 47.5311,
|
||||
"erode_px": 29,
|
||||
"hair_pixels": 186798,
|
||||
"closed_pixels": 191712,
|
||||
"mask_pixels": 140299,
|
||||
"image_size": {
|
||||
"width": 1257,
|
||||
"height": 1495
|
||||
},
|
||||
"timings_ms": {
|
||||
"mask": 1462,
|
||||
"swap": 5596,
|
||||
"blend": 220
|
||||
},
|
||||
"redraw": {
|
||||
"enabled": false
|
||||
},
|
||||
"_rid": "bc7205a4",
|
||||
"steps": {
|
||||
"input_base64": "<omitted 427407 chars>",
|
||||
"baseline_overlay_base64": "<omitted 435895 chars>",
|
||||
"upper_overlay_base64": "<omitted 384479 chars>",
|
||||
"hair_seg_overlay_base64": "<omitted 428039 chars>",
|
||||
"top_fill_overlay_base64": "",
|
||||
"closed_overlay_base64": "",
|
||||
"hairline_overlay_base64": "<omitted 445467 chars>",
|
||||
"pushed_overlay_base64": "<omitted 452803 chars>",
|
||||
"mask_overlay_base64": "<omitted 420375 chars>",
|
||||
"mask_base64": "<omitted 8026 chars>",
|
||||
"swap_raw_base64": "<omitted 340791 chars>",
|
||||
"hard_paste_base64": "<omitted 420679 chars>",
|
||||
"alpha_base64": "<omitted 7762 chars>",
|
||||
"final_base64": "<omitted 415811 chars>",
|
||||
"redraw_band_overlay_base64": "",
|
||||
"redraw_a_base64": "",
|
||||
"redraw_c_base64": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 319 KiB |
|
After Width: | Height: | Size: 304 KiB |
|
After Width: | Height: | Size: 314 KiB |
|
After Width: | Height: | Size: 326 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 313 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 250 KiB |
|
After Width: | Height: | Size: 282 KiB |
@@ -0,0 +1,182 @@
|
||||
# 接口11 运行记录 — `image/hair_test.jpg`
|
||||
|
||||
> 实测时间:2026-07-15
|
||||
> 调用:`POST http://127.0.0.1:8187/api/v1/hairline/grow`
|
||||
> 鉴权:`X-Internal-Token: dev-shared-secret-2026`
|
||||
> 输入图:`image/hair_test.jpg`(1257×1495)
|
||||
> `hairline_id`:`chang_zhixian`(直线);其余全部走接口默认值
|
||||
> 业务结果:`code=0`,`rid=bc7205a4`
|
||||
> 产物目录:`docs/iface11_hair_test_run/`
|
||||
|
||||
---
|
||||
|
||||
## 1. 本次调用用到的全部默认参数
|
||||
|
||||
未在 Form 里显式传的参数均取 `app.py` / `generate_hairline_grow` 默认值;下表即本次实际生效值。
|
||||
|
||||
| 参数 | 本次值 | 说明 |
|
||||
|------|--------|------|
|
||||
| `hairline_id` | `chang_zhixian` | **必填**。发际线类型 = change_hair 的 `hair_id`(直线) |
|
||||
| `gen_backend` | `swaphair` | 生成后端:换发型 LoRA |
|
||||
| `hairgrow_strength` | `0.75` | 仅 `hairgrow` 后端用;本次未走该路径 |
|
||||
| `is_hr` | `false` | 高清关闭(576×768 档,非 1152×1536) |
|
||||
| `seg_model` | `segformer` | 头发分割模型 |
|
||||
| `erode_cm` | `0.6` | baseline 参考内缩(cm);pushed 下影响很小 |
|
||||
| `hairline_push_cm` | `1.0` | 发际线内轮廓径向外推距离(cm) |
|
||||
| `hairline_edge` | `column` | 兼容入参;当前内轮廓提取不再按它分支 |
|
||||
| `swap_mode` | `ext_mask` | 把 pushed 遮罩作为 `ext_mask` 传给 swapHair |
|
||||
| `edge_erode_px` | `3` | 贴图前遮罩内缩像素 |
|
||||
| `denoising_strength` | `0.6` | 换发型 webui 重绘强度 |
|
||||
| `mb_levels` | `5` | 多频段金字塔层数 |
|
||||
| `blend_method` | `multiband` | 接缝融合:多频段金字塔 |
|
||||
| `color_match` | `true` | 融合前 Reinhard 颜色迁移 |
|
||||
| `color_match_strength` | `1.0` | 颜色迁移强度(全迁移) |
|
||||
| `mb_feather_px` | `1` | 多频段最细层掩码轻羽化 |
|
||||
| `transition_band_px` | `-1` | keep-region 过渡带:自动按层数 `2**n` |
|
||||
| `redraw` | `false` | 发际线带重绘关闭 |
|
||||
| `inpainting_fill` | `1` | change_hair 填充噪声 |
|
||||
| `mask_blur` | `11` | change_hair 遮罩边缘模糊像素 |
|
||||
| `mask_dilate_scale` | `1.0` | change_hair 遮罩膨胀缩放 |
|
||||
| `comfyui_prompt` | `null` | 仅 `redraw`+Flux-2 路用;本次未用 |
|
||||
| `mask_type` | `pushed`(固定) | 代码写死,不可选 |
|
||||
|
||||
图片入参:仅传了 `image_file`(三选一中的文件上传)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 返回元数据(无 base64)
|
||||
|
||||
| 字段 | 值 |
|
||||
|------|-----|
|
||||
| `px_per_cm` | 47.5311(虹膜直径标定) |
|
||||
| `erode_px` | 29(≈ 0.6cm × px_per_cm) |
|
||||
| `hair_pixels` | 186798 |
|
||||
| `closed_pixels` | 191712 |
|
||||
| `mask_pixels` | 140299 |
|
||||
| `image_size` | 1257 × 1495 |
|
||||
| `timings_ms.mask` | 1462 |
|
||||
| `timings_ms.swap` | 5596 |
|
||||
| `timings_ms.blend` | 220 |
|
||||
| `redraw.enabled` | false |
|
||||
| 总耗时(curl) | ≈ 7.4 s |
|
||||
|
||||
完整精简 JSON:`docs/iface11_hair_test_run/response_meta.json`
|
||||
完整原始响应(含 base64):`docs/iface11_hair_test_run/response.json`
|
||||
|
||||
---
|
||||
|
||||
## 3. 管线分步说明与产物
|
||||
|
||||
管线:① pushed 遮罩 → ② swapHair 生成 → ③ 硬贴回 → ④ multiband 融合。
|
||||
各步图保存在 `docs/iface11_hair_test_run/steps/`。
|
||||
|
||||
### ①-a 发际线分割线(baseline)
|
||||
|
||||
- **做什么**:MediaPipe 关键点连成眉骨折线(中心为 151 眉心),并向左右边缘水平延长。
|
||||
- **图**:[`steps/baseline_overlay.jpg`](iface11_hair_test_run/steps/baseline_overlay.jpg)
|
||||
- **含义**:黄线 = baseline;151 中心点为后续径向外推圆心。
|
||||
|
||||
### ①-b 分割线上半区(upper)
|
||||
|
||||
- **做什么**:baseline 折线以上的多边形区域,作为后续裁剪范围。
|
||||
- **图**:[`steps/upper_overlay.jpg`](iface11_hair_test_run/steps/upper_overlay.jpg)
|
||||
- **含义**:青 = 上半区。
|
||||
|
||||
### ①-c 头发分割(hair_seg)
|
||||
|
||||
- **做什么**:SegFormer 得到头发二值掩码。
|
||||
- **图**:[`steps/hair_seg_overlay.jpg`](iface11_hair_test_run/steps/hair_seg_overlay.jpg)
|
||||
- **含义**:绿 = 原始头发像素(本次 `hair_pixels=186798`)。
|
||||
|
||||
### ①-d / ①-e(旧 eroded/closed 中间步)
|
||||
|
||||
- pushed 模式**不走**这两步;返回字段为空字符串。
|
||||
- `top_fill_overlay` / `closed_overlay`:本次无图。
|
||||
|
||||
### ①-f 头发内轮廓线(hairline)
|
||||
|
||||
- **做什么**:取头发朝脸一侧的内轮廓(额头弧 + 两侧到下颌),有序折线。
|
||||
- **图**:[`steps/hairline_overlay.jpg`](iface11_hair_test_run/steps/hairline_overlay.jpg)
|
||||
- **含义**:绿 = 内轮廓;黄 = baseline。
|
||||
|
||||
### ①-g 外推发际线(pushed)
|
||||
|
||||
- **做什么**:以眉心 151 为圆心,内轮廓逐点向外推 `hairline_push_cm=1.0`(≈ 47.5 px),与 baseline 组闭合区域。
|
||||
- **图**:[`steps/pushed_overlay.jpg`](iface11_hair_test_run/steps/pushed_overlay.jpg)
|
||||
- **含义**:青 = 外推线;红 = 外推遮罩区域。
|
||||
|
||||
### ① 最终遮罩
|
||||
|
||||
- **叠加图**:[`steps/mask_overlay.jpg`](iface11_hair_test_run/steps/mask_overlay.jpg) — 红 = 遮罩区(贴回/生成区)
|
||||
- **纯遮罩**:[`steps/mask.png`](iface11_hair_test_run/steps/mask.png) — 白 = 生成/贴回区
|
||||
- 本次 `mask_pixels=140299`;贴图前再内缩 `edge_erode_px=3`。
|
||||
|
||||
### ② 生成全帧(swap_raw)
|
||||
|
||||
- **做什么**:`gen_backend=swaphair` + `swap_mode=ext_mask`,把遮罩交给 change_hair(`:8801`),LoRA=`chang_zhixian`,`denoising_strength=0.6`。
|
||||
- **图**:[`steps/swap_raw.jpg`](iface11_hair_test_run/steps/swap_raw.jpg)
|
||||
- **含义**:生成结果已与原图同分辨率对齐;耗时约 5.6 s。
|
||||
|
||||
### ③ 严格按遮罩贴回(hard_paste)
|
||||
|
||||
- **做什么**:遮罩内用生成图,遮罩外保持原图,无融合。
|
||||
- **图**:[`steps/hard_paste.jpg`](iface11_hair_test_run/steps/hard_paste.jpg)
|
||||
- **含义**:用于对比接缝融合前后差异。
|
||||
|
||||
### ④ 融合权重 alpha + 最终结果
|
||||
|
||||
- **做法**:`blend_method=multiband`,`mb_levels=5`,`color_match=true`(强度 1.0),`mb_feather_px=1`。
|
||||
- **alpha**:[`steps/alpha.png`](iface11_hair_test_run/steps/alpha.png) — 白 = 更多采用生成图
|
||||
- **最终输出**:[`steps/final.jpg`](iface11_hair_test_run/steps/final.jpg)(副本:[`final.jpg`](iface11_hair_test_run/final.jpg))
|
||||
- **输入对照**:[`steps/input.jpg`](iface11_hair_test_run/steps/input.jpg)
|
||||
|
||||
### ⑤ 发际线带重绘(本次关闭)
|
||||
|
||||
`redraw=false`,故 `redraw_band_overlay` / `redraw_a` / `redraw_c` 均为空。
|
||||
|
||||
---
|
||||
|
||||
## 4. 最终输出
|
||||
|
||||
**主结果文件**:[`docs/iface11_hair_test_run/final.jpg`](iface11_hair_test_run/final.jpg)
|
||||
|
||||
含义:同一人、同一发型观感下,按直线发际线类型(`chang_zhixian`)压低发际线后的合成图;遮罩外像素保持原图不动。
|
||||
|
||||
---
|
||||
|
||||
## 5. 复现命令
|
||||
|
||||
```bash
|
||||
curl -sS -X POST "http://127.0.0.1:8187/api/v1/hairline/grow" \
|
||||
-H "X-Internal-Token: dev-shared-secret-2026" \
|
||||
-F "image_file=@image/hair_test.jpg" \
|
||||
-F "hairline_id=chang_zhixian" \
|
||||
-o docs/iface11_hair_test_run/response.json
|
||||
```
|
||||
|
||||
(其余参数全部省略即可走默认值。)
|
||||
|
||||
---
|
||||
|
||||
## 6. 产物清单
|
||||
|
||||
```
|
||||
docs/接口11_hair_test运行记录.md ← 本文档
|
||||
docs/iface11_hair_test_run/
|
||||
final.jpg ← 最终结果
|
||||
response.json ← 完整 API 响应(含 base64)
|
||||
response_meta.json ← 去掉大图的元数据
|
||||
steps/
|
||||
input.jpg
|
||||
baseline_overlay.jpg
|
||||
upper_overlay.jpg
|
||||
hair_seg_overlay.jpg
|
||||
hairline_overlay.jpg
|
||||
pushed_overlay.jpg
|
||||
mask_overlay.jpg
|
||||
mask.png
|
||||
swap_raw.jpg
|
||||
hard_paste.jpg
|
||||
alpha.png
|
||||
final.jpg
|
||||
```
|
||||