sprite-gen帧提取内部原理:Cell模型、连通分量与Manifest契约设计
【免费下载链接】sprite-genGenerate clean 2D game sprites & animation atlases — component-row pipeline: state rows, alpha cleanup, frame extraction, runtime atlases. Codex/Claude skill.项目地址: https://gitcode.com/gh_mirrors/sp/sprite-gen
sprite-gen 是一个把单张 AI 生成图变成干净透明 2D 游戏精灵帧与动画雪碧图的组件行流水线工具。本文拆解它最核心的帧提取(extract)阶段:一个cell对象如何驱动三个阶段、连通分量算法如何把一条横向生成条带切成 N 帧透明精灵,以及frames-manifest.json背后的契约式设计——读完你会明白为什么这条流水线"要么完整成功,要么原样保留旧结果"。
🧩 帧提取在流水线中的位置
sprite-gen 的图集流水线只有一处 AI 步骤(每个状态一条生成条带),之后的extract → compose全部是确定性计算:同样输入永远得到同样输出。
| 阶段 | 输入 | 输出 |
|---|---|---|
prepare | 角色基图 + 请求参数 | sprite-request.json+ 逐状态布局指引 |
gen | 提示词 + 参考图 | raw/<state>.png条带(唯一 AI 产物) |
extract | raw/<state>.png | frames/<state>/frame-N.png+frames-manifest.json |
compose-atlas | frames/ | 运行时图集 +manifest.json |
阶段 I/O 的完整契约见 docs/run-contract.md,代码域划分见 docs/architecture.md。提取阶段的核心源码在 sprite_gen/frames/extract.py,融合姿态的可选分割算法在 sprite_gen/frames/segment.py。
📐 Cell 模型:一个 cell 对象驱动三个阶段
sprite-request.json里只有一个cell对象(默认方形 256,可设为矩形),它同时驱动三处几何计算——这是整个工具最容易被误解、也最关键的设计:
- 生成期:布局指引按
frames × cell_width × cell_height绘制,提示词要求模型把条带当成"隐形帧槽"; - 提取期:
fit_to_cell()把每个提取出的姿态重新装入cell_width × cell_height的透明单元; - 图集期:
compose-atlas把每帧放进同尺寸槽位,雪碧图尺寸 =最大帧数×cell宽 × 状态数×cell高。
fit_to_cell的关键性质是基于内容而非槽位:它先裁掉内容 bbox,再按比例缩放(scale = min(...) ≤ 1.0,只缩小不放大),最后按align_x(默认foot-centroid,锚定脚部重心,避免长发飘尾把身体拉偏)和align_y(默认bottom,双脚钉在共享基线上)摆放进 cell。完整实现见 extract.py 的 fit_to_cell,设计说明见 architecture.md 第 4 节。
🎨 色键去背:从硬切到软 alpha 的四级链
提取的第一步remove_chroma_background()并不是简单的"变透明"。它是一条四级链(默认--key-threshold 96):
- 背景色实测:模型画出的绿/品红往往不是纯键色,引擎先从画面四角和边框采样出"实际涂成的键色",双距离取小者参与硬切,避免整片背景残留;
- 硬切:颜色距离球内像素整体擦除;
- 软 alpha 解混:抗锯齿边缘是"主体×(1−k)+键色×k"的混合像素,引擎按混合模型反解出主体色与部分透明度——in-band 混合只处理距键 2 像素内的 AA 带,out-of-band 混合处理到
unmix_reach(默认 4); - 困色去溢:生成器常把键色"溢"进主体内部(红发里的绿色碎条),引擎用连通簇大小甄别——小簇是溢色,就地去色但保留 alpha;大簇是有意着色的材料,绝不碰。
可选的chroma.mode: "ycbcr"走色度平面抠图,容忍阴影键色和 JPEG 色度噪声。参数与诊断见 docs/chroma-alpha.md,核心函数入口在 remove_chroma_background。
🔗 连通分量:一条条带如何被切成 N 帧
去背完成后,条带上剩下若干互不相连的不透明"团块"。connected_components()对 alpha 通道做 4 连通洪水填充(alpha > 16 计为实体),记录每个团块的pixels / area / bbox / x 中心,实现见 connected_components。
切帧逻辑(extract_component_images,源码)分四步:
- 选种子:面积 ≥
max(120, 最大团块×20%)的团块是种子候选;不足frame_count时按面积补齐; - 按 x 中心排序:种子即帧顺序,武器伸展造成的 bbox 漂移不影响排序;
- 卫星合并:小团块(飘带、飘心、汗滴)只并入"bbox 外扩 15% 邻域内"的最近种子——远处的色键残片会被可观测量地丢弃并在 stderr 报告,而不是悄悄挂到帧上撑大 bbox;
- 失败即阻塞:凑不够
frame_count个姿态时整行失败(--allow-slot-fallback等宽切割仅供调试,且会在 manifest 中记录method: slots-explicit)。
这正是 sprite-gen 与"按槽位均分条带"式工具的本质区别:它相信像素内容,而不是相信生成器把姿态画在等宽槽里。
🧷 融合姿态救援:投影剖面 + DP 最优切割
当 AI 把两个姿态用发丝/武器"粘"成一个连通团块时,连通分量会数错帧。可选的fit.segmentation: "projection"路径(sprite_gen/frames/segment.py)改用另一套信号:
- 先算列方向 alpha 投影剖面
P[x] = Σ_y α(x,y),姿态之间的透明"沟槽"天然就是切割候选; - 沟槽消失(姿态完全贴合)时,用动态规划求
Σ P[cut] + λ·(width−ideal)²最小的切割列——在质量最薄处下刀,且惩罚偏离理想宽度的分段; - 分离失败时不碰条带、只在 stderr 报告,默认
components路径保持字节级不变。
这是"宁可不切、不静默乱切"原则的又一个例子。
📦 Manifest 契约:ok、一致性、原子性
每次成功提取都会发布frames/frames-manifest.json——它不是普通报告,而是运行时的可验证契约:
{ "ok": true, "engine": "component-row", "rows": [ { "state": "idle", "frames": 4, "method": "components", "files": ["frames/idle/frame-0.png"], "frame_records": [{ "index": 0, "nontransparent_pixels": 2400, "bbox": [28, 28, 68, 88] }], "engine_revision": "a1b2c3d4e5f6", "ok": true } ], "errors": [], "warnings": [] }完整样例可看测试夹具 expected-frames-manifest.json。契约有三道防线:
① 读取即校验(Fail Loud)。load_frames_manifest()对任何损坏、缺字段、errors/warnings/rows不是列表的记录直接SystemExit,绝不当成"空文件"吞掉(源码)——静默读取一个{}会把未解决的失败从视野里抹掉。
② 与物理帧树双向对账。_require_generation_consistency()(源码)要求:请求里的每个状态恰好一行、manifest 不允许出现请求外的旧状态行、frames/下不允许存在 manifest 未登记的孤立帧目录、每行文件列表与磁盘上的frame-*.png完全相等、帧数与请求声明(含 takes)一致。帧文件和 manifest 是一个事务发布的,不一致即意味着损坏。
③ 原子提交 + 自我修复。新帧先写入 staging 目录,再在publish_guard下与"逐状态失败证据extract-failure.json"一起换入frames/,任一步 I/O 失败则两个面一起回滚(_commit_generation)。失败的提取永不把部分产物发布进frames/,旧完整世代逐字节保留,失败信号落在frames/之外的extract-failure.json,供自动纠错循环消费。每行还 stamped 了engine_revision(引擎源码哈希,engine_revision),消费者发现版本漂移会由heal_run()从raw/自动重新推导——frames/因此被定义为"raw + request + 引擎"的派生缓存,而不是真相。
这套"完整性 + 对账 + 原子性"三件套,是让任何人(或任何 Agent)随时打开这个 run 目录、都得到同一份可信视图的根基。
📚 延伸阅读
- docs/architecture.md — cell 模型、提取内部细节的完整架构说明
- docs/run-contract.md — 阶段契约、run 目录树、失败提取的原子性条款
- docs/chroma-alpha.md — 色键选择与 alpha 清理诊断
- docs/sheet-slicing.md — 多角色网格表的按格切割(同一套 alpha 算法)
- docs/pixel-unfake.md —
fit.pixel_unfake的像素格检测与无抖动行走路径
【免费下载链接】sprite-genGenerate clean 2D game sprites & animation atlases — component-row pipeline: state rows, alpha cleanup, frame extraction, runtime atlases. Codex/Claude skill.项目地址: https://gitcode.com/gh_mirrors/sp/sprite-gen
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考