feat: Unmult 增加「主体保护」开关,控制是否采纳 subject_mask
subject_mask 的合并逻辑此前已存在,本次补上开关: - 启用(默认):alpha 取 max(unmult 结果, subject_mask) - 关闭:即便上游已连线也完全不采纳,等同纯 Unmult 想对比「有无 AI 介入」的差别时拨开关即可,不必拔线。 兼容旧英文名 use_subject_mask。 顺带把黑点/白点 tooltip 里的「(主体保护)」字样去掉 —— 那是描述 参数作用的措辞,和新开关撞名会让人以为是同一功能。 实测(黑底 + 暗色实体,alpha 真值恒为 1,下半近纯黑): 不接 mask 暗部 alpha 0.080 ← 黑衣黑发被扣穿 接 mask + 保护启用 暗部 alpha 1.000 接 mask + 保护关闭 暗部 alpha 0.080,与不接 mask 逐元素一致 即开关确实起作用,且关闭时行为与纯 Unmult 完全等价。 这同时解掉了上次记录的适用边界:黑底 unmult 本质是拿亮度当不透明度, 对实体不成立;现在接一路语义抠图的 alpha 进 subject_mask 即可破解 —— 语义模型负责「哪里是主体」,Unmult 负责「边缘有多透」。README 已按此改写。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
adb1de6329
commit
a1f52de801
@@ -1203,6 +1203,8 @@ Unity/Godot 归一化 pivot(左下为原点):(0.5411, 0.0699)
|
||||
- `bg_color` (STRING): 要去除的背景色,`#RRGGBB`。常用 `#000000` / `#FFFFFF` / `#00FF00` / `#FF00FF`
|
||||
- `黑点` (FLOAT, 滑块): 低于此值的 alpha 归零,用于清除背景残留噪点。调太高会丢边缘细节
|
||||
- `白点` (FLOAT, 滑块): 高于此值的 alpha 归一,用于让主体更实。调太低会让边缘硬化
|
||||
- `主体保护` (BOOLEAN): 是否采纳 `subject_mask`。**关闭时即便已连线也完全不采纳**,等同纯 Unmult——想对比「有无 AI 介入」时拨这个开关即可,不必拔线
|
||||
- `subject_mask` (MASK, 可选): 接抠图节点输出的 alpha,节点执行 `max(unmult_α, subject_mask)` 合并
|
||||
|
||||
后两项用中文参数名 + `display: slider`,界面上就是两条滑块,与 LayerStyle 的 BiRefNet Ultra 观感一致。函数内部用 `**kwargs` 接收(中文名不能直接做函数形参),并兼容旧的 `alpha_low`/`alpha_high` 调用。
|
||||
|
||||
@@ -1218,20 +1220,24 @@ Unity/Godot 归一化 pivot(左下为原点):(0.5411, 0.0699)
|
||||
|
||||
数学上是精确解,三种底色都能完美还原。
|
||||
|
||||
**⚠ 适用边界(很重要,选错底色会翻车)**:
|
||||
**⚠ 适用边界与破解办法**:
|
||||
|
||||
| 素材 | 结果 |
|
||||
|:-----|:-----|
|
||||
| 光效、火焰、烟雾、粒子、UI 特效 | ✅ 最佳选择,半透明层次完整保留 |
|
||||
| 绿幕/品红等**与素材反差大**的底色 | ✅ 实体素材也能扣干净 |
|
||||
| **黑底 + 暗色实体** | ❌ **暗部会被当成背景扣掉** |
|
||||
| 素材 | 纯 Unmult | 接 `subject_mask` 后 |
|
||||
|:-----|:---------|:--------------------|
|
||||
| 光效、火焰、烟雾、粒子、UI 特效 | ✅ 最佳选择,半透明层次完整保留 | 一般不需要 |
|
||||
| 绿幕/品红等**与素材反差大**的底色 | ✅ 实体素材也能扣干净 | 一般不需要 |
|
||||
| **黑底 + 暗色实体** | ❌ **暗部会被当成背景扣掉** | ✅ **已解决** |
|
||||
|
||||
实测同一个实体素材(alpha 真值恒为 1):
|
||||
实测同一个实体素材(alpha 真值恒为 1,下半部分接近纯黑):
|
||||
|
||||
- 黑底:亮部还原 alpha 0.900,**暗部只有 0.080** —— 黑头发、深色衣服、鞋子会被扣穿
|
||||
- 绿幕:亮部 0.900,**暗部 0.940** ✓ 正常
|
||||
| 条件 | 暗部还原 alpha |
|
||||
|:-----|-------------:|
|
||||
| 黑底,不接 mask | **0.080** ← 黑头发、深色衣服、鞋子被扣穿 |
|
||||
| 黑底,接 mask 且「主体保护」启用 | **1.000** ✅ |
|
||||
| 黑底,接 mask 但「主体保护」关闭 | 0.080(与不接完全一致,开关确实生效)|
|
||||
| 绿幕,不接 mask | 0.940 ✓ 本来就正常 |
|
||||
|
||||
原因是黑底 unmult 本质在用"亮度当不透明度",这对发光物成立,对实体不成立。**所以黑底的角色素材请用 [Lucida](#23-lucida-抠图--lucida-matting) 或 [FeyNobg](#22-feynobg-抠图--feynobg-matting) 这类语义抠图**,unmult 留给光效。
|
||||
根因是黑底 unmult 本质在用"亮度当不透明度",这对发光物成立、对实体不成立。**破法是接一路语义抠图(Lucida / FeyNobg / BiRefNet)的 alpha 进 `subject_mask`**:主体区域强制不透明,主体之外仍走 Unmult 的精确半透明。两者各取所长——语义模型负责"哪里是主体",Unmult 负责"边缘有多透"。
|
||||
|
||||
**四个抠图节点怎么选**:
|
||||
|
||||
|
||||
+20
-3
@@ -11,6 +11,7 @@
|
||||
|
||||
AI 主体保护(可选):接入 BiRefNet / FeyNobg 等抠图节点输出的 subject_mask,
|
||||
用 max(unmult_α, subject_mask) 合并,防止主体中与背景色相近的区域被误判为透明。
|
||||
该合并由「主体保护」开关控制,关闭时即便连了 mask 也不采纳。
|
||||
典型场景:黑底光效中人物穿黑衣 → 纯 Unmult 会让黑衣半透明,
|
||||
接入主体 mask 后黑衣区域强制保留为不透明。
|
||||
|
||||
@@ -96,15 +97,27 @@ class RuiUnmult:
|
||||
"黑点": ("FLOAT", {
|
||||
"default": 0.0, "min": 0.0, "max": 0.5, "step": 0.01,
|
||||
"display": "slider",
|
||||
"tooltip": "黑点(主体保护):低于此值的 alpha 强制归零。\n"
|
||||
"tooltip": "低于此值的 alpha 强制归零。\n"
|
||||
"调高可清除背景残留噪点,但过高会丢失边缘细节。"
|
||||
}),
|
||||
"白点": ("FLOAT", {
|
||||
"default": 1.0, "min": 0.3, "max": 1.0, "step": 0.01,
|
||||
"display": "slider",
|
||||
"tooltip": "白点(主体保护):高于此值的 alpha 强制归一。\n"
|
||||
"tooltip": "高于此值的 alpha 强制归一。\n"
|
||||
"调低可让主体更实、减少半透明损失,但过低会让边缘硬化。"
|
||||
}),
|
||||
"主体保护": ("BOOLEAN", {
|
||||
"default": True,
|
||||
"label_on": "启用",
|
||||
"label_off": "关闭",
|
||||
"tooltip": "是否采纳下方接入的 subject_mask。\n\n"
|
||||
"启用:alpha 取 max(unmult 结果, subject_mask),\n"
|
||||
" 主体区域强制不透明,光效边缘仍保留半透明。\n"
|
||||
" 黑底素材里的黑衣、黑发全靠它保住。\n\n"
|
||||
"关闭:即便已经连了 subject_mask 也完全不采纳,\n"
|
||||
" 等同于纯 Unmult。想对比「有无 AI 介入」的差别时,\n"
|
||||
" 拨这个开关即可,不必拔线。"
|
||||
}),
|
||||
},
|
||||
"optional": {
|
||||
"subject_mask": ("MASK", {
|
||||
@@ -114,7 +127,7 @@ class RuiUnmult:
|
||||
"主体内部强制不透明,光效边缘保留半透明。\n\n"
|
||||
"典型场景:黑底光效中人物穿黑衣 →\n"
|
||||
"纯 Unmult 会让黑衣半透明,接入主体 mask 后黑衣保留。\n\n"
|
||||
"不连接时等同于纯 Unmult,无 AI 介入。"
|
||||
"不连接、或上方「主体保护」关闭时,等同于纯 Unmult,无 AI 介入。"
|
||||
}),
|
||||
},
|
||||
}
|
||||
@@ -129,7 +142,11 @@ class RuiUnmult:
|
||||
bg_color = kwargs.get("bg_color", "#000000")
|
||||
alpha_low = kwargs.get("黑点", kwargs.get("alpha_low", 0.0))
|
||||
alpha_high = kwargs.get("白点", kwargs.get("alpha_high", 1.0))
|
||||
# 主体保护开关:关闭时彻底忽略 subject_mask,哪怕上游已经连线
|
||||
use_subject = kwargs.get("主体保护", kwargs.get("use_subject_mask", True))
|
||||
subject_mask_tensor = kwargs.get("subject_mask", None)
|
||||
if not use_subject:
|
||||
subject_mask_tensor = None
|
||||
|
||||
bg_rgb = _hex_to_rgb01(bg_color)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user