Compare commits

...
9 Commits
17 changed files with 101 additions and 46 deletions
+6
View File
@@ -52,6 +52,12 @@ git clone https://github.com/yolain/ComfyUI-Easy-Use
## 📜 更新日志
**v1.3.4**
- 修复 `easy seedList` 最大值 #879
- 为xyplot添加controlnet input #877
- 为 `easy indexAnything` 支持 `反向索引`
**v1.3.3**
- 删除CSS类名称`gird-cols-1` #859
+6
View File
@@ -47,6 +47,12 @@ Double-click install.bat to install the required dependencies
## 📜 Changelog
**v1.3.4**
- Fix `easy seedList` max_num #879
- Add controlnet input to xyplot #877
- Support `nagative indexing` for `easy indexAnything`
**v1.3.3**
- Removed the definition of the CSS class name gird-cols-1 #859
+1 -1
View File
@@ -1,4 +1,4 @@
__version__ = "1.3.3"
__version__ = "1.3.4"
import yaml
import json
+1 -1
View File
@@ -68,7 +68,7 @@
"name": "样式选择器显示类型",
"tooltip": "样式选择器显示类型,如果设置为“网格”,则显示为网格,如果设置为“列表”,则显示为列表",
"options": {
"Gird": "网格",
"Grid": "网格",
"List": "列表"
}
}
+2 -1
View File
@@ -430,7 +430,8 @@ class easyXYPlot():
strength = item[2]
start_percent = item[3]
end_percent = item[4]
positive, negative = easyControlnet().apply(control_net_name, image, positive, negative, strength, start_percent, end_percent, None, 1)
provided_control_net = item[5] if len(item) > 5 else None
positive, negative = easyControlnet().apply(control_net_name, image, positive, negative, strength, start_percent, end_percent, provided_control_net, 1)
# Flux guidance
if self.x_type == "Flux Guidance" or self.y_type == "Flux Guidance":
positive = plot_image_vars["positive_cond"] if "positive" in plot_image_vars else None
+9 -2
View File
@@ -1,5 +1,6 @@
import re
import torch
import folder_paths
import comfy.utils, comfy.sample, comfy.samplers, comfy.controlnet, comfy.model_base, comfy.model_management, comfy.sampler_helpers, comfy.supported_models
from comfy_extras.nodes_compositing import JoinImageWithAlpha
from comfy.clip_vision import load as load_clip_vision
@@ -180,7 +181,10 @@ class icLightApply:
image = self.removebg(image)
else:
mask = torch.full((1, height, width), 1.0, dtype=torch.float32, device="cpu")
image, = JoinImageWithAlpha().join_image_with_alpha(image, mask)
try:
image, = JoinImageWithAlpha().execute(image, mask)
except:
image, = JoinImageWithAlpha().join_image_with_alpha(image, mask)
iclight = ICLight()
if mode == 'Foreground':
@@ -190,7 +194,10 @@ class icLightApply:
if source not in ['Use Background Image', 'Use Flipped Background Image']:
_, height, width, _ = lighting_image.shape
mask = torch.full((1, height, width), 1.0, dtype=torch.float32, device="cpu")
lighting_image, = JoinImageWithAlpha().join_image_with_alpha(lighting_image, mask)
try:
lighting_image, = JoinImageWithAlpha().execute(lighting_image, mask)
except:
lighting_image, = JoinImageWithAlpha().join_image_with_alpha(lighting_image, mask)
if batch_size < 2:
image = self.batch(image, lighting_image)
else:
+7 -3
View File
@@ -1043,8 +1043,8 @@ class imageChooser(PreviewImage):
id = my_unique_id[0]
id = id.split('.')[len(id.split('.')) - 1] if "." in id else id
if (kwargs['images'] is None):
return (None,)
if (kwargs.get('images') is None):
return (torch.zeros(1, 1, 1, 3),)
images_in = torch.cat(kwargs.pop('images'))
for x in kwargs: kwargs[x] = kwargs[x][0]
@@ -1396,7 +1396,11 @@ class humanSegmentation:
alpha = 1.0 - mask
output_image, = JoinImageWithAlpha().join_image_with_alpha(image, alpha)
try:
output_image, = JoinImageWithAlpha().execute(image, alpha)
except:
output_image, = JoinImageWithAlpha().join_image_with_alpha(image, alpha)
elif method == "human_parts (deeplabv3p)":
if method in cache:
+4 -1
View File
@@ -331,7 +331,10 @@ class applyInpaint:
new_pipe = self.inpaint_model_conditioning(new_pipe, image, vae, mask, grow_mask_by, noise_mask=noise_mask)
cls = ALL_NODE_CLASS_MAPPINGS['DifferentialDiffusion']
if cls is not None:
model, = cls().apply(new_pipe['model'])
try:
model, = cls().execute(new_pipe['model'])
except Exception:
model, = cls().apply(new_pipe['model'])
new_pipe['model'] = model
else:
raise Exception("Differential Diffusion not found,please update comfyui")
+22 -5
View File
@@ -908,6 +908,10 @@ COMPARE_FUNCTIONS = {
"a > b": lambda a, b: a > b,
"a <= b": lambda a, b: a <= b,
"a >= b": lambda a, b: a >= b,
"a > 0": lambda a, b: a > 0,
"a <= 0": lambda a, b: a <= 0,
"b > 0": lambda a, b: b > 0,
"b <= 0": lambda a, b: b <= 0,
}
@@ -917,7 +921,7 @@ class Compare:
def INPUT_TYPES(s):
compare_functions = list(COMPARE_FUNCTIONS.keys())
return {
"required": {
"optional": {
"a": (any_type, {"default": 0}),
"b": (any_type, {"default": 0}),
"comparison": (compare_functions, {"default": "a == b"}),
@@ -929,7 +933,7 @@ class Compare:
FUNCTION = "compare"
CATEGORY = "EasyUse/Logic/Math"
def compare(self, a, b, comparison):
def compare(self, a=0, b=0, comparison="a == b"):
return (COMPARE_FUNCTIONS[comparison](a, b),)
@@ -1209,7 +1213,7 @@ class indexAnything:
return {
"required": {
"any": (any_type, {}),
"index": ("INT", {"default": 0, "min": 0, "max": 1000000, "step": 1}),
"index": ("INT", {"default": 0, "min": -1000000, "max": 1000000, "step": 1}),
},
"hidden":{
"prompt": "PROMPT",
@@ -1235,14 +1239,26 @@ class indexAnything:
node_class = ALL_NODE_CLASS_MAPPINGS[class_type]
output_is_list = node_class.OUTPUT_IS_LIST[slot] if hasattr(node_class, 'OUTPUT_IS_LIST') else False
def normalize_index(index, length):
"""标准化索引,处理负索引并确保在有效范围内"""
if index < 0:
index = length + index
if index < 0:
index = 0
return min(max(0, index), length - 1)
if output_is_list or len(any) > 1:
index = normalize_index(index, len(any))
return (any[index],)
elif isinstance(any[0], torch.Tensor):
batch_index = min(any[0].shape[0] - 1, index)
index = normalize_index(index, any[0].shape[0])
s = any[0][index:index + 1].clone()
return (s,)
else:
return (any[0][index],)
if hasattr(any[0], '__len__') and len(any[0]) > 0:
index = normalize_index(index, len(any[0]))
return (any[0][index],)
return (any[0],)
class batchAnything:
@@ -1790,3 +1806,4 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"easy saveText": "Save Text",
"easy sleep": "Sleep",
}
+23 -15
View File
@@ -1,6 +1,7 @@
import sys, re, time
import torch
import comfy.utils, comfy.sample, comfy.samplers, comfy.controlnet, comfy.model_base, comfy.model_management, comfy.sampler_helpers, comfy.supported_models
import folder_paths
from comfy.model_patcher import ModelPatcher
from comfy_extras.nodes_mask import GrowMask
import comfy_extras.nodes_custom_sampler as custom_samplers
@@ -118,7 +119,14 @@ class samplerFull:
def get_custom_cls(self, sampler_name):
try:
cls = custom_samplers.__dict__[sampler_name]
return cls()
cls = cls()
if hasattr(cls, "get_sigmas"):
cls.execute = cls.get_sigmas
elif hasattr(cls, "get_guider"):
cls.execute = cls.get_guider
elif hasattr(cls, "get_sampler"):
cls.execute = cls.get_sampler
return cls
except:
raise Exception(f"Custom sampler {sampler_name} not found, Please updated your ComfyUI")
@@ -156,15 +164,15 @@ class samplerFull:
sigmas = optional_sigmas
else:
if scheduler == 'vp':
sigmas, = self.get_custom_cls('VPScheduler').get_sigmas(steps, beta_d, beta_min, eps_s)
sigmas, = self.get_custom_cls('VPScheduler').execute(steps, beta_d, beta_min, eps_s)
elif scheduler == 'karrasADV':
sigmas, = self.get_custom_cls('KarrasScheduler').get_sigmas(steps, sigma_max, sigma_min, rho)
sigmas, = self.get_custom_cls('KarrasScheduler').execute(steps, sigma_max, sigma_min, rho)
elif scheduler == 'exponentialADV':
sigmas, = self.get_custom_cls('ExponentialScheduler').get_sigmas(steps, sigma_max, sigma_min)
sigmas, = self.get_custom_cls('ExponentialScheduler').execute(steps, sigma_max, sigma_min)
elif scheduler == 'polyExponential':
sigmas, = self.get_custom_cls('PolyexponentialScheduler').get_sigmas(steps, sigma_max, sigma_min, rho)
sigmas, = self.get_custom_cls('PolyexponentialScheduler').execute(steps, sigma_max, sigma_min, rho)
elif scheduler == 'sdturbo':
sigmas, = self.get_custom_cls('SDTurboScheduler').get_sigmas(model, steps, denoise)
sigmas, = self.get_custom_cls('SDTurboScheduler').execute(model, steps, denoise)
elif scheduler == 'alignYourSteps':
model_type = get_sd_version(model)
if model_type == 'unknown':
@@ -173,11 +181,11 @@ class samplerFull:
elif scheduler == 'gits':
sigmas, = gitsScheduler().get_sigmas(coeff, steps, denoise)
else:
sigmas, = self.get_custom_cls('BasicScheduler').get_sigmas(model, scheduler, steps, denoise)
sigmas, = self.get_custom_cls('BasicScheduler').execute(model, scheduler, steps, denoise)
# filp_sigmas
if flip_sigmas:
sigmas, = self.get_custom_cls('FlipSigmas').get_sigmas(sigmas)
sigmas, = self.get_custom_cls('FlipSigmas').execute(sigmas)
#######################################################################################
# brushnet
@@ -209,12 +217,12 @@ class samplerFull:
positive = c
if guider in ['CFG', 'IP2P+CFG']:
_guider, = self.get_custom_cls('CFGGuider').get_guider(model, positive, negative, cfg)
_guider, = self.get_custom_cls('CFGGuider').execute(model, positive, negative, cfg)
elif guider in ['DualCFG', 'IP2P+DualCFG']:
_guider, = self.get_custom_cls('DualCFGGuider').get_guider(model, positive, middle,
_guider, = self.get_custom_cls('DualCFGGuider').execute(model, positive, middle,
negative, cfg, cfg_negative)
else:
_guider, = self.get_custom_cls('BasicGuider').get_guider(model, positive)
_guider, = self.get_custom_cls('BasicGuider').execute(model, positive)
# sampler
if optional_sampler:
@@ -223,7 +231,7 @@ class samplerFull:
if sampler_name == 'inversed_euler':
_sampler, = self.get_inversed_euler_sampler()
else:
_sampler, = self.get_custom_cls('KSamplerSelect').get_sampler(sampler_name)
_sampler, = self.get_custom_cls('KSamplerSelect').execute(sampler_name)
return (_guider, _sampler, sigmas)
@@ -277,18 +285,18 @@ class samplerFull:
if width_downscale_factor > 1.75:
log_node_warn("Patch model unet add downscale...")
log_node_warn("Downscale factor:" + str(width_downscale_factor))
(samp_model,) = cls().patch(samp_model, downscale_options['block_number'], width_downscale_factor, 0, 0.35, True, "bicubic",
(samp_model,) = cls().execute(samp_model, downscale_options['block_number'], width_downscale_factor, 0, 0.35, True, "bicubic",
"bicubic")
elif height_downscale_factor > 1.25:
log_node_warn("Patch model unet add downscale....")
log_node_warn("Downscale factor:" + str(height_downscale_factor))
(samp_model,) = cls().patch(samp_model, downscale_options['block_number'], height_downscale_factor, 0, 0.35, True, "bicubic",
(samp_model,) = cls().execute(samp_model, downscale_options['block_number'], height_downscale_factor, 0, 0.35, True, "bicubic",
"bicubic")
else:
cls = ALL_NODE_CLASS_MAPPINGS['PatchModelAddDownscale']
log_node_warn("Patch model unet add downscale....")
log_node_warn("Downscale factor:" + str(downscale_options['downscale_factor']))
(samp_model,) = cls().patch(samp_model, downscale_options['block_number'], downscale_options['downscale_factor'], downscale_options['start_percent'], downscale_options['end_percent'], downscale_options['downscale_after_skip'], downscale_options['downscale_method'], downscale_options['upscale_method'])
(samp_model,) = cls().execute(samp_model, downscale_options['block_number'], downscale_options['downscale_factor'], downscale_options['start_percent'], downscale_options['end_percent'], downscale_options['downscale_after_skip'], downscale_options['downscale_method'], downscale_options['upscale_method'])
return samp_model
def process_sample_state(pipe, samp_model, samp_clip, samp_samples, samp_vae, samp_seed, samp_positive,
+1 -1
View File
@@ -27,7 +27,7 @@ class seedList:
return {
"required": {
"min_num": ("INT", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
"max_num": ("INT", {"default": MAX_SEED_NUM, "min": 0 }),
"max_num": ("INT", {"default": MAX_SEED_NUM, "max": MAX_SEED_NUM, "min": 0 }),
"method": (["random", "increment", "decrement"], {"default": "random"}),
"total": ("INT", {"default": 1, "min": 1, "max": 100000}),
"seed": ("INT", {"default": 0, "min": 0, "max": MAX_SEED_NUM,}),
+13 -10
View File
@@ -413,6 +413,9 @@ class XYplot_Control_Net:
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.00, "max": 1.0, "step": 0.01}),
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.00, "max": 1.0, "step": 0.01}),
},
"optional": {
"control_net": ("CONTROL_NET",),
},
}
RETURN_TYPES = ("X_Y",)
@@ -421,7 +424,7 @@ class XYplot_Control_Net:
CATEGORY = "EasyUse/XY Inputs"
def xy_value(self, control_net_name, image, target_parameter, batch_count, first_strength, last_strength, first_start_percent,
last_start_percent, first_end_percent, last_end_percent, strength, start_percent, end_percent):
last_start_percent, first_end_percent, last_end_percent, strength, start_percent, end_percent, control_net=None):
axis, = None,
@@ -430,38 +433,38 @@ class XYplot_Control_Net:
if target_parameter == "strength":
axis = "advanced: ControlNetStrength"
values.append([(control_net_name, image, first_strength, start_percent, end_percent)])
values.append([(control_net_name, image, first_strength, start_percent, end_percent, control_net)])
strength_increment = (last_strength - first_strength) / (batch_count - 1) if batch_count > 1 else 0
for i in range(1, batch_count - 1):
values.append([(control_net_name, image, first_strength + i * strength_increment, start_percent,
end_percent)])
end_percent, control_net)])
if batch_count > 1:
values.append([(control_net_name, image, last_strength, start_percent, end_percent)])
values.append([(control_net_name, image, last_strength, start_percent, end_percent, control_net)])
elif target_parameter == "start_percent":
axis = "advanced: ControlNetStart%"
percent_increment = (last_start_percent - first_start_percent) / (batch_count - 1) if batch_count > 1 else 0
values.append([(control_net_name, image, strength, first_start_percent, end_percent)])
values.append([(control_net_name, image, strength, first_start_percent, end_percent, control_net)])
for i in range(1, batch_count - 1):
values.append([(control_net_name, image, strength, first_start_percent + i * percent_increment,
end_percent)])
end_percent, control_net)])
# Always add the last start_percent if batch_count is more than 1.
if batch_count > 1:
values.append((control_net_name, image, strength, last_start_percent, end_percent))
values.append([(control_net_name, image, strength, last_start_percent, end_percent, control_net)])
elif target_parameter == "end_percent":
axis = "advanced: ControlNetEnd%"
percent_increment = (last_end_percent - first_end_percent) / (batch_count - 1) if batch_count > 1 else 0
values.append([(control_net_name, image, image, strength, start_percent, first_end_percent)])
values.append([(control_net_name, image, strength, start_percent, first_end_percent, control_net)])
for i in range(1, batch_count - 1):
values.append([(control_net_name, image, strength, start_percent,
first_end_percent + i * percent_increment)])
first_end_percent + i * percent_increment, control_net)])
if batch_count > 1:
values.append([(control_net_name, image, strength, start_percent, last_end_percent)])
values.append([(control_net_name, image, strength, start_percent, last_end_percent, control_net)])
return ({"axis": axis, "values": values},)
+2 -2
View File
@@ -1,9 +1,9 @@
[project]
name = "comfyui-easy-use"
description = "To enhance the usability of ComfyUI, optimizations and integrations have been implemented for several commonly used nodes."
version = "1.3.3"
version = "1.3.4"
license = { file = "LICENSE" }
dependencies = ["diffusers", "accelerate", "clip_interrogator>=0.6.0", "sentencepiece", "lark", "onnxruntime", "spandrel", "opencv-python", "matplotlib", "peft"]
dependencies = ["diffusers", "accelerate", "clip_interrogator>=0.6.0", "sentencepiece", "lark", "onnxruntime", "spandrel", "opencv-python-headless", "matplotlib", "peft"]
[project.urls]
Repository = "https://github.com/yolain/ComfyUI-Easy-Use"
+1 -1
View File
@@ -3,7 +3,7 @@ accelerate
clip_interrogator>=0.6.0
lark
onnxruntime
opencv-python
opencv-python-headless
sentencepiece
spandrel
matplotlib
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long