MOSS BBox Enhancer
MOSS 布局 JSON 导入与可视化边界框编辑:面板手绘深度图/深度图层、背景图裁剪、DWPose 人体部位识别、尺寸映射与按框色绘制。
MOSS BBox Enhancer
v1.8.5
用于 ComfyUI 的 MOSS 布局 JSON 导入、边界框编辑、尺寸映射和按框色绘制边界框的插件。
功能
- 从 MOSS JSON 生成官方边界框元素数组。
- 在节点面板中可视化编辑边界框。
- 支持新增、删除、移动、缩放、框选多选、Alt 拖拽复制、锁定边界框。
- 支持文字框、描述、标签和调色板编辑。
- 支持对象 / 角色 / 文字三种条目类型。
- 支持撤销 / 重做(顶部工具条右侧的 ↶ ↷)和方向键微移。
- 支持右侧边界框列表拖动排序。
- 属性面板可独立悬浮并拖动,面板位置与尺寸会记住。
- 支持多张背景图(各自独立的位置/尺寸/透明度/裁剪/显隐/锁定,可拖动排序)、导入、粘贴、画布模式设置;背景图以 WebP(长边 ≤1600、质量 0.8)存进
node.properties.moss_bg,重开工作流不丢。点工具条的背景图按钮直接进入背景图模式(按钮变蓝,下方出现工具条),拖动或拉伸背景图时遵循顶部「无吸附 / 对象吸附 / 网格吸附」:对象吸附对齐画布与各边界框的边/中线(含等距),网格吸附对齐网格线,按住Alt临时关闭;命中时画出和框一致的蓝色虚线辅助线。背景图本身可以裁剪:点工具条「裁剪」拖橙色框圈出可见区域,只影响显示、不动原图,Alt+ 点「裁剪」恢复整图。 - 支持从生成图片的 PNG 元数据中提取提示词和布局信息。
- 支持固定坐标、等比缩放和暴力拉伸三种尺寸映射方式。
- 支持根据 JSON 中的边界框自动推测原始画布尺寸。
- 支持给每个框单独设置颜色,并按颜色把框绘制到图片上。
- 支持提示词预设:内置人体部位、漫画对话框、平面贴图、层级、方向五组,可多选套用,也能自定义类型与内容;写入时可按类型自动带上
类型名:前缀。 - 支持角色:在主提示词里维护一份「角色名,描述」清单,可增删改;属性面板选中角色后自动把
角色名,加到框描述最前面。纯文本改动,不给 JSON 加字段。 - 支持提示词模板:把整段主提示词存成命名模板,点一下覆盖、Shift 点击追加,可改名和删除。
- 支持从背景图识别人体部位:DWPose wholebody 出 133 个关键点,取包围盒得到面部 / 肘部 / 手部 / 胯部 / 膝部 / 脚部六类矩形(不区分左右),多人自动编号。
- 支持手绘深度图:面板里用 5 档灰阶涂抹远近(白=近),输出可直接接 Depth ControlNet;也能导入现成深度图再改。
节点
MOSS 布局编辑器
输入 MOSS 布局 JSON,输出:
元素数组:官方画布使用的归一化元素数组。主提示词:summary.caption中的主提示词。完整提示词:包含边界框时输出完整 JSON,否则输出纯文本提示词。边界框:绘制用的边界框数组,每项为{x, y, width, height, metadata, color},可直接连到「MOSS 绘制边界框」。它的metadata只有type/text/desc,不包含palette。画布宽度/画布高度:本次执行实际使用的画布尺寸(INT)。接了image并开启「使用背景图并修改尺寸」时,输出的是图片宽高。
边界框 里的颜色来自面板里的「框色」(属性面板中,与调色板无关):设置后画布描边也会用该颜色。颜色是框的附加属性,不写入 layout_json,只在这个输出里携带。这个输出也能直接连到官方「创建边界框」的 bboxes 输入——官方会读 x/y/width/height/metadata,color 被忽略。
各输出里颜色的归属是固定的:元素数组 的 color_palette 只放 JSON 里的调色板(构图信息,原样搬运,不会追加框色);框色只出现在 边界框 的 color 字段里。没设颜色的条目不输出 color。
可选连接 image 输入后,插件可以使用图片尺寸作为画布尺寸,并将图片显示为编辑面板背景。
节点上的 preview 开关(默认开)控制执行后是否在节点下方显示画布预览:按当前画布尺寸画一张图,每个框用各自的颜色描边、左上角标序号;接了 image 时直接画在图片上。预览最长边 768px,等比缩小,存到 ComfyUI 的 temp 目录,不写入工作流。关掉就完全不生成图片。
选中多个框后拖动其中任意一个,整组会一起移动并保持相对位置;锁住的框不跟着动,整组贴到画布边界时会一起停住。
面板可以拖标题栏移动,四条边和四个角都能拖动缩放,宽度不会超出视口;高度不再被自动压矮,往下拖标题栏时面板可以临时沉到屏幕下方,抓住标题栏拖回来即可。把标题栏拖到上边界时按指针位置分三段贴靠:左 / 中 / 右 1/3 分别占左 / 中 / 右 2/3;拖到左右边界则各占半屏。右栏和节点上都带一个「分辨率」选择器:手动输入 / 按像素 / 按比例三种方式,按像素时给百万像素和倍数(8/16/32/64),按比例时选宽高比再填一边、另一边自动。节点上仍然只有「画布宽度 / 画布高度」两个输入框;分辨率选择器放在画布右侧面板里。在边缘停住约 0.3 秒才亮出半透明预览框(快速扫过不会闪),松手才生效并平滑展开到目标尺寸;从贴靠状态拖出来会恢复贴靠前的尺寸。面板打开 / 关闭带轻微的缩放淡入淡出。右侧「主提示词」框最多拉到右边栏高度的 3/4,再高也不会把下面的框列表挤出面板。
选择与快捷键
| 操作 | 效果 |
|---|---|
| 拖空白处 | 新建一个框,朝左上 / 右上 / 左下 / 右下任意方向都能拖出;拖动中越过起点会自动换向 |
| Shift + 拖空白处 | 框选,与选框相交的框全部选中;Ctrl 叠加为追加框选 |
| Ctrl + 点击框 / 数字标签 | 增减单个框到选区 |
| Alt + 拖动框 | 复制选中的框,拖动的是副本,原件留在原处 |
| Ctrl + A | 全选所有框 |
| Ctrl + D | 原地复制选中的框(副本与原件重合,复制后处于选中状态,可直接拖走) |
| Esc | 取消选择;框选拖到一半时作废这次框选 |
| Ctrl + C / Ctrl + V | 复制框到系统剪贴板 / 粘贴框或背景图 |
| Delete / Backspace | 删除选中框 |
| 方向键 / Shift + 方向键 | 微移 1px / 一个吸附步长 |
复制出来的框会继承原框的颜色、标签、描述和调色板等信息。快捷键只在编辑面板打开、且焦点不在文本输入框里时生效。
按住 Alt / Ctrl / Shift 时,画布顶部会弹出该组快捷键的文字提示,松开即收起;每次快捷键操作(复制、粘贴、全选、原地复制、删除、框选、微移、撤销等)完成后,也会在同一位置短暂显示操作结果,例如「已复制 2 个框」。提示不拦截鼠标事件,不影响画布操作。
提示词预设
属性面板里「框色」右侧有一个「提示词预设」按钮,位置在「描述」输入框上方,点开是分组弹层:
-
点标签只是选中,可以多选;点右上角「写入」才把选中标签的文本写进当前选中框的描述。写入左边的「取消选中」清空已选标签,不会改动描述。
-
标题栏下方有一条预览,按选中顺序拼出真正会写入的文本(先选的排在前面,用
,连接),选得多时可以在这条里上下滚动。 -
写入默认追加到原描述后面(用
,连接);**按住 Shift 点「写入」**则覆盖整个描述。写入后清空选中并关闭弹层。 -
类型前缀:「漫画对话框」和「平面贴图」写入时会自动带上
类型名:,例如漫画对话框:气泡、平面贴图:黑色打码线条,这两组的标题显示为红色。自己新建的类型默认不带前缀,新建时勾选「带前缀」才会带(我的类型:我的预设),勾选过的类型标题同样是红色。人体部位、层级默认不带前缀,方向仍按起点 / 终点配对。 -
Alt + 点击标签可以逐项反转前缀:默认带的改成不带(
气泡),默认不带的改成带(人体部位:头部)。反转只作用于本次选中的这一项,选中后标签左侧的小红点表示会带前缀;方向的两半不参与前缀切换。 -
弹层最高 68vh,标签多出来时往下滚动即可;顶部「取消选中 / 写入」这一行固定不动,不用滚回顶部。
-
标签本身写什么就是什么,不做中英转换;预设也不会自动切换对象 / 角色 / 文字类型,特殊用途可以自己搭配。
-
内置五组:人体部位(头部、胸部、臀部、胯部、肘部、手部、膝盖、脚部)、漫画对话框(气泡、爆炸、思考气泡、耳语气泡、呐喊气泡、心形气泡、颤抖气泡、旁白框、矩形对话框、圆角对话框、竖排文字框、黑底白字框)、平面贴图(黄色柴犬狗头表情包、猫猫头表情包、黑色打码线条)、层级(前景、中景、后景、背景)、方向(16 项)。
-
「方向」组按起点 / 终点分成两段(段首有标签),每段各占两行:第一行是四个正方向「从左 / 从右 / 从上 / 从下」,第二行是四个斜方向「从左上 / 从左下 / 从右上 / 从右下」(终点同理,第二行从「到左上」开始)。这样每行都是 4 个,不会因为面板宽度把斜方向拆成 5 + 3 的参差样子。
-
起点和终点会两两拼成一段:
从左+到右→从左到右,段内不加逗号。两行的点击先后不影响结果,先点终点再点起点同样是从左到右;段的位置取两半里先被选中的那个位置。 -
一次选多组也可以:第 1 个起点配第 1 个终点、第 2 个配第 2 个,段与段之间才用
,(例如从左到右, 从上到下)。只选了一头时按原样单独写入,预览下方会提示「还有 1 个起点没配对」。 -
其他分组仍是单行平铺,选中几个就写几个;用户自定义项会额外占一行,并且不参与配对。
-
自定义预设:弹层底部先选类型,再填内容,点「添加」即可;类型下拉里选「+ 新建类型」可以只建空类型,也可以直接带着内容一起创建,旁边的「带前缀」勾选框决定这个类型写不写
类型名:。自定义项右上角有×可删除,内置项只读。往内置类型里加的项跟随该类型是否带前缀(漫画对话框、平面贴图带,其他不带)。自建类型的标题鼠标移上去会高亮,交互和插件里的标签一致:双击标题改名(回车确认,Esc 取消,重名会被拒绝),右键标题删除;也可以单击标题,约 0.4 秒后右侧滑出×再点它。删除会弹出确认框,确认后连同该类型下的所有预设一起删除,改名后前缀跟着新名字走;内置类型不能整组删除。
内置预设在 web/src/panel/preset-data.js,随仓库一起发布;自定义的类型和内容存在插件根目录的 user_presets.json,该文件已加入 .gitignore,不会进仓库,插件升级也不会被覆盖。如果插件目录不可写,会降级存到浏览器本地存储并给出提示。
预设只改框的 caption(描述),走正常保存流程因此可以撤销;不会碰 text、palette、框色,也不会给 layout_json 增加字段。
角色
右栏顶部是三层列表的页签 框 / 背景 / 深度(带数量角标):框是边界框,背景是背景图层(可多张),深度是深度图图层。三者共用一套行样式(拖动柄、锁、眼睛、双击改名、右键删除),但数据各归各的,互不影响。深度页里点任意一行会自动进入深度模式,点背景那行则进入背景图模式。
右栏「🎭 角色」卡片用来维护本次创作的角色清单,和属性面板里「对象 / 角色 / 文字」的那个类型不是一回事——它只是提示词层面的临时预设。
- 增加:点「+ 增加角色」,填角色名和描述(如
少女A/坐姿),确定后往主提示词末尾追加一行少女A,坐姿(空行分隔);提示词里已经有同名行时就地改写,不会加出第二行。描述框是多行的(Enter 换行、Ctrl+Enter 提交),写进主提示词时会压成一行,保证「一行一个角色」。 - 修改:双击角色行,或点行尾的
✎;改完替换主提示词里对应的那一行,行序不变。改名时,各个框描述开头引用了旧名字的前缀会一起换成新名字(只动开头,正文里同名的词不碰),提示会显示同步了几个框。 - 多行描述:对话框里可以换行,写进主提示词时按「一行一个角色」压成单行(换行变空格)。在对话框里来回改不会丢换行(同步时两边压平后再比较,判定没变就不回写);只有你直接在提示词里改那一行,描述才会变成单行。
- 反向同步:直接在主提示词里改角色那一行(比如把
少女A,红发改成少女A,蓝发),松手 300ms 后角色列表里的描述会跟着变。识别规则是「行首是已有角色的名字 + 中/英文逗号」,所以普通正文不会被误判;把那一行整行删掉时,角色本身保留(要删角色请点×,否则会连带清掉框描述里的前缀)。多行描述写进提示词时被压成一行,这种「压平后相同」的情况不算改动,不会把你对话框里的换行吃掉。 - 删除:右键角色行,或点行尾的
×;主提示词里按名字定位那一行移除——手改过描述也能删干净,重复行一起去,删完自动收掉多余空行。 - 绑定到框:属性面板「描述」上方的角色下拉,选中后把
角色名,插到描述最前面,换角色时替换旧前缀,选「(不指定)」移除。下拉的回显靠解析描述开头,所以手改描述后会自动回到「(不指定)」。
角色清单存在 node.properties.moss_characters,跟着工作流保存,但不会写进 layout_json:顶层仍然只有 summary 和 items,items 也仍然只有 label / caption / bbox / text / color / palette / tags 这些原有字段。原因是底层模型只认官方 schema,能在文本层做的就不动结构。
删除角色时,框描述开头的 角色名, 前缀会一起清掉(只动开头,正文里同名的词不碰),避免框还挂着一个已经不存在的角色;主提示词里对应的那一行同样移除。
提示词模板
和「提示词预设」不是一个东西:预设改的是框描述里的标签,模板换的是整段主提示词。
主提示词卡片右上角有一个 📚 按钮,点开是模板弹层:
- 保存当前:把当前
summary.caption整段存成模板。名字留空时自动取主提示词第一行;同名会覆盖并提示「已覆盖模板」。 - 套用:点模板条目直接替换主提示词;按住 Shift 点击则追加到末尾。走正常输入流程,可以 Ctrl+Z 撤销。
- 编辑 / 删除:
✎打开编辑弹窗,上面是模板名、下面是整段主提示词的多行文本框(Ctrl+Enter 保存、Esc 取消、重名拒绝),×直接删除。
模板和标签预设共用插件根目录的 user_presets.json,分别存在 templates 和 groups 两个分区。保存接口是「带哪个字段就更新哪个」,所以保存其中一套不会影响另一套。这个文件同样在 .gitignore 里,不进仓库。
节点还提供“导入图片中的提示词 JSON”按钮,可从带有 ComfyUI 生成参数的图片中提取 MOSS JSON、官方边界框或文本提示词。点击后先选导入范围,再选图片:
- 导入完整提示词:主提示词、全部 bbox 与布局一起导入,覆盖当前内容(原来的行为);
- 仅导入主提示词:只替换主提示词,保留现有 bbox 与画布尺寸;
- 仅导入 bbox 及其布局:只替换 bbox、布局与画布尺寸,保留现有主提示词。
后两种用于“图片里的框我不想要,只要提示词”或“提示词我自己写,只要框”的场景;图片里没有对应内容时会提示并停手,不会把现有内容清空。
主提示词 和 完整提示词 都是字符串输出,可以直接连接到正向提示词输入或正向文本编码节点:
- 使用
主提示词:只传递整体画面描述。 - 使用
完整提示词:包含边界框时传递完整 MOSS 布局提示词,没有边界框时等同于主提示词。
识别人体部位
点工具条上的背景图按钮进入背景图模式,下方工具条里有「识别人体」按钮:对当前背景图跑一次 DWPose wholebody,得到 133 个关键点,再按部位取包围盒,直接追加到画布。
133 点的分布:身体 0-16、脚 17-22、脸 23-90、左手 91-111、右手 112-132。不区分左右,只出六类:
| 部位 | 怎么来的 | 说明 | |---|---|---| | 面部 | 68 个脸部点的包围盒,外扩 12% | 像素级,不受朝向影响 | | 手部 | 每只手 21 个点的包围盒,外扩 15% | 两只手各出一个框 | | 脚部 | 踝 + 大趾 + 小趾 + 脚跟 4 点包围盒 | 两只脚各出一个框 | | 肘部 | 肘关节为中心,边长 = 身高 × 0.08 | 关键点只有位置,尺寸按比例给 | | 膝部 | 膝关节为中心,边长 = 身高 × 0.08 | 同上 | | 胯部 | 两髋中点,宽 = 髋距 × 1.35,高 = 身高 × 0.12 | 胯只有一个框 |
脸、手、脚的框尺寸来自像素(关键点自己撑出来的),所以前景的脚会明显比远景的大——这是「透视」在数据上的正确表现,不是按身高比例猜的。 肘、膝、胯没有形状可言,只能按人体高度给比例,所以识别按钮下面的「关节框缩放」只作用于这三类。
- 多人自动编号:
人物1,面部、人物2,手部(同一人的两只手都是「手部」,靠位置区分)。 - 关键点置信度低于 0.3 的点不参与;某组有效点太少、或撑出的框大于身高的 0.5~0.7 倍(说明点散了、没测准)就不出这个框。
- 检测置信度默认 0.5(可在请求里调);只有零散肢体的检测会被忽略:既没有面部也没有胯部就整套丢弃。
- 识别完会在「🎭 角色」里补上
人物1、人物2占位(同名复用),补个描述就能用下拉绑定。 - 正向一个都没检出时会自动换朝向再试(逆/顺时针 90°、180°、水平翻转),命中后把关键点映射回原图。
- 框是一次性快照:之后拖动 / 缩放背景图,框不会跟随,需要重新识别。
模型:models/ 下需要两个文件(已加入 .gitignore,不进仓库):
| 文件 | 作用 | 大小 | CPU 耗时 |
|---|---|---|---|
| yolox_m_8xb8-300e_humanart-c2c7a14a.onnx | 人体检测(HumanArt,含插画) | 97MB | ~0.15s |
| rtmw-dw-x-l_simcc-cocktail14_270e-256x192_20231122.onnx | 133 点姿态(RTMW-x) | 219MB | ~0.2s/人 |
首次识别会自动下载这两个文件:页面顶部弹出常驻提示并显示合计百分比,下完提示自动消失,然后直接开始识别。走 hf-mirror.com,失败回退 huggingface.co;先写 .part 再原子改名,中断不会留半截文件。只需下载一次。
想手动准备也可以用:
# 检测(97MB)
curl -L -o models/yolox_m_8xb8-300e_humanart-c2c7a14a.onnx \
https://hf-mirror.com/Claquasse/Anima-Control-Pose/resolve/main/detector/yolox_m_8xb8-300e_humanart-c2c7a14a.onnx
# 姿态(219MB)
curl -L -o models/rtmw-dw-x-l_simcc-cocktail14_270e-256x192_20231122.onnx \
https://hf-mirror.com/Claquasse/Anima-Control-Pose/resolve/main/detector/rtmw-dw-x-l_simcc-cocktail14_270e-256x192_20231122.onnx
推理走 onnxruntime(有 CUDA 用 GPU,否则自动退回 CPU),不依赖 torch / rtmlib / mmcv——预处理、仿射裁剪、simcc 解码都在 MOSS_Pose.py 里实现。
换模型:不用改代码
- 文件按通配符找,优先顺序:检测
*humanart*.onnx→*yolox*.onnx;姿态*rtmw*.onnx→*dwpose*.onnx→*wholebody*.onnx。同目录有多个时按文件名排序取第一个,想指定就只留一个。 - 输入尺寸从 ONNX 读:检测的
H/W、姿态的W/H、长宽比、simcc 倍数(simcc_x长度 ÷ 输入宽)全部在加载时读取。所以256x192、384x288、416、640这些版本都能直接放进去。 - 只接受 133 点 wholebody(身体 17 + 脚 6 + 脸 68 + 双手各 21)。换成 17 点 body、26 点 halpe 会在加载时直接报错并说明原因,不会算出乱框。
- 检测模型必须自带 NMS(输出
[N,5]+labels)。拿到的是原始网格输出([1,8400,85])会明确报错,提示换带 NMS 的导出。
例如想更快,把 yolox_m(640)换成 yolox_tiny(416)再放一个 rtmw-dw-l-m_..._256x192.onnx,只需删旧文件、放新文件,重启即可。
这两个权重来自 mmpose 的 DWPose(Apache-2.0),上面的地址只是镜像。之前版本的
yolov8m-pose.onnx/yolov8n-pose.onnx已经不再使用,可以直接删掉。
手绘深度图
bbox 能定位置,但定不了空间关系。深度图补的就是这一块:在面板里直接画一张灰度深度图,从节点新输出的「深度图」接 Depth ControlNet。
入口:工具条上的四段灰阶按钮(在「背景图」按钮右边)。点一下进入深度模式,按钮变蓝、下方出现深度工具条;切进去之后画布上叠一层深度图层,bbox 只留轮廓当参考,不会误选。两种模式互斥,进一个会自动退出另一个。
五档灰阶(白 = 近,黑 = 远,和 MiDaS / Depth-Anything / 主流 Depth ControlNet 一致):
| 档位 | 值 | 含义 | |---|---|---| | 1 | 255 | 最近 | | 2 | 192 | 近 | | 3 | 128 | 中(也是未涂区域的底色) | | 4 | 64 | 远 | | 5 | 0 | 最远 |
色块只是快捷入口,旁边的「灰度」滑块可以在 0~255 之间连续取值,两者双向同步:点色块滑块跟着走;滑块正好停在 255 / 192 / 128 / 64 / 0 上时,对应色块自动高亮,停在别的值上就都不亮,提示当前是自定义灰阶。
工具:灰度滑块(0~255)、笔刷大小(4~240)、移动、橡皮(涂回中灰)、填充(把当前选中的 bbox 填成当前灰阶,椭圆)、清空、导入、导出 PNG、图层列表、删层、裁剪、层灰度(撤销 / 重做由顶部那两颗按钮接管,深度条上不再重复放)。灰度和笔刷的数值都支持双击直接输入,回车或点别处生效,Esc 放弃;超出范围会夹到上下限。
快捷键:1~5 选灰阶,[ ] 调笔刷,E 橡皮。撤销 / 重做只用工具条按钮(深度模式下顶部的 ↶ ↷ 会自动切到深度图的栈,Shift + 点击则强制撤回画布)——Ctrl+Z 是 ComfyUI 自己的「撤销工作流」,在捕获阶段就被它吃掉,面板这边既抢不到也没法屏蔽(硬拦反而会把工作流一起撤回去),所以干脆不绑。
导入(作为图层):
- 深度模式下
Ctrl+V直接粘贴深度图;框选模式下粘贴仍是背景图——按当前模式分流,不弹窗;焦点不在画布上时同样按模式分流(以前这种情况会一律当背景图,还会顺手把背景图模式打开);也可以点工具条「导入」选文件; - 导入的是一个新图层,不会覆盖已经画好的笔刷内容。按原比例缩到画布内并居中(比画布大就缩小,比画布小保持原始像素),导入后自动切到「移动」工具,直接在画布上拖着对位;导入本身也进撤销栈,按错了能退回去;
- 选中图层有 8 个控制点(四角 + 四边中点),拖它们缩放;缩放以对边为基准,最小 8px,不会翻转;
- 移动和缩放会按顶部的无吸附 / 对象吸附 / 网格吸附吸附:对象吸附对齐画布四边与中线、以及其它图层的边/中线,网格吸附对齐网格线,只有「无吸附」时完全自由;命中画蓝色虚线,按住
Alt临时关闭; - 图层列表在右侧栏的「深度」页(不再是工具条弹层):从顶到底排列,按住
≡上下拖就能改遮挡顺序(上面的盖住下面的)。每行有锁(锁定后画布上不能拖动/缩放、也不接受笔刷)和●/○(显示/隐藏);双击名称就地改名;右键删除(可撤销);Ctrl/Cmd/Shift + 点击多选,选中 2 个以上时底部出现「隐藏 / 锁定 / 删除」批量条。列表最底下那行是笔刷层(最底层),选中它就回到不依附任何图层的地板层;选中任意一行会自动进入深度模式; - 层灰度:选中某层后拖工具条上的「层灰度」(
-128~+128),整层一起变黑或变白——负值更黑(更远),正值更白(更近)。它不改原图,只影响这一层的显示与合成结果,所以随时能拖回 0 恢复; - 「删层」删掉选中图层,底层笔刷不受影响;
- 选中某个图层时,笔刷 / 橡皮 / 填充都画在这一层上(不再落到最底层),撤销也会连这层的位图一起回滚;
- 裁剪:点「裁剪」进入裁剪模式,橙色框是保留区域,被裁掉的部分压暗显示;拖框或拖 8 个控制点调整,只能裁小不能超出图层。裁剪只改可见区域,原图位图不动,随时能拉回来;按住
Alt点「裁剪」恢复整层; - 彩色图会按亮度转灰度并提示;
- 撤销 / 重做走深度图自己的栈,覆盖笔刷、图层位置与尺寸、裁剪、增删图层、清空;按类型记最小差量,移动缩放这类只占几十字节,不额外编码位图。
输入:节点上有可选的 depth_image(IMAGE)输入。接上之后会自动按画布宽高缩放、按亮度转成三通道灰度(白=近,黑=远,多张只取第一张);执行完成后面板会把它当成一个图层注入,打开面板就能直接拖着对位、继续在上面画。文件名带内容哈希,同一个来源只注入一次,不会每次执行都叠一张。
输出:节点第 7 个输出「深度图」(IMAGE,尺寸 = 画布宽高,三通道同值)。输出的是合成结果:笔刷层打底,再按图层顺序盖上所有可见图层,超出画布的部分会被裁掉。
取值优先级:面板内容 → 节点接的 depth_image → 中灰 0.5。面板里有东西就用面板(合成图,含你拖过的位置和手绘笔迹),面板是空的才用节点输入的图;都没有就输出中灰,代表「未指定」,避免整张全黑被当成「全部极远」。
面板里的合成图存在隐藏控件 depth_png(base64 PNG)里;图层的结构(每张图层的位图 + 位置尺寸)另外存在 node.properties.moss_depth,所以刷新浏览器、重开工作流之后仍然是可以继续移动和缩放的图层,不会被拍平成一张扁图。老工作流没有这份结构时,退回把 depth_png 当扁平笔刷层读取。这个控件在节点上不显示,也不占高度,layout_json 完全不受影响。外部输入注入图层时不会立刻写回 depth_png,所以第一次执行就能直接输出你接进来的图,不用「再跑一次才对」;你真正拖动或涂抹之后才提交合成结果。
存储:隐藏控件 depth_png 里的 base64 PNG,5 档硬边的图通常 30~60KB,对工作流体积影响很小。删掉它面板手绘的深度图就没法跟着工作流走了,所以保留但不显示;只想用外部 depth_image 的话,不接面板也完全不受影响。
已知限制:
- 深度图层只在深度模式显示,切回框选就隐藏(数据还在);
- 改画布宽高时,已有笔迹会被拉伸到新尺寸,不会裁剪;
- 椭圆填充不会羽化边缘,需要过渡就换小笔刷手动修。
MOSS BBox 尺寸映射器
将 MOSS JSON 中心坐标系的边界框映射到目标画布尺寸。
输出:
元素数组:0–1000 归一化的官方元素数组,接MOSSImageLayoutPrompt的element输入。映射后JSON:保留映射后的 MOSS JSON 字符串。目标宽度目标高度边界框:映射后的像素框(左上角原点),可直接接官方Create Bounding Boxes的bboxes输入,或接「MOSS 绘制边界框」;条目本身带color时一并透传。
映射器没有框色通道(框色存在导入节点的面板里),也不会拿调色板首色冒充框色——JSON 里没写 color 就不带这个字段,绘制时用兜底色。
映射模式:
保持固定坐标(不缩放):保留边界框的中心坐标和尺寸。保持长宽比(等比缩放):按较小缩放比例适配目标画布,并保持比例。暴力拉伸(铺满画布):分别按宽高缩放,填满目标画布。
MOSS 绘制边界框
把边界框按各自的颜色画到图片上。官方「绘制边界框」按 COCO 标签取固定颜色,这个节点改成读框自带的颜色。
输入:
bboxes:边界框列表,可直接接上面节点的边界框输出;也支持官方[[{x, y, width, height}]]、单个框对象或 JSON 字符串。image:底图,可选。不接时按框的最大范围生成一张黑底图;输入带 alpha(RGBA)时输出同样保留 alpha,透明区域不会被转成黑色。line_width:线宽,默认 3。show_index:在框左上角画序号。show_label:在框内画描述 / 文字内容(放不下时自动跳过;多行文本压成一行显示,超宽按宽度截断)。fallback_color:没有携带颜色的框使用这个颜色,默认#ff4a4a,节点上是取色器,点一下就能选。
颜色只取边框自带的 color,没有就用 fallback_color;metadata.palette 属于构图信息,不参与描边。
节点上的显示名是中文(边界框 / 线宽 / 显示序号 / 显示描述 / 兜底颜色),只改前端显示,输入 key 不变,老工作流照常读取。
输出:图像。
JSON 格式
MOSS JSON 使用以画布中心为原点的像素坐标,BBox 顺序为:
[ymin, xmin, ymax, xmax]
示例:
{
"summary": {
"caption": "一个人在城市街道上行走"
},
"items": [
{
"label": "object",
"caption": "人物",
"bbox": [-256, -128, 256, 128]
},
{
"label": "text",
"caption": "招牌文字",
"text": "OPEN",
"bbox": [-100, 180, 20, 420]
}
],
"bbox_coord_space": "abs_centralized",
"bbox_format": "yxyx"
}
官方元素数组使用 0~1000 的归一化坐标,字段名保持官方格式,例如 type、bbox、desc、text、tags 和 color_palette。编辑面板中的标签和调色板都可以通过 + 添加,双击或右键已有项目即可删除。
字段约束
label只有object、character、text三种,编辑面板顶部三个按钮切换。- 只有
label: "text"的条目带text字段;切回对象/角色时会自动删除该字段。 tags和palette为空数组时会从 JSON 中整个删除该字段,不输出"tags": []。- 官方元素数组的
type只有obj和text,所以character转换后等同obj。角色身份由官方MOSSImageLayoutPrompt节点的character_boxes按框序号指定(例如1, 3)。
坐标格式(两种官方写法都支持)
| 格式 | bbox_coord_space | bbox_format | 原点 | 画布尺寸 |
|---|---|---|---|---|
| 草稿(官方 Pixel Layout draft) | abs | xyxy | 左上角 | 顶层 width / height |
| 模型(ComfyUI 官方节点使用) | abs_centralized | yxyx | 画布中心 | 顶层 width / height(可选),或由节点控件给出 |
本插件统一以模型格式为规范。粘贴草稿格式的 JSON 时,绘制面板和两个节点会自动换算成 abs_centralized / yxyx,并把草稿里的 width / height 同步到画布的宽高控件,无需手动转换。
模型格式里也可以保留 width / height(用于记录画布尺寸):它们会同步到画布控件,与控件双向保持一致;但生成 完整提示词 时会自动剥离,不会进入喂给模型的提示词。尺寸映射器的 映射后JSON 则会把它们更新为目标画布尺寸。
使用建议
- 将 MOSS JSON文本 复制或连接到
MOSS 布局编辑器或MOSS BBox 尺寸映射器使用。 - 如果目标画布尺寸与原 JSON 不同,使用尺寸映射器,保证尺寸不偏移,可以连接到
创建边界框节点预览一下映射后的布局。 - 将官方画布输出的元素数组连接到
MOSSImageLayoutPrompt。 - 将
主提示词或完整提示词可以直接连接或复制到正向提示词;需要布局控制时优先使用完整提示词。
安装
通过 ComfyUI Manager(推荐)
在 Manager 里搜 MOSS BBox,或直接装:
comfy node install moss-bbox-enhancer
装完重启 ComfyUI。
手动安装
将插件目录放入:
ComfyUI/custom_nodes/MOSS_BBox_Enhancer
重启 ComfyUI 后即可使用。
可选依赖(只影响「识别人体部位」)
核心节点不引入任何新依赖(numpy / Pillow ComfyUI 自带)。人体部位识别额外需要 opencv-python 和 onnxruntime:
pip install opencv-python onnxruntime
没有硬塞进主依赖,是因为 onnxruntime 与 onnxruntime-gpu 会互相覆盖,强制安装容易把已经配好 GPU 版的环境搞坏。
示例工作流
仓库里的 example_workflows/ 放了两份可直接拖进 ComfyUI 的工作流:
| 文件 | 内容 |
|---|---|
| Moss_BBox控制 示例.json | 基础用法:布局编辑器 → 创建边界框 → 采样 |
| Moss_BBox控制+深度图控制.json | 在上面基础上接了深度图:MoGe 估深度 + 面板手绘的深度图层一起进采样 |
两份都用了新版 ComfyUI 的子图(subgraph),前端版本较旧的话打不开;里面的 MarkdownNote 写了用到的模型下载地址,按需从 UNETLoader 换成自己有的模型即可。
说明
前端可以直接读取上游节点中的静态 JSON 文本控件。对于 Python 节点运行后才生成的动态输出,必须先执行工作流,上游结果生成后尺寸映射器才能读取并推测尺寸。
本插件不新增第三方依赖。
节点运行时的版本号只在 MOSS_Version.py 的 __version__ 一处(Registry 侧另有一份在 pyproject.toml,见下节),布局编辑器标题栏右侧的版本胶囊通过 GET /moss/version 读取,前端不再单独存一份。节点左下角那颗 MOSS_BBox_Enhancer 徽标来自 ComfyUI 前端注册的包名,不受版本号影响,插件侧没有可改的字段。
发布到 Comfy Registry(维护者)
Registry 从 pyproject.toml 读版本号,节点标题栏读 MOSS_Version.py,所以发版要同时改两处:
pyproject.toml→[project] versionMOSS_Version.py→__version__
推到 main 后 .github/workflows/publish.yml 会自动跑到 Registry。workflow 里有一道版本一致性检查,两处不一致会直接失败并提示,不会发出「页面写 1.7.0、插件里显示 1.6.x」的版本。
需要在仓库 Settings → Secrets and variables → Actions 里配 REGISTRY_ACCESS_TOKEN,值是 registry.comfy.org 上 yumu2497 这个 publisher 的 API Key。