文档整理
This commit is contained in:
@@ -17,3 +17,121 @@
|
||||
- 测试在 `ai-spine` 环境下执行:`conda run -n ai-spine npm test`。不要为了绕过依赖问题临时新建环境。
|
||||
- 验证结果必须如实记录;缺少依赖导致未运行的检查,不得声称通过。
|
||||
- 保留用户已有修改和实验产物,不覆盖旧实验输出。
|
||||
|
||||
## 跨会话上下文与阅读顺序
|
||||
|
||||
本节于 2026-09-21 根据当前代码与已检查产物整理。它是后续对话的上下文入口;后续修改应同步更新对应状态,实际源码、配置和具体实验 manifest 优先于历史总结。不要把旧实验统计套到新输出上。
|
||||
|
||||
1. 先阅读本文件和 `git status --short`,保留用户已有修改。
|
||||
2. 阅读 [README](README.md) 了解项目、环境、配置与命令。
|
||||
3. 按任务阅读 [第一阶段](docs/1-understanding-stage.md)、[第二阶段](docs/2-segmentation-stage.md)、[第三阶段](docs/3-completion-stage.md),再核对相关实现与实际产物。
|
||||
4. 用户说“继续”时,先核对工作区和最近任务进展,不能只凭历史总结重复请求付费模型或覆盖实验。
|
||||
|
||||
## 用户目标与固定偏好
|
||||
|
||||
- 目标是将单张 2D 角色图拆成可以用于 Spine 的部件,保留画风、姿态、左右、不对称性及原有像素关系,补足遮挡和关节连接。
|
||||
- 第二阶段使用本地 SAM 代码和权重,通过临时 Conda 子进程在本机 GPU 推理,完成后退出;不部署常驻独立服务。
|
||||
- 需要可直接执行的 PowerShell 命令;说明当前已实现行为、实测结果与未来计划,不能把几何通过写成资产合格。
|
||||
- 不确定的部件语义、遮挡和候选点需要复核,不得用前景检查、覆盖率或模型分数代替语义准确性。
|
||||
- 输出使用独立目录,保留原候选和诊断;已有候选优先离线复检,避免无意义重复生成。
|
||||
|
||||
## 文档维护约定
|
||||
|
||||
- 各文档文件名保持不变。`docs/` 当前保留三份阶段文档;`docs/model-stages.md` 在本次文档整理前已处于用户删除状态,不自行恢复,相关说明归入 README 和阶段文档。
|
||||
- 三份阶段文档有且仅有以下八个二级章节,细节必须归入对应章节:
|
||||
1. 阶段简介
|
||||
2. 输入、输出与执行链路
|
||||
3. 阶段执行命令示例及参数说明
|
||||
4. 输入格式要求
|
||||
5. 执行链路中重要部分代码文件及原理说明(包括重点说明)
|
||||
6. 各个代码文件职责索引
|
||||
7. 产物详细说明
|
||||
8. 当前阶段可改进点说明
|
||||
- 外层 README 负责整体介绍、Conda 准备、配置及每阶段命令;本文件负责约定和后续会话必要上下文。已存在的环境与修改约定必须保留。
|
||||
- 改进项明确写为待实现/待验证;实现后更新状态、命令、产物说明及本文件。PowerShell 反引号后不能有空格;示例变量先定义,示例输出目录相互独立。
|
||||
|
||||
## 工作区、环境与配置
|
||||
|
||||
- 当前实际项目目录:`F:\Study\taonier\AI_spine`。用户历史命令也出现过 `F:\Study\taonier\AI\_spine`,不要盲目复制旧路径,先确认 cwd。
|
||||
- 当前 SAM 根目录为 `F:\Study\SAM3`;源码仓库 `F:\Study\SAM3\sam3`;权重 `F:\Study\SAM3\sam3.1checkpoint\sam3.1_multiplex.pt`。早期 `F:\Study\sam3.1` 已不是当前约定路径。
|
||||
- 已验证组合:Python 3.11、torch 2.7.1+cu126、torchvision 0.22.1、NumPy 1.26.4、OpenCV 4.11.0.86;RTX 3060 Laptop 6 GB。机器环境可能变化,执行前按需探测。
|
||||
- Node.js >=20,无额外 npm 运行时依赖。自动化使用 Conda ai-spine 执行 Node/Python;运行 SAM 可用 `conda run --no-capture-output -n ai-spine node ...`。
|
||||
- 默认配置是 `configs/astra-qwen.json`;示例推荐明确传 config,避免环境变量导致选错提供方。
|
||||
- `configs/deepseek-qwen.json`:deepseek-flash / Chat Completions / 非流式;补全 qwen-image-3.0。
|
||||
- `configs/astra-qwen.json`:gpt-6-astra / Responses / 流式;补全 qwen-image-3.0。
|
||||
- 上述两份读取 VECTOR_ENGINE_BASE_URL / VECTOR_ENGINE_API_KEY,模型变量为 SPINE_UNDERSTANDING_MODEL / SPINE_COMPLETION_MODEL。
|
||||
- `configs/tiantoken.json`:独立 TIANTOKEN_BASE_URL / TIANTOKEN_API_KEY,地址 https://api.tiantoken.com;理解 gpt-6-astra,补全 gpt-image-2;模型变量为 TIANTOKEN_UNDERSTANDING_MODEL / TIANTOKEN_COMPLETION_MODEL。
|
||||
- CLI 模型 > stage.model > 对应模型环境变量 > default_model;shell 同名变量优先于 .env。模型 ID 原样发送,不加隐式别名。
|
||||
- 用户提供的密钥仅留在本地忽略的 `.env`;禁止在文档、命令日志、聊天或提交中暴露,不要读取/打印完整 .env 来诊断。
|
||||
- 三份配置的图片编辑能力均为 multiple_images=false、mask=false。接口已预留分支不代表中转已支持;开启前需验证。Astra 理解接口与图片编辑接口不同,当前没有 Astra Responses 图片生成工具链。
|
||||
|
||||
## 三阶段实现与不能丢失的边界
|
||||
|
||||
### 第一阶段:理解与几何候选
|
||||
|
||||
- 入口 `tools/model-check.mjs --stage understanding`,或 `pipeline.mjs --mode annotated-parts`;后者仅转发新入口。
|
||||
- `stages/model-stage.mjs` 调用视觉模型,`lib/validate-parts.mjs` 校验 v2:rig_role、bind_to、三项 completion 及 needs_completion 一致性。
|
||||
- `normalize_reference.py` 保留原画布,使用 Alpha 或边界连通近白背景处理;`geometry_grounding.py` 用 Alpha/ROI 距离变换生成候选,不是再次请求 AI。
|
||||
- 模型原始点仅诊断;程序候选也未获语义确认;pivot 独立保留,不吸附前景。
|
||||
- 第二阶段输入必须为同一实验的 source.png、semantic-parts.json、segmentation-prompts.json。
|
||||
- `--parts-file` 可离线迁移 v1/检查 v2 并生成新候选;旧 annotated.svg 不会自动更新。
|
||||
|
||||
### 第二阶段:SAM 可见拆件
|
||||
|
||||
- 入口 `--stage segmentation --input-dir 理解目录`;实现为 stages/segmentation-stage.mjs、sam_runtime.py、sam_segment.py、segmentation_outputs.py。
|
||||
- 环境探测与推理分别为短期子进程,禁止在线下载权重。multiplex detector 适配实际严格加载 1130 个张量,忽略 36 个未使用视频 neck 张量;不要因此改成 strict=False 或修改外部 SAM 源码。
|
||||
- BF16 仅用于推理 autocast;不要整体转换模型而破坏复数缓冲区/FP32 路径。
|
||||
- 使用文本和文本+粗框两组候选;当前图像概念接口未接收点提示,Alpha 种子仅参与 mask 排序。
|
||||
- 与原图 Alpha 取交集后提取原像素;mask 为原画布二值图,parts 为紧裁剪 RGBA。重叠保留、覆盖率仅为像素覆盖,semantic_verified=false。
|
||||
- annotated.png 为原图纹理上半透明颜色叠加,parts-sheet.png 为白底拆件;纯色遮罩角色图与可选大模型去毛边尚未实现。
|
||||
|
||||
### 第三阶段:受限部件补全
|
||||
|
||||
- 入口 `--stage completion --input-dir SAM目录`;实现为 stages/completion-stage.mjs、completion_geometry.py、providers/image-edits.mjs。
|
||||
- 输入须含 source.png、v2 计划、segmentation.json 及所有记录的全画布 masks;单独 parts/ 不够。
|
||||
- 仅处理 needs_completion=true、非隐藏、有可见 mask 且允许区域非空的部件。--part 不绕过筛选;目前不重新评估 SAM 缺损。
|
||||
- 默认 1024 方形局部画布,原像素不缩放。允许区来自轮廓外 32 像素范围与遮挡 mask / pivot 圆盘交集,排除可见 mask;不是完整隐藏形状生成。
|
||||
- 当前真实请求只发白底 input.png;context.png、edit-mask.png 默认不发送。开启 multiple_images 也只是发送同坐标局部 context,并非独立全角色参考。
|
||||
- 图片解码已修复“空 b64_json 但有有效 URL”情况,回退下载 URL;该问题与画布尺寸不符不同。
|
||||
- 在线请求现显式传 size,配置冲突失败。strict 默认拒绝尺寸不同;uniform 仅恢复同宽高比整画布尺寸,保留原候选,继续原有验收,不单独移动/缩放物体。
|
||||
- 验收阈值:可见不透明像素 RGB MAE≤30、保留率≥95%;有效新增须在允许区且连接可见部件;原可见 RGBA 随后逐像素恢复。
|
||||
- unfulfilled_regions 当前只记录、不硬拒绝;语义错误、接缝、关节补够与否尚无可靠验收。错误 SAM 可见像素会被强制保留。
|
||||
- prepare-only 不联网;candidates-dir 可读平铺 ID.png 或匹配 manifest 的旧任务首张候选。--resume 不是失败断点续发,准备/生成/复检使用独立目录。
|
||||
- parts/ 只含通过检查的补全部件,不包含全部原拆件。完整角色组装、旋转验收、新管线 Spine 导出尚未接入。
|
||||
- 旧 `--stage completion --image ... --prompt-file ...` 是接口探针,不能和 input-dir 混用,不执行完整几何验收。
|
||||
|
||||
## 已检查实验与质量结论
|
||||
|
||||
以下为已有实验记录,不代表后续每次运行的结果;不必为了文档修改重跑 GPU 或付费模型。
|
||||
|
||||
| 目录(相对于项目) | 事实与意义 |
|
||||
| --- | --- |
|
||||
| output/sombrero-grounding-v2 | 旧计划离线几何检查,28 个程序候选通过前景检查;未证明语义正确 |
|
||||
| output/sombrero-sam31-v3 | 较早 SAM 实验,28 个 mask,约 67.18% 覆盖率;肢体/鞋子重复、漏分,不合格 |
|
||||
| output/20260918-183532/sam | 当前讨论基线:32 个计划项、10 个 hidden、22 个 mask;约 83.3% 覆盖,32719 像素未分配;前臂/手混入衣料、袖子与上衣缺损 |
|
||||
| output/20260918-183532/complete2_gpt | 真实 Tiantoken gpt-image-2 请求 12 部件;旧请求未传 size,返回 1248/1254,预期 1024,全部 CANVAS_SIZE_MISMATCH |
|
||||
| output/20260918-183532/complete2_gpt-size-recheck-v2 | 离线 uniform 复检,未重生成:8 个几何通过;head、pants_thigh_l、pants_thigh_r、shoe_l 4 个拒绝;通过项仍有误分和未完成区域 |
|
||||
| output/20260918-183532/complete-recovered-head-check | 更早 Qwen 头部候选恢复检查,不能与 GPT 批次混为一谈 |
|
||||
|
||||
- 当前 22→12 的原因:sombrero、sleeve_l、sleeve_r、eye_l、eye_r、eyebrow_l、eyebrow_r、nose、mouth、mustache 共 10 个被第一阶段标记 NO_COMPLETION_NEEDED;不能解释为它们的实际 SAM mask 已完整。
|
||||
- 2026-09-20 尺寸修复后曾通过 22 项 Node 测试(含 Python 补全回归)。这是历史验证;新改动按范围重新验证,不自动沿用“全部通过”。显式 size 构造已测试,修复后中转是否遵守尚无新实测。
|
||||
- 总体判断:上游部件归属、模型缺少原图参考与遮罩、区域规则粗糙、验收不足共同导致低质量。不能仅换模型、强制处理全部 mask、放宽阈值或解决尺寸错误就宣称修好。
|
||||
|
||||
## 当前改进方向与后续顺序
|
||||
|
||||
本轮用户要求重整文档,以下功能是待实现需求,不因写入文档就成为已完成功能:
|
||||
|
||||
1. 第二阶段输出仅色彩遮罩组成的完整角色图,保留当前原图叠色预览,并明确未分配/重叠区域。
|
||||
2. 第二阶段每个 SAM 部件可选经过一次大模型去毛边,保留原始拆件、原图参考、坐标、变更区域与前后对照。
|
||||
3. 第三阶段将角色原图或部件相关原图局部作为参考交给补全模型,验证中转多图/遮罩能力及实际发送内容。
|
||||
4. 第三阶段输出使用补全部件组装的完整角色,复用无需补全的原部件,明确失败/回退状态。
|
||||
5. 技术优先级:先修正 SAM 部件归属与输入门槛,再按实际 mask 重建补全计划;用头、前臂、上衣三类小样验证参考图和遮罩,然后增加回贴与关节旋转验收,最后批量与 Spine 导出。
|
||||
|
||||
详细改进说明保留在各阶段文档第 8 节;若后续用户改变优先级,应更新此处。
|
||||
|
||||
## 旧管线与范围识别
|
||||
|
||||
- `pipeline.mjs` 未指定 --mode annotated-parts 时走旧“生成拆件图→CV 定位→Spine”流程,不是新三阶段自动串联。
|
||||
- `segment.py` 为旧拆件图分割;`compose_preview.py` 为旧布局组装;`run_case_matrix.py` 为旧定位对照工具。不要因为 IDE 当前打开这些文件就误改新阶段入口。
|
||||
- 相邻 `spine-animation-ai` 为外部只读依赖,保留其 PolyForm Noncommercial 许可证约束;新阶段尚未复用为完成的导出流程。
|
||||
- 不要把文档改写任务扩大成付费图片生成、SAM 推理、依赖安装或功能实现;需要实现时遵从用户后续任务范围。
|
||||
|
||||
@@ -1,83 +1,45 @@
|
||||
# AI Spine 角色拆件与动画管线
|
||||
|
||||
本项目用于把单张 2D 角色参考图转换为可供 Spine 动画使用的语义部件、透明拆件和骨骼资源。
|
||||
本项目探索将单张 2D 角色图转换为可用于 Spine 动画的部件与骨骼资源。当前主线分为三个阶段:视觉 LLM 理解结构、本地 SAM 分割可见部件、图片编辑模型补全隐藏区域和关节连接。
|
||||
|
||||
当前正在实现的新管线分为三个核心阶段:
|
||||
| 阶段 | 输入 → 输出 | 当前状态 |
|
||||
| --- | --- | --- |
|
||||
| 1. 结构理解 | PNG → v2 语义计划、粗框、pivot、程序候选点 | 可在线理解或离线复检;语义待复核 |
|
||||
| 2. SAM 分割 | 第一阶段目录 → mask、原像素透明部件、标注图与拆解图 | 本机 GPU 实测可运行;存在误分与漏分 |
|
||||
| 3. 部件补全 | SAM 目录 → 局部编辑候选、几何 QA、通过检查的补全部件 | 已真实调用图片模型;结果质量尚不合格 |
|
||||
|
||||
1. 视觉 LLM 输出语义、层级、骨骼/附件分类、遮挡、粗框和粗关节;程序用 Alpha 检查 ROI 并生成候选种子。
|
||||
2. 使用 SAM 根据语义、粗框和程序候选生成 mask,经语义/几何检查后从原图提取可见像素。
|
||||
3. 使用图片编辑模型补全被遮挡的部件,再进行几何验收和 Spine 导出。
|
||||
第三阶段尚未输出使用补全部件组装的完整角色,新管线 Spine 导出也未完成。执行成功、mask 覆盖率高、几何检查通过,均不等于动画资产可用。
|
||||
|
||||
目前第一、二阶段可运行,第三阶段已接入部件画布准备、图片编辑请求、候选几何检查及可见像素恢复。第二阶段在 `ai-spine` Conda 环境的临时子进程中加载本地 SAM 3.1 权重,使用 GPU 分割并生成半透明标注图、白底拆解图和透明部件。分割与补全结果仍需语义复核;新管线的 Spine 导出尚未完成。第三阶段已通过离线及 mock 接口验证,真实图片编辑质量尚待验证。
|
||||
仓库保留旧版“生成白底拆件图 → OpenCV 拆分 → Genielabs 定位 → Spine 导出”作为对照;它与当前三阶段主线并存,产物不能直接混用。
|
||||
|
||||
仓库仍保留旧版“AI 生成白底拆件图 → OpenCV 拆分 → Genielabs 定位 → Spine 导出”流程,用于对照和回归测试。
|
||||
## 文档入口
|
||||
|
||||
## 文档
|
||||
- [AGENTS.md](AGENTS.md):修改约定、跨会话上下文、当前基线及后续优先级。
|
||||
- [第一阶段](docs/1-understanding-stage.md):理解、数据契约、Alpha 候选与粗标注。
|
||||
- [第二阶段](docs/2-segmentation-stage.md):本地 SAM、mask 选择、拆件与质量边界。
|
||||
- [第三阶段](docs/3-completion-stage.md):筛选、局部画布、图片请求、几何验收及补全改进。
|
||||
|
||||
- [项目修改约定](AGENTS.md):每次修改都必须遵守,Python 固定使用 `ai-spine` Conda 环境。
|
||||
- [第一阶段:视觉 LLM 角色结构理解](docs/1-understanding-stage.md):执行流程、代码对应关系、数据格式和输出文件。
|
||||
- [第二阶段:本地 SAM 分割](docs/2-segmentation-stage.md):环境、运行命令、权重适配、输出和质量边界。
|
||||
- [第三阶段:部件补全](docs/3-completion-stage.md):局部画布、遮挡/关节延展区域、生成调用、可见像素恢复及几何检查。
|
||||
- [模型阶段配置与实验说明](docs/model-stages.md):模型切换、协议适配、图片编辑探针、缓存和错误处理。
|
||||
阶段文档统一采用八节:简介;输入输出与链路;命令参数;输入格式;重要代码原理;职责索引;产物;可改进点。配置与实验说明已归入上述文档。
|
||||
|
||||
## 环境准备
|
||||
## Conda 环境准备
|
||||
|
||||
### Node.js
|
||||
所有 Python 操作固定使用 **ai-spine**,不使用 `.venv`、其他虚拟环境、Conda base 或系统 Python。Node.js 要求 20 或以上;项目没有额外 npm 运行时依赖。
|
||||
|
||||
第一阶段要求 Node.js 20 或更高版本,以及下方 Python 几何依赖;没有额外 npm 运行时依赖。
|
||||
在 PowerShell 中进入实际项目根目录。本工作区路径如下;若本机使用其他目录,仅替换这一行:
|
||||
|
||||
```powershell
|
||||
Set-Location F:\Study\taonier\AI_spine
|
||||
node --version
|
||||
conda run -n ai-spine npm test
|
||||
conda env list
|
||||
```
|
||||
|
||||
### 中转站配置
|
||||
|
||||
在项目目录复制环境变量模板:
|
||||
仅在没有 ai-spine 环境的新机器上,手动创建一次;当前机器已有环境则跳过:
|
||||
|
||||
```powershell
|
||||
Copy-Item .\.env.example .\.env
|
||||
conda create -n ai-spine python=3.11 -y
|
||||
```
|
||||
|
||||
编辑 `.env`:
|
||||
|
||||
```dotenv
|
||||
VECTOR_ENGINE_BASE_URL=https://router.genarrative.world/v1
|
||||
VECTOR_ENGINE_API_KEY=你的令牌
|
||||
|
||||
# 可选:覆盖配置文件中的默认模型
|
||||
SPINE_UNDERSTANDING_MODEL=deepseek-flash
|
||||
SPINE_COMPLETION_MODEL=qwen-image-3.0
|
||||
|
||||
# 本地 SAM 根目录和源码仓库;分割结束后子进程退出
|
||||
SAM_MODEL_DIR=F:/Study/SAM3
|
||||
SAM_CODE_DIR=F:/Study/SAM3/sam3
|
||||
```
|
||||
|
||||
模型 ID 会原样发送给中转站,不进行隐式别名转换。不要把 API Key 写进 JSON 配置或提交到版本库。
|
||||
|
||||
另一个中转站 Tiantoken 使用独立配置 [configs/tiantoken.json](configs/tiantoken.json)。在本地 `.env` 设置 `TIANTOKEN_BASE_URL=https://api.tiantoken.com` 和 `TIANTOKEN_API_KEY`,运行时增加 `--config .\configs\tiantoken.json`;原中转站配置保持独立。
|
||||
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --config .\configs\tiantoken.json --list-models
|
||||
node .\tools\model-check.mjs --config .\configs\tiantoken.json --dry-run
|
||||
```
|
||||
|
||||
该配置默认第一阶段使用 `gpt-6-astra`(Responses),第三阶段使用 `gpt-image-2`(images/edits),可通过 `TIANTOKEN_UNDERSTANDING_MODEL`、`TIANTOKEN_COMPLETION_MODEL` 或对应 CLI 参数覆盖。2026-09-20 已验证认证与模型列表访问,返回 113 个模型,含上述两个 ID;尚未验证实际理解、图片编辑或 Responses 图片生成工具能力。此配置不等于已接入 Astra 主导的第三阶段图片生成。
|
||||
|
||||
### Python 与外部项目
|
||||
|
||||
本项目固定使用 **Conda 环境 `ai-spine`**,不使用或创建 `.venv`。第一阶段的 Alpha 校验需要 Python 3、`Pillow`、`numpy`、`opencv-python`。
|
||||
|
||||
执行项目命令前先 `conda activate ai-spine`。Node 管线会检查 Python 属于该 Conda 环境;`--python` 也只能指定该环境的解释器。未激活环境或缺少依赖时会报错,不会自动创建环境或安装依赖。
|
||||
|
||||
旧版拆件和 Spine 导出还需要:
|
||||
|
||||
- Python 3;
|
||||
- `Pillow`、`numpy`、`opencv-python`;
|
||||
- 相邻目录中的 `spine-animation-ai` 项目。
|
||||
|
||||
当前本机验证组合为 Python 3.11、PyTorch 2.7.1 + CUDA 12.6、torchvision 0.22.1。在 `AI_spine` 目录补全依赖;已有此 CUDA 版本时跳过第一条安装命令:
|
||||
补齐项目依赖。以下是本机已验证的 CUDA 12.6 组合;已有匹配 PyTorch 时可跳过第一条安装命令。代码不会自动安装依赖或创建环境。
|
||||
|
||||
```powershell
|
||||
conda activate ai-spine
|
||||
@@ -86,174 +48,183 @@ python -m pip install -r .\requirements.txt
|
||||
python -m pip install --no-deps --no-build-isolation -e F:\Study\SAM3\sam3
|
||||
```
|
||||
|
||||
不激活终端也可明确指定安装目标:
|
||||
不激活终端时,明确指定目标环境:
|
||||
|
||||
```powershell
|
||||
conda run -n ai-spine python -m pip install -r .\requirements.txt
|
||||
```
|
||||
|
||||
检查解释器和依赖:
|
||||
本地 SAM 代码和权重由用户提供,当前位置为:
|
||||
|
||||
```powershell
|
||||
conda run -n ai-spine python -c "import sys, cv2, PIL, numpy; print(sys.executable); print('Dependencies OK')"
|
||||
```text
|
||||
F:/Study/SAM3/sam3/ 源码仓库
|
||||
F:/Study/SAM3/sam3.1checkpoint/sam3.1_multiplex.pt 权重
|
||||
```
|
||||
|
||||
`spine-animation-ai` 是外部只读依赖,使用时需要遵守其 PolyForm Noncommercial 许可证。
|
||||
|
||||
## 常用命令
|
||||
|
||||
以下命令默认在 `AI_spine` 目录、已激活的 `ai-spine` Conda 环境中运行。自动化可使用 `conda run -n ai-spine node ...`。
|
||||
|
||||
### 查询中转站模型
|
||||
检查解释器、基础依赖与 GPU:
|
||||
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --list-models
|
||||
conda run -n ai-spine python -c "import sys, cv2, PIL, numpy, torch; print(sys.executable); print('torch', torch.__version__); print('CUDA', torch.cuda.is_available()); print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'No CUDA GPU')"
|
||||
```
|
||||
|
||||
### 检查本地配置
|
||||
第二阶段要求可用 CUDA GPU。本机已验证 RTX 3060 Laptop 6 GB;默认 BF16 推理保留模型参数和缓冲区所需精度。第一、三阶段的本地几何处理不运行 SAM。Node 入口会验证 Python 属于 ai-spine;`--python` 也不能绕过此约定。
|
||||
|
||||
不请求模型,也不生成付费内容:
|
||||
## 中转站配置
|
||||
|
||||
仅在本地 `.env` 不存在时复制模板,随后自行填写密钥:
|
||||
|
||||
```powershell
|
||||
node .\pipeline.mjs --mode annotated-parts `
|
||||
if (-not (Test-Path .\.env)) { Copy-Item .\.env.example .\.env }
|
||||
```
|
||||
|
||||
```dotenv
|
||||
# 原中转站
|
||||
VECTOR_ENGINE_BASE_URL=https://router.genarrative.world/v1
|
||||
VECTOR_ENGINE_API_KEY=填写你的令牌
|
||||
|
||||
# Tiantoken 独立配置
|
||||
TIANTOKEN_BASE_URL=https://api.tiantoken.com
|
||||
TIANTOKEN_API_KEY=填写你的令牌
|
||||
|
||||
# 本地 SAM
|
||||
SAM_MODEL_DIR=F:/Study/SAM3
|
||||
SAM_CODE_DIR=F:/Study/SAM3/sam3
|
||||
```
|
||||
|
||||
不要把密钥写入文档、JSON 配置或提交到版本库;不要输出 `.env` 内容。
|
||||
|
||||
| 配置文件 | 第一阶段 | 第三阶段 | 模型环境变量 |
|
||||
| --- | --- | --- | --- |
|
||||
| [deepseek-qwen.json](configs/deepseek-qwen.json) | deepseek-flash,Chat Completions,非流式 | qwen-image-3.0,images/edits | SPINE_UNDERSTANDING_MODEL / SPINE_COMPLETION_MODEL |
|
||||
| [astra-qwen.json](configs/astra-qwen.json) | gpt-6-astra,Responses,流式 | qwen-image-3.0,images/edits | 同上 |
|
||||
| [tiantoken.json](configs/tiantoken.json) | gpt-6-astra,Responses,流式 | gpt-image-2,images/edits | TIANTOKEN_UNDERSTANDING_MODEL / TIANTOKEN_COMPLETION_MODEL |
|
||||
|
||||
CLI > 配置 stage.model > 对应模型环境变量 > default_model;shell 环境变量优先于 `.env`。不指定配置时入口默认 astra-qwen.json,建议实验始终显式指定。模型 ID 原样发送,中转能力以实际请求为准。Tiantoken 图片编辑已真实执行;第三阶段尚未适配 Astra Responses 图片生成工具。
|
||||
|
||||
三个配置当前均关闭多图参考与编辑 mask 能力。第三阶段默认只发送白底单部件图;本地 context.png/edit-mask.png 已生成但不默认发送。改进计划见第三阶段文档。
|
||||
|
||||
查询模型列表和检查配置:
|
||||
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --config .\configs\tiantoken.json --list-models
|
||||
node .\tools\model-check.mjs --config .\configs\tiantoken.json --dry-run
|
||||
```
|
||||
|
||||
前者联网,后者不请求模型;列表存在某个 ID 不代表其所有能力已验证。
|
||||
|
||||
## 三阶段执行命令
|
||||
|
||||
以下命令按顺序在同一个 PowerShell 会话执行。反引号后不能带空格。每次实验使用新的 runId;分阶段重开终端时,将路径变量设置成已有的对应目录。
|
||||
|
||||
```powershell
|
||||
conda activate ai-spine
|
||||
$runId = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||
$runRoot = ".\output\$runId"
|
||||
$reference = ".\output\20260918-183532\sam\source.png"
|
||||
```
|
||||
|
||||
示例复用现有角色原图,可替换 `$reference` 为自己的 PNG。不要混用不同实验的 source、计划和 mask。
|
||||
|
||||
### 第一阶段:理解角色结构
|
||||
|
||||
此命令调用视觉模型:
|
||||
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --stage understanding `
|
||||
--config .\configs\deepseek-qwen.json `
|
||||
--reference ..\spine-animation-ai\demo\character_reference.png `
|
||||
--dry-run
|
||||
--reference $reference `
|
||||
--out-dir "$runRoot\understand"
|
||||
```
|
||||
|
||||
### 使用 DeepSeek Flash 理解角色结构
|
||||
检查 `understand/report.html`、`semantic-parts.json`、`geometry-validation.json`。程序候选点来自 Alpha 距离变换,落在前景不代表属于正确部件。
|
||||
|
||||
当前已验证可用的配置是 `deepseek-flash + chat-completions + stream=false`:
|
||||
已有计划可离线重新检查;输出独立目录,不重跑模型:
|
||||
|
||||
```powershell
|
||||
node .\pipeline.mjs --mode annotated-parts `
|
||||
--config .\configs\deepseek-qwen.json `
|
||||
--reference ..\spine-animation-ai\demo\character_reference.png `
|
||||
--out-dir .\output\sombrero-understand-deepseek `
|
||||
--stop-after understand
|
||||
node .\tools\model-check.mjs --stage understanding `
|
||||
--reference .\output\20260918-183532\sam\source.png `
|
||||
--parts-file .\output\20260918-183532\sam\semantic-parts.json `
|
||||
--out-dir "$runRoot\understand-offline"
|
||||
```
|
||||
|
||||
重点检查输出目录中的:
|
||||
|
||||
- `report.html`:人工复核页面;
|
||||
- `semantic-parts.json`:v2 语义计划,包含 `rig_role`、`bind_to`、三项 `completion`;
|
||||
- `geometry-validation.json`:原始点诊断、框内前景比例、候选及阻塞原因;
|
||||
- `segmentation-prompts.json`:程序生成的 SAM 候选提示;模型原始正负点不会传入;
|
||||
- `validation.json`:本地结构校验结果;
|
||||
- `manifest.json`:模型、输入、代码版本和产物记录。
|
||||
|
||||
输入保留画布尺寸。已有透明背景直接保留 Alpha;不透明白底只移除与边界连通的近白区域。其他背景需先提供抠图 PNG。候选来自粗框内前景的距离变换,不能保证属于目标部件,仍需语义复核。关节点不会吸附到前景。
|
||||
|
||||
已有结果可离线检查,无需再次请求模型:
|
||||
### 第二阶段:本地 SAM 分割
|
||||
|
||||
```powershell
|
||||
node .\tools\model-check.mjs `
|
||||
--reference .\output\sombrero-understand-deepseek-flash\source.png `
|
||||
--parts-file .\output\sombrero-understand-deepseek-flash\semantic-parts.json `
|
||||
--out-dir .\output\sombrero-grounding-review
|
||||
```
|
||||
|
||||
旧版 v1 计划会保守迁移到 v2,迁移推断写入 notes,仍需复核;原文件不覆盖。
|
||||
|
||||
### 使用 GPT-6 Astra 做对照实验
|
||||
|
||||
```powershell
|
||||
node .\pipeline.mjs --mode annotated-parts `
|
||||
--config .\configs\astra-qwen.json `
|
||||
--reference ..\spine-animation-ai\demo\character_reference.png `
|
||||
--out-dir .\output\sombrero-understand-astra `
|
||||
--stop-after understand
|
||||
```
|
||||
|
||||
当前中转站的 Astra 通道要求 Responses 协议和流式响应。若中转站返回 overloaded,应使用新的输出目录稍后重试。
|
||||
|
||||
### 临时覆盖理解模型
|
||||
|
||||
```powershell
|
||||
node .\pipeline.mjs --mode annotated-parts `
|
||||
--config .\configs\deepseek-qwen.json `
|
||||
--understanding-model YOUR_EXACT_MODEL_ID `
|
||||
--understanding-protocol chat-completions `
|
||||
--stream false `
|
||||
--reference .\reference.png `
|
||||
--out-dir .\output\model-experiment `
|
||||
--stop-after understand
|
||||
```
|
||||
|
||||
每组模型实验应使用独立的输出目录,避免覆盖对照结果。只有输入、配置、代码和产物哈希全部一致时,才可以通过 `--resume` 复用结果。
|
||||
|
||||
### 使用本地 SAM 生成标注和拆解图
|
||||
|
||||
复用已有第一阶段结果,不重新请求 DeepSeek,也不需要中转站密钥:
|
||||
|
||||
```powershell
|
||||
conda run --no-capture-output -n ai-spine node .\tools\model-check.mjs `
|
||||
--stage segmentation `
|
||||
--input-dir .\output\sombrero-grounding-v2 `
|
||||
--out-dir .\output\sombrero-sam-local `
|
||||
node .\tools\model-check.mjs --stage segmentation `
|
||||
--input-dir "$runRoot\understand" `
|
||||
--out-dir "$runRoot\sam" `
|
||||
--sam-dir F:/Study/SAM3
|
||||
```
|
||||
|
||||
打开输出目录的 `report.html`:`annotated.png` 是原图上的不同半透明颜色标注,`parts-sheet.png` 是白底拆解图,`parts/` 保存原像素透明部件。运行期间加载 GPU 权重,完成后子进程退出,不启动常驻服务。
|
||||
若使用前面的离线计划,input-dir 改为 understand-offline。该命令只运行本地临时 GPU 子进程;添加 `--dry-run` 可探测环境而不加载模型。检查 `sam/report.html`、`annotated.png`、`parts-sheet.png`、漏分图和 mask 归属,错误部件应先修正。
|
||||
|
||||
加入 `--dry-run` 可检查环境与本地路径,不加载权重推理。输入必须含 `source.png`、v2 `semantic-parts.json`、`segmentation-prompts.json`。完整参数与质量检查见[第二阶段文档](docs/2-segmentation-stage.md)。
|
||||
### 第三阶段:准备与补全
|
||||
|
||||
### 第三阶段:按部件补全
|
||||
|
||||
先从已有 SAM 输出准备画布、允许新增区域和提示词,不请求模型:
|
||||
先离线准备任务,不请求模型:
|
||||
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --stage completion `
|
||||
--input-dir .\output\sombrero-sam31-v3 `
|
||||
--out-dir .\output\sombrero-completion-prepare `
|
||||
--completion-model qwen-image-3.0 `
|
||||
--config .\configs\tiantoken.json `
|
||||
--input-dir "$runRoot\sam" `
|
||||
--out-dir "$runRoot\complete-prepare" `
|
||||
--prepare-only
|
||||
```
|
||||
|
||||
打开 `report.html` 检查部件和允许新增区域。以下命令对 `head` 发起一次部件编辑任务,再检查候选并恢复原图可见像素;会调用中转站图片模型:
|
||||
复核允许区域后,按实际存在的 ID 试一个部件;下面会调用图片模型:
|
||||
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --stage completion `
|
||||
--input-dir .\output\sombrero-sam31-v3 `
|
||||
--out-dir .\output\sombrero-completion-head `
|
||||
--completion-model qwen-image-3.0 `
|
||||
--config .\configs\tiantoken.json `
|
||||
--input-dir "$runRoot\sam" `
|
||||
--out-dir "$runRoot\complete-head" `
|
||||
--part head
|
||||
```
|
||||
|
||||
`--part` 可重复;省略则处理所有具备可见 mask、补全需求和允许区域的部件。当前 SAM 示例仍有错分,应先复核。补全不会自动纠正上游语义;通过几何检查的 PNG 保存到 `parts/`,仍需人工复核。完整参数、离线候选导入与限制见[第三阶段文档](docs/3-completion-stage.md)。
|
||||
|
||||
第三阶段请求会显式发送与局部画布一致的 `size`(默认 `1024x1024`)。如果中转站仍返回其他尺寸,可使用 `--candidates-dir 旧补全目录 --candidate-size-policy uniform` 离线复查:只允许同宽高比的画布等比例缩放,保留原候选,继续检查位置与新增区域并恢复原像素。默认 strict 模式仍拒绝尺寸不符;详细命令见第三阶段文档。
|
||||
|
||||
### 单独测试图片补全接口
|
||||
|
||||
此命令只验证图片编辑适配器并保存原始候选,不代表补全部件已经验收通过:
|
||||
处理所有具备可见 mask、补全需求和允许区域的部件:
|
||||
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --stage completion `
|
||||
--image .\local-part.png `
|
||||
--prompt-file .\task.txt `
|
||||
--out-dir .\output\qwen-edit-test `
|
||||
--completion-model qwen-image-3.0
|
||||
--config .\configs\tiantoken.json `
|
||||
--input-dir "$runRoot\sam" `
|
||||
--out-dir "$runRoot\complete"
|
||||
```
|
||||
|
||||
### 运行旧版完整管线
|
||||
省略 part 不意味着强制补全全部 mask。检查 `completion-plan.json` 的跳过原因和 `completion-result.json` 的 QA;parts/ 仅包含通过检查的补全部件。所有结果仍需语义复核。
|
||||
|
||||
旧候选尺寸不符时,可离线导入复检,避免重新生成:
|
||||
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --stage completion `
|
||||
--config .\configs\tiantoken.json `
|
||||
--input-dir .\output\20260918-183532\sam `
|
||||
--candidates-dir .\output\20260918-183532\complete2_gpt `
|
||||
--out-dir "$runRoot\complete-size-recheck" `
|
||||
--candidate-size-policy uniform
|
||||
```
|
||||
|
||||
uniform 仅恢复同宽高比的整画布尺寸,不纠正物体位移、变形或语义。在线请求现已显式传 size;参数及中转实测边界见[第三阶段文档](docs/3-completion-stage.md)。
|
||||
|
||||
## 旧管线与验证
|
||||
|
||||
旧版依赖相邻 `spine-animation-ai` 外部项目,使用时遵守其 PolyForm Noncommercial 许可证;不要修改外部依赖。旧版命令会调用图片生成并尝试定位、导出:
|
||||
|
||||
```powershell
|
||||
node .\pipeline.mjs `
|
||||
--reference ..\spine-animation-ai\demo\character_reference.png `
|
||||
--out-dir .\output\legacy-character `
|
||||
--reference $reference `
|
||||
--out-dir "$runRoot\legacy" `
|
||||
--genielabs-dir ..\spine-animation-ai `
|
||||
--image-model qwen-image-3.0 `
|
||||
--attempts 1 `
|
||||
--animations idle,walk,wave
|
||||
```
|
||||
|
||||
旧流程依赖生成式拆件与传统 CV 定位,对低纹理、低分辨率和生成后外观变化较大的角色不稳定。其输出应通过 `assembled.png` 和 `preview-rigged.html` 人工检查后再导入 Spine。
|
||||
`segment.py` 为旧版拆件分割,`compose_preview.py` 组装预览,`run_case_matrix.py` 对照定位方案;当前 SAM 入口为 sam_segment.py。旧产物需检查 assembled.png 和 preview-rigged.html,不能据此声称新三阶段已经完成 Spine 导出。
|
||||
|
||||
### 运行测试
|
||||
测试与命令帮助:
|
||||
|
||||
```powershell
|
||||
conda run -n ai-spine npm test
|
||||
conda run --no-capture-output -n ai-spine npm test
|
||||
node .\tools\model-check.mjs --help
|
||||
```
|
||||
|
||||
测试使用本地 mock HTTP 服务或注入响应,不调用真实付费模型。
|
||||
测试使用本地 mock 或注入响应,不请求真实付费模型。自动化运行任一阶段可用 `conda run --no-capture-output -n ai-spine node ...`。保留旧实验;resume 只复用完整匹配产物,失败任务另建输出目录。
|
||||
|
||||
+115
-339
@@ -1,371 +1,147 @@
|
||||
# 第一阶段:视觉 LLM 角色结构理解
|
||||
|
||||
第一阶段把单张角色参考图转换为结构化的语义部件计划,供后续 SAM 分割、遮挡补全和 Spine 骨骼生成使用。
|
||||
## 1. 阶段简介
|
||||
|
||||
本阶段只做角色结构理解和粗标注,不生成精确 mask、透明拆件 PNG 或补全后的隐藏部件。
|
||||
将单张角色图转换为部件语义计划:确定部件名称、骨骼与附件分类、运动层级、遮挡、可见区域粗框、关节点和补全需求。视觉模型负责结构理解;本地程序负责格式校验和前景候选点生成。
|
||||
|
||||
## 1. 输入、输出与执行链路
|
||||
本阶段不生成精确 mask、透明拆件、隐藏纹理或 Spine 文件。结构合法不等于识别正确,结果仍为 `quality_status=needs_review`。
|
||||
|
||||
输入是一张完整的 PNG 角色参考图。核心输出是 <code>semantic-parts.json</code>,其中记录:
|
||||
## 2. 输入、输出与执行链路
|
||||
|
||||
- 角色由哪些可动部件组成;
|
||||
- 每个部件的语义名称;
|
||||
- 部件之间的运动父子关系;
|
||||
- 部件之间的视觉遮挡关系;
|
||||
- 可见、部分可见或完全隐藏状态;
|
||||
- 可见区域粗框、预计关节位置,骨骼/附件角色与绑定目标;
|
||||
- 程序用 Alpha 校验后另行输出的 SAM 候选点;
|
||||
- 是否需要在第三阶段补全;
|
||||
- 模型对判断结果的自报置信度。
|
||||
输入为 PNG 角色图;在线模式需要模型配置与密钥,离线模式需要已有语义计划。核心输出为语义计划和 SAM 提示。
|
||||
|
||||
整体执行链路:
|
||||
```text
|
||||
tools/model-check.mjs(或 pipeline.mjs --mode annotated-parts)
|
||||
→ 读取配置、图片、提示词与 Schema,计算实验指纹
|
||||
→ Python 保留 Alpha / 去除边界连通白底,保持原画布
|
||||
→ 在线:视觉模型理解;离线:读取计划并按需迁移 v1
|
||||
→ 提取 JSON,校验字段、引用、层级和补全一致性
|
||||
→ 在 Alpha 前景与粗框交集中生成距离变换候选点
|
||||
→ 保存 semantic-parts.json、segmentation-prompts.json、诊断及报告
|
||||
→ 第二阶段读取 source.png + 计划 + SAM 提示
|
||||
```
|
||||
|
||||
~~~text
|
||||
角色原图
|
||||
↓
|
||||
保留 Alpha 或去除边界连通白底(不缩放裁剪)
|
||||
↓
|
||||
读取模型配置、提示词和输出 Schema
|
||||
↓
|
||||
构造视觉 LLM 请求
|
||||
↓
|
||||
DeepSeek Flash / GPT-6 Astra
|
||||
↓
|
||||
提取模型返回的 JSON 文本
|
||||
↓
|
||||
Schema 校验和部件关系校验
|
||||
↓
|
||||
semantic-parts.json
|
||||
↓
|
||||
Alpha / ROI 校验、距离变换候选点、segmentation-prompts.json
|
||||
↓
|
||||
生成 annotated.svg 和 report.html
|
||||
↓
|
||||
人工复核后交给 SAM 分割阶段
|
||||
~~~
|
||||
`--parts-file` 不请求模型,也不运行 SAM。`--stop-after segment` 可接续第二阶段,输出到理解目录的 `segmentation/`;第三阶段独立调用。
|
||||
|
||||
## 2. 命令入口
|
||||
## 3. 阶段执行命令示例及参数说明
|
||||
|
||||
示例:
|
||||
以下 PowerShell 命令在项目根目录执行,环境准备见 [README](../README.md)。反引号必须在行尾,后面不能有空格。
|
||||
|
||||
~~~powershell
|
||||
node .\tools\model-check.mjs `
|
||||
--stage understanding `
|
||||
--understanding-model gpt-6-astra `
|
||||
--reference .\output\sombrero-grounding-v2\source.png `
|
||||
--out-dir ".\output\$runId\understand" `
|
||||
--config .\configs\tiantoken.json
|
||||
~~~
|
||||
```powershell
|
||||
conda activate ai-spine
|
||||
$runId = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||
node .\tools\model-check.mjs --stage understanding `
|
||||
--config .\configs\deepseek-qwen.json `
|
||||
--reference .\output\20260918-183532\sam\source.png `
|
||||
--out-dir ".\output\$runId\understand"
|
||||
```
|
||||
|
||||
第一步由以下两个文件负责:
|
||||
参考图可替换成自己的 PNG。切换 Tiantoken:将配置改为 `--config .\configs\tiantoken.json`,默认理解模型为 `gpt-6-astra`,也可显式传入 `--understanding-model gpt-6-astra`。
|
||||
|
||||
1. [pipeline.mjs](../pipeline.mjs) 检测 <code>--mode annotated-parts</code>,把命令转交给新管线,不进入旧版“生成拆件图 → CV 定位”流程。
|
||||
2. [tools/model-check.mjs](../tools/model-check.mjs) 解析参数、加载配置、应用命令行覆盖、检查输入并调用 <code>runUnderstanding()</code>。
|
||||
已有计划离线生成新候选,不重跑 AI:
|
||||
|
||||
## 3. 配置解析
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --stage understanding `
|
||||
--reference .\output\20260918-183532\sam\source.png `
|
||||
--parts-file .\output\20260918-183532\sam\semantic-parts.json `
|
||||
--out-dir ".\output\$runId\understand-offline"
|
||||
```
|
||||
|
||||
当前提供两组实验配置:
|
||||
|
||||
| 配置 | 理解模型 | 协议 | 流式 |
|
||||
| --- | --- | --- | --- |
|
||||
| [configs/deepseek-qwen.json](../configs/deepseek-qwen.json) | <code>deepseek-flash</code> | <code>chat-completions</code> | <code>false</code> |
|
||||
| [configs/astra-qwen.json](../configs/astra-qwen.json) | <code>gpt-6-astra</code> | <code>responses</code> | <code>true</code> |
|
||||
|
||||
[lib/config.mjs](../lib/config.mjs) 负责读取:
|
||||
|
||||
- JSON 配置文件;
|
||||
- 项目 <code>.env</code> 或 <code>--env-file</code>;
|
||||
- 当前 shell 环境变量;
|
||||
- 模型、协议、输出模式、超时和重试设置;
|
||||
- 阶段提示词;
|
||||
- SAM checkpoint 路径。
|
||||
|
||||
模型选择优先级:
|
||||
|
||||
~~~text
|
||||
命令行 --understanding-model
|
||||
> stage.model
|
||||
> SPINE_UNDERSTANDING_MODEL
|
||||
> stage.default_model
|
||||
~~~
|
||||
|
||||
Shell 环境变量优先于 <code>.env</code>。模型 ID 会原样传给中转站,不做隐式别名转换。
|
||||
|
||||
配置中的 <code>params</code> 不能覆盖模型、消息体、输入、流式选项和认证字段,避免实验配置改变基础请求语义或泄漏密钥。
|
||||
|
||||
## 4. 读取参考图
|
||||
|
||||
[lib/images.mjs](../lib/images.mjs) 读取参考图,并得到:
|
||||
|
||||
- 原始文件字节;
|
||||
- MIME 类型;
|
||||
- 图片宽高;
|
||||
- SHA-256;
|
||||
- 模型请求使用的 Base64 Data URL。
|
||||
|
||||
本阶段要求参考图为 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. 理解提示词
|
||||
|
||||
提示词位于 [prompts/understand-v1.txt](../prompts/understand-v1.txt),要求视觉 LLM:
|
||||
|
||||
- 保留角色原始姿势、朝向和不对称性;
|
||||
- 仅在独立运动有意义且图像支持时拆分部件;
|
||||
- 区分运动父子关系和视觉遮挡关系;
|
||||
- 使用完整画布的归一化坐标;
|
||||
- 输出语义、粗框、预计关节和 rig_role/bind_to;正负提示点留空;
|
||||
- 不把粗框声称为像素级 mask;
|
||||
- 不凭空创造没有视觉证据的隐藏肢体或附件;
|
||||
- 将不确定性和假设写入 <code>notes</code>。
|
||||
|
||||
请求适配器还会附加原图画布尺寸和完整 JSON Schema,并要求模型只返回符合 Schema 的 JSON。最终提示词副本保存在 <code>prompt.txt</code>。
|
||||
|
||||
## 6. 输出数据契约
|
||||
|
||||
结构定义位于 [schemas/semantic-parts.schema.json](../schemas/semantic-parts.schema.json)。顶层格式:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"schema_version": 2,
|
||||
"coordinate_space": "normalized_xy_top_left",
|
||||
"parts": [],
|
||||
"notes": []
|
||||
}
|
||||
~~~
|
||||
|
||||
每个部件包含:
|
||||
|
||||
| 字段 | 含义 |
|
||||
| 参数 | 说明 |
|
||||
| --- | --- |
|
||||
| <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> | 模型粗估点,仅为旧版诊断兼容保留,新请求留空 |
|
||||
| <code>negative_points_norm</code> | 模型负点,仅保留作记录,不传给 SAM |
|
||||
| <code>occluded_by</code> | 视觉上遮挡当前部件的其他部件 |
|
||||
| <code>completion</code> | occlusion_fill / joint_extension_parent / joint_extension_child 三项 boolean |
|
||||
| <code>needs_completion</code> | 三项 completion 的逻辑或;包括独立旋转需要的隐藏纹理和关节重叠 |
|
||||
| <code>confidence</code> | LLM 自报置信度,范围 0~1 |
|
||||
| `--stage understanding` | 第一阶段,也是入口默认阶段 |
|
||||
| `--reference FILE` | 必需,角色 PNG |
|
||||
| `--out-dir DIR` | 实际执行必需,使用独立新目录 |
|
||||
| `--config FILE` | JSON 配置;默认 `configs/astra-qwen.json` |
|
||||
| `--env-file FILE` | 默认项目 `.env`;shell 同名变量优先 |
|
||||
| `--understanding-model ID` | 原样发送模型 ID,不转换别名 |
|
||||
| `--understanding-protocol NAME` | `chat-completions` 或 `responses` |
|
||||
| `--stream true/false` | 覆盖配置流式设置 |
|
||||
| `--output-mode NAME` | `text-json`、`json-object`、`json-schema`;需确认中转能力 |
|
||||
| `--parts-file FILE` | 离线读取有效 v2 或保守迁移 v1 |
|
||||
| `--python FILE` | 仅允许 Conda ai-spine 的解释器 |
|
||||
| `--stop-after understand/segment` | 理解结束或接续 SAM |
|
||||
| `--dry-run` | 检查配置与图片格式,不生成产物;不代表完整 Python 几何链路已验证 |
|
||||
| `--resume` | 仅复用已完成且指纹、产物哈希一致的结果,不是失败请求续发 |
|
||||
| `--list-models` | 联网查询所选提供方模型列表,不能与 dry-run 同用 |
|
||||
|
||||
所有坐标都以完整画布左上角为原点并归一化到 0~1。例如:
|
||||
模型优先级:CLI > `stage.model` > 配置指定的模型环境变量 > `stage.default_model`。提示词路径相对于配置文件。DeepSeek 预设为 Chat Completions 非流式;两个 Astra 预设为 Responses 流式。配置不代表中转所有能力均已验证。
|
||||
|
||||
~~~json
|
||||
"bbox_norm_xyxy": [0.36, 0.36, 0.70, 0.62]
|
||||
~~~
|
||||
## 4. 输入格式要求
|
||||
|
||||
对应像素坐标:
|
||||
参考图必须是有效 PNG,建议单角色、透明背景、完整画布。透明图保留 Alpha;不透明白底只去除与边界连通、RGB 各通道均 ≥240 的区域。复杂背景需先抠图,空前景会失败;白色主体接触边界可能被误删。
|
||||
|
||||
~~~text
|
||||
xmin = canvas_width × 0.36
|
||||
ymin = canvas_height × 0.36
|
||||
xmax = canvas_width × 0.70
|
||||
ymax = canvas_height × 0.62
|
||||
~~~
|
||||
离线计划采用 [v2 Schema](../schemas/semantic-parts.schema.json):顶层 `schema_version=2`、`coordinate_space=normalized_xy_top_left`、`parts` 数组和 `notes`。实际部件数量为 1~64。
|
||||
|
||||
## 7. 构造视觉模型请求
|
||||
|
||||
[providers/vision.mjs](../providers/vision.mjs) 根据配置选择请求格式。
|
||||
|
||||
### Chat Completions
|
||||
|
||||
DeepSeek Flash 使用:
|
||||
|
||||
~~~text
|
||||
POST /v1/chat/completions
|
||||
~~~
|
||||
|
||||
一个用户消息中同时包含文本提示词、画布尺寸、Schema 和采用 Data URL 编码的角色原图。
|
||||
|
||||
### Responses
|
||||
|
||||
GPT-6 Astra 使用:
|
||||
|
||||
~~~text
|
||||
POST /v1/responses
|
||||
~~~
|
||||
|
||||
适配器把同一任务转换成 <code>input_text</code> 和 <code>input_image</code> 格式,因此模型业务逻辑与具体 API 协议保持分离。
|
||||
|
||||
<code>output_mode</code> 支持:
|
||||
|
||||
- <code>text-json</code>:通过提示词约束 JSON,再在本地严格校验;
|
||||
- <code>json-object</code>:中转站确认支持后使用 JSON Object 模式;
|
||||
- <code>json-schema</code>:中转站确认支持后使用 Structured Outputs。
|
||||
|
||||
当前已验证的 DeepSeek 配置使用 <code>text-json</code>。
|
||||
|
||||
## 8. 中转站通信
|
||||
|
||||
[providers/http.mjs](../providers/http.mjs) 负责:
|
||||
|
||||
- 拼接 base URL 和协议路由;
|
||||
- 添加 Bearer Authorization;
|
||||
- 控制请求超时;
|
||||
- 对明确的 HTTP 429 和 5xx 有限重试;
|
||||
- 解析普通 JSON 或完整 SSE;
|
||||
- 拒绝被截断的流式响应;
|
||||
- 记录请求 ID、模型、token、耗时和尝试次数;
|
||||
- 从错误信息和落盘文件中脱敏 API Key。
|
||||
|
||||
超时或网络中断不会自动重试,因为服务端可能已经执行并计费。失败时会尽量生成 <code>response.error.json</code>,保存脱敏后的状态码、响应片段或网络错误码。
|
||||
|
||||
## 9. 提取与校验模型结果
|
||||
|
||||
[providers/vision.mjs](../providers/vision.mjs) 从不同协议的响应中提取模型文本,并拒绝:
|
||||
|
||||
- 模型 refusal;
|
||||
- 非正常 <code>finish_reason</code>;
|
||||
- 未完成的 Responses 状态;
|
||||
- 没有结构理解文本的响应。
|
||||
|
||||
提取后的内容保存在 <code>response.txt</code>。
|
||||
|
||||
[lib/validate-parts.mjs](../lib/validate-parts.mjs) 首先去掉模型可能添加的 Markdown JSON 代码块,然后执行 JSON 解析和两层本地校验。
|
||||
|
||||
### Schema 校验
|
||||
|
||||
- 必填字段是否齐全;
|
||||
- 类型与枚举是否正确;
|
||||
- ID 格式是否合法;
|
||||
- 坐标和置信度是否在 0~1;
|
||||
- 部件数量是否在 1~64;
|
||||
- 是否出现未知字段。
|
||||
|
||||
### 结构语义校验
|
||||
|
||||
- 部件 ID 不能重复;
|
||||
- <code>parent</code> 和 <code>occluded_by</code> 必须引用已有部件;
|
||||
- 部件不能引用自己;
|
||||
- 父子关系和遮挡关系不能形成环;
|
||||
- 可见部件必须具有正面积 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) 将结构理解结果叠加到原图:
|
||||
|
||||
- 彩色矩形:模型预测的可见区域粗框;
|
||||
- 红色实心圆:无效模型点;黄色实心圆:前景上的不可信模型点;
|
||||
- 青色方块:程序生成的 Alpha 候选,仍需确认部件语义;
|
||||
- 空心圆:部件 pivot;
|
||||
- 虚线:当前部件到父部件的关系;
|
||||
- 文本:部件 ID。
|
||||
|
||||
它会生成:
|
||||
|
||||
- <code>annotated.svg</code>:可缩放的原图标注;
|
||||
- <code>report.html</code>:包含标注图、校验结果、部件表、模型说明和请求元数据的自包含检查页。
|
||||
|
||||
<code>status=completed</code> 只表示请求、解析和本地校验完成。成功结果仍设置 <code>quality_status=needs_review</code>,因为结构合法不等于语义和框位置一定正确。
|
||||
|
||||
人工复核至少应检查:
|
||||
|
||||
1. 是否遗漏身体、头部或关键肢体;
|
||||
2. 左右肢体是否符合画面方向;
|
||||
3. 是否过度拆分面部或服饰细节;
|
||||
4. 父子关系能否支持预期动画;
|
||||
5. 遮挡关系是否与原图一致;
|
||||
6. bbox 和提示点是否落在正确部件上;
|
||||
7. <code>needs_completion</code> 是否覆盖确实需要补全的部分。
|
||||
|
||||
## 11. 阶段调度与实验留档
|
||||
|
||||
[stages/model-stage.mjs](../stages/model-stage.mjs) 是第一阶段总调度器:
|
||||
|
||||
~~~text
|
||||
读取图片
|
||||
→ 计算输入、Schema、配置和代码指纹
|
||||
→ 创建运行目录
|
||||
→ 保存输入、提示词和请求摘要
|
||||
→ 调用视觉 LLM
|
||||
→ 保存原始响应和请求元数据
|
||||
→ 提取并校验 JSON
|
||||
→ 保存正式语义结果
|
||||
→ 生成标注和检查报告
|
||||
→ 更新 manifest
|
||||
~~~
|
||||
|
||||
[lib/run-artifacts.mjs](../lib/run-artifacts.mjs) 负责输出目录、恢复校验、产物哈希和最终状态。
|
||||
|
||||
<code>--resume</code> 只在原图、模型、协议、参数、提示词、Schema、相关源代码和已有产物全部一致时复用结果。不同模型或提示词实验应使用不同输出目录。
|
||||
|
||||
## 12. 输出文件
|
||||
|
||||
| 文件 | 作用 |
|
||||
| 部件字段 | 格式与含义 |
|
||||
| --- | --- |
|
||||
| <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> | 中转站原始成功响应 |
|
||||
| <code>response.txt</code> | 从协议响应中提取的模型文本 |
|
||||
| <code>request-metadata.json</code> | 请求模型、返回模型、request ID、usage、耗时、次数和 wire format |
|
||||
| <code>validation.json</code> | Schema 与结构语义校验结果 |
|
||||
| <code>semantic-parts.json</code> | 校验通过后的正式结构理解结果 |
|
||||
| <code>annotated.svg</code> | 原图上的粗框、pivot、提示点和父子连线 |
|
||||
| <code>report.html</code> | 用于人工语义复核的综合页面 |
|
||||
| <code>manifest.json</code> | 状态、配置、输入哈希、代码版本、SAM 信息和全部产物哈希 |
|
||||
| <code>response.error.json</code> | HTTP、SSE 或网络失败时的脱敏诊断信息;成功时不存在 |
|
||||
| `id` / `semantic` | 唯一小写 ASCII ID / 语义说明 |
|
||||
| `parent` | 父骨骼 ID 或 null;运动关系 |
|
||||
| `rig_role` | `bone_part`、`attachment`、`facial_feature` |
|
||||
| `bind_to` | 附件绑定的骨骼 ID 或 null(root);骨骼自身为 null |
|
||||
| `visibility` | `visible`、`partial`、`hidden` |
|
||||
| `bbox_norm_xyxy` | `[xmin,ymin,xmax,ymax]` 可见粗框;隐藏为 null |
|
||||
| `pivot_norm` | `[x,y]` 关节或连接点,可处于遮挡区域 |
|
||||
| `positive_points_norm` / `negative_points_norm` | 旧模型点兼容字段,新提示词要求留空 |
|
||||
| `occluded_by` | 遮挡者 ID 数组,与运动关系分开 |
|
||||
| `completion` | `occlusion_fill`、`joint_extension_parent`、`joint_extension_child` 三个布尔值 |
|
||||
| `needs_completion` | 三项 completion 的逻辑或 |
|
||||
| `confidence` | 0~1 自报置信度;说明与不确定性写入顶层 notes,部件内没有 notes 字段 |
|
||||
|
||||
<code>request.json</code> 是请求身份摘要,不等同于线上发送的完整 HTTP body。图片内容单独保存在 <code>source.png</code>,密钥不会写入产物。
|
||||
坐标以完整画布左上角为原点,归一化到 0~1。可见框须为正面积;partial/hidden 必须声明遮挡补全,hidden 无可见框和正点。附件及面部特征不能声明独立骨骼关节延展。引用必须存在,不能自引用或形成父子/遮挡环路,绑定目标必须是骨骼。完整类型与必填项以 Schema 为准。
|
||||
|
||||
## 13. 代码职责索引
|
||||
v1 迁移依据 ID 推断角色分类和补全需求,推断写入 notes,不重新识别图片、不覆盖旧文件。计划必须对应同一张图、同一画布。
|
||||
|
||||
## 5. 执行链路中重要部分代码文件及原理说明(包括重点说明)
|
||||
|
||||
**请求和结构校验。** `stages/model-stage.mjs` 调度;`providers/vision.mjs` 将图片 Data URL、画布尺寸、提示词与 Schema 转成对应协议,再提取 JSON,拒绝 refusal、异常结束和未完成响应。`lib/validate-parts.mjs` 校验字段、引用、层级和补全一致性,成功后写正式计划。低置信度等产生告警,不能据结构校验认定语义正确。
|
||||
|
||||
**候选点并非重新由 AI 生成。** `geometry_grounding.py` 对粗框与 `alpha>0` 的交集计算距离变换,选取远离边界的像素中心;无有效前景则 blocked。归一化点转像素采用 floor,1 映射到最后一个像素;粗框按 floor/ceil 转半开范围。候选仍可能属于框内的其他部件。
|
||||
|
||||
**pivot 与种子独立。** 关节点不吸附到前景,模型原始正负点仅作诊断。第二阶段当前只用程序种子排序返回的 mask,未把它们作为 SAM 点提示。
|
||||
|
||||
**通信、可视化与留档。** `providers/http.mjs` 负责 HTTP、SSE、超时和脱敏;明确的 429/5xx 有限重试,超时/网络中断不自动重复请求。`lib/report.mjs` 用红/黄圆区分原模型点、青色方块表示程序候选、空心圆表示 pivot。旧输出不会随代码修改自动更新。`lib/run-artifacts.mjs` 按输入、模型、参数、提示词、Schema、代码和产物哈希复用结果;completed 仅表示执行完成。
|
||||
|
||||
## 6. 各个代码文件职责索引
|
||||
|
||||
| 文件 | 职责 |
|
||||
| --- | --- |
|
||||
| [pipeline.mjs](../pipeline.mjs) | 顶层入口;把 annotated-parts 模式转发到新管线 |
|
||||
| [tools/model-check.mjs](../tools/model-check.mjs) | CLI 参数解析、配置解析入口、模型列表和阶段分发 |
|
||||
| [configs/deepseek-qwen.json](../configs/deepseek-qwen.json) | DeepSeek 理解 + Qwen 补全实验预设 |
|
||||
| [configs/astra-qwen.json](../configs/astra-qwen.json) | Astra 理解 + Qwen 补全实验预设 |
|
||||
| [prompts/understand-v1.txt](../prompts/understand-v1.txt) | 第一阶段任务约束 |
|
||||
| [schemas/semantic-parts.schema.json](../schemas/semantic-parts.schema.json) | 第一阶段输出数据契约 |
|
||||
| [lib/config.mjs](../lib/config.mjs) | JSON、环境变量和阶段配置解析 |
|
||||
| [lib/images.mjs](../lib/images.mjs) | 图片读取、格式识别、尺寸、哈希和 Data URL |
|
||||
| [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) | 第一阶段总调度与失败处理 |
|
||||
| [pipeline.mjs](../pipeline.mjs) / [tools/model-check.mjs](../tools/model-check.mjs) | 新管线转发 / CLI、模型列表和阶段分发 |
|
||||
| [stages/model-stage.mjs](../stages/model-stage.mjs) | 理解总调度与留档;另含图片编辑探针 |
|
||||
| [lib/config.mjs](../lib/config.mjs) / [lib/images.mjs](../lib/images.mjs) | 配置解析 / 图片格式、尺寸、哈希和 Data URL |
|
||||
| [lib/python-runtime.mjs](../lib/python-runtime.mjs) / [lib/geometry.mjs](../lib/geometry.mjs) | Conda 检查 / Python 几何调用 |
|
||||
| [normalize_reference.py](../normalize_reference.py) / [geometry_grounding.py](../geometry_grounding.py) | Alpha 与去白底 / ROI 诊断和候选生成 |
|
||||
| [providers/vision.mjs](../providers/vision.mjs) / [providers/http.mjs](../providers/http.mjs) | 视觉协议 / 通信与脱敏 |
|
||||
| [lib/validate-parts.mjs](../lib/validate-parts.mjs) | 解析、Schema/关系校验、v1 迁移 |
|
||||
| [lib/report.mjs](../lib/report.mjs) / [lib/run-artifacts.mjs](../lib/run-artifacts.mjs) | SVG/HTML / 状态、指纹与缓存 |
|
||||
| [prompts/understand-v1.txt](../prompts/understand-v1.txt) | 理解提示词;文件名保留 v1,当前使用 v2 契约 |
|
||||
| [v2 Schema](../schemas/semantic-parts.schema.json) / [v1 Schema](../schemas/semantic-parts-v1.schema.json) | 正式契约 / 兼容输入 |
|
||||
| [DeepSeek](../configs/deepseek-qwen.json)、[Astra](../configs/astra-qwen.json)、[Tiantoken](../configs/tiantoken.json) 配置 | 模型、协议和环境变量预设 |
|
||||
| [tests/model-stages.test.mjs](../tests/model-stages.test.mjs) / [tests/test_geometry.py](../tests/test_geometry.py) | 协议、计划、留档及几何回归 |
|
||||
|
||||
## 14. 当前边界与下一阶段接口
|
||||
## 7. 产物详细说明
|
||||
|
||||
第一阶段输出的是语义计划,而不是分割结果:
|
||||
| 路径 | 内容与用途 |
|
||||
| --- | --- |
|
||||
| `source-original.png` | 原始输入副本 |
|
||||
| `source.png` | 预处理 RGBA,在线模型所见图片,后续坐标基准 |
|
||||
| `preprocessing.json` | 背景处理方式与像素统计 |
|
||||
| `semantic-parts.json` / `validation.json` | 正式 v2 计划 / 字段、关系校验及告警 |
|
||||
| `geometry-validation.json` | 原点诊断、ROI 前景比例、连通域、候选与阻塞原因 |
|
||||
| `segmentation-prompts.json` | 画布、部件 ID、candidate/hidden/blocked 状态、粗框、程序种子和 QA 要求 |
|
||||
| `annotated.svg` / `report.html` | 粗标注 / 综合复核页;不是 SAM 分割图 |
|
||||
| `prompt.txt` / `request.json` | 阶段提示词副本 / 请求身份摘要,不是完整 HTTP body |
|
||||
| `response.raw.json` / `response.txt` | 响应留档 / 提取文本;离线模式使用本地计划记录 |
|
||||
| `request-metadata.json` | 请求与返回模型、request ID、usage、耗时、次数和协议元数据 |
|
||||
| `response.error.json` | 可获取时保存的脱敏请求失败诊断 |
|
||||
| `manifest.json` | 模式、状态、输入/代码/产物哈希;SAM 路径仅记录,不加载模型 |
|
||||
|
||||
~~~text
|
||||
视觉 LLM 输出
|
||||
= 部件语义 + 层级 + rig_role/bind_to + 遮挡 + 粗框 + 粗关节 + 补全需求
|
||||
失败可能只有部分产物。第二阶段前应复核左右、粗框、层级、遮挡、分类和补全需求,不能只看点是否落在前景。
|
||||
|
||||
视觉 LLM 不输出
|
||||
= 可信的像素 mask + 透明拆件 + 隐藏区域补全 + 最终骨骼
|
||||
~~~
|
||||
## 8. 当前阶段可改进点说明
|
||||
|
||||
已实现的[第二阶段](2-segmentation-stage.md)读取 <code>source.png</code>、<code>semantic-parts.json</code> 和 <code>segmentation-prompts.json</code>,仅处理 status=candidate 的可见部件。SAM 图像概念接口接收文本和框;程序候选点参与返回 mask 的排序,不作为点提示传入此接口。模型原始正负点不传给 SAM。候选始终 semantic_verified=false:框内可能混有多个部件,Alpha、重叠和连通域检查不能替代语义复核。
|
||||
|
||||
已有 v1 结果可以通过 <code>--parts-file 旧计划.json --reference 原图.png --out-dir 新目录</code> 离线迁移与校验,不请求模型。迁移按 ID 推断骨骼/附件类型,袖子优先绑定同侧上臂,面部绑定头部;部分可见部件开启遮挡补全,骨骼连接处保守建议延展。这些推断在 notes 标注为待复核,不替代模型或人工判断。输入计划哈希和所有新产物参与 resume 校验。
|
||||
|
||||
第一阶段 <code>manifest.json</code> 只记录 SAM 路径信息,<code>runtime_status=local_subprocess_not_probed</code>,第一阶段不加载 SAM。第二阶段单独探测 Conda/CUDA、严格加载本地权重,并在自己的 manifest 中记录运行环境、权重哈希及子进程退出状态。
|
||||
- 明确角色左右与画面左右命名约定,提升粗框、遮挡及隐藏状态判断,减少 SAM 衣料/肢体混淆。
|
||||
- 根据预期动画审查拆分粒度与附件绑定,区分隐藏骨骼占位项和真正可见拆件。
|
||||
- 增加可审阅的计划修正流程,修正后重新生成几何提示;Alpha 候选不能代替语义复核。
|
||||
- 第二阶段后根据实际 mask 重新评估补全需求,不能因第一阶段 needs_completion=false 永久跳过有缺损的拆件。
|
||||
- 增加结构和像素证据一致性检查,区分“不确定”“结构合法”“人工确认正确”。
|
||||
|
||||
+121
-81
@@ -1,116 +1,156 @@
|
||||
# 第二阶段:本地 SAM 分割
|
||||
|
||||
本阶段读取第一阶段的语义计划,使用本地 SAM 3.1 图像检测分支生成部件 mask,从原图提取可见像素,并输出两张预览图。Python 固定使用 `ai-spine` Conda 环境,遵守 [AGENTS.md](../AGENTS.md)。
|
||||
## 1. 阶段简介
|
||||
|
||||
## 运行方式
|
||||
读取第一阶段语义计划,用本地 SAM 3.1 图像检测分支生成部件 mask,再从原图提取可见像素。当前输出半透明颜色叠加的角色图、白底拆解图和透明部件。
|
||||
|
||||
在 `AI_spine` 目录执行:
|
||||
SAM 在 Conda `ai-spine` 的临时 GPU 子进程中运行,结束后退出;不部署常驻服务、不下载权重、不调用中转站、不自动回退 CPU。本阶段尚无大模型去毛边步骤,也不补画隐藏纹理。
|
||||
|
||||
## 2. 输入、输出与执行链路
|
||||
|
||||
输入为第一阶段目录,加本地 SAM 代码和权重;输出为可见部件 mask、原像素拆件、诊断和预览。
|
||||
|
||||
```text
|
||||
tools/model-check.mjs --stage segmentation
|
||||
→ stages/segmentation-stage.mjs 检查输入、路径、参数与 Conda
|
||||
→ 临时探测子进程检查依赖和 CUDA,不加载权重
|
||||
→ 计算输入、代码、权重指纹,复制输入到新输出目录
|
||||
→ 临时推理子进程:sam_segment.py → sam_runtime.py
|
||||
→ 严格加载检测分支,一次编码原图
|
||||
→ 每部件分别取得文本、文本+粗框候选,排序选 mask
|
||||
→ 与原图 Alpha 取交集,提取原像素并渲染报告
|
||||
→ 子进程退出,manifest 记录产物与退出状态
|
||||
→ 第三阶段读取 source.png、计划、segmentation.json 和 masks/
|
||||
```
|
||||
|
||||
`hidden/blocked` 不进入推理;没有合格候选会记录跳过原因,不用矩形或种子伪造 mask。所有输出仍为 `semantic_verified=false`、`quality_status=needs_review`。
|
||||
|
||||
## 3. 阶段执行命令示例及参数说明
|
||||
|
||||
在项目根目录执行,环境安装见 [README](../README.md)。以下独立命令复用已有计划,无需模型密钥:
|
||||
|
||||
```powershell
|
||||
conda activate ai-spine
|
||||
$runId = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||
node .\tools\model-check.mjs --stage segmentation `
|
||||
--input-dir .\output\sombrero-grounding-v2 `
|
||||
--out-dir ".\output\$runId\sam" `
|
||||
--sam-dir F:/Study/SAM3
|
||||
```
|
||||
|
||||
将 `--input-dir` 替换为本次第一阶段的 `understand` 目录,即可接续新实验。自动化可以使用 `conda run --no-capture-output -n ai-spine node ...`。
|
||||
|
||||
仅探测环境与输入,不进行模型推理:
|
||||
|
||||
```powershell
|
||||
conda run --no-capture-output -n ai-spine node .\tools\model-check.mjs `
|
||||
--stage segmentation `
|
||||
--input-dir .\output\sombrero-grounding-v2 `
|
||||
--out-dir .\output\sombrero-sam-local `
|
||||
--sam-dir F:/Study/SAM3
|
||||
|
||||
node .\tools\model-check.mjs `
|
||||
--stage segmentation `
|
||||
--input-dir ".\output\$runId\understand" `
|
||||
--out-dir ".\output\$runId\sam" `
|
||||
--sam-dir F:/Study/SAM3
|
||||
--sam-dir F:/Study/SAM3 `
|
||||
--dry-run
|
||||
```
|
||||
|
||||
输出目录必须是新目录。相同输入、代码、权重、参数及完整产物可加 `--resume` 复用;失败结果保留,另建目录重跑。独立分割不调用视觉 LLM 或图片编辑接口,不需要 API Key。
|
||||
|
||||
输入目录必须包含:
|
||||
|
||||
| 文件 | 要求 |
|
||||
| 参数 | 说明 |
|
||||
| --- | --- |
|
||||
| `source.png` | 第一阶段预处理后的原尺寸 RGBA |
|
||||
| `semantic-parts.json` | 通过结构校验的 v2 语义计划 |
|
||||
| `segmentation-prompts.json` | 与计划 ID、画布匹配的程序候选提示 |
|
||||
| `--stage segmentation` | 独立运行第二阶段 |
|
||||
| `--input-dir DIR` | 必需,第一阶段输出目录 |
|
||||
| `--out-dir DIR` | 推理必需,使用独立新目录;dry-run 可省略 |
|
||||
| `--sam-dir DIR` | SAM 根目录,优先于 SAM_MODEL_DIR 和配置默认值 |
|
||||
| `--sam-code-dir DIR` | 源码仓库,优先于 SAM_CODE_DIR 和根目录下 sam3 |
|
||||
| `--sam-checkpoint FILE` | 显式本地权重,覆盖根目录自动查找 |
|
||||
| `--sam-confidence FLOAT` | 候选模型分数阈值,默认 0.2,严格介于 0 和 1;不是语义准确率 |
|
||||
| `--sam-precision NAME` | 默认 bf16,可选 fp32;后者显存占用更高 |
|
||||
| `--config FILE` / `--env-file FILE` | 配置与环境变量文件,默认 astra-qwen.json / 项目 .env |
|
||||
| `--python FILE` | 仅允许 ai-spine 的解释器 |
|
||||
| `--dry-run` | 检查路径、Conda、依赖导入和 CUDA;不校验完整权重加载或推理显存 |
|
||||
| `--resume` | 输入、参数、代码、权重和完整产物一致时复用;失败任务另建目录 |
|
||||
|
||||
仅 `status=candidate` 的可见部件进入推理。hidden/blocked 记入跳过列表;无可用 SAM mask 的部件记录失败原因,不用矩形或候选点伪造分割。
|
||||
也可在第一阶段命令上使用 `--stop-after segment --sam-dir F:/Study/SAM3`,输出位于理解目录的 `segmentation/`。该方式会先执行理解阶段,可能调用付费模型。
|
||||
|
||||
可以在命令末尾加 `--dry-run` 检查代码路径、权重存在性、Conda、依赖导入和 CUDA;它不加载权重,因此不验证权重内容或完整推理显存需求。
|
||||
## 4. 输入格式要求
|
||||
|
||||
如需从第一阶段接续运行,在原结构理解命令中使用 `--stop-after segment --sam-dir F:/Study/SAM3`。第二阶段输出到理解目录下的 `segmentation/`。原理解命令仍可能请求付费模型;已有计划优先使用上面的独立命令。
|
||||
| 输入 | 要求 |
|
||||
| --- | --- |
|
||||
| `source.png` | 第一阶段预处理 RGBA,保留完整原画布 |
|
||||
| `semantic-parts.json` | 通过结构校验的 v2 计划,旧版须先离线迁移 |
|
||||
| `segmentation-prompts.json` | 宽高匹配 source;部件 ID 与计划完整一致 |
|
||||
| candidate 提示 | 非隐藏部件,seed_source 为 alpha_roi_distance_transform;整数粗框在画布内;至少一个整数种子在粗框与 Alpha 前景内 |
|
||||
| SAM 代码 | 源码仓库内部必须有 sam3/model_builder.py |
|
||||
| SAM 权重 | 本地 sam3.1_multiplex.pt,与本项目适配的检测分支结构匹配 |
|
||||
|
||||
## 环境与权重
|
||||
|
||||
本机已经验证:Python 3.11、PyTorch `2.7.1+cu126`、torchvision `0.22.1+cu126`、NumPy `1.26.4`、OpenCV `4.11.0.86`、Windows Triton `3.3.1.post21`,GPU 为 RTX 3060 Laptop 6 GB。
|
||||
|
||||
环境补全命令见 [README](../README.md#python-与外部项目),依赖记录在 [requirements.txt](../requirements.txt)。程序不会自动安装依赖、创建环境或切换到 CPU。
|
||||
|
||||
默认布局:
|
||||
当前本机布局:
|
||||
|
||||
```text
|
||||
F:/Study/SAM3/
|
||||
sam3/ 源码仓库
|
||||
sam3/
|
||||
sam3/model_builder.py
|
||||
sam3.1checkpoint/
|
||||
sam3.1_multiplex.pt
|
||||
```
|
||||
|
||||
路径优先级为 CLI 覆盖、环境变量、配置默认值。`SAM_MODEL_DIR` 指定根目录,`SAM_CODE_DIR` 可单独指定源码仓库。若 `.env` 中仍是旧路径,修改为上述路径或显式传入 CLI 参数。
|
||||
权重默认先查找上述子目录,再查找 SAM 根目录下同名文件。当前已验证环境为 Python 3.11、PyTorch 2.7.1+cu126、torchvision 0.22.1、NumPy 1.26.4、OpenCV 4.11.0.86,RTX 3060 Laptop 6 GB。这是本机验证组合,不是所有机器的兼容保证。
|
||||
|
||||
| 参数 | 含义 |
|
||||
## 5. 执行链路中重要部分代码文件及原理说明(包括重点说明)
|
||||
|
||||
**本地生命周期与权重。** `stages/segmentation-stage.mjs` 先探测,再启动一次推理进程;离线环境变量禁止 Hugging Face 下载。推理超时 20 分钟,结束、报错或取消后退出。`sam_runtime.py` 从 multiplex 权重提取 detector 分支,适配三个特征尺度,移除未使用的第四尺度并取消 scalp;忽略不参与当前推理的视频 neck,实际加载参数使用 strict=True。外部 SAM 源码不作修改。
|
||||
|
||||
**精度不能简单全模型转换。** 模型参数和复数位置编码缓冲区保持原精度,在推理上下文开启 BF16 autocast;直接对整个模型调用 BF16 转换会影响复数缓冲区及要求 FP32 的路径。
|
||||
|
||||
**提示和选择。** `sam_segment.py` 将原图合成白底 RGB,GPU 只编码一次;每个部件分别收集 text_only 与 text_and_box 候选。排序结合模型分数、粗框内比例、Alpha 越界比例和种子命中;前景不足 4 像素或框内比例低于 10% 的候选被拒绝。粗框是提示,并非强制裁剪边界。
|
||||
|
||||
**重点:当前不是 SAM 点提示分割。** 所用图像概念接口接受文本和框。第一阶段程序种子仅参与返回 mask 排序,模型原始点不传入 SAM。提高种子前景命中率不能保证选中正确部件。
|
||||
|
||||
**像素与质量。** `segmentation_outputs.py` 用原图 Alpha 裁掉背景,从原图复制 RGB/Alpha,不重绘、不缩放;保留多部件重叠。记录越界、碎片、未命中种子、漏分、重叠和 IoU≥0.8 的疑似重复。覆盖率不是语义准确率,原像素保真也不能修复错误归属。
|
||||
|
||||
**当前预览含原图纹理。** `annotated.png` 是原图上 Alpha=100 的彩色 mask 叠加,不是仅用纯色区域组成的角色图;`parts-sheet.png` 为带 ID 的白底拆件。纯色遮罩角色图属于第 8 节的待实现项。
|
||||
|
||||
## 6. 各个代码文件职责索引
|
||||
|
||||
| 文件 | 职责 |
|
||||
| --- | --- |
|
||||
| `--sam-dir` | SAM 根目录 |
|
||||
| `--sam-code-dir` | 源码仓库目录,内部应包含 `sam3/model_builder.py` |
|
||||
| `--sam-checkpoint` | 本地权重文件 |
|
||||
| `--sam-confidence` | SAM 候选分数阈值,默认 0.2,不是语义正确率 |
|
||||
| `--sam-precision` | 默认 bf16 自动混合精度;可设 fp32,可能需要更多显存 |
|
||||
| [tools/model-check.mjs](../tools/model-check.mjs) | 独立分割入口、参数解析 |
|
||||
| [stages/segmentation-stage.mjs](../stages/segmentation-stage.mjs) | 输入校验、环境探测、子进程、哈希、日志与失败处理 |
|
||||
| [lib/config.mjs](../lib/config.mjs) | SAM 路径与配置解析 |
|
||||
| [lib/python-runtime.mjs](../lib/python-runtime.mjs) | ai-spine 解释器与基础依赖检查 |
|
||||
| [lib/images.mjs](../lib/images.mjs) / [lib/validate-parts.mjs](../lib/validate-parts.mjs) | PNG 元数据 / v2 计划结构校验 |
|
||||
| [lib/run-artifacts.mjs](../lib/run-artifacts.mjs) | 输出目录、复用、产物哈希 |
|
||||
| [sam_runtime.py](../sam_runtime.py) | 依赖/CUDA 探测、源码路径、检测权重适配与严格加载 |
|
||||
| [sam_segment.py](../sam_segment.py) | 提示校验、GPU 推理、候选排序、诊断与阶段组织 |
|
||||
| [segmentation_outputs.py](../segmentation_outputs.py) | mask QA、原像素提取、标注图、拆件图、HTML |
|
||||
| [tests/test_segmentation.py](../tests/test_segmentation.py) | 候选、提示、Alpha、裁剪保真和重叠回归 |
|
||||
| [tests/model-stages.test.mjs](../tests/model-stages.test.mjs) | 阶段入口和相关本地回归调度 |
|
||||
|
||||
Node 先启动环境探测子进程,再启动一次推理子进程。模型只加载到后者;没有监听端口或常驻服务,正常结束、报错、超时或收到取消信号后退出。推理超时为 20 分钟。禁用 Hugging Face 在线下载,权重只能来自本地。
|
||||
`segment.py` 是旧版白底拆件图分割器,不是本阶段 SAM 入口;`compose_preview.py`、`run_case_matrix.py` 是旧版定位/组装对照工具,不应与新阶段混用。
|
||||
|
||||
`sam_runtime.py` 从 multiplex checkpoint 提取 `detector.*`。SAM 3.1 的检测分支有三个特征尺度;图像 builder 的第四尺度原本会被 scalp 丢弃,因此适配器移除该未使用尺度并取消 scalp。忽略视频交互/传播 neck,随后 `strict=True` 加载所有实际使用参数;结构不匹配会报错。未修改外部 SAM 源码。
|
||||
## 7. 产物详细说明
|
||||
|
||||
保留 FP32 参数和复数位置编码缓冲区,仅在推理上下文开启 BF16 autocast。不能直接把整个模型转换为 BF16,这会破坏复数缓冲区及上游要求 FP32 的解码器路径。
|
||||
|
||||
## 提示、选择与质量检查
|
||||
|
||||
1. 在白色背景上合成参考图,保持原尺寸;GPU 只编码一次图像。
|
||||
2. 每个部件先用语义文本推理,再加入归一化粗框推理,保留两组候选。
|
||||
3. 根据模型分数、粗框内比例、越出角色 Alpha 的比例及候选点命中情况排序。拒绝前景不足 4 像素或框内比例低于 10% 的结果。
|
||||
4. 最终 mask 与原图 Alpha 前景取交集,从原图提取 RGB 和 Alpha,不重绘、不缩放。原始选中 mask 另存用于检查越界。
|
||||
5. 记录漏分、重叠、碎片化、候选点未覆盖,以及不同部件 mask IoU ≥ 0.8 的疑似重复。
|
||||
|
||||
当前使用的 SAM 图像概念接口接受文本与框,不接受点。第一阶段的 Alpha 候选点仅用于 mask 排序;模型原始点仍只用于第一阶段诊断。这次 mask 来自真实 GPU 模型推理。
|
||||
|
||||
粗框、候选点及模型分数都不能保证部件语义正确。因此所有结果保持 `quality_status=needs_review`、`semantic_verified=false`。重叠 mask 保留,未强行分配成互斥部件,也未补全遮挡纹理。人工复核通过后才能继续补全或导出。
|
||||
|
||||
## 输出
|
||||
|
||||
| 文件 | 内容 |
|
||||
| 路径 | 内容与用途 |
|
||||
| --- | --- |
|
||||
| `annotated.png` | 原尺寸角色图,各候选部件用不同半透明颜色叠加,透明背景显示为白色 |
|
||||
| `parts-sheet.png` | 白底拆解图,部件保持原尺寸、分开排布,并标注 ID 和颜色 |
|
||||
| `parts/<id>.png` | 紧裁剪的 RGBA 部件,保留原图像素及 Alpha |
|
||||
| `masks/<id>.png` | 原图尺寸黑白 mask,已裁掉 Alpha 背景 |
|
||||
| `candidates/<id>-raw.png` | 选中的 SAM 原始 mask,裁掉背景前 |
|
||||
| `unassigned-mask.png` | 白色表示没有被任何部件 mask 覆盖的角色像素 |
|
||||
| `overlap-mask.png` | 白色表示被多个部件 mask 覆盖的像素 |
|
||||
| `segmentation.json` | 裁剪坐标、拆解图坐标、颜色、质量指标、运行环境和模型加载信息 |
|
||||
| `candidate-diagnostics.json` | 两种提示的候选分数、排序、拒绝原因及最终选择 |
|
||||
| `report.html` | 两张预览、部件链接、告警、漏分及重复检查 |
|
||||
| `worker.log` / `worker-error.json` | 子进程日志 / 失败诊断(发生错误时) |
|
||||
| `manifest.json` | 状态、输入/代码/权重/产物哈希,完成时记录子进程已退出 |
|
||||
| `source.png` / `semantic-parts.json` / `segmentation-prompts.json` | 输入副本,保留坐标与语义来源 |
|
||||
| `annotated.png` | 原尺寸原图 + 半透明彩色 mask,背景合成白色 |
|
||||
| `parts-sheet.png` | 原尺寸拆件分开排布的白底图,含 ID 与颜色标记 |
|
||||
| `parts/<id>.png` | 紧裁剪 RGBA 部件,保留原图像素 |
|
||||
| `masks/<id>.png` | 原画布尺寸的二值 mask,0/255,已裁掉 Alpha 背景 |
|
||||
| `candidates/<id>-raw.png` | 选中的原始 SAM mask,尚未裁 Alpha,用于越界诊断 |
|
||||
| `unassigned-mask.png` | 白色为没有任何部件覆盖的角色前景 |
|
||||
| `overlap-mask.png` | 白色为多个部件共同覆盖的区域 |
|
||||
| `segmentation.json` | 部件路径、crop_xyxy、sheet_xyxy、颜色、QA、跳过列表、覆盖率、运行环境、加载记录 |
|
||||
| `candidate-diagnostics.json` | 两种提示候选的分数、排序、拒绝原因和最终选择 |
|
||||
| `report.html` | 预览、部件链接、告警及漏分/重复复核 |
|
||||
| `worker.log` / `worker-error.json` | 日志 / 子进程错误诊断(失败时) |
|
||||
| `manifest.json` | 状态、输入/代码/权重/产物哈希;完成后 gpu_worker_exited=true |
|
||||
|
||||
`crop_xyxy` 使用原图坐标,右下角为开区间;`sheet_xyxy` 使用白底拆解图坐标。覆盖率是像素覆盖比例,不是准确率。
|
||||
`crop_xyxy` 为原图坐标,`sheet_xyxy` 为拆解图坐标,右下角均为开区间。第三阶段依赖全画布 masks,不以紧裁剪 parts 反推位置。
|
||||
|
||||
## 代码与验证记录
|
||||
当前质量基线是 `output/20260918-183532/sam`:32 个计划项中 10 个 hidden 跳过,22 个 mask,前景覆盖率约 83.3%,32719 像素未分配。图中 forearm_r/hand_r 存在衣料误分,前臂混入手部,上衣及袖子存在缺失。更早 `sombrero-sam31-v3` 为另一批 28 个 mask、约 67.18% 覆盖率,不能混用统计。真实 GPU 推理跑通不代表拆件可直接用于动画。
|
||||
|
||||
- [stages/segmentation-stage.mjs](../stages/segmentation-stage.mjs):输入校验、Conda 子进程、哈希、缓存、日志和失败处理。
|
||||
- [sam_runtime.py](../sam_runtime.py):环境探测和本地权重严格加载。
|
||||
- [sam_segment.py](../sam_segment.py):GPU 推理、两组候选选择和诊断。
|
||||
- [segmentation_outputs.py](../segmentation_outputs.py):mask QA、原像素拆件、两张预览和报告。
|
||||
- [tests/test_segmentation.py](../tests/test_segmentation.py):Alpha 越界、候选选择、提示完整性、像素保真和重叠/重复检查。
|
||||
## 8. 当前阶段可改进点说明
|
||||
|
||||
2026-09-18 实测 `output/sombrero-grounding-v2` → `output/sombrero-sam31-v3`:28 个部件返回 mask,严格加载 1130 个检测参数/缓冲张量;推理及渲染约 11.64 秒(不含环境探测和加载权重),PyTorch 峰值已分配显存约 4.97 GiB,结束后无 SAM 子进程。
|
||||
以下均为待实现或待验证的改进方向:
|
||||
|
||||
这组结果覆盖原图前景约 67.18%,仍有 64286 像素未覆盖、30569 像素重叠。`shin_left` 和 `foot_left` 的 mask IoU 约 0.843,实际都分到了鞋子;躯干及其他肢体也存在碎片或错分。文本候选对照未解决这些问题。这说明推理和输出链路已跑通,但当前旧语义计划与提示策略尚不能产出合格的最终拆件;需要修正部件粗框并继续验证提示及 mask 语义。
|
||||
|
||||
同日 `conda run --no-capture-output -n ai-spine npm test` 的 17 项测试全部通过(包括 Python 分割回归用例);真实产物 `--resume` 哈希校验复用通过。测试通过仅验证程序行为,不表示上述分割质量合格。
|
||||
|
||||
后续已接入[第三阶段部件补全](3-completion-stage.md)。该阶段直接读取本目录的 `source.png`、`semantic-parts.json`、`segmentation.json` 和全画布 `masks/`;保留本阶段的告警,不能通过生成隐藏纹理来修复错误的部件归属。
|
||||
- **输出仅色彩遮罩的完整角色图。** 在原画布上以各部件纯色展示分区,不叠加原图纹理;保留现有 annotated.png。需明确重叠显示顺序,将未分配区域单独标识,不能为了“完整”伪造已识别区域。
|
||||
- **可选的大模型去毛边。** 对每个通过部件归属复核的 SAM 拆件增加一次可选边缘清理,提供对应原图局部参考,约束修改范围,保存清理前后、mask 差异和坐标。默认保留原始拆件;清理不能冒充隐藏补全,也不能把重绘结果称为原像素。
|
||||
- **先修正语义误分。** 明确左右、隐藏状态和粗框,复核衣料/皮肤/手部归属;对明显错误、缺失或疑似重复输出阻断性状态,再进入补全。
|
||||
- **改善覆盖和边界。** 对未分配前景、过度重叠及大孔洞做定位复核;区分合理遮挡与分割缺口,避免一刀切强制所有 mask 互斥。
|
||||
- **重评补全需求。** 基于实际 mask 检查袖子、衣服等缺损,反馈第三阶段;不能仅沿用第一阶段 needs_completion。
|
||||
- **增加语义验收。** 模型分数、前景命中和覆盖率只作辅助;将原图、候选、最终 mask 并排复核,记录人工修正及来源。
|
||||
|
||||
+148
-104
@@ -1,149 +1,193 @@
|
||||
# 第三阶段:部件补全
|
||||
|
||||
本阶段处理第一阶段声明的 `occlusion_fill`、`joint_extension_parent`、`joint_extension_child`,读取第二阶段的可见 mask,为部件生成局部画布,调用图片编辑模型并合并受限的新增像素。原图已可见区域的 RGBA 像素始终从原图恢复,不使用模型重绘的版本。
|
||||
## 1. 阶段简介
|
||||
|
||||
使用 [AGENTS.md](../AGENTS.md) 规定的 Conda `ai-spine` 环境,不需要额外安装依赖。第三阶段几何处理使用本地 Python;图片生成通过现有中转站 `images/edits` 接口完成。
|
||||
读取 SAM 可见 mask,为需要遮挡补全或关节延伸的部件准备局部画布,调用中转站图片编辑模型,再将允许区域内的新增像素与原可见像素合并。Python 几何处理固定使用 Conda `ai-spine`;图片生成在远端完成,本阶段不加载本地 SAM。
|
||||
|
||||
切换 Tiantoken 中转站时,在命令中增加 `--config .\configs\tiantoken.json`,并删除示例中的 `--completion-model qwen-image-3.0`,或改为 `--completion-model gpt-image-2`。该配置读取独立的 `TIANTOKEN_BASE_URL` / `TIANTOKEN_API_KEY`,第三阶段默认 `gpt-image-2`。目前仅验证模型列表可访问,实际图片编辑能力尚未实测;`gpt-6-astra` 的 Responses 图片生成工具仍需另行适配。
|
||||
当前已实现准备、真实图片请求、离线候选导入、几何检查与透明补全部件输出。尚未输出使用补全部件组装的完整角色,尚未接入新管线 Spine 导出。几何通过仍为 `needs_review`,不能等同于部件可用。
|
||||
|
||||
## 命令
|
||||
## 2. 输入、输出与执行链路
|
||||
|
||||
在 PowerShell 中进入项目并激活环境:
|
||||
输入是第二阶段目录;输出是任务画布、候选、检查报告及通过几何检查的补全部件。
|
||||
|
||||
```text
|
||||
tools/model-check.mjs --stage completion --input-dir SAM目录
|
||||
→ stages/completion-stage.mjs 校验计划、mask 文件、参数及 Conda
|
||||
→ completion_geometry.py prepare
|
||||
筛选需求 → 计算允许区域 → 建立局部画布与编辑 mask
|
||||
→ prepare-only:保存任务和报告后结束
|
||||
→ 否则:串行请求 images/edits,或读取离线候选
|
||||
→ completion_geometry.py merge
|
||||
检查画布/前景/对齐 → 限制新增区域与连通性 → 恢复原可见像素
|
||||
→ 每部件选第一个通过几何检查的候选
|
||||
→ finalize 输出透明部件、原图坐标和报告
|
||||
```
|
||||
|
||||
任务必须同时满足:计划 `needs_completion=true`、非 hidden、有可见 SAM mask、允许新增区域非空。指定 `--part` 只缩小范围,不强制绕过筛选。分别记录 `NO_COMPLETION_NEEDED`、`NO_VISIBLE_SAM_MASK`、`NO_ALLOWED_EXTENSION`。
|
||||
|
||||
以 `output/20260918-183532/sam` 为例:32 个计划项中 10 个 hidden 没有 mask;22 个有 mask,其中 12 个进入补全。帽子、两袖、两眼、两眉、鼻、嘴、胡子这 10 个因第一阶段标记不需补全而跳过,没有重新由模型判断实际 mask 完整性。
|
||||
|
||||
## 3. 阶段执行命令示例及参数说明
|
||||
|
||||
以下命令在项目根目录执行;输入示例是已有实验,不代表其 mask 已合格。
|
||||
|
||||
```powershell
|
||||
Set-Location F:\Study\taonier\AI_spine
|
||||
conda activate ai-spine
|
||||
$runId = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||
```
|
||||
$samInput = ".\output\20260918-183532\sam"
|
||||
|
||||
只准备任务(离线、无需 API Key):
|
||||
|
||||
```powershell
|
||||
# 离线准备所有符合条件的任务,无需密钥
|
||||
node .\tools\model-check.mjs --stage completion `
|
||||
--input-dir .\output\sombrero-sam31-v3 `
|
||||
--out-dir ".\output\$runId-prepare" `
|
||||
--completion-model qwen-image-3.0 `
|
||||
--config .\configs\tiantoken.json `
|
||||
--input-dir $samInput `
|
||||
--out-dir ".\output\$runId\complete-prepare" `
|
||||
--prepare-only
|
||||
```
|
||||
|
||||
真正调用模型补全一个部件,需要 `.env` 中的中转站地址与密钥,会产生图片请求:
|
||||
|
||||
```powershell
|
||||
# 单部件真实图片编辑请求
|
||||
node .\tools\model-check.mjs --stage completion `
|
||||
--input-dir .\output\sombrero-sam31-v3 `
|
||||
--out-dir ".\output\$runId-complete-head" `
|
||||
--completion-model qwen-image-3.0 `
|
||||
--config .\configs\tiantoken.json `
|
||||
--input-dir $samInput `
|
||||
--out-dir ".\output\$runId\complete-head" `
|
||||
--completion-model gpt-image-2 `
|
||||
--part head
|
||||
```
|
||||
|
||||
`--part head --part neck` 指定多个部件。省略 `--part` 时处理所有可用且需要补全的部件,每个部件单独发出请求;当前模型配置 `n=1`。程序串行调用,沿用提供方的超时及显式 429/5xx 重试策略,超时/网络中断不自动重复生成。发生请求错误保留候选和诊断,停止后续部件。
|
||||
|
||||
离线导入已经生成的候选(无需 API Key):
|
||||
|
||||
```powershell
|
||||
# 所有符合条件的部件,逐部件请求模型
|
||||
node .\tools\model-check.mjs --stage completion `
|
||||
--input-dir .\output\sombrero-sam31-v3 `
|
||||
--out-dir ".\output\$runId-merge" `
|
||||
--part head `
|
||||
--candidates-dir .\completion-candidates
|
||||
--config .\configs\tiantoken.json `
|
||||
--input-dir $samInput `
|
||||
--out-dir ".\output\$runId\complete"
|
||||
```
|
||||
|
||||
候选文件名为 `completion-candidates/head.png`,必须与对应任务的局部画布尺寸、坐标完全一致。准备与合并必须使用相同输入、`--completion-size` 和 `--extension-radius`。缺失候选记为 `missing_candidate`,不会联网补发。可将先前任务保存的原始候选复制为 `ID.png`,离线检查它,避免重复计费。
|
||||
使用 Qwen 时改为 `--config .\configs\deepseek-qwen.json --completion-model qwen-image-3.0`,读取原中转配置。Tiantoken 配置第三阶段为 `gpt-image-2`,第一阶段的 `gpt-6-astra` 不是当前图片编辑接入的替代品;未实现 Astra Responses 图片生成工具链。
|
||||
|
||||
`--candidates-dir` 也支持直接指向旧补全输出目录:读取 `tasks/<id>/candidate-1.png`(亦支持 jpg/webp),不下载、不重新生成。程序先核对旧 manifest 中的源图、语义计划、SAM mask 哈希及画布/延展参数是否与本次一致;不同则拒绝复用。该模式只取每部件首张原候选。
|
||||
|
||||
### 返回尺寸与输入不一致时
|
||||
|
||||
`--completion-size` 控制局部画布,不能单靠提示词保证模型输出相同尺寸。修复后第三阶段会同时发送 multipart 参数 `size=画布宽x画布高`,默认 `1024x1024`,并在每部件 `request.json` 记录实际请求尺寸。配置中的 `completion.params.size` 若与画布不同会在调用前报错。[OpenAI 编辑接口的 size 参数](https://developers.openai.com/api/reference/cli/resources/images/methods/edit)有明确的输出尺寸含义,但中转站是否遵守仍以实测结果为准。
|
||||
|
||||
默认 `--candidate-size-policy strict` 仍拒绝尺寸不一致。已有候选可以使用 `uniform` 模式离线尝试恢复:仅允许相同宽高比的整张画布等比例缩放,再执行原有的颜色/位置、可见像素保留率、新增区域和连通性检查。不对物体单独缩放、不平移、不裁剪,也不放宽对齐阈值。原图和 SAM mask 始终不缩放。
|
||||
旧候选离线复检,不重新请求模型:
|
||||
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --stage completion `
|
||||
--config .\configs\tiantoken.json `
|
||||
--input-dir .\output\20260918-183532\sam `
|
||||
--input-dir $samInput `
|
||||
--candidates-dir .\output\20260918-183532\complete2_gpt `
|
||||
--out-dir ".\output\$runId-size-recheck" `
|
||||
--out-dir ".\output\$runId\complete-recheck" `
|
||||
--candidate-size-policy uniform
|
||||
```
|
||||
|
||||
该命令不请求图片模型。原始候选保留,缩放后的候选另存为 `merged-N-normalized.png`,QA 记录原始/目标尺寸、比例、重采样方法和告警。即便最终通过几何检查也仍需语义复核;如果模型同时重绘、放大或移动了部件,可能继续报 `VISIBLE_ALIGNMENT_MISMATCH`。
|
||||
仅测试图片编辑接口的独立探针:
|
||||
|
||||
2026-09-20 对 `complete2_gpt` 的 12 张原始候选实测:输入均为 1024×1024,输出为 1248×1248 或 1254×1254。旧请求未发送 size。离线 uniform 复查后 8 个通过几何检查、4 个因对齐不符或无有效新增像素拒绝;原始文件未覆盖,也没有重新请求生成。报告位于 `output/20260918-183532/complete2_gpt-size-recheck-v2/report.html`。22 项测试通过,含请求 size、等比例恢复后的像素保真、宽高比/偏移拒绝及旧任务输入匹配检查。显式 size 已通过请求构造测试,尚未再次付费验证中转站是否遵守。
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --stage completion `
|
||||
--config .\configs\tiantoken.json `
|
||||
--image .\output\20260918-183532\complete2_gpt\tasks\head\input.png `
|
||||
--prompt-file .\output\20260918-183532\complete2_gpt\tasks\head\prompt.txt `
|
||||
--out-dir ".\output\$runId\edit-probe"
|
||||
```
|
||||
|
||||
每个输出目录必须是新目录;`--resume` 仅复用已完整结束且输入、参数、源码和产物哈希一致的任务。准备模式与生成模式使用不同目录。失败任务不自动续发请求。
|
||||
探针只保存候选,不执行部件准备与几何验收,不能与 `--input-dir` 混用。
|
||||
|
||||
| 参数 | 作用 |
|
||||
| 参数 | 说明 |
|
||||
| --- | --- |
|
||||
| `--input-dir` | SAM 输出目录,必须含 `source.png`、v2 计划、`segmentation.json`、`masks/<id>.png` |
|
||||
| `--part ID` | 指定部件,可重复;省略时处理全部有补全需求的部件 |
|
||||
| `--prepare-only` | 只准备画布、区域与提示词,不请求图片模型 |
|
||||
| `--candidates-dir` | 离线读取 `ID.png` 或旧补全目录首张候选,与 prepare-only 互斥 |
|
||||
| `--candidate-size-policy` | strict(默认):严格尺寸一致;uniform:同宽高比缩放后重新检查 |
|
||||
| `--completion-size` | 方形局部画布边长,默认 1024,128~4096;不缩放原像素 |
|
||||
| `--extension-radius` | 新增区域距可见 mask 的最大距离,默认 32 像素,1~256 |
|
||||
| `--completion-model` | 图片模型原始 ID,当前示例使用 qwen-image-3.0 |
|
||||
| `--dry-run` | 检查输入文件、计划、参数和 Python 环境,不生成画布或请求模型 |
|
||||
| `--input-dir DIR` | 完整 SAM 输出目录,部件补全必需 |
|
||||
| `--out-dir DIR` | 独立新目录,准备与生成使用不同目录 |
|
||||
| `--part ID` | 可重复,ID 必须存在且不重复;省略时处理所有符合筛选条件的部件 |
|
||||
| `--prepare-only` | 只生成画布、区域、提示词和报告,不请求模型 |
|
||||
| `--candidates-dir DIR` | 离线导入候选,与 prepare-only 互斥 |
|
||||
| `--completion-size N` | 方形画布边长,默认 1024,整数 128~4096;原像素不缩放 |
|
||||
| `--extension-radius N` | 轮廓延展距离与关节圆盘半径,默认 32,整数 1~256 |
|
||||
| `--candidate-size-policy NAME` | strict 默认拒绝尺寸不符;uniform 允许同宽高比整画布缩放后复检 |
|
||||
| `--completion-model ID` | 图片模型 ID,原样发送 |
|
||||
| `--config FILE` / `--env-file FILE` | 默认 astra-qwen.json / 项目 .env;shell 同名变量优先 |
|
||||
| `--python FILE` | 仅允许 ai-spine 解释器 |
|
||||
| `--dry-run` | 检查输入文件、计划、参数和 Python 基础环境,不准备画布或请求模型;完整像素级 mask 校验在 prepare 中执行 |
|
||||
| `--resume` | 仅复用已完成、输入/配置/源码/产物一致的任务,不自动续发失败请求 |
|
||||
| `--image FILE` / `--prompt-file FILE` | 仅用于探针:PNG 图片 / 文本提示词;多次 image 需配置多图能力 |
|
||||
| `--mask FILE` | 仅用于探针:透明处可编辑的 RGBA PNG,需配置 mask 能力 |
|
||||
|
||||
旧的 `--stage completion --image ... --prompt-file ...` 保留为独立接口探针,不能与 `--input-dir` 混用。`--stop-after` 目前仍只支持 understand/segment;第三阶段独立调用。
|
||||
配置中默认 `n=1`,逐部件串行调用。明确的 429/5xx 有限重试,超时/断网不自动重试;请求失败保留诊断并停止后续部件,几何拒绝会记录结果并继续。`--stop-after` 不支持 completion。
|
||||
|
||||
## 允许新增区域
|
||||
## 4. 输入格式要求
|
||||
|
||||
候选不可以随意扩大部件。程序在原图坐标中构造以下区域,并始终排除原可见 mask:
|
||||
|
||||
- 遮挡补全:可见轮廓外 `extension-radius` 范围,与 `occluded_by` 指向的 SAM mask 的交集。
|
||||
- 向父关节延展:同一距离范围,与本部件 `pivot_norm` 附近半径为 `extension-radius` 的圆盘的交集。
|
||||
- 向子关节延展:同一距离范围,与直接子骨骼部件的 pivot 圆盘的交集。
|
||||
|
||||
这些是保守的几何候选区域,不是推断出的完整隐藏形状。缺少遮挡 mask、关节过远或没有子骨骼时,相应区域为空并记录告警。所有区域都为空时跳过该部件。完全隐藏或没有可见 SAM mask 的部件也跳过,不凭空生成完整肢体。
|
||||
|
||||
局部画布包含可见区域与允许新增区域,至少留 16 像素边距。`origin_xy` 记录局部左上角在原图中的坐标,可为负数;只有平移和补透明边,不进行缩放。所需范围放不下时失败,需增大画布。新增区域目前限定在原图画布范围内。
|
||||
|
||||
输入给模型的是白底可见部件。只有配置明确声明 `capabilities.mask=true` 时才发送 RGBA 编辑 mask(透明处可编辑);只有 `multiple_images=true` 时才发送第二张局部原图参考。默认配置二者均为 false,不假定中转站支持这些能力。无论是否发送编辑 mask,返回候选都经过本地允许区域约束。
|
||||
|
||||
## 返回候选的检查和合并
|
||||
|
||||
1. 默认要求尺寸与局部画布完全一致。显式选择 uniform 时,只对同宽高比候选做整画布等比例恢复;宽高比不同仍拒绝。所有模式都不自动重定位或裁切。
|
||||
2. 已有透明背景保留;不透明白底使用边界连通近白区域去底。无法提取前景则拒绝。
|
||||
3. 使用原部件 Alpha ≥240 的像素检查对齐:候选保留率至少 95%,RGB 平均绝对误差不大于 30。无不透明锚点则拒绝。这只能发现明显偏移或重绘,不能保证语义正确。
|
||||
4. 只保留允许区域中的新增像素,并去掉与原可见部分不连通的新增块。越界和不连通像素数量写入 QA。没有新增像素则拒绝。
|
||||
5. 原可见 mask 内 RGBA 逐像素恢复;候选仅提供新增像素。记录各补全子区域新增数量及 `unfulfilled_regions`,存在空缺的要求不会冒充已完成。
|
||||
6. 每个返回候选分别检查,选择第一个通过几何条件的候选。输出始终 `semantic_verified=false`、`quality_status=needs_review`。
|
||||
|
||||
上游 SAM mask 有碎片、重复或语义错分时会原样影响补全,告警保存在 JSON 和报告中。颜色/位置检查也不能验证隐藏纹理是否合理。白底去除可能影响贴边白色细节,仍需人工检查。
|
||||
|
||||
## 产物
|
||||
|
||||
| 路径 | 内容 |
|
||||
| 输入 | 要求 |
|
||||
| --- | --- |
|
||||
| `completion-plan.json` | 所有已准备任务、区域及跳过原因 |
|
||||
| `tasks/<id>/input.png` | 发给模型的白底局部部件 |
|
||||
| `tasks/<id>/visible.png` | 从原图保存的 RGBA 可见部件,合并时恢复像素 |
|
||||
| `tasks/<id>/context.png` | 同坐标局部原图参考 |
|
||||
| `tasks/<id>/edit-mask.png` | RGBA 编辑 mask,透明处允许编辑 |
|
||||
| `tasks/<id>/allowed-mask.png` | 白色表示允许新增像素的区域 |
|
||||
| `tasks/<id>/<补全字段>.png` | 三种补全要求各自的允许区域 |
|
||||
| `tasks/<id>/task.json` / `prompt.txt` | 坐标、补全需求、上游告警 / 实际提示词 |
|
||||
| `tasks/<id>/candidate-N.*` | 模型或离线导入的原始候选,拒绝时也保留 |
|
||||
| `tasks/<id>/qa-N.json` | 单候选检查结果与拒绝原因 |
|
||||
| `tasks/<id>/merged-N.png` | 通过几何检查后的局部 RGBA,已恢复可见像素 |
|
||||
| `parts/<id>.png` | 被选中的补全候选,紧裁剪透明 PNG |
|
||||
| `completion-result.json` | 每部件状态、候选 QA、原图裁剪坐标和输出路径 |
|
||||
| `report.html` | 原可见部件、允许新增区域、补全候选和告警 |
|
||||
| `manifest.json` | 运行模式、网络请求标记、输入/代码/产物哈希及计数 |
|
||||
| `source.png` | 原画布 PNG,使用第二阶段的 RGBA 原图 |
|
||||
| `semantic-parts.json` | 有效 v2 计划;部件分类、遮挡、pivot 和补全需求合法 |
|
||||
| `segmentation.json` | parts 数组,ID 唯一且存在于计划中 |
|
||||
| `masks/<id>.png` | segmentation.parts 中每个 ID 都必须有文件;原画布尺寸,灰度值仅 0/255,非空,不覆盖原图 Alpha=0 区域 |
|
||||
| 中转配置 | 在线模式需地址、密钥、images-edits 提供方及图片模型;prepare-only/离线导入无需密钥 |
|
||||
|
||||
`parts/` 只包含本次被选中且通过几何检查的补全部件。无需补全、未选中和被拒绝的部件不会被伪装成新补全结果;最终组装需结合原 SAM 部件及这里的替换文件。Spine 导出尚未接入。
|
||||
只提供 SAM 的 `parts/` 或白底拆解图不满足要求。输入目录中无需存在 annotated.png 才能运行,但建议先通过报告复核语义。
|
||||
|
||||
## 实现和验证
|
||||
离线候选支持两种形式:
|
||||
|
||||
[stages/completion-stage.mjs](../stages/completion-stage.mjs) 调度准备、请求、候选检查及缓存;[completion_geometry.py](../completion_geometry.py) 实现区域构造、Alpha 提取、原像素恢复和报告;[providers/image-edits.mjs](../providers/image-edits.mjs) 复用现有图片接口。
|
||||
- 平铺目录:`<id>.png`,必须对应本次局部画布坐标、尺寸与部件;平铺文件没有旧任务 manifest 可自动核对,需自行保证一致。
|
||||
- 旧补全目录:含 manifest 和 `tasks/<id>/candidate-1.png`,也支持 jpg/webp;逐项核对源图、计划、segmentation.json、全部 mask 哈希以及画布/延展参数。每部件只取首张候选。缺失记为 missing_candidate,不联网补发。
|
||||
|
||||
测试覆盖原尺寸坐标映射、Alpha 保真、三个补全字段、越界裁剪、尺寸/位移/空白候选拒绝、离线模式、显式多图与 mask 能力、错误诊断和缓存失效。使用 `conda run --no-capture-output -n ai-spine npm test` 执行,不调用真实付费模型。
|
||||
不同原图、mask 或参数的候选不能混用。尺寸之外,部件位置、朝向、比例也必须保持一致。
|
||||
|
||||
最初接入时,sombrero-sam31-v3 输出可离线准备 17 个补全任务,11 个部件因无需补全而跳过。当时验证了真实输入的画布准备与 mock 编辑响应的完整合并链路,尚未执行真实 Qwen 图片生成。
|
||||
## 5. 执行链路中重要部分代码文件及原理说明(包括重点说明)
|
||||
|
||||
本轮验证结果:22 项 Node 测试通过(其中包含 7 个 Python 补全用例),真实输入的 `--prepare-only` 和 `--resume` 均成功。准备产物位于 `output/sombrero-completion-prepared-v2/`,打开其中 `report.html` 可检查每个部件的画布与允许新增区域。
|
||||
**允许区域。** `completion_geometry.py::allowed_regions()` 先计算可见 mask 外、距轮廓不超过 extension-radius 的区域,再分别与以下区域取交集:遮挡补全用 occluded_by 的 mask 并集;父关节延展用本部件 pivot 周围圆盘;子关节延展用直接子骨骼部件 pivot 圆盘。始终排除原可见 mask,新增范围限制在原图画布内。它是保守几何范围,不是完整隐藏形状推断。
|
||||
|
||||
2026-09-20 用户运行 `output/20260918-183532/sam` 的补全任务时,head 的真实响应同时含有有效 `url` 和空字符串 `b64_json`。原解码器将空字符串误当图片,报“不支持的 PNG/JPEG/WebP 格式”。已修复为空值时使用 URL 下载,并覆盖空串、空白字符串及 null 的回归测试;22 项测试通过。
|
||||
**局部坐标。** `prepare()` 将可见区和允许区居中放入方形画布,至少留 16 像素边距,只平移和补边。`origin_xy` 是局部左上角在原图的位置,可为负数;原图位置=局部位置+origin。放不下时失败,不能偷偷缩放原像素。
|
||||
|
||||
本次已从保存的 `complete/tasks/head/response.raw.json` 下载原生成结果,没有再次调用生成接口。图片保存在同级 `complete-recovered-candidates/head.png`。真实输出为 2048×2048,输入画布为 1024×1024,因此离线合并被 `CANVAS_SIZE_MISMATCH` 拒绝,报告位于 `complete-recovered-head-check/report.html`。这次格式解析问题已解决,但尺寸约束尚未通过;不能把已有 1024 输入任务的候选直接改用 `--completion-size 2048` 合并,因为新画布的像素坐标也会变化。
|
||||
**重点:当前实际发送什么。** `stages/completion-stage.mjs` 默认只发送白底 `input.png`。三个现有配置均为 `multiple_images=false`、`mask=false`,因此本地生成 context.png 和 edit-mask.png 不意味着发给模型。只有开启并验证对应能力后,分支才发送第二张同坐标局部原图参考和编辑遮罩;当前没有独立全角色参考图输入。文字边界说明及返回后的区域裁剪不能替代模型侧遮罩约束。
|
||||
|
||||
**图片解码与尺寸。** `providers/image-edits.mjs` 使用 multipart images/edits,支持非空 b64_json 或返回 URL 下载;空 b64_json 会回退有效 URL。当前部件请求显式发送 size=画布宽x高,并写入 request.json;配置 params.size 冲突会报错。strict 模式拒绝 CANVAS_SIZE_MISMATCH;uniform 仅将同宽高比整画布 LANCZOS 缩放到目标尺寸,保留原候选,不平移、不裁剪、不单独缩放物体,也不改变原图/mask。
|
||||
|
||||
**几何验收与合并。** `merge_candidate()` 去除边界连通白底,在原部件 Alpha≥240 的像素处检查 RGB 平均绝对误差≤30、可见保留率≥95%;无不透明锚点拒绝。只取允许区域内且与原部件连通的新增像素,没有有效新增即拒绝。通过后逐像素恢复原可见 RGBA,模型只提供新增部分。
|
||||
|
||||
**重点:验收仍有缺口。** `unfulfilled_regions` 记录未补到的子区域,但当前不是硬性拒绝条件;某一区域新增少量像素也不代表关节补够。语义、接缝、材质、运动露底没有自动验收。错误 SAM 像素会被原样恢复;若头部 mask 已含眼睛/胡子,当前规则也不能清除这些内部附件生成干净脸底。
|
||||
|
||||
## 6. 各个代码文件职责索引
|
||||
|
||||
| 文件 | 职责 |
|
||||
| --- | --- |
|
||||
| [tools/model-check.mjs](../tools/model-check.mjs) | 部件补全与独立探针分发、参数互斥检查 |
|
||||
| [stages/completion-stage.mjs](../stages/completion-stage.mjs) | 输入指纹、准备、串行请求/离线读取、候选选择、状态留档 |
|
||||
| [completion_geometry.py](../completion_geometry.py) | allowed_regions、prepare、merge_candidate、finalize 与报告 |
|
||||
| [normalize_reference.py](../normalize_reference.py) | 候选 Alpha 保留、边界连通白底提取 |
|
||||
| [providers/image-edits.mjs](../providers/image-edits.mjs) | multipart 编辑请求、能力检查、Base64/URL 图片解码 |
|
||||
| [providers/http.mjs](../providers/http.mjs) | HTTP、超时、重试、诊断和脱敏 |
|
||||
| [stages/model-stage.mjs](../stages/model-stage.mjs) | runCompletionProbe,仅验证编辑接口 |
|
||||
| [lib/config.mjs](../lib/config.mjs) / [lib/images.mjs](../lib/images.mjs) | 提供方、模型与能力配置 / 图片格式、尺寸和哈希 |
|
||||
| [lib/python-runtime.mjs](../lib/python-runtime.mjs) / [lib/validate-parts.mjs](../lib/validate-parts.mjs) | Conda 检查 / v2 结构校验 |
|
||||
| [lib/run-artifacts.mjs](../lib/run-artifacts.mjs) | 输出目录、复用、状态和产物哈希 |
|
||||
| [prompts/complete-v1.txt](../prompts/complete-v1.txt) | 保持姿势、尺寸、可见纹理与隐藏区域补全约束 |
|
||||
| [Tiantoken](../configs/tiantoken.json)、[DeepSeek/Qwen](../configs/deepseek-qwen.json)、[Astra/Qwen](../configs/astra-qwen.json) 配置 | 图片模型、认证变量、请求参数与能力开关 |
|
||||
| [tests/completion-stage.test.mjs](../tests/completion-stage.test.mjs) / [tests/test_completion.py](../tests/test_completion.py) | mock 编辑、离线复用、尺寸/对齐拒绝、像素保真与区域回归 |
|
||||
| [tests/model-stages.test.mjs](../tests/model-stages.test.mjs) | 提供方与探针相关回归 |
|
||||
|
||||
## 7. 产物详细说明
|
||||
|
||||
| 路径 | 内容与用途 |
|
||||
| --- | --- |
|
||||
| `source.png`、`semantic-parts.json`、`segmentation.json`、`masks/` | 输入快照,用于复现与离线候选身份核对 |
|
||||
| `completion-plan.json` | 准备任务、允许区域、参数和跳过原因 |
|
||||
| `tasks/<id>/input.png` | 白底局部可见部件,默认唯一模型输入图 |
|
||||
| `tasks/<id>/visible.png` | 原图可见 RGBA,合并时恢复像素 |
|
||||
| `tasks/<id>/context.png` | 同坐标局部原图参考,当前默认不发送 |
|
||||
| `tasks/<id>/edit-mask.png` | RGBA 编辑遮罩,透明处可编辑,当前默认不发送 |
|
||||
| `tasks/<id>/allowed-mask.png` | 白色表示允许新增区域 |
|
||||
| `tasks/<id>/<补全字段>.png` | 启用的补全子区域 mask |
|
||||
| `tasks/<id>/task.json` / `prompt.txt` | origin、区域、需求和告警 / 实际提示词 |
|
||||
| `tasks/<id>/request.json` | 在线请求模型、图片哈希、是否发送 mask;修复后含 size |
|
||||
| `tasks/<id>/response.raw.json` / `request-metadata.json` | 在线响应留档 / 请求 ID、耗时等元数据 |
|
||||
| `tasks/<id>/response.error.json` | 可获取时保存的脱敏请求失败诊断 |
|
||||
| `tasks/<id>/candidate-N.*` | 模型或离线导入的原始候选,拒绝也保留 |
|
||||
| `tasks/<id>/merged-N-normalized.png` | uniform 实际重采样时保存的候选;不代表通过 |
|
||||
| `tasks/<id>/qa-N.json` | 尺寸、对齐、新增/丢弃像素、各区域完成情况、拒绝原因 |
|
||||
| `tasks/<id>/merged-N.png` | 通过几何检查且恢复原可见像素后的局部 RGBA |
|
||||
| `parts/<id>.png` | 每部件选中结果的紧裁剪透明 PNG |
|
||||
| `completion-result.json` | 每部件状态、候选 QA、原图 crop_xyxy 和路径 |
|
||||
| `report.html` / `manifest.json` | 人工检查页 / 模式、网络标记、状态、输入/代码/产物哈希 |
|
||||
|
||||
parts/ 只含本次选中且通过检查的补全部件,不是全部 SAM 部件集合。无需补全、失败和未选中的部件不会自动复制进来,也没有完整角色组装图。
|
||||
|
||||
当前实验:`output/20260918-183532/complete2_gpt` 已真实请求 Tiantoken gpt-image-2 共 12 个部件。旧请求未传 size,返回 1248/1254 方形图,预期为 1024,全部严格尺寸拒绝。`complete2_gpt-size-recheck-v2` 离线复用原候选后,8 个几何通过;head、pants_thigh_l、pants_thigh_r、shoe_l 共 4 个因对齐或无有效新增拒绝。通过项中仍有衣料误分、错误手部和未补全子区域。显式 size 的请求构造已验证,但尚无修复后中转遵守 size 的新实测结论。
|
||||
|
||||
## 8. 当前阶段可改进点说明
|
||||
|
||||
- **补全后输出使用补全部件的完整角色。** 按原图坐标和遮挡顺序组装,复用无需补全的原拆件,明确标记失败项及回退来源;输出补全前后对比、接缝/重叠诊断。不能只展示少数 parts 文件作为完整结果。
|
||||
- **把原图或部件相关原图区域交给补全模型参考。** 接入并实测全角色/局部上下文参考和编辑 mask,记录实际发送内容。不能仅把 capabilities 改为 true 就宣称中转支持;需验证图片顺序、mask 语义、返回尺寸和画面保持能力。
|
||||
- **根据 SAM 实际结果重建需求。** 区分分割缺口修复、遮挡补全、关节延伸、附件底图清理;对应建立保留区域与可编辑区域,避免误分像素被永久保护。
|
||||
- **改进画布与补全区域。** 固定 32 像素不适配所有部件;小部件在 1024 大白底中占比低。可验证按部件设计区域、显式局部放大并记录逆变换,保证回贴坐标可检查。
|
||||
- **加强验收。** 对必需区域定义有效覆盖要求,增加部件语义、接缝、材质、回贴和关节旋转露底检查;不能放宽阈值来掩盖重绘、位移或错误输入。
|
||||
- **按小样验证后批量。** 先修正 SAM 输入,再用头、前臂、上衣验证参考图与遮罩,比较原输入、原候选、合并图和回贴图,确认改善后再跑全量。
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
# 第一阶段:可替换模型接口与角色结构理解
|
||||
|
||||
本轮实现结构理解、图片编辑适配器、结构 JSON 校验、Alpha 几何校验、候选种子、诊断预览和实验缓存。几何层需要 Python 与 requirements.txt,不运行旧的“拆件图 → SIFT 定位”流程。
|
||||
|
||||
结构理解支持停在 `understand`,也可通过 `--stop-after segment` 接续本地 SAM 分割,或使用 `--stage segmentation --input-dir` 独立执行第二阶段。第三阶段使用 `--stage completion --input-dir SAM目录` 完成部件画布准备、候选生成、限制新增区域和原像素恢复,详见[第三阶段文档](3-completion-stage.md)。掩码语义修正、补全的语义验收和 Spine 骨骼导出尚未完成。旧的 `--image --prompt-file` 图片编辑探针仍只保存原始候选。
|
||||
|
||||
## 环境与模型
|
||||
|
||||
要求 Node.js 20 或更高版本,无新增 npm 依赖。在 `AI_spine` 目录、已激活的 `ai-spine` Conda 环境中运行。每次修改须遵守 [AGENTS.md](../AGENTS.md)。
|
||||
|
||||
复用现有 `.env` 的地址和密钥,可增加:
|
||||
|
||||
```dotenv
|
||||
SPINE_UNDERSTANDING_MODEL=gpt-6-astra
|
||||
SPINE_COMPLETION_MODEL=qwen-image-3.0
|
||||
SAM_MODEL_DIR=F:/Study/SAM3
|
||||
```
|
||||
|
||||
不配置这三项时,`configs/astra-qwen.json` 已提供相同默认值。不会自动改写用户的 `.env`。
|
||||
|
||||
查询中转站模型 ID(只读取列表,不调用生成):
|
||||
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --list-models
|
||||
```
|
||||
|
||||
模型展示名不等于 API ID。2026-09-17 的本机接口查询包含 `gpt-6-astra` 和 `qwen-image-3.0`。支持列表不保证所有端点/多图/mask 参数可用,需要分别验证。
|
||||
|
||||
本地配置检查(不联网,不生成图片):
|
||||
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --dry-run
|
||||
```
|
||||
|
||||
## 运行结构理解
|
||||
|
||||
```powershell
|
||||
node .\pipeline.mjs --mode annotated-parts --reference ..\spine-animation-ai\demo\character_reference.png --out-dir .\output\sombrero-astra --stop-after understand
|
||||
```
|
||||
|
||||
首次调用会向配置的中转站发送参考图。每个实验使用新输出目录;本轮不会自动覆盖旧产物。
|
||||
|
||||
切换理解模型:
|
||||
|
||||
```powershell
|
||||
node .\pipeline.mjs --mode annotated-parts --reference ..\spine-animation-ai\demo\character_reference.png --out-dir .\output\sombrero-other --understanding-model YOUR_EXACT_MODEL_ID --stop-after understand
|
||||
```
|
||||
|
||||
切换协议(需中转站实际支持):
|
||||
|
||||
```powershell
|
||||
node .\pipeline.mjs --mode annotated-parts --reference ..\spine-animation-ai\demo\character_reference.png --out-dir .\output\sombrero-responses --understanding-protocol responses --stop-after understand
|
||||
```
|
||||
|
||||
协议可选 `chat-completions` / `responses`,默认 `responses`:本机中转站实测 Astra 的 codex channel 明确拒绝 `/v1/chat/completions`。输出模式默认 `text-json`:在提示词中提供 Schema,并始终在本地严格校验。显式确认中转站支持后,可使用 `--output-mode json-object` 或 `--output-mode json-schema`。不会因 400/不支持的协议自动换模型或偷偷降低输出约束。
|
||||
|
||||
该 Astra 通道还要求 `stream=true`,所以默认配置启用流式 Responses,并设置 `store=false`。适配器收集 SSE 后只接受完整的终止事件,输出仍是普通 JSON 文件。新模型可在阶段配置中设置 `stream: false`。`response.raw.json` 对 SSE 保存终止事件中的 response 对象,非逐字节 SSE 日志;`request-metadata.json` 记录 wire_format。
|
||||
|
||||
切换到非流式 Chat Completions 模型时可使用 `--understanding-protocol chat-completions --stream false`,不会沿用 Astra 的流式设置。
|
||||
|
||||
项目同时提供 `configs/deepseek-qwen.json`。它把第一阶段固定为
|
||||
`deepseek-flash + chat-completions + stream=false`,第三阶段仍使用
|
||||
`qwen-image-3.0`,适合与默认的 `configs/astra-qwen.json` 做对照实验:
|
||||
|
||||
```powershell
|
||||
node .\pipeline.mjs --mode annotated-parts `
|
||||
--config .\configs\deepseek-qwen.json `
|
||||
--reference ..\spine-animation-ai\demo\character_reference.png `
|
||||
--out-dir .\output\sombrero-understand-deepseek `
|
||||
--stop-after understand
|
||||
```
|
||||
|
||||
主要产物:
|
||||
|
||||
| 文件 | 含义 |
|
||||
| --- | --- |
|
||||
| `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` | 字段、坐标、引用、父子环和遮挡环校验结果 |
|
||||
| `response.raw.json` / `response.txt` | 原始服务端响应 / 提取的文本 |
|
||||
| `prompt.txt` / `request.json` | 提示词 / 请求设置与输入哈希;图片内容单独保存在 source.png |
|
||||
| `request-metadata.json` | requested/returned model、request ID、usage、耗时和请求次数 |
|
||||
| `manifest.json` | 运行状态、配置、代码版本、源文件哈希和产物哈希 |
|
||||
|
||||
`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 或分割模型出错。
|
||||
|
||||
## 独立测试图片编辑接口
|
||||
|
||||
先准备一个局部部件 PNG 和任务文本 `task.txt`,例如:
|
||||
|
||||
```text
|
||||
The input canvas contains the screen-left forearm. Complete the hidden elbow
|
||||
connection behind the sleeve. Keep the visible hand and forearm in their exact
|
||||
positions. Preserve the original outline and shading. Do not add other parts.
|
||||
```
|
||||
|
||||
调用 Qwen:
|
||||
|
||||
```powershell
|
||||
node .\tools\model-check.mjs --stage completion --image .\local-part.png --prompt-file .\task.txt --out-dir .\output\qwen-edit-test --completion-model qwen-image-3.0
|
||||
```
|
||||
|
||||
改 `--completion-model` 即可对比另一个兼容的图片编辑模型。此命令直接调用图片接口并可能计费,不调用结构理解。
|
||||
|
||||
结果保存 `candidate-1.png`(或服务端实际返回的 JPEG/WebP 扩展名)、输入图、任务提示词、原始响应和运行记录。PNG 输出会记录是否与输入画布同尺寸;尺寸相同不代表内容对齐。
|
||||
|
||||
默认图片适配器只发送一张图。若中转站确认支持多图,在配置中启用 `capabilities.multiple_images`,并使用重复 `--image`:第一张是局部画布,其余是原图/标注图参考。字段名通过 `image_field` 选择 `image` 或 `image[]`。
|
||||
|
||||
若确认支持编辑 mask,再启用 `capabilities.mask` 并使用 `--mask edit-mask.png`。当前适配器约定透明像素可编辑,要求 mask 与第一张图同尺寸、包含 alpha 通道。SAM 的普通黑白 mask 不能直接当作编辑 alpha mask。未启用能力时参数会明确报错,不静默忽略。
|
||||
|
||||
本轮没有恢复原始可见像素,也没有生成隐藏区域的透明掩码;因此候选始终标记 `raw_completion_probe` 和 `needs_review`,不能直接接入最终 atlas。
|
||||
|
||||
## 配置与切换规则
|
||||
|
||||
`configs/astra-qwen.json` 分离 `providers` 和 `stages`:
|
||||
|
||||
- provider:协议、base URL/key 的环境变量名、超时、重试次数、多图和 mask 声明。
|
||||
- stage:provider 名称、模型、提示词文件、输出模式和模型特定参数。
|
||||
- 提示词路径相对于配置 JSON 所在目录解析;命令行输入/输出路径相对于当前目录。
|
||||
- 模型优先级:CLI > 阶段显式 `model` > `model_env` 环境变量 > `default_model`。
|
||||
- shell 环境覆盖 `.env`。实验 JSON 不应存放密钥,仅引用密钥环境变量名。
|
||||
- 不同服务可配置各自的 base URL/key 环境变量。
|
||||
- 模型 ID 原样发送,不再把 `gpt-image-2.5` 映射成其他模型。
|
||||
- `params` 允许模型特定参数,但不能覆盖 model、prompt、messages、input 等适配器保留字段。
|
||||
- 新模式的超时/重试来自 provider 配置;旧模式的图片超时仍用 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`。
|
||||
|
||||
例如把理解阶段改为固定模型:
|
||||
|
||||
```json
|
||||
{
|
||||
"provider": "relay-vision",
|
||||
"model": "YOUR_EXACT_MODEL_ID",
|
||||
"prompt": "../prompts/understand-v1.txt",
|
||||
"output_mode": "text-json",
|
||||
"params": {}
|
||||
}
|
||||
```
|
||||
|
||||
## 重跑与对比
|
||||
|
||||
同一命令增加 `--resume`,仅当上次完整结束,且模型、协议、参数、提示词、Schema、源图、适配器代码和所有产物校验一致时复用。模型变化时要求新的输出目录,防止覆盖对照组。失败任务也保留原目录,使用新目录重跑。
|
||||
|
||||
理解、SAM、部件补全和补全探针各自记录独立缓存。SAM 额外校验输入计划、候选提示、本地源码和权重哈希;部件补全校验语义计划、所有输入 mask、画布参数、源码及离线候选哈希。对比补全模型时,固定相同局部画布、任务文本与掩码。
|
||||
|
||||
显式 429/5xx 最多按配置重试,超时或网络断开不自动重试,因为服务端可能已经执行任务。完整请求不保证模型内容可复现;seed 只在提供方确认支持时放入 params,usage 不存在时记录 null,不估造价格或 token 数。
|
||||
|
||||
## SAM 路径
|
||||
|
||||
默认根目录 `F:/Study/SAM3`:源码位于 `sam3/`,权重位于 `sam3.1checkpoint/sam3.1_multiplex.pt`。可通过 `--sam-dir`、`--sam-code-dir`、`--sam-checkpoint` 覆盖。独立分割无需中转站凭据,在 `ai-spine` Conda 临时子进程加载 GPU 模型,结束即退出。命令、权重适配及当前质量限制见[第二阶段文档](2-segmentation-stage.md)。
|
||||
|
||||
## 测试
|
||||
|
||||
```powershell
|
||||
conda run -n ai-spine npm test
|
||||
```
|
||||
|
||||
测试使用本地 mock HTTP 服务或注入响应,不调用真实付费模型。覆盖模型优先级、协议请求/响应、multipart、能力限制、数值/引用/环校验、错误响应、重试、缓存和 CLI 全链路。
|
||||
|
||||
2026-09-17 的集成检查:模型列表请求成功;Astra 要求 Responses + stream=true,切换后服务端返回 overloaded,尚未得到成功的真实角色标注。Qwen 适配器通过 mock 请求/响应测试,本轮未执行真实图片编辑生成。此状态不等于视觉质量已验证。
|
||||
Reference in New Issue
Block a user