feat: 新增52号发际线接口并限制GPU worker来源IP

保留5号历史三档实现,新增中下庭高度定位、扶正裁切、矩形叠加与30案例对比页。

worker仅允许本机和配置白名单访问;网关不增加IP限制。空图片URL字段改写限定为52号,保持旧接口兼容。同步接口、裁切与部署文档。

验证:113项测试通过;1项历史数值基线失败,在未修改的a3fddbb版本复现。浏览器验证5/52及30案例对比页通过。
This commit is contained in:
xsl
2026-11-04 10:20:29 +08:00
parent a3fddbbc34
commit 5b2b73f5d5
35 changed files with 2826 additions and 26 deletions
+119
View File
@@ -0,0 +1,119 @@
# 接口52上传图片裁切与扶正规划
状态:2026-11-04 在原3L规则上将人物显示缩小约10%,裁切高度改为(3÷0.9)L≈3.3333L、宽度2.5L,已接入接口52与对比页。参考图先扶正后重新标定,以下旧预检数值仅为历史记录,当前标准以 `hairline/reference/framing_profile.json` 为准。
## 接口拆分
- 接口5已按11月2日前最新提交`a3fddbb`恢复:`POST /api/v1/hairline/generate`,返回middle/high/low三档,测试页`/static/test_interface5.html`。
- 当前新规则完整迁至接口52:`POST /api/v1/hairline/generate-52`,测试页`/static/test_interface52.html`,30案例对比`/static/test_interface52_compare.html`。接口52保留迁移前所有参数和返回字段,页面显式开启`normalize_image=true`。
- 原`test_interface5_compare.html`书签跳转至52号对比页;公开5号与52号的处理路由、生成函数和网关转发均独立。
## 已确定的要求
- 仅用于接口52与当前旧/新规则对比页。
- 先扶正:变换后的9号点与152号点保持同一X坐标,9在上、152在下。
- 原图空间够时按目标人脸比例和位置裁切;标准窗口不足时,偏长图片在保留人脸的前提下裁为3:4,其余仍仅扶正。3:4无法保留完整人脸时不强裁。
- 输出保留实际像素尺寸,不为了凑参考图尺寸而放大小图。
- 当前展示:全部30个案例,每个案例一行,未裁切原图放最前,旧规则图仅一张,新规则男女各7型横排,人物图片完整显示。选择新样式时旧图同步对应形状;失败案例仍保留原图并显示原因。
## 已扶正标准(当前生效)
- 标准图:`static/framing_reference.png`,786×1048,3:4。
- 两点X均为385.18783691;9号Y为360.65437127,152号Y为725.82510480。
- 相对位置:9号点 x=49.00608612%,y=34.41358504%。
- 当前裁切高/L=3÷0.9≈3.3333、宽/L=2.5(3:4),L为9→152长度。参考图自身测得的宽/L=2.15241783589、高/L=2.86989044785作为原始标定记录保留;眉心在画面中的位置比例继续使用参考图数值。
- 校准旋转约0.25962484°,变换后横向误差约5.7e-14像素。参数取自扶正并去空角后的图,不再使用未扶正原图的比例。
- 重标定脚本:`./venv/bin/python scripts/calibrate_hairline_framing.py <参考图路径>`。
- 使用同一套原始检测点作刚体变换与后续测量,避免二次检测抖动破坏轴线竖直。
- 公开接口新增`normalize_image`默认false,旧请求保持原图尺寸和坐标;显式true开启预处理。规则页主动传true,对比调试页默认开启。响应明确返回`coordinate_space`、当前底图和坐标变换。
## 原始参考构图(旧测量)
[用户指定参考图](https://raw.githubusercontent.com/feastfuyan/yonghe-badcase-0917/main/misc/20261103_user.jpg)
测量采用当前发际线管线的MediaPipe FaceLandmarker:
| 指标 | 测量值 |
|---|---|
| 画面 | 792×1056,3:4 |
| 9号点 | (388.93, 364.62) |
| 152号点 | (387.27, 729.79) |
| 9→152长度L | 365.17像素 |
| 面部轴线距竖直方向 | 约0.26° |
| 9号点画面相对位置 | x约49.1%,y约34.5% |
| 152号点画面相对高度 | y约69.1% |
| 画面宽度/L | 约2.16885 |
| 画面高度/L | 约2.89180 |
参考图接近竖直。以9号点为定位锚点,用9→152长度作为缩放无关的构图标尺。这里的L仅为眉心到下巴的距离,不是头顶到下巴的全头高度。
## 实施流程
1. 读取上传原图、处理EXIF方向,再检测人脸关键点。
2. 用9→152方向计算二维旋转,使转换后两点竖直。不改变脸部比例。
3. 按本人的L算目标裁切尺寸:高(3÷0.9)L、宽2.5L;令9号点位于裁切画面约(49.0061%,34.4136%)处。高度取最接近的4的倍数,宽=高×3/4,不改变原图像素尺度。
4. 将裁切窗口四角反算回原图,四角均在有效图片区域内才执行标准构图。采用一次仿射变换合并旋转与裁切,降低重复插值。
5. 标准窗口空间不足时,偏长图片采用原图内最大的3:4有效窗口,约束所有人脸关键点在框内,并尽量靠近目标眉心位置。若无法保留完整人脸则仅扶正并给出原因。其余图片仍仅扶正,最小去除旋转空角。
6. 后续测量、分割、旧/新发际线和70%参考框使用同一个处理后底图与坐标系。保留原图及原图/处理后坐标转换关系,防止叠图错位。
7. 页面展示原图、处理后图、旋转角、是否标准裁切、跳过原因与前后尺寸。旧/新规则对比使用同一处理后底图,避免构图变化混入高度规则差异。
## 当前:长图与矩形发际线预览
- 长图即使放不下标准人脸占比窗口,也尝试在原图有效区域裁出最大的3:4窗口;通过可行区域约束保留468个人脸关键点,并尽量贴近参考眉心位置。无法完整保留人脸时回退仅扶正,响应说明原因。
- 案例7从1080×1920裁为1062×1416,保持9→152竖直。长图7、20、21、22、50、51的男女各7型已更新,84组均成功;对比页30张、378组结果统一使用当前规则。
- 规则页展示原图、middle、裁切发际线叠加、生发图。新增预览使用共享矩形几何裁切透明发际线,矩形外清空透明,底图仍是完整处理后人像。
## 人物缩小10%的验证(长图规则加入前)
- 裁切高=(3÷0.9)L、宽=2.5L,使同样展示尺寸下的人物线性尺寸约为原3L规则的90%。
- 案例1由828×1104改为918×1224,人脸相对大小约90.20%,差异来自原像素窗口取整;底图、发际线和实际生发图均为918×1224。
- 对比页保留全部30张。重新计算了1、3、42、43、44、45;其余48组结果验证新窗口仍超出有效范围,且只扶正后的矩阵和尺寸完全一致,复用原定位图并更新裁切参数。
- 当前生成378组对比,43、44、45的男女组仍显示原图及定位失败原因。布局、眉心比例和9→152扶正方向保持一致。
## 历史:3L规则的五个案例验证
2026-11-04 按3L规则重跑男女各7型,共70组,失败0组。保留原始像素,不缩放人脸;实际尺寸如下。
| 案例 | 原尺寸 | 处理后尺寸 | 实际处理 |
|---|---|---|---|
| 1 | 1088×1406 | 828×1104 | 按3L规则裁切 |
| 2 | 1088×1406 | 1042×1346 | 空间不足,仅扶正并去除旋转空角 |
| 3 | 1088×1406 | 810×1080 | 按3L规则裁切 |
| 4 | 1088×1406 | 1042×1346 | 空间不足,仅扶正并去除旋转空角 |
| 5 | 1088×1367 | 1071×1346 | 空间不足,仅扶正并去除旋转空角 |
## 历史几何预检(未扶正参考图)
以下为修改前的预检记录,当前生效尺寸见上表。
| 案例 | 原尺寸 | 所需裁切尺寸(约) | 预计处理 |
|---|---|---|---|
| 1 | 1088×1406 | 797×1063 | 可按参考构图裁切并扶正 |
| 2 | 1088×1406 | 1442×1923 | 空间不足,仅扶正 |
| 3 | 1088×1406 | 782×1042 | 可按参考构图裁切并扶正 |
| 4 | 1088×1406 | 1465×1953 | 空间不足,仅扶正 |
| 5 | 1088×1367 | 1463×1950 | 空间不足,仅扶正 |
## 历史:3L规则的全部30张验证
- 按3L规则运行全部30张、男女各7型,共60次请求;55组请求成功,生成385组旧/新规则对比。27张男女均成功,案例43额外生成男性7型。
- 案例43女性:模板在面部中轴处没有有效曲线;案例44、45男女:扶正后无法保留9/152参考点。三个案例均在对应行显示完整原图和未生成组合的原因,不隐藏失败案例。
- 页面顺序为未裁切原图、旧规则、全部新规则;案例筛选包括失败图片,重跑按钮运行完整30张。
- 页面筛选、旧图切换、末尾图片加载及移动端横向浏览均通过;3L调参后再次检查全部输出尺寸与混合成功/失败案例的筛选。
## 验收重点
- 处理后的9、152号点X差不超过1像素,保证9在152上方。
- 标准裁切成功时,画面比例及两点位置接近参考构图,保留实际像素,不放大小图。
- 空间不足的案例明确提示,仍完成扶正。
- 旧/新规则叠图、参考框与底图坐标一致,原图坐标可通过逆变换还原。
- 全部30案例均可查看,成功案例显示男女各7型,失败案例显示原图与原因;沿用每人一行、单张旧规则图的展示。
## 2026-11-04 提交前 Review 与验证
- 接口5的请求处理函数、三档PNG生成函数与`a3fddbb`逐项AST比较一致,测试页逐字节一致;新高度规则、扶正裁切和矩形叠加均在接口52。
- 修复网关空图片字段改名影响旧接口的兼容性问题:仅接口52开启`*_base64: null`→`*_url: null`,接口2/3/5等旧接口保留原字段名;已增加递归改写和真实转发函数的回归测试。
- GPU worker所有动态接口启用直连IP白名单,本机和网关`49.232.51.171`可访问;网关侧不启用IP限制。配置与部署见[接口IP白名单](接口IP白名单.md)。
- `./venv/bin/pytest -q`:113项通过、1项已有失败。`tests/test_pipeline.py::test_numeric_regression`期望全脸总高24.01cm,当前实测22.47cm;从未修改的`a3fddbb`导出代码、夹具后独立运行,同样失败。此次保留历史断言,未通过修改基线掩盖差异。
- 浏览器实测:接口5返回middle/high/low且保持868×1166;接口52长图案例7返回1062×1416、`status=aspect_crop`,四栏图和裁切边框正常;对比页显示30个案例、378组结果,旧书签可跳转52,未出现页面脚本错误。定位验证均关闭ComfyUI生发,本轮未重复运行耗时的真实生发。
- 批量结果与上传图位于被Git忽略的`static/annotations/`及`tests/output/`,不随提交分发;新环境执行`scripts/compare_hairline_height.py`重建。420是计划组合数,378为当前成功结果,失败组及原因保留在报告中。