feat: ControlNetApply (SEGS) - support control_image

feat: SEGSPreviewCnet
This commit is contained in:
Dr.Lt.Data
2024-01-12 16:26:01 +09:00
parent 3169234402
commit 7f7646b72f
5 changed files with 70 additions and 7 deletions
+3
View File
@@ -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.
+4 -1
View File
@@ -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']:
+1 -1
View File
@@ -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
+11 -3
View File
@@ -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
+51 -2
View File
@@ -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)