diff --git a/README.en.md b/README.en.md index 823472e..db69a41 100644 --- a/README.en.md +++ b/README.en.md @@ -31,6 +31,12 @@ ## Changelog +**v1.1.2 (2024/3/25)** + +- `easy kSamplerInpainting` add *additional* widget,you can choose 'Differential Diffusion' or 'Only InpaintModelConditioning' +- Fixed `easy pipeEdit` error when add lora to prompt +- Fixed layerDiffuse xyplot bug + **v1.1.1 (2024/3/16)** - The issue that the seed is 0 when a node with a seed control is added and **control before generate** is fixed for the first time run queue prompt. diff --git a/README.md b/README.md index 56b46cf..62fde05 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,12 @@ ## 更新日志 +**v1.1.2 (2024/3/25)** + +- `easy kSamplerInpainting` 增加 *additional* 属性,可设置成 Differential Diffusion 或 Only InpaintModelConditioning +- 修复 `easy pipeEdit` 提示词输入lora时报错 +- 修复 layerDiffuse xyplot相关bug + **v1.1.1 (2024/3/21)** - 修复首次添加含seed的节点且当前模式为control_before_generate时,seed为0的问题 diff --git a/__init__.py b/__init__.py index e1f7289..876f2fc 100644 --- a/__init__.py +++ b/__init__.py @@ -73,4 +73,4 @@ WEB_DIRECTORY = "./web" __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS', "WEB_DIRECTORY"] -print('\033[34mComfy-Easy-Use (v1.1.1): \033[92mLoaded\033[0m') \ No newline at end of file +print('\033[34mComfy-Easy-Use (v1.1.2): \033[92mLoaded\033[0m') \ No newline at end of file diff --git a/py/easyNodes.py b/py/easyNodes.py index 6953fa5..c0453ed 100644 --- a/py/easyNodes.py +++ b/py/easyNodes.py @@ -10,7 +10,7 @@ from urllib.request import urlopen from PIL import Image from server import PromptServer -from nodes import MAX_RESOLUTION, LatentFromBatch, RepeatLatentBatch, NODE_CLASS_MAPPINGS as ALL_NODE_CLASS_MAPPINGS, ConditioningSetMask, ConditioningConcat, CLIPTextEncode, VAEEncodeForInpaint +from nodes import MAX_RESOLUTION, LatentFromBatch, RepeatLatentBatch, NODE_CLASS_MAPPINGS as ALL_NODE_CLASS_MAPPINGS, ConditioningSetMask, ConditioningConcat, CLIPTextEncode, VAEEncodeForInpaint, InpaintModelConditioning from .config import MAX_SEED_NUM, BASE_RESOLUTIONS, RESOURCES_DIR, INPAINT_DIR, FOOOCUS_STYLES_DIR, FOOOCUS_INPAINT_HEAD, FOOOCUS_INPAINT_PATCH from .log import log_node_info, log_node_error, log_node_warn from .wildcards import process_with_loras, get_wildcard_list, process @@ -3054,6 +3054,7 @@ class samplerSimpleInpainting: "image_output": (["Hide", "Preview", "Save", "Hide/Save", "Sender", "Sender/Save"],{"default": "Preview"}), "link_id": ("INT", {"default": 0, "min": 0, "max": sys.maxsize, "step": 1}), "save_prefix": ("STRING", {"default": "ComfyUI"}), + "additional": (["None", "Differential Diffusion", "Only InpaintModelConditioning"],{"default": "None"}) }, "optional": { "model": ("MODEL",), @@ -3072,62 +3073,73 @@ class samplerSimpleInpainting: FUNCTION = "run" CATEGORY = "EasyUse/Sampler" - def run(self, pipe, grow_mask_by, image_output, link_id, save_prefix, model=None, mask=None, patch=None, tile_size=None, prompt=None, extra_pnginfo=None, my_unique_id=None, force_full_denoise=False, disable_noise=False): + def run(self, pipe, grow_mask_by, image_output, link_id, save_prefix, additional, model=None, mask=None, patch=None, tile_size=None, prompt=None, extra_pnginfo=None, my_unique_id=None, force_full_denoise=False, disable_noise=False): model = model if model is not None else pipe['model'] + latent = pipe['samples'] if 'samples' in pipe else None + if 'noise_mask' in latent: + mask = latent['noise_mask'] if mask is not None: + positive = pipe['positive'] + negative = pipe['negative'] pixels = pipe["images"] if pipe and "images" in pipe else None - if pixels is None: - raise Exception("No Images found") vae = pipe["vae"] if pipe and "vae" in pipe else None - if pixels is None: - raise Exception("No VAE found") - x = (pixels.shape[1] // 8) * 8 - y = (pixels.shape[2] // 8) * 8 - mask = torch.nn.functional.interpolate(mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])), - size=(pixels.shape[1], pixels.shape[2]), mode="bilinear") - - pixels = pixels.clone() - if pixels.shape[1] != x or pixels.shape[2] != y: - x_offset = (pixels.shape[1] % 8) // 2 - y_offset = (pixels.shape[2] % 8) // 2 - pixels = pixels[:, x_offset:x + x_offset, y_offset:y + y_offset, :] - mask = mask[:, :, x_offset:x + x_offset, y_offset:y + y_offset] - - if grow_mask_by == 0: - mask_erosion = mask + if additional != "None": + positive, negative, latent = InpaintModelConditioning().encode(positive, negative, pixels, vae, mask) + if additional == "Differential Diffusion": + cls = ALL_NODE_CLASS_MAPPINGS['DifferentialDiffusion'] + if cls is not None: + model, = cls().apply(model) + else: + raise Exception("Differential Diffusion not found,please update comfyui") else: - kernel_tensor = torch.ones((1, 1, grow_mask_by, grow_mask_by)) - padding = math.ceil((grow_mask_by - 1) / 2) + if 'noise_mask' not in latent: + if pixels is None: + raise Exception("No Images found") + if vae is None: + raise Exception("No VAE found") + x = (pixels.shape[1] // 8) * 8 + y = (pixels.shape[2] // 8) * 8 + mask = torch.nn.functional.interpolate(mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])), + size=(pixels.shape[1], pixels.shape[2]), mode="bilinear") - mask_erosion = torch.clamp(torch.nn.functional.conv2d(mask.round(), kernel_tensor, padding=padding), 0, - 1) + pixels = pixels.clone() + if pixels.shape[1] != x or pixels.shape[2] != y: + x_offset = (pixels.shape[1] % 8) // 2 + y_offset = (pixels.shape[2] % 8) // 2 + pixels = pixels[:, x_offset:x + x_offset, y_offset:y + y_offset, :] + mask = mask[:, :, x_offset:x + x_offset, y_offset:y + y_offset] - m = (1.0 - mask.round()).squeeze(1) - for i in range(3): - pixels[:, :, :, i] -= 0.5 - pixels[:, :, :, i] *= m - pixels[:, :, :, i] += 0.5 - t = vae.encode(pixels) + if grow_mask_by == 0: + mask_erosion = mask + else: + kernel_tensor = torch.ones((1, 1, grow_mask_by, grow_mask_by)) + padding = math.ceil((grow_mask_by - 1) / 2) - latent = {"samples": t, "noise_mask": (mask_erosion[:, :, :x, :y].round())} + mask_erosion = torch.clamp(torch.nn.functional.conv2d(mask.round(), kernel_tensor, padding=padding), 0, + 1) - # when patch was linked - if patch is not None: - worker = InpaintWorker(node_name="easy kSamplerInpainting") - model, = worker.patch(model, latent, patch) + m = (1.0 - mask.round()).squeeze(1) + for i in range(3): + pixels[:, :, :, i] -= 0.5 + pixels[:, :, :, i] *= m + pixels[:, :, :, i] += 0.5 + t = vae.encode(pixels) + + latent = {"samples": t, "noise_mask": (mask_erosion[:, :, :x, :y].round())} + + # when patch was linked + if patch is not None: + worker = InpaintWorker(node_name="easy kSamplerInpainting") + model, = worker.patch(model, latent, patch) new_pipe = { + **pipe, "model": model, - "positive": pipe['positive'], - "negative": pipe['negative'], - "vae": pipe['vae'], - "clip": pipe['clip'], - + "positive": positive, + "negative": negative, + "vae": vae, "samples": latent, - "images": pipe['images'], - "seed": pipe['seed'], - "loader_settings": pipe["loader_settings"], } else: