增加几何校验

This commit is contained in:
Ukawka
2026-09-17 18:50:43 +08:00
parent 4a49fe14e9
commit 1a7b2f14a9
19 changed files with 662 additions and 88 deletions
+39 -13
View File
@@ -13,7 +13,8 @@
- 部件之间的运动父子关系;
- 部件之间的视觉遮挡关系;
- 可见、部分可见或完全隐藏状态;
- 可见区域粗框、预计关节位置和 SAM 提示点;
- 可见区域粗框、预计关节位置,骨骼/附件角色与绑定目标;
- 程序用 Alpha 校验后另行输出的 SAM 候选点;
- 是否需要在第三阶段补全;
- 模型对判断结果的自报置信度。
@@ -22,6 +23,8 @@
~~~text
角色原图
↓
保留 Alpha 或去除边界连通白底(不缩放裁剪)
↓
读取模型配置、提示词和输出 Schema
↓
构造视觉 LLM 请求
@@ -34,6 +37,8 @@ Schema 校验和部件关系校验
↓
semantic-parts.json
↓
Alpha / ROI 校验、距离变换候选点、segmentation-prompts.json
↓
生成 annotated.svg 和 report.html
↓
人工复核后交给 SAM 分割阶段
@@ -97,7 +102,9 @@ Shell 环境变量优先于 <code>.env</code>。模型 ID 会原样传给中转
- SHA-256;
- 模型请求使用的 Base64 Data URL。
本阶段要求参考图为 PNG。实际提交给模型的输入会原样复制为输出目录中的 <code>source.png</code>,不缩放、不裁剪。
本阶段要求参考图为 PNG。原始输入保存为 <code>source-original.png</code>,模型实际看到的预处理 RGBA 保存为 <code>source.png</code>,不缩放、不裁剪。已有透明背景时保留原像素;不透明白底使用连通域仅去除与画布边界相连、RGB 各通道均 ≥240 的区域。其他背景或空前景会在请求模型前失败,需先提供抠图 PNG。去白底存在白色主体接触边界的局限,预处理记录保存在 <code>preprocessing.json</code>。
这一层调用 <code>normalize_reference.py</code> 和 <code>geometry_grounding.py</code>,固定使用 Conda 环境 <code>ai-spine</code> 及 requirements.txt 中的依赖。先执行 <code>conda activate ai-spine</code>;自动化使用 <code>conda run -n ai-spine node ...</code>。--python 也只能指定该环境的解释器,不创建其他环境。每次修改须遵守 [AGENTS.md](../AGENTS.md)。
## 5. 理解提示词
@@ -107,7 +114,7 @@ Shell 环境变量优先于 <code>.env</code>。模型 ID 会原样传给中转
- 仅在独立运动有意义且图像支持时拆分部件;
- 区分运动父子关系和视觉遮挡关系;
- 使用完整画布的归一化坐标;
- 输出粗框、预计关节和 SAM 提示点;
- 输出语义、粗框、预计关节和 rig_role/bind_to;正负提示点留空;
- 不把粗框声称为像素级 mask;
- 不凭空创造没有视觉证据的隐藏肢体或附件;
- 将不确定性和假设写入 <code>notes</code>。
@@ -120,7 +127,7 @@ Shell 环境变量优先于 <code>.env</code>。模型 ID 会原样传给中转
~~~json
{
"schema_version": 1,
"schema_version": 2,
"coordinate_space": "normalized_xy_top_left",
"parts": [],
"notes": []
@@ -134,13 +141,16 @@ Shell 环境变量优先于 <code>.env</code>。模型 ID 会原样传给中转
| <code>id</code> | 稳定、唯一的小写 ASCII 部件 ID |
| <code>semantic</code> | 部件语义说明 |
| <code>parent</code> | 运动层级中的父部件;<code>null</code> 表示未来挂到 root |
| <code>rig_role</code> | bone_part / attachment / facial_feature,附件不自动创建骨骼 |
| <code>bind_to</code> | 附件绑定的 bone_part;骨骼部件使用 parent,bind_to 为 null |
| <code>visibility</code> | <code>visible</code>、<code>partial</code> 或 <code>hidden</code> |
| <code>bbox_norm_xyxy</code> | 可见区域粗框 <code>[xmin, ymin, xmax, ymax]</code> |
| <code>pivot_norm</code> | 预计的关节或连接点 |
| <code>positive_points_norm</code> | 后续 SAM 的正提示点 |
| <code>negative_points_norm</code> | 后续 SAM 的负提示点 |
| <code>positive_points_norm</code> | 模型粗估点,仅为旧版诊断兼容保留,新请求留空 |
| <code>negative_points_norm</code> | 模型负点,仅保留作记录,不传给 SAM |
| <code>occluded_by</code> | 视觉上遮挡当前部件的其他部件 |
| <code>needs_completion</code> | 是否需要补全不可见区域 |
| <code>completion</code> | occlusion_fill / joint_extension_parent / joint_extension_child 三项 boolean |
| <code>needs_completion</code> | 三项 completion 的逻辑或;包括独立旋转需要的隐藏纹理和关节重叠 |
| <code>confidence</code> | LLM 自报置信度,范围 0~1 |
所有坐标都以完整画布左上角为原点并归一化到 0~1。例如:
@@ -234,19 +244,26 @@ POST /v1/responses
- 部件不能引用自己;
- 父子关系和遮挡关系不能形成环;
- 可见部件必须具有正面积 bbox;
- 可见部件必须至少有一个正提示点;
- 正提示点必须位于 bbox 内;
- 模型正点可为空;落在 bbox 外只产生警告并丢弃其提示作用;
- bind_to 必须引用骨骼部件,骨骼的 parent 也必须是骨骼部件;
- partial/hidden 必须声明 occlusion_fill,needs_completion 与三项补全字段一致;
- 附件和面部特征不能声明独立骨骼关节延展;
- 完全隐藏部件必须没有可见框和正点,并设置 <code>needs_completion=true</code>;
- 自报置信度低于 0.6 时产生人工复核警告。
校验结果写入 <code>validation.json</code>。只有校验通过时才会写出正式的 <code>semantic-parts.json</code>。
随后进行像素几何检查:以 <code>alpha > 0</code> 为前景,记录原始模型点是否落在前景和粗框内。在粗框与前景交集中,用距离变换选择远离轮廓和 ROI 边界的像素作为候选。像素坐标使用 floor(norm × size),1 映射到最后一个像素;候选归一化坐标使用像素中心。粗框按 floor/ceil 转为半开像素范围。
框内无前景、没有像素中心或 Alpha 不可用时标记 blocked,不生成点。隐藏部件标记 hidden。记录框内前景比例、连通域数量和候选到轮廓距离,不把候选声称为已确认的语义种子;原始 pivot 完全保留。
## 10. 可视化与人工复核
[lib/report.mjs](../lib/report.mjs) 将结构理解结果叠加到原图:
- 彩色矩形:模型预测的可见区域粗框;
- 实心圆:SAM 正提示点;
- 红色实心圆:无效模型点;黄色实心圆:前景上的不可信模型点;
- 青色方块:程序生成的 Alpha 候选,仍需确认部件语义;
- 空心圆:部件 pivot;
- 虚线:当前部件到父部件的关系;
- 文本:部件 ID。
@@ -293,7 +310,11 @@ POST /v1/responses
| 文件 | 作用 |
| --- | --- |
| <code>source.png</code> | 模型实际看到的原始输入副本 |
| <code>source-original.png</code> | 原始输入副本 |
| <code>source.png</code> | 模型实际看到的预处理 RGBA |
| <code>preprocessing.json</code> | 背景处理方式和像素统计 |
| <code>geometry-validation.json</code> | 原始点诊断、框内前景比例、连通域、候选和阻塞原因 |
| <code>segmentation-prompts.json</code> | 语义、粗框、程序生成的正点;负点为空,requires_mask_qa=true |
| <code>prompt.txt</code> | 本次解析后的阶段提示词 |
| <code>request.json</code> | 可复现实验的请求摘要,不包含 API Key 或完整 Base64 请求体 |
| <code>response.raw.json</code> | 中转站原始成功响应 |
@@ -323,6 +344,9 @@ POST /v1/responses
| [providers/vision.mjs](../providers/vision.mjs) | Chat Completions/Responses 请求构造与文本提取 |
| [providers/http.mjs](../providers/http.mjs) | HTTP、认证、超时、重试、SSE、元数据和脱敏 |
| [lib/validate-parts.mjs](../lib/validate-parts.mjs) | JSON 解析、Schema 校验和关系校验 |
| [lib/geometry.mjs](../lib/geometry.mjs) | Python 环境选择与几何阶段调用 |
| [geometry_grounding.py](../geometry_grounding.py) | Alpha/ROI 诊断与距离变换候选生成 |
| [normalize_reference.py](../normalize_reference.py) | RGBA 保留与边界连通白底去除 |
| [lib/report.mjs](../lib/report.mjs) | SVG 标注和 HTML 检查报告 |
| [lib/run-artifacts.mjs](../lib/run-artifacts.mjs) | 输出目录、恢复校验、状态和产物哈希 |
| [stages/model-stage.mjs](../stages/model-stage.mjs) | 第一阶段总调度与失败处理 |
@@ -333,12 +357,14 @@ POST /v1/responses
~~~text
视觉 LLM 输出
= 部件语义 + 层级 + 遮挡 + 粗框 + 提示点
= 部件语义 + 层级 + rig_role/bind_to + 遮挡 + 粗框 + 粗关节 + 补全需求
视觉 LLM 不输出
= 可信的像素 mask + 透明拆件 + 隐藏区域补全 + 最终骨骼
~~~
下一阶段应读取 <code>semantic-parts.json</code>,把每个可见或部分可见部件的粗框和正负提示点转换为像素坐标,再交给 SAM 3.1 生成候选 mask。
下一阶段应读取 <code>semantic-parts.json</code> 和 <code>segmentation-prompts.json</code>,仅使用 status=candidate 的语义、粗框和程序候选点。模型原始正负点不传给 SAM。候选始终 semantic_verified=false:框内可能混有多个部件,未来仍需要 mask 语义选择、越出角色 Alpha 比例等 QA。
已有 v1 结果可以通过 <code>--parts-file 旧计划.json --reference 原图.png --out-dir 新目录</code> 离线迁移与校验,不请求模型。迁移按 ID 推断骨骼/附件类型,袖子优先绑定同侧上臂,面部绑定头部;部分可见部件开启遮挡补全,骨骼连接处保守建议延展。这些推断在 notes 标注为待复核,不替代模型或人工判断。输入计划哈希和所有新产物参与 resume 校验。
<code>manifest.json</code> 当前只记录 SAM checkpoint 是否存在,<code>runtime_status</code> 仍为 <code>not_integrated</code>,不会加载权重或占用 GPU。
+11 -4
View File
@@ -1,12 +1,12 @@
# 第一阶段:可替换模型接口与角色结构理解
本轮实现 GPT6Astra 结构理解、Qwen Image 3.0 图片编辑适配器、结构 JSON 校验、粗标注预览、实验记录和缓存。新增模式不需要 Python,不运行旧的“拆件图 → SIFT 定位”流程。
本轮实现结构理解、图片编辑适配器、结构 JSON 校验、Alpha 几何校验、候选种子、诊断预览和实验缓存。几何层需要 Python 与 requirements.txt,不运行旧的“拆件图 → SIFT 定位”流程。
结构理解当前停在 `understand`;SAM 分割、掩码修正、隐藏部件合并、Spine 骨骼导出是后续阶段。图片编辑测试保存的是原始候选,不是验收通过的最终资产。
## 环境与模型
要求 Node.js 20 或更高版本,无新增 npm 依赖。在 `AI_spine` 目录运行。
要求 Node.js 20 或更高版本,无新增 npm 依赖。在 `AI_spine` 目录、已激活的 `ai-spine` Conda 环境中运行。每次修改须遵守 [AGENTS.md](../AGENTS.md)。
复用现有 `.env` 的地址和密钥,可增加:
@@ -74,8 +74,11 @@ node .\pipeline.mjs --mode annotated-parts `
| 文件 | 含义 |
| --- | --- |
| `source.png` | 实际提交的原图,不缩放、不裁剪 |
| `source-original.png` / `source.png` | 原始输入 / 预处理 RGBA,不缩放、不裁剪 |
| `preprocessing.json` | Alpha 保留或边界连通白底去除记录 |
| `semantic-parts.json` | 已通过结构校验的部件清单 |
| `geometry-validation.json` | 原始点 Alpha 检查、ROI 前景比例、候选来源和阻塞原因 |
| `segmentation-prompts.json` | 语义 + 粗框 + 程序候选点;不转发模型原始点,始终需要 mask QA |
| `annotated.svg` | 原图上的粗框、关节点、正点和父子连线,可直接浏览器打开 |
| `report.html` | 自包含检查页面,带部件表和模型记录 |
| `validation.json` | 字段、坐标、引用、父子环和遮挡环校验结果 |
@@ -86,6 +89,10 @@ node .\pipeline.mjs --mode annotated-parts `
`status=completed` 仅表示这一步执行完成。`quality_status=needs_review` 表示仍需人工检查语义和框的位置。粗框不是像素 mask,输出也不是自动批准的骨骼。
v2 计划新增 `rig_role`、`bind_to` 和 `completion`(遮挡补全、父关节延展、子关节延展),`needs_completion` 必须等于三项逻辑或。新提示词让模型正负点留空;旧点仅用于诊断,程序从 ROI ∩ Alpha 前景重新生成候选,pivot 不参与前景吸附。空 ROI 标记 blocked,不生成替代点。
使用 `--parts-file semantic-parts.json --reference source.png --out-dir 新目录` 可离线迁移 v1 或检查 v2,无需密钥或网络。Python 固定使用 Conda 环境 `ai-spine`,`--python` 也必须指向该环境。依赖安装命令为 `conda run -n ai-spine python -m pip install -r requirements.txt`,完整说明见 README。背景预处理无法获得可用 Alpha 时在模型请求前失败。边界连通白底去除是一种保守启发式,贴到画布边缘的白色角色区域仍需人工检查。
校验失败保存原始响应、validation 和报告,退出码为非零,不继续分割。网络/API 失败保存失败 manifest。拒绝、截断和不完整 Responses 都不会被当作成功。
HTTP/SSE/网络失败还保存 `response.error.json`:状态码、请求 ID、耗时、尝试次数、响应体(最多 2 MB)或网络错误代码,密钥会脱敏。若服务端返回 overloaded,使用新目录稍后重跑;这不表示 schema 或分割模型出错。
@@ -157,7 +164,7 @@ node .\tools\model-check.mjs --stage completion --image .\local-part.png --promp
## 测试
```powershell
npm test
conda run -n ai-spine npm test
```
测试使用本地 mock HTTP 服务或注入响应,不调用真实付费模型。覆盖模型优先级、协议请求/响应、multipart、能力限制、数值/引用/环校验、错误响应、重试、缓存和 CLI 全链路。