diff --git a/README.MD b/README.MD
index ad2674e..bebe5ee 100644
--- a/README.MD
+++ b/README.MD
@@ -1382,6 +1382,7 @@ Generate a mask based on the selected color.
Node Options:

* image: Input image.
+* mask: This input is optional, if there is a mask, only the colors inside the mask are included in the range.
* color: Color selector. Click on the color block to select a color, and you can use the straws on the color picker panel to pick up the screen color. Note: When using straws, maximize the browser window.
* color_in_HEX4: Enter color values. If this item has input, it will be used first, ignoring the color selected by the ```color``` .
* threshold: Mask range threshold, the larger the value, the larger the mask range.
diff --git a/README_CN.MD b/README_CN.MD
index 789ad52..024c017 100644
--- a/README_CN.MD
+++ b/README_CN.MD
@@ -1368,6 +1368,7 @@ PersonMaskUltra的V2升级版,增加了VITMatte边缘处理方法。(注意:
节点选项说明:

* image: 图像输入。
+* mask: 遮罩输入。此输入是可选项,如果有遮罩则仅遮罩内的颜色被纳入范围。
* color: 颜色选择器。点击色块选择颜色,可以使用选色器面板上的吸管拾取屏幕颜色。注意:使用吸管时,需将浏览器窗口最大化。
* color_in_HEX4: 输入色值。如果此项有输入,则优先使用,忽略```color```选取的颜色。
* threshold: 遮罩范围阈值,数值越大,遮罩范围越大。
diff --git a/image/mask_by_color_example.jpg b/image/mask_by_color_example.jpg
index 4dcb74c..a7688db 100644
Binary files a/image/mask_by_color_example.jpg and b/image/mask_by_color_example.jpg differ
diff --git a/image/mask_by_color_node.jpg b/image/mask_by_color_node.jpg
index 7a0e341..fc6561a 100644
Binary files a/image/mask_by_color_node.jpg and b/image/mask_by_color_node.jpg differ
diff --git a/py/mask_by_color.py b/py/mask_by_color.py
index 03e253d..8888c1b 100644
--- a/py/mask_by_color.py
+++ b/py/mask_by_color.py
@@ -15,6 +15,9 @@ class MaskByColor:
"fix_gap": ("INT", {"default": 2, "min": 0, "max": 32, "step": 1}),
"fix_threshold": ("FLOAT", {"default": 0.75, "min": 0.01, "max": 0.99, "step": 0.01}),
"invert_mask": ("BOOLEAN", {"default": False}), # 反转mask
+ },
+ "optional": {
+ "mask": ("MASK",), #
}
}
@@ -24,20 +27,41 @@ class MaskByColor:
CATEGORY = '😺dzNodes/LayerMask'
def mask_by_color(self, image, color, color_in_HEX, threshold,
- fix_gap, fix_threshold, invert_mask):
+ fix_gap, fix_threshold, invert_mask, mask=None):
if color_in_HEX != "" and color_in_HEX.startswith('#') and len(color_in_HEX) == 7:
color = color_in_HEX
ret_masks = []
+ l_images = []
+ l_masks = []
- for i in image:
- img = tensor2pil(i.unsqueeze(0))
- mask = create_mask_from_color_tensor(img, color, threshold)
+ for l in image:
+ l_images.append(torch.unsqueeze(l, 0))
+ m = tensor2pil(l)
+ if m.mode == 'RGBA':
+ l_masks.append(m.split()[-1])
+ else:
+ l_masks.append(Image.new('L', m.size, 'white'))
+ if mask is not None:
+ if mask.dim() == 2:
+ mask = torch.unsqueeze(mask, 0)
+ l_masks = []
+ for m in mask:
+ if invert_mask:
+ m = 1 - m
+ l_masks.append(tensor2pil(torch.unsqueeze(m, 0)).convert('L'))
+
+ for i in range(len(l_images)):
+ img = l_images[i] if i < len(l_images) else l_images[-1]
+ img = tensor2pil(img)
+ _mask = l_masks[i] if i < len(l_masks) else l_masks[-1]
+
+ mask = Image.new('L', _mask.size, 'black')
+ mask.paste(create_mask_from_color_tensor(img, color, threshold), mask=_mask)
mask = image2mask(mask)
if invert_mask:
mask = 1 - mask
-
if fix_gap:
mask = mask_fix(mask, 1, fix_gap, fix_threshold, fix_threshold)
ret_masks.append(mask)
diff --git a/workflow/mask_by_color_example.json b/workflow/mask_by_color_example.json
new file mode 100644
index 0000000..fccc72c
--- /dev/null
+++ b/workflow/mask_by_color_example.json
@@ -0,0 +1,216 @@
+{
+ "last_node_id": 14,
+ "last_link_id": 17,
+ "nodes": [
+ {
+ "id": 13,
+ "type": "LayerMask: RmBgUltra V2",
+ "pos": [
+ 391,
+ 687
+ ],
+ "size": {
+ "0": 315,
+ "1": 198
+ },
+ "flags": {},
+ "order": 1,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "link": 14
+ }
+ ],
+ "outputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "links": null,
+ "shape": 3
+ },
+ {
+ "name": "mask",
+ "type": "MASK",
+ "links": [
+ 17
+ ],
+ "shape": 3,
+ "slot_index": 1
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LayerMask: RmBgUltra V2"
+ },
+ "widgets_values": [
+ "VITMatte",
+ 6,
+ 6,
+ 0.01,
+ 0.99,
+ false
+ ]
+ },
+ {
+ "id": 9,
+ "type": "LayerMask: MaskPreview",
+ "pos": [
+ 1145,
+ 509
+ ],
+ "size": {
+ "0": 438.5014343261719,
+ "1": 316.36749267578125
+ },
+ "flags": {},
+ "order": 3,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "mask",
+ "type": "MASK",
+ "link": 13
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LayerMask: MaskPreview"
+ }
+ },
+ {
+ "id": 2,
+ "type": "LoadImage",
+ "pos": [
+ -103,
+ 516
+ ],
+ "size": [
+ 419.90505599864827,
+ 365.47580918489507
+ ],
+ "flags": {},
+ "order": 0,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 12,
+ 14
+ ],
+ "shape": 3,
+ "slot_index": 0
+ },
+ {
+ "name": "MASK",
+ "type": "MASK",
+ "links": null,
+ "shape": 3
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ },
+ "widgets_values": [
+ "1344x768_redcar (1).png",
+ "image"
+ ]
+ },
+ {
+ "id": 12,
+ "type": "LayerMask: MaskByColor",
+ "pos": [
+ 774,
+ 519
+ ],
+ "size": {
+ "0": 293.6735534667969,
+ "1": 242.63502502441406
+ },
+ "flags": {},
+ "order": 2,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "link": 12
+ },
+ {
+ "name": "mask",
+ "type": "MASK",
+ "link": 17
+ }
+ ],
+ "outputs": [
+ {
+ "name": "mask",
+ "type": "MASK",
+ "links": [
+ 13
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LayerMask: MaskByColor"
+ },
+ "widgets_values": [
+ "#e64549",
+ "",
+ 100,
+ 2,
+ 0.75,
+ false
+ ]
+ }
+ ],
+ "links": [
+ [
+ 12,
+ 2,
+ 0,
+ 12,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 13,
+ 12,
+ 0,
+ 9,
+ 0,
+ "MASK"
+ ],
+ [
+ 14,
+ 2,
+ 0,
+ 13,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 17,
+ 13,
+ 1,
+ 12,
+ 1,
+ "MASK"
+ ]
+ ],
+ "groups": [],
+ "config": {},
+ "extra": {
+ "ds": {
+ "scale": 1.0610764609500107,
+ "offset": [
+ 424.17121706587216,
+ -130.40930841577526
+ ]
+ }
+ },
+ "version": 0.4
+}
\ No newline at end of file