Upgrade to v1.0.9
This commit is contained in:
+12
-15
@@ -29,7 +29,7 @@ After installing the node package, the UI interface will be automatically switch
|
||||
|
||||
### Stable Cascade
|
||||
|
||||
[WorkFlow Example](https://github.com/yolain/ComfyUI-Easy-Use?tab=readme-ov-file#StableCascade) <br><br>
|
||||
[WorkFlow Example](https://github.com/yolain/ComfyUI-Easy-Use/blob/main/README.en.md#StableCascade) <br><br>
|
||||
Currently, txt2img and img2img are supported,Lora and Controlnet are comming soon!<br><br>
|
||||
|
||||
Usage:<br>
|
||||
@@ -39,24 +39,21 @@ Usage:<br>
|
||||
|
||||
## Changelog
|
||||
|
||||
**2024-02-29**
|
||||
**v1.0.9 [2024-3-2]**
|
||||
|
||||
- Fixed `easy svdLoader` error when the positive or negative is empty
|
||||
- Added `easy instantIDApply` - you need installed [ComfyUI_InstantID](https://github.com/cubiq/ComfyUI_InstantID) fisrt, Workflow[Example](https://github.com/yolain/ComfyUI-Easy-Use/blob/main/README.en.md#InstantID)
|
||||
- Fixed `easy detailerFix` not added to the list of nodes available for saving images formatting extensions
|
||||
- Fixed `easy XYInputs: PromptSR` errors are reported when replacing negative prompts
|
||||
|
||||
**2024-02-28**
|
||||
|
||||
- Fixed the issue that 'easy preSampling' and other similar node, latent could not be generated based on the batch index after passing in
|
||||
|
||||
**2024-02-26**
|
||||
|
||||
- `easy fullLoader` **positive**、**negative**、**latent** added to the output items
|
||||
- Fixed the error of SDXLClipModel in ComfyUI revision 2016[c2cb8e88] and above (the revision number was judged to be compatible with the old revision)
|
||||
- Fixed `easy detailerFix` generation error when batch size is greater than 1
|
||||
|
||||
**v1.0.8(2024-02-25)**
|
||||
**v1.0.8 (f28cbf7)**
|
||||
|
||||
- `easy cascadeLoader` stage_c and stage_b support the checkpoint model (Download [checkpoints](https://huggingface.co/stabilityai/stable-cascade/tree/main/comfyui_checkpoints) models)
|
||||
- `easy styleSelector` The search box is modified to be case-insensitive
|
||||
- `easy fullLoader` **positive**、**negative**、**latent** added to the output items
|
||||
- Fixed the issue that 'easy preSampling' and other similar node, latent could not be generated based on the batch index after passing in
|
||||
- Fixed `easy svdLoader` error when the positive or negative is empty
|
||||
- Fixed the error of SDXLClipModel in ComfyUI revision 2016[c2cb8e88] and above (the revision number was judged to be compatible with the old revision)
|
||||
- Fixed `easy detailerFix` generation error when batch size is greater than 1
|
||||
- Optimize the code, reduce a lot of redundant code and improve the running speed
|
||||
|
||||
**v1.0.7 (2024-02-19)**
|
||||
@@ -66,7 +63,7 @@ Usage:<br>
|
||||
- Added `easy fullCascadeKSampler` - stable cascade stage-c ksampler full
|
||||
- Added `easy cascadeKSampler` - stable cascade stage-c ksampler simple
|
||||
-
|
||||
- Optimize the image to image[Example](https://github.com/yolain/ComfyUI-Easy-Use?tab=readme-ov-file#image-to-image)
|
||||
- Optimize the image to image[Example](https://github.com/yolain/ComfyUI-Easy-Use/blob/main/README.en.md#image-to-image)
|
||||
|
||||
**v1.0.6**
|
||||
|
||||
|
||||
@@ -43,33 +43,28 @@ stage_c 与 stage_b 可以使用[checkpoints](https://huggingface.co/stabilityai
|
||||
|
||||
## 更新日志
|
||||
|
||||
**2024-02-29**
|
||||
|
||||
- 修复 `easy svdLoader` 报错
|
||||
**v1.0.9 [2024-3-2]**
|
||||
|
||||
**2024-02-28**
|
||||
- 新增 `easy instantIDApply` - 需要先安装 [ComfyUI_InstantID](https://github.com/cubiq/ComfyUI_InstantID), 工作流参考[示例](https://github.com/yolain/ComfyUI-Easy-Use?tab=readme-ov-file#InstantID)
|
||||
- 修复 `easy detailerFix` 未添加到保存图片格式化扩展名可用节点列表
|
||||
- 修复 `easy XYInputs: PromptSR` 在替换负面提示词时报错
|
||||
|
||||
**v1.0.8 (f28cbf7)**
|
||||
|
||||
- `easy cascadeLoader` stage_c 与 stage_b 支持checkpoint模型 (需要下载[checkpoints](https://huggingface.co/stabilityai/stable-cascade/tree/main/comfyui_checkpoints))
|
||||
- `easy styleSelector` 搜索框修改为不区分大小写匹配
|
||||
- `easy fullLoader` 增加 **positive**、**negative**、**latent** 输出项
|
||||
- 修复 SDXLClipModel 在 ComfyUI 修订版本号 2016[c2cb8e88] 及以上的报错(判断了版本号可兼容老版本)
|
||||
- 修复 `easy detailerFix` 批次大小大于1时生成出错
|
||||
- 修复`easy preSampling`等 latent传入后无法根据批次索引生成的问题
|
||||
|
||||
**2024-02-27**
|
||||
|
||||
- 修复 `easy svdLoader` 报错
|
||||
- 优化代码,减少了诸多冗余,提升运行速度
|
||||
- 去除中文翻译对照文本
|
||||
|
||||
(翻译对照已由 [AIGODLIKE-COMFYUI-TRANSLATION](https://github.com/AIGODLIKE/AIGODLIKE-ComfyUI-Translation) 统一维护啦!
|
||||
首次下载或者版本较早的朋友请更新 AIGODLIKE-COMFYUI-TRANSLATION 和本节点包至最新版本。)
|
||||
|
||||
**2024-02-26**
|
||||
|
||||
- `easy fullLoader` 增加 **positive**、**negative**、**latent** 输出项
|
||||
- 修复 SDXLClipModel 在 ComfyUI 修订版本号 2016[c2cb8e88] 及以上的报错(判断了版本号可兼容老版本)
|
||||
- 修复 `easy detailerFix` 批次大小大于1时生成出错
|
||||
|
||||
**v1.0.8(2024-02-25)**
|
||||
|
||||
- `easy cascadeLoader` stage_c 与 stage_b 支持checkpoint模型 (需要下载[checkpoints](https://huggingface.co/stabilityai/stable-cascade/tree/main/comfyui_checkpoints))
|
||||
- `easy styleSelector` 搜索框修改为不区分大小写匹配
|
||||
- 优化代码,减少了诸多冗余,提升运行速度
|
||||
|
||||
**v1.0.7**
|
||||
|
||||
- 增加 `easy cascadeLoader` - stable cascade 加载器
|
||||
@@ -255,9 +250,9 @@ stage_c 与 stage_b 可以使用[checkpoints](https://huggingface.co/stabilityai
|
||||
|
||||
<img src="https://raw.githubusercontent.com/yolain/yolain-comfyui-workflow/main/Workflows/Simple/image_to_image_controlnet.png">
|
||||
|
||||
#### SDTurbo+高清修复+SVD
|
||||
#### InstantID
|
||||
|
||||
<img src="https://raw.githubusercontent.com/yolain/yolain-comfyui-workflow/main/Workflows/Simple/sdturbo_hiresfix_svd.png">
|
||||
<img src="https://raw.githubusercontent.com/yolain/yolain-comfyui-workflow/main/Workflows/Simple/instantID.png">
|
||||
|
||||
### StableCascade
|
||||
#### 文生图
|
||||
@@ -266,6 +261,7 @@ stage_c 与 stage_b 可以使用[checkpoints](https://huggingface.co/stabilityai
|
||||
#### 图生图
|
||||
<img src="https://raw.githubusercontent.com/yolain/yolain-comfyui-workflow/main/Workflows/StableCascade/image_to_image.png">
|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
[ComfyUI](https://github.com/comfyanonymous/ComfyUI) - 功能强大且模块化的Stable Diffusion GUI
|
||||
|
||||
+1
-1
@@ -74,4 +74,4 @@ WEB_DIRECTORY = "./web"
|
||||
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS', "WEB_DIRECTORY"]
|
||||
|
||||
|
||||
print('\033[34mComfy-Easy-Use (v1.0.8): \033[92mLoaded\033[0m')
|
||||
print('\033[34mComfy-Easy-Use (v1.0.9): \033[92mLoaded\033[0m')
|
||||
+91
-22
@@ -1441,6 +1441,7 @@ class controlnetSimple:
|
||||
"loader_settings": pipe["loader_settings"]
|
||||
}
|
||||
|
||||
del pipe
|
||||
return (new_pipe, positive, negative)
|
||||
|
||||
# controlnetADV
|
||||
@@ -1535,6 +1536,8 @@ class LLLiteLoader:
|
||||
|
||||
return (model_lllite,)
|
||||
|
||||
#---------------------------------------------------------------测试 开始----------------------------------------------------------------------#
|
||||
|
||||
# FooocusInpaint (Testing)
|
||||
from .fooocus import InpaintHead, InpaintWorker
|
||||
inpaint_head_model = None
|
||||
@@ -1567,6 +1570,90 @@ class fooocusInpaintLoader:
|
||||
|
||||
return ((inpaint_head_model, inpaint_lora),)
|
||||
|
||||
#Apply InstantID
|
||||
class instantIDApply:
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required":{
|
||||
"pipe": ("PIPE_LINE",),
|
||||
"image": ("IMAGE",),
|
||||
"instantid_file": (folder_paths.get_filename_list("instantid"),),
|
||||
"insightface": (["CPU", "CUDA", "ROCM"],),
|
||||
"control_net_name": (folder_paths.get_filename_list("controlnet"),),
|
||||
"cn_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"cn_soft_weights": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001},),
|
||||
"weight": ("FLOAT", {"default": .8, "min": 0.0, "max": 5.0, "step": 0.01, }),
|
||||
"start_at": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001, }),
|
||||
"end_at": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001, }),
|
||||
"noise": ("FLOAT", {"default": 0.35, "min": 0.0, "max": 1.0, "step": 0.05, }),
|
||||
},
|
||||
"optional": {
|
||||
"image_kps": ("IMAGE",),
|
||||
"mask": ("MASK",),
|
||||
"control_net": ("CONTROL_NET",),
|
||||
},
|
||||
"hidden": {
|
||||
"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO", "my_unique_id": "UNIQUE_ID"
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("PIPE_LINE", "MODEL", "CONDITIONING", "CONDITIONING")
|
||||
RETURN_NAMES = ("pipe", "model", "positive", "negative")
|
||||
OUTPUT_NODE = True
|
||||
|
||||
FUNCTION = "apply"
|
||||
CATEGORY = "EasyUse/__for_testing"
|
||||
|
||||
def error(self):
|
||||
raise Exception(f"[ERROR] To use instantIDApply, you need to install 'ComfyUI_InstantID'")
|
||||
|
||||
def apply(self, pipe, image, instantid_file, insightface, control_net_name, cn_strength, cn_soft_weights, weight, start_at, end_at, noise, image_kps=None, mask=None, control_net=None, prompt=None, extra_pnginfo=None, my_unique_id=None):
|
||||
instantid_model, insightface_model, face_embeds = None, None, None
|
||||
model = pipe['model']
|
||||
positive = pipe['positive']
|
||||
negative = pipe['negative']
|
||||
# Load InstantID
|
||||
if "InstantIDModelLoader" in ALL_NODE_CLASS_MAPPINGS:
|
||||
load_instant_cls = ALL_NODE_CLASS_MAPPINGS["InstantIDModelLoader"]
|
||||
instantid_model, = load_instant_cls().load_model(instantid_file)
|
||||
else:
|
||||
self.error()
|
||||
if "InstantIDFaceAnalysis" in ALL_NODE_CLASS_MAPPINGS:
|
||||
load_insightface_cls = ALL_NODE_CLASS_MAPPINGS["InstantIDFaceAnalysis"]
|
||||
insightface_model, = load_insightface_cls().load_insight_face(insightface)
|
||||
else:
|
||||
self.error()
|
||||
|
||||
# Apply InstantID
|
||||
if "ApplyInstantID" in ALL_NODE_CLASS_MAPPINGS:
|
||||
instantid_apply = ALL_NODE_CLASS_MAPPINGS['ApplyInstantID']
|
||||
control_net = easyControlnet().load_controlnet(control_net_name, control_net, cn_soft_weights)
|
||||
model, positive, negative = instantid_apply().apply_instantid(instantid_model, insightface_model, control_net, image, model, positive, negative, start_at, end_at, weight=weight, ip_weight=None, cn_strength=cn_strength, noise=noise, image_kps=image_kps, mask=None)
|
||||
else:
|
||||
self.error()
|
||||
|
||||
new_pipe = {
|
||||
"model": model,
|
||||
"positive": positive,
|
||||
"negative": negative,
|
||||
"vae": pipe['vae'],
|
||||
"clip": pipe['clip'],
|
||||
|
||||
"samples": pipe["samples"],
|
||||
"images": pipe["images"],
|
||||
"seed": 0,
|
||||
|
||||
"loader_settings": pipe["loader_settings"]
|
||||
}
|
||||
|
||||
del pipe
|
||||
|
||||
return (new_pipe, model, positive, negative)
|
||||
#---------------------------------------------------------------预采样 开始----------------------------------------------------------------------#
|
||||
|
||||
# 预采样设置(基础)
|
||||
@@ -3373,26 +3460,6 @@ class detailerFix:
|
||||
|
||||
return {"ui": {"images": results}, "result": (new_pipe, result_img, result_cropped_enhanced, result_cropped_enhanced_alpha, result_mask, result_cnet_images )}
|
||||
|
||||
def add_folder_path_and_extensions(folder_name, full_folder_paths, extensions):
|
||||
for full_folder_path in full_folder_paths:
|
||||
folder_paths.add_model_folder_path(folder_name, full_folder_path)
|
||||
if folder_name in folder_paths.folder_names_and_paths:
|
||||
current_paths, current_extensions = folder_paths.folder_names_and_paths[folder_name]
|
||||
updated_extensions = current_extensions | extensions
|
||||
folder_paths.folder_names_and_paths[folder_name] = (current_paths, updated_extensions)
|
||||
else:
|
||||
folder_paths.folder_names_and_paths[folder_name] = (full_folder_paths, extensions)
|
||||
|
||||
model_path = folder_paths.models_dir
|
||||
add_folder_path_and_extensions("ultralytics_bbox", [os.path.join(model_path, "ultralytics", "bbox")], folder_paths.supported_pt_extensions)
|
||||
add_folder_path_and_extensions("ultralytics_segm", [os.path.join(model_path, "ultralytics", "segm")], folder_paths.supported_pt_extensions)
|
||||
add_folder_path_and_extensions("ultralytics", [os.path.join(model_path, "ultralytics")], folder_paths.supported_pt_extensions)
|
||||
add_folder_path_and_extensions("mmdets_bbox", [os.path.join(model_path, "mmdets", "bbox")], folder_paths.supported_pt_extensions)
|
||||
add_folder_path_and_extensions("mmdets_segm", [os.path.join(model_path, "mmdets", "segm")], folder_paths.supported_pt_extensions)
|
||||
add_folder_path_and_extensions("mmdets", [os.path.join(model_path, "mmdets")], folder_paths.supported_pt_extensions)
|
||||
add_folder_path_and_extensions("sams", [os.path.join(model_path, "sams")], folder_paths.supported_pt_extensions)
|
||||
add_folder_path_and_extensions("onnx", [os.path.join(model_path, "onnx")], {'.onnx'})
|
||||
|
||||
class ultralyticsDetectorForDetailerFix:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
@@ -4697,7 +4764,8 @@ NODE_CLASS_MAPPINGS = {
|
||||
# "easy imageRemoveBG": imageREMBG,
|
||||
"dynamicThresholdingFull": dynamicThresholdingFull,
|
||||
# __for_testing 测试
|
||||
"easy fooocusInpaintLoader": fooocusInpaintLoader
|
||||
"easy fooocusInpaintLoader": fooocusInpaintLoader,
|
||||
"easy instantIDApply": instantIDApply,
|
||||
}
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
# prompt 提示词
|
||||
@@ -4773,5 +4841,6 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"easy imageRemoveBG": "ImageRemoveBG",
|
||||
"dynamicThresholdingFull": "DynamicThresholdingFull",
|
||||
# __for_testing 测试
|
||||
"easy fooocusInpaintLoader": "Load Fooocus Inpaint"
|
||||
"easy fooocusInpaintLoader": "Load Fooocus Inpaint",
|
||||
"easy instantIDApply": "Easy Apply InstantID"
|
||||
}
|
||||
+56
-34
@@ -1,12 +1,13 @@
|
||||
import folder_paths
|
||||
import comfy.controlnet
|
||||
import comfy.model_management
|
||||
from nodes import NODE_CLASS_MAPPINGS
|
||||
|
||||
class easyControlnet:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def apply(self, control_net_name, image, positive, negative, strength, start_percent=0, end_percent=1, control_net=None, scale_soft_weights=1):
|
||||
def load_controlnet(self, control_net_name, control_net, scale_soft_weights):
|
||||
if control_net is None:
|
||||
if scale_soft_weights < 1:
|
||||
if "ScaledSoftControlNetWeights" in NODE_CLASS_MAPPINGS:
|
||||
@@ -19,43 +20,64 @@ class easyControlnet:
|
||||
else:
|
||||
controlnet_path = folder_paths.get_full_path("controlnet", control_net_name)
|
||||
control_net = comfy.controlnet.load_controlnet(controlnet_path)
|
||||
return control_net
|
||||
|
||||
def apply(self, control_net_name, image, positive, negative, strength, start_percent=0, end_percent=1, control_net=None, scale_soft_weights=1, mask=None):
|
||||
if strength == 0:
|
||||
return (positive, negative)
|
||||
|
||||
control_net = self.load_controlnet(control_net_name, control_net, scale_soft_weights)
|
||||
|
||||
if mask is not None:
|
||||
mask = mask.to(self.device)
|
||||
|
||||
if mask is not None and len(mask.shape) < 3:
|
||||
mask = mask.unsqueeze(0)
|
||||
|
||||
control_hint = image.movedim(-1, 1)
|
||||
|
||||
if strength != 0:
|
||||
if negative is None:
|
||||
p = []
|
||||
for t in positive:
|
||||
n = [t[0], t[1].copy()]
|
||||
c_net = control_net.copy().set_cond_hint(control_hint, strength, (start_percent, end_percent))
|
||||
if 'control' in t[1]:
|
||||
c_net.set_previous_controlnet(t[1]['control'])
|
||||
n[1]['control'] = c_net
|
||||
n[1]['control_apply_to_uncond'] = True
|
||||
p.append(n)
|
||||
positive = p
|
||||
else:
|
||||
cnets = {}
|
||||
out = []
|
||||
for conditioning in [positive, negative]:
|
||||
c = []
|
||||
for t in conditioning:
|
||||
d = t[1].copy()
|
||||
is_cond = True
|
||||
if negative is None:
|
||||
p = []
|
||||
for t in positive:
|
||||
n = [t[0], t[1].copy()]
|
||||
c_net = control_net.copy().set_cond_hint(control_hint, strength, (start_percent, end_percent))
|
||||
if 'control' in t[1]:
|
||||
c_net.set_previous_controlnet(t[1]['control'])
|
||||
n[1]['control'] = c_net
|
||||
n[1]['control_apply_to_uncond'] = True
|
||||
if mask is not None:
|
||||
n[1]['mask'] = mask
|
||||
n[1]['set_area_to_bounds'] = False
|
||||
p.append(n)
|
||||
positive = p
|
||||
else:
|
||||
cnets = {}
|
||||
out = []
|
||||
for conditioning in [positive, negative]:
|
||||
c = []
|
||||
for t in conditioning:
|
||||
d = t[1].copy()
|
||||
|
||||
prev_cnet = d.get('control', None)
|
||||
if prev_cnet in cnets:
|
||||
c_net = cnets[prev_cnet]
|
||||
else:
|
||||
c_net = control_net.copy().set_cond_hint(control_hint, strength, (start_percent, end_percent))
|
||||
c_net.set_previous_controlnet(prev_cnet)
|
||||
cnets[prev_cnet] = c_net
|
||||
prev_cnet = d.get('control', None)
|
||||
if prev_cnet in cnets:
|
||||
c_net = cnets[prev_cnet]
|
||||
else:
|
||||
c_net = control_net.copy().set_cond_hint(control_hint, strength, (start_percent, end_percent))
|
||||
c_net.set_previous_controlnet(prev_cnet)
|
||||
cnets[prev_cnet] = c_net
|
||||
|
||||
d['control'] = c_net
|
||||
d['control_apply_to_uncond'] = False
|
||||
n = [t[0], d]
|
||||
c.append(n)
|
||||
out.append(c)
|
||||
positive = out[0]
|
||||
negative = out[1]
|
||||
d['control'] = c_net
|
||||
d['control_apply_to_uncond'] = False
|
||||
|
||||
if mask is not None:
|
||||
d['mask'] = mask
|
||||
d['set_area_to_bounds'] = False
|
||||
|
||||
n = [t[0], d]
|
||||
c.append(n)
|
||||
out.append(c)
|
||||
positive = out[0]
|
||||
negative = out[1]
|
||||
|
||||
return (positive, negative)
|
||||
+1
-1
@@ -367,7 +367,7 @@ class easyXYPlot():
|
||||
w_max=1.0,
|
||||
apply_to_pooled="enable", a1111_prompt_style=a1111_prompt_style, steps=steps)
|
||||
if "negative_cond" in plot_image_vars:
|
||||
positive = positive + plot_image_vars["negative_cond"]
|
||||
negative = negative + plot_image_vars["negative_cond"]
|
||||
|
||||
# ControlNet
|
||||
if "ControlNet" in self.x_type or "ControlNet" in self.y_type:
|
||||
|
||||
@@ -4,7 +4,7 @@ import { applyTextReplacements } from "/scripts/utils.js";
|
||||
app.registerExtension({
|
||||
name: "Comfy.Easy.SaveImageExtraOutput",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
if (["easy imageSave", "easy fullkSampler", "easy kSampler", "easy kSamplerTiled","easy kSamplerInpainting", "easy kSamplerDownscaleUnet", "easy kSamplerSDTurbo"].includes(nodeData.name)) {
|
||||
if (["easy imageSave", "easy fullkSampler", "easy kSampler", "easy kSamplerTiled","easy kSamplerInpainting", "easy kSamplerDownscaleUnet", "easy kSamplerSDTurbo","easy detailerFix"].includes(nodeData.name)) {
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated;
|
||||
// When the SaveImage node is created we want to override the serialization of the output name widget to run our S&R
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
|
||||
Reference in New Issue
Block a user