diff --git a/README.MD b/README.MD
index ac57ff2..f922877 100644
--- a/README.MD
+++ b/README.MD
@@ -80,6 +80,7 @@ When this error has occurred, please check the network environment.
## Update
**If the dependency package error after updating, please reinstall the relevant dependency packages.
+* [GetColorToneV2](#GetColorToneV2) node add the ```mask``` method to the color selection option, which can accurately obtain the main color and average color within the mask.
* [ImageScaleByAspectRatioV2](#ImageScaleByAspectRatioV2) node add the "background_color" option.
* [LUT Apply](#LUT) Add the "strength" option.
* Commit [AutoAdjustV2](#AutoAdjustV2) node, add optional mask input and support for multiple automatic color adjustment modes.
@@ -814,13 +815,14 @@ V2 upgrade of GetColorTone. You can specify the dominant or average color to get
The following changes have been made on the basis of GetColorTong:

-* color_of: Provides three options, entire, background, and subject, to select the color of the entire picture, background, or body, respectively.
+* color_of: Provides 4 options, mask, entire, background, and subject, to select the color of the mask area, entire picture, background, or subject, respectively.
* remove_background_method: There are two methods of background recognition: BiRefNet and RMBG V1.4.
* invert_mask: Whether to reverse the mask.
* mask_grow: Mask expansion. For subject, a larger value brings the obtained color closer to the color at the center of the body.
Output:
* image: Solid color picture output, the size is the same as the input picture.
+* mask: Mask output.
### ExtendCanvas
Extend the canvas
diff --git a/README_CN.MD b/README_CN.MD
index cd6c3fd..fb9bc9a 100644
--- a/README_CN.MD
+++ b/README_CN.MD
@@ -80,6 +80,7 @@ git clone https://github.com/chflame163/ComfyUI_LayerStyle.git
## 更新说明
**如果本插件更新后出现依赖包错误,请重新安装相关依赖包。
+* [GetColorToneV2](#GetColorToneV2) 节点的取色选项增加```mask```方法,可精确获取遮罩内的主色和平均色。
* [ImageScaleByAspectRatioV2](#ImageScaleByAspectRatioV2) 节点增加background_color选项。
* [LUT Apply](#LUT) 节点增加strenght选项。
* 添加 [AutoAdjustV2](#AutoAdjustV2) 节点,增加可选遮罩输入,增加多种自动调色模式支持。
@@ -800,18 +801,19 @@ ImageScaleByAspectRatio的V2升级版
### GetColorToneV2
GetColorTone的V2升级版。可以指定获取主体或背景的主色或平均色。
-
+
+
在GetColorTong基础上做了如下改变:

-* color_of: 提供三个选项,entire, background和subject, 分别表示选择整个图片,背景,或主体的颜色。
+* color_of: 提供4个选项,mask, entire, background和subject, 分别表示选择遮罩区域,整个图片,背景,或主体的颜色。
* remove_background_method: 背景识别的方法, 有BiRefNet和RMBG V1.4两种可以选择。
* invert_mask: 是否反转遮罩。
* mask_grow: 遮罩扩张。对于subject, 更大的值使获得的颜色更接近主体中心的颜色。
输出:
* image: 纯色图片输出, 尺寸与输入的图片相同。
-
+* mask: 遮罩输出。
### ExtendCanvas
扩展画布。
diff --git a/image/get_color_tone_v2_example2.jpg b/image/get_color_tone_v2_example2.jpg
new file mode 100644
index 0000000..606ebc9
Binary files /dev/null and b/image/get_color_tone_v2_example2.jpg differ
diff --git a/image/get_color_tone_v2_node.jpg b/image/get_color_tone_v2_node.jpg
index 8717c99..5f656a9 100644
Binary files a/image/get_color_tone_v2_node.jpg and b/image/get_color_tone_v2_node.jpg differ
diff --git a/py/get_color_tone_v2.py b/py/get_color_tone_v2.py
index be16ecc..630548b 100644
--- a/py/get_color_tone_v2.py
+++ b/py/get_color_tone_v2.py
@@ -9,8 +9,8 @@ class GetColorToneV2:
@classmethod
def INPUT_TYPES(self):
- remove_background_list = ['BiRefNet', 'RMBG 1.4',]
- subject_list = ['entire', 'background', 'subject']
+ remove_background_list = ['none','BiRefNet', 'RMBG 1.4',]
+ subject_list = ['mask','entire', 'background', 'subject']
mode_list = ['main_color', 'average']
return {
"required": {
@@ -19,15 +19,15 @@ class GetColorToneV2:
"color_of": (subject_list,),
"remove_bkgd_method": (remove_background_list,),
"invert_mask": ("BOOLEAN", {"default": False}), # 反转mask#
- "mask_grow": ("INT", {"default": 16, "min": -999, "max": 999, "step": 1}),
+ "mask_grow": ("INT", {"default": 0, "min": -999, "max": 999, "step": 1}),
},
"optional": {
"mask": ("MASK",), #
}
}
- RETURN_TYPES = ("IMAGE", "STRING", "LIST",)
- RETURN_NAMES = ("image", "color_in_hex", "HSV color in list",)
+ RETURN_TYPES = ("IMAGE", "STRING", "LIST", "MASK")
+ RETURN_NAMES = ("image", "color_in_hex", "HSV color in list", "mask",)
FUNCTION = 'get_color_tone_v2'
CATEGORY = '😺dzNodes/LayerUtility'
@@ -38,6 +38,7 @@ class GetColorToneV2:
_images = []
_masks = []
ret_images = []
+ ret_masks = []
need_rmbg = False
for i in image:
_images.append(torch.unsqueeze(i, 0))
@@ -45,14 +46,15 @@ class GetColorToneV2:
if m.mode == 'RGBA':
_masks.append(1 - image2mask(m.split()[-1]))
else:
- need_rmbg = True
+ _masks.append(pil2tensor(Image.new("L", (m.width, m.height), color="white")))
+ if remove_bkgd_method != 'none':
+ need_rmbg = True
+
if mask is not None:
if mask.dim() == 2:
mask = torch.unsqueeze(mask, 0)
_masks = []
for m in mask:
- if not invert_mask:
- m = 1 - m
_masks.append(torch.unsqueeze(m, 0))
need_rmbg = False
@@ -71,32 +73,40 @@ class GetColorToneV2:
else:
_mask = RMBG(_image)
_mask = image2mask(_mask)
- _mask = 1 - _mask
else:
_mask = _masks[i] if i < len(_masks) else _masks[-1]
+ if invert_mask:
+ _mask = 1 - _mask
+
if mask_grow != 0:
_mask = expand_mask(_mask, mask_grow, 0) # 扩张,模糊
- if color_of == 'subject':
- _mask = 1 - _mask
-
if color_of == 'entire':
blured_image = gaussian_blur(_image, int((_image.width + _image.height) / 400))
else:
+ if color_of == 'background':
+ _mask = 1 - _mask
_mask = tensor2pil(_mask)
pixel_spread_image = pixel_spread(_image, _mask.convert('RGB'))
blured_image = gaussian_blur(pixel_spread_image, int((_image.width + _image.height) / 400))
- if mode == 'main_color':
+
+ ret_color = '#000000'
+ if mode == 'main_color' and color_of != 'mask':
ret_color = get_image_color_tone(blured_image)
- else:
+ elif mode == 'average' and color_of != 'mask':
ret_color = get_image_color_average(blured_image)
+ elif mode == 'main_color' and color_of == 'mask':
+ ret_color = get_image_color_tone(blured_image, mask=_mask)
+ elif mode == 'average' and color_of == 'mask':
+ ret_color = get_image_color_average(blured_image, mask=_mask)
ret_image = Image.new('RGB', size=_image.size, color=ret_color)
ret_images.append(pil2tensor(ret_image))
+ ret_masks.append(pil2tensor(_mask))
log(f"{NODE_NAME} Processed {len(ret_images)} image(s).", message_type='finish')
hsv_color = RGB_to_HSV(Hex_to_RGB(ret_color))
- return (torch.cat(ret_images, dim=0), ret_color, hsv_color,)
+ return (torch.cat(ret_images, dim=0), ret_color, hsv_color, torch.cat(ret_masks, dim=0),)
NODE_CLASS_MAPPINGS = {
"LayerUtility: GetColorToneV2": GetColorToneV2
diff --git a/py/imagefunc.py b/py/imagefunc.py
index ceb400f..1fa46e7 100644
--- a/py/imagefunc.py
+++ b/py/imagefunc.py
@@ -893,12 +893,22 @@ def adjust_levels(image:Image, input_black:int=0, input_white:int=255, midtones:
img = img.astype(np.uint8)
return cv22pil(img)
-
-def get_image_color_tone(image:Image) -> str:
+def get_image_color_tone(image:Image, mask:Image=None) -> str:
image = image.convert('RGB')
max_score = 0.0001
dominant_color = (255, 255, 255)
- for count, (r, g, b) in image.getcolors(image.width * image.height):
+ if mask is not None:
+ if mask.mode != 'L':
+ mask = mask.convert('L')
+ canvas = Image.new('RGB', size=image.size, color='black')
+ canvas.paste(image, mask=mask)
+ image = canvas
+
+ all_colors = image.getcolors(image.width * image.height)
+ for count, (r, g, b) in all_colors:
+ if mask is not None:
+ if r + g + b < 2: # 忽略黑色
+ continue
saturation = colorsys.rgb_to_hsv(r / 255.0, g / 255.0, b / 255.0)[1]
y = min(abs(r * 2104 + g * 4130 + b * 802 + 4096 + 131072) >> 13,235)
y = (y - 16.0) / (235 - 16)
@@ -909,22 +919,29 @@ def get_image_color_tone(image:Image) -> str:
ret_color = RGB_to_Hex(dominant_color)
return ret_color
-def get_image_color_average(image:Image) -> str:
+def get_image_color_average(image:Image, mask:Image=None) -> str:
image = image.convert('RGB')
width, height = image.size
total_red = 0
total_green = 0
total_blue = 0
+ total_pixel =0
for y in range(height):
for x in range(width):
+ if mask is not None:
+ if mask.mode != 'L':
+ mask = mask.convert('L')
+ if mask.getpixel((x, y)) <= 127:
+ continue
rgb = image.getpixel((x, y))
total_red += rgb[0]
total_green += rgb[1]
total_blue += rgb[2]
+ total_pixel += 1
- average_red = total_red // (width * height)
- average_green = total_green // (width * height)
- average_blue = total_blue // (width * height)
+ average_red = total_red // total_pixel
+ average_green = total_green // total_pixel
+ average_blue = total_blue // total_pixel
color = (average_red, average_green, average_blue)
ret_color = RGB_to_Hex(color)
return ret_color
diff --git a/pyproject.toml b/pyproject.toml
index 7f297a1..99ddead 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,7 +1,7 @@
[project]
name = "comfyui_layerstyle"
description = "A set of nodes for ComfyUI it generate image like Adobe Photoshop's Layer Style. the Drop Shadow is first completed node, and follow-up work is in progress."
-version = "1.0.12"
+version = "1.0.13"
license = "MIT"
dependencies = ["numpy", "pillow", "torch", "matplotlib", "Scipy", "scikit_image", "opencv-contrib-python", "pymatting", "segment_anything", "timm", "addict", "yapf", "colour-science", "wget", "mediapipe", "loguru", "typer_config", "fastapi", "rich", "google-generativeai", "diffusers", "omegaconf", "tqdm", "transformers", "kornia", "image-reward", "ultralytics", "blend_modes", "blind-watermark", "qrcode", "pyzbar", "psd-tools"]