diff --git a/README.md b/README.md index 178fd04..b0cda5c 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ This custom node helps to conveniently enhance images through Detector, Detailer * ControlNet * ControlNetApply (SEGS) - To apply ControlNet in SEGS, you need to use the Preprocessor Provider node from the Inspire Pack to utilize this node. + * `SEGSPreprocessor` and `Image` can be selectively applied. If an `Image` is given, `SEGSPreprocessor` will be ignored. + * If set to `Image`, you can preview the cropped cnet image through `SEGSPreview (CNET Image)`. Images generated by `SEGSPreprocessor` should be verified through the `cnet_pil` output of each Detailer. * ControlNetClear (SEGS) - Clear applied ControlNet in SEGS * Bitwise(SEGS & SEGS) - Performs a 'bitwise and' operation between two SEGS. @@ -81,6 +83,7 @@ This custom node helps to conveniently enhance images through Detector, Detailer * SEGSPreview - Provides a preview of SEGS. * This option is used to preview the improved image through `SEGSDetailer` before merging it into the original. Prior to going through ```SEGSDetailer```, SEGS only contains mask information without image information. If fallback_image_opt is connected to the original image, SEGS without image information will generate a preview using the original image. However, if SEGS already contains image information, fallback_image_opt will be ignored. * This node can be used in conjunction with the processing results of AnimateDiff. + * SEGSPreview (CNET Image) - Show images configured with `ControlNetApply (SEGS)` for debugging purposes. * SEGSToImageList - Convert SEGS To Image List * SEGSToMaskList - Convert SEGS To Mask List * SEGS Filter (label) - This node filters SEGS based on the label of the detected areas. diff --git a/__init__.py b/__init__.py index 48042e1..0196735 100644 --- a/__init__.py +++ b/__init__.py @@ -253,6 +253,7 @@ NODE_CLASS_MAPPINGS = { "SEGSDetailer": SEGSDetailer, "SEGSPaste": SEGSPaste, "SEGSPreview": SEGSPreview, + "SEGSPreviewCNet": SEGSPreviewCNet, "SEGSToImageList": SEGSToImageList, "ImpactSEGSToMaskList": SEGSToMaskList, "ImpactSEGSToMaskBatch": SEGSToMaskBatch, @@ -430,7 +431,9 @@ NODE_DISPLAY_NAME_MAPPINGS = { "ImpactSEGSClassify": "SEGS Classify", "LatentSwitch": "Switch (latent/legacy)", - "SEGSSwitch": "Switch (SEGS/legacy)" + "SEGSSwitch": "Switch (SEGS/legacy)", + + "SEGSPreviewCNet": "SEGSPreview (CNET Image)" } if not impact.config.get_config()['mmdet_skip']: diff --git a/modules/impact/config.py b/modules/impact/config.py index a883288..890e668 100644 --- a/modules/impact/config.py +++ b/modules/impact/config.py @@ -2,7 +2,7 @@ import configparser import os -version_code = [4, 62] +version_code = [4, 63] version = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '') dependency_version = 20 diff --git a/modules/impact/core.py b/modules/impact/core.py index 7066c8f..786d5dc 100644 --- a/modules/impact/core.py +++ b/modules/impact/core.py @@ -1592,13 +1592,19 @@ class PixelKSampleUpscaler: class ControlNetWrapper: - def __init__(self, control_net, strength, preprocessor, prev_control_net=None): + def __init__(self, control_net, strength, preprocessor, prev_control_net=None, + original_size=None, crop_region=None, control_image=None): self.control_net = control_net self.strength = strength self.preprocessor = preprocessor - self.image = None self.prev_control_net = prev_control_net + if original_size is not None and crop_region is not None and control_image is not None: + self.control_image = utils.tensor_resize(control_image, original_size[1], original_size[0]) + self.control_image = torch.tensor(utils.tensor_crop(self.control_image, crop_region)) + else: + self.control_image = None + def apply(self, conditioning, image, mask=None): cnet_pils = [] prev_cnet_pils = [] @@ -1606,7 +1612,9 @@ class ControlNetWrapper: if self.prev_control_net is not None: conditioning, prev_cnet_pils = self.prev_control_net.apply(conditioning, image, mask) - if self.preprocessor is not None: + if self.control_image is not None: + cnet_pil = self.control_image + elif self.preprocessor is not None: cnet_pil = self.preprocessor.apply(image, mask) else: cnet_pil = image diff --git a/modules/impact/segs_nodes.py b/modules/impact/segs_nodes.py index 5f6e5fa..55ffe1b 100644 --- a/modules/impact/segs_nodes.py +++ b/modules/impact/segs_nodes.py @@ -270,6 +270,53 @@ class SEGSPaste: return (result, ) +class SEGSPreviewCNet: + def __init__(self): + self.output_dir = folder_paths.get_temp_directory() + self.type = "temp" + + @classmethod + def INPUT_TYPES(s): + return {"required": {"segs": ("SEGS", ),}, } + + RETURN_TYPES = ("IMAGE", ) + OUTPUT_IS_LIST = (True, ) + FUNCTION = "doit" + + CATEGORY = "ImpactPack/Util" + + OUTPUT_NODE = True + + def doit(self, segs): + full_output_folder, filename, counter, subfolder, filename_prefix = \ + folder_paths.get_save_image_path("impact_seg_preview", self.output_dir, segs[0][1], segs[0][0]) + + results = list() + result_image_list = [] + + for seg in segs[1]: + file = f"{filename}_{counter:05}_.webp" + + if seg.control_net_wrapper is not None and seg.control_net_wrapper.control_image is not None: + cnet_image = seg.control_net_wrapper.control_image + result_image_list.append(cnet_image) + else: + cnet_image = empty_pil_tensor(64, 64) + + cnet_pil = utils.tensor2pil(cnet_image) + cnet_pil.save(os.path.join(full_output_folder, file)) + + results.append({ + "filename": file, + "subfolder": subfolder, + "type": self.type + }) + + counter += 1 + + return {"ui": {"images": results}, "result": (result_image_list,)} + + class SEGSPreview: def __init__(self): self.output_dir = folder_paths.get_temp_directory() @@ -1128,6 +1175,7 @@ class ControlNetApplySEGS: }, "optional": { "segs_preprocessor": ("SEGS_PREPROCESSOR",), + "control_image": ("IMAGE",) } } @@ -1136,11 +1184,12 @@ class ControlNetApplySEGS: CATEGORY = "ImpactPack/Util" - def doit(self, segs, control_net, strength, segs_preprocessor=None): + def doit(self, segs, control_net, strength, segs_preprocessor=None, control_image=None): new_segs = [] for seg in segs[1]: - control_net_wrapper = core.ControlNetWrapper(control_net, strength, segs_preprocessor, seg.control_net_wrapper) + control_net_wrapper = core.ControlNetWrapper(control_net, strength, segs_preprocessor, seg.control_net_wrapper, + original_size=segs[0], crop_region=seg.crop_region, control_image=control_image) new_seg = SEG(seg.cropped_image, seg.cropped_mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, control_net_wrapper) new_segs.append(new_seg)