Files
rui40000-RUI-Nodes/__init__.py
T
rui40000andClaude Opus 4.8 e1a575fcda feat: 新增 SDMatte 精细抠图节点,实测复现官方效果
基于 SDMatte(vivo 相机研究院,ICCV 2025)的交互式抠图节点,
擅长发丝、绒毛、玻璃、烟雾等常规抠图模型处理不好的边缘。

实现要点:
- 严格照搬官方 configs/SDMatte.py 的推理配置(bbox 视觉提示、fp32、1024 分辨率),
  不做任何启发式后处理,输出即模型原始 alpha
- 内置官方 LongfeiHuang/SDMatte 的配置文件,无需下载 SD 2.1 权重,也无需联网。
  官方 load_weight=False 只用 config 搭骨架,全部权重由 checkpoint 覆盖;
  原版 SD 2.1 的 config 缺 bbox_time_embed_dim 等三个专有字段,缺字段时直接报错而非猜测
- 同时支持官方 .pth(12.1GB)与社区 .safetensors(5.19GB)。两者模型权重实测
  逐像素完全相同,pth 多出的 6.5GB 是 detectron2 的优化器状态;读 pth 时以受限
  Unpickler 只解析 model 段,内存占用与 safetensors 相当
- 自动适配 transformers 5.x 移除 text_model 包装层导致的键名漂移,
  避免 text_encoder 的 372 个权重被静默丢弃
- 加载后校验 1316 个张量全部对齐,有任何未覆盖/未使用的权重即中止报错
- 默认开启注意力分片,1024 下显存峰值由约 15.5GB 降至 9.1GB,速度反而略快

实测(官方效果图中的羊驼,对比官方公布 alpha):MAD=0.0113。
同图同权重下 ComfyUI-SDMatte 为 MAD=0.0884,相差 7.8 倍,主因是其
aux_input="trimap" —— 官方 aux_input_list 只含 point_mask/bbox_mask/mask,
trimap 从未作为视觉提示参与训练,且该分支坐标恒为 [0,0,1,1]、定位信息丢失。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 11:16:36 +08:00

86 lines
5.5 KiB
Python

# 顶部已有的导入
from .saturation_node import NODE_CLASS_MAPPINGS as SAT_NODE_CLASS_MAPPINGS
from .saturation_node import NODE_DISPLAY_NAME_MAPPINGS as SAT_NODE_DISPLAY_NAME_MAPPINGS
from .flip_node import NODE_CLASS_MAPPINGS as FLIP_NODE_CLASS_MAPPINGS
from .flip_node import NODE_DISPLAY_NAME_MAPPINGS as FLIP_NODE_DISPLAY_NAME_MAPPINGS
from .load_image_node import NODE_CLASS_MAPPINGS as LOAD_NODE_CLASS_MAPPINGS
from .load_image_node import NODE_DISPLAY_NAME_MAPPINGS as LOAD_NODE_DISPLAY_NAME_MAPPINGS
from .load_image_with_name_node import NODE_CLASS_MAPPINGS as LOAD_NAME_NODE_CLASS_MAPPINGS
from .load_image_with_name_node import NODE_DISPLAY_NAME_MAPPINGS as LOAD_NAME_NODE_DISPLAY_NAME_MAPPINGS
from .qwenedit_node import NODE_CLASS_MAPPINGS as QWEN_NODE_CLASS_MAPPINGS
from .qwenedit_node import NODE_DISPLAY_NAME_MAPPINGS as QWEN_NODE_DISPLAY_NAME_MAPPINGS
from .shot_splitter_node import NODE_CLASS_MAPPINGS as SHOT_NODE_CLASS_MAPPINGS
from .shot_splitter_node import NODE_DISPLAY_NAME_MAPPINGS as SHOT_NODE_DISPLAY_NAME_MAPPINGS
from .dialogue_extractor_node import NODE_CLASS_MAPPINGS as DIALOGUE_NODE_CLASS_MAPPINGS
from .dialogue_extractor_node import NODE_DISPLAY_NAME_MAPPINGS as DIALOGUE_NODE_DISPLAY_NAME_MAPPINGS
# 新增:遮罩筛选节点
from .mask_selector_node import NODE_CLASS_MAPPINGS as MASKSELECT_NODE_CLASS_MAPPINGS
from .mask_selector_node import NODE_DISPLAY_NAME_MAPPINGS as MASKSELECT_NODE_DISPLAY_NAME_MAPPINGS
from .page_narration_remover_node import NODE_CLASS_MAPPINGS as NARRATION_NODE_CLASS_MAPPINGS
from .page_narration_remover_node import NODE_DISPLAY_NAME_MAPPINGS as NARRATION_NODE_DISPLAY_NAME_MAPPINGS
from .text_list_node import NODE_CLASS_MAPPINGS as TEXTLIST_NODE_CLASS_MAPPINGS
from .text_list_node import NODE_DISPLAY_NAME_MAPPINGS as TEXTLIST_NODE_DISPLAY_NAME_MAPPINGS
from .mask_preview_node import NODE_CLASS_MAPPINGS as MASKPREVIEW_NODE_CLASS_MAPPINGS
from .mask_preview_node import NODE_DISPLAY_NAME_MAPPINGS as MASKPREVIEW_NODE_DISPLAY_NAME_MAPPINGS
from .utf8_converter_node import NODE_CLASS_MAPPINGS as UTF8_NODE_CLASS_MAPPINGS
from .utf8_converter_node import NODE_DISPLAY_NAME_MAPPINGS as UTF8_NODE_DISPLAY_NAME_MAPPINGS
from .openai_node import NODE_CLASS_MAPPINGS as OPENAI_NODE_CLASS_MAPPINGS
from .openai_node import NODE_DISPLAY_NAME_MAPPINGS as OPENAI_NODE_DISPLAY_NAME_MAPPINGS
# 新增:颜色匹配器节点
from .color_matcher_node import NODE_CLASS_MAPPINGS as COLORMATCHER_NODE_CLASS_MAPPINGS
from .color_matcher_node import NODE_DISPLAY_NAME_MAPPINGS as COLORMATCHER_NODE_DISPLAY_NAME_MAPPINGS
# 新增:素材拆分节点
from .image_splitter_node import NODE_CLASS_MAPPINGS as IMAGESPLITTER_NODE_CLASS_MAPPINGS
from .image_splitter_node import NODE_DISPLAY_NAME_MAPPINGS as IMAGESPLITTER_NODE_DISPLAY_NAME_MAPPINGS
# 新增:SDMatte 精细抠图节点(依赖 diffusers/transformers,缺失时不影响其余节点加载)
try:
from .sdmatte_node import NODE_CLASS_MAPPINGS as SDMATTE_NODE_CLASS_MAPPINGS
from .sdmatte_node import NODE_DISPLAY_NAME_MAPPINGS as SDMATTE_NODE_DISPLAY_NAME_MAPPINGS
except Exception as _e:
print(f"[Ruinode] SDMatte 节点未加载:{_e}")
print("[Ruinode] 如需使用,请安装:pip install diffusers transformers safetensors scipy opencv-python")
SDMATTE_NODE_CLASS_MAPPINGS = {}
SDMATTE_NODE_DISPLAY_NAME_MAPPINGS = {}
# 合并节点映射字典
NODE_CLASS_MAPPINGS = {}
NODE_CLASS_MAPPINGS.update(SAT_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(FLIP_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(LOAD_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(LOAD_NAME_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(QWEN_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(SHOT_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(DIALOGUE_NODE_CLASS_MAPPINGS)
# 新增:合并遮罩筛选节点
NODE_CLASS_MAPPINGS.update(MASKSELECT_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(NARRATION_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(TEXTLIST_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(MASKPREVIEW_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(UTF8_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(OPENAI_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(COLORMATCHER_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(IMAGESPLITTER_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(SDMATTE_NODE_CLASS_MAPPINGS)
# 合并节点显示名称映射
NODE_DISPLAY_NAME_MAPPINGS = {}
NODE_DISPLAY_NAME_MAPPINGS.update(SAT_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(FLIP_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(LOAD_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(LOAD_NAME_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(QWEN_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(SHOT_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(DIALOGUE_NODE_DISPLAY_NAME_MAPPINGS)
# 新增:合并遮罩筛选节点显示名
NODE_DISPLAY_NAME_MAPPINGS.update(MASKSELECT_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(NARRATION_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(TEXTLIST_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(MASKPREVIEW_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(UTF8_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(OPENAI_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(COLORMATCHER_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(IMAGESPLITTER_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(SDMATTE_NODE_DISPLAY_NAME_MAPPINGS)
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']