From 0e4e439d39d38431cf724221b96db6d2b4c54b12 Mon Sep 17 00:00:00 2001 From: "Dr.Lt.Data" Date: Fri, 27 Sep 2024 23:17:35 +0900 Subject: [PATCH] feat: SEGS Merge --- README.md | 3 +- __init__.py | 2 ++ modules/impact/config.py | 2 +- modules/impact/segs_nodes.py | 62 ++++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- 5 files changed, 68 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dcac071..455a8ff 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ This custom node helps to conveniently enhance images through Detector, Detailer * `SEGS Filter (range)` - This node retrieves only SEGs from SEGS that have a size and position within a certain range. * `SEGS Assign (label)` - Assign labels sequentially to SEGS. This node is useful when used with `[LAB]` of FaceDetailer. * `SEGSConcat` - Concatenate segs1 and segs2. If source shape of segs1 and segs2 are different from segs2 will be ignored. + * `SEGS Merge` - SEGS contains multiple SEGs. SEGS Merge integrates several SEGs into a single merged SEG. The label is changed to `merged` and the confidence becomes the minimum confidence. The applied controlnet and cropped_image are removed. * `Picker (SEGS)` - Among the input SEGS, you can select a specific SEG through a dialog. If no SEG is selected, it outputs an empty SEGS. Increasing the batch_size of SEGSDetailer can be used for the purpose of selecting from the candidates. * `Set Default Image For SEGS` - Set a default image for SEGS. SEGS with images set this way do not need to have a fallback image set. When override is set to false, the original image is preserved. * `Remove Image from SEGS` - Remove the image set for the SEGS that has been configured by "Set Default Image for SEGS" or SEGSDetailer. When the image for the SEGS is removed, the Detailer node will operate based on the currently processed image instead of the SEGS. @@ -242,7 +243,7 @@ This custom node helps to conveniently enhance images through Detector, Detailer ### Logics (experimental) * These nodes are experimental nodes designed to implement the logic for loops and dynamic switching. - * `ImpactCompare`, `ImpactConditionalBranch`, `ImpactConditionalBranchSelMode`, `ImpactInt`, `ImpactValueSender`, `ImpactValueReceiver`, `ImpactImageInfo`, `ImpactMinMax`, `ImpactNeg`, `ImpactConditionalStopIteration` + * `ImpactCompare`, `ImpactConditionalBranch`, `ImpactConditionalBranchSelMode`, `ImpactInt`, `ImpactBoolean`, `ImpactValueSender`, `ImpactValueReceiver`, `ImpactImageInfo`, `ImpactMinMax`, `ImpactNeg`, `ImpactConditionalStopIteration` * `ImpactIsNotEmptySEGS` - This node returns `true` only if the input SEGS is not empty. * `ImpactIfNone` - Returns `true` if any_input is None, and returns `false` if it is not None. * `Queue Trigger` - When this node is executed, it adds a new queue to assist with repetitive tasks. It will only execute if the signal's status changes. diff --git a/__init__.py b/__init__.py index 8c50825..7fee160 100644 --- a/__init__.py +++ b/__init__.py @@ -223,6 +223,7 @@ NODE_CLASS_MAPPINGS = { "ImpactSEGSConcat": SEGSConcat, "ImpactSEGSPicker": SEGSPicker, "ImpactMakeTileSEGS": MakeTileSEGS, + "ImpactSEGSMerge": SEGSMerge, "SEGSDetailerForAnimateDiff": SEGSDetailerForAnimateDiff, @@ -368,6 +369,7 @@ NODE_DISPLAY_NAME_MAPPINGS = { "ImpactSEGSToMaskBatch": "SEGS to Mask Batch", "ImpactSEGSPicker": "Picker (SEGS)", "ImpactMakeTileSEGS": "Make Tile SEGS", + "ImpactSEGSMerge": "SEGS Merge", "ImpactDecomposeSEGS": "Decompose (SEGS)", "ImpactAssembleSEGS": "Assemble (SEGS)", diff --git a/modules/impact/config.py b/modules/impact/config.py index 6f414c4..27277d9 100644 --- a/modules/impact/config.py +++ b/modules/impact/config.py @@ -1,7 +1,7 @@ import configparser import os -version_code = [7, 7, 2] +version_code = [7, 8] version = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '') dependency_version = 23 diff --git a/modules/impact/segs_nodes.py b/modules/impact/segs_nodes.py index 24758e8..600c246 100644 --- a/modules/impact/segs_nodes.py +++ b/modules/impact/segs_nodes.py @@ -704,6 +704,68 @@ class SEGSToMaskBatch: return (mask_batch,) +class SEGSMerge: + @classmethod + def INPUT_TYPES(s): + return {"required": { + "segs": ("SEGS", ), + }, + } + + RETURN_TYPES = ("SEGS",) + FUNCTION = "doit" + + CATEGORY = "ImpactPack/Util" + + DESCRIPTION = "SEGS contains multiple SEGs. SEGS Merge integrates several SEGs into a single merged SEG. The label is changed to `merged` and the confidence becomes the minimum confidence. The applied controlnet and cropped_image are removed." + + def doit(self, segs): + crop_left = sys.maxsize + crop_right = 0 + crop_top = sys.maxsize + crop_bottom = 0 + + bbox_left = sys.maxsize + bbox_right = 0 + bbox_top = sys.maxsize + bbox_bottom = 0 + + min_confidence = 1.0 + + for seg in segs[1]: + cx1 = seg.crop_region[0] + cy1 = seg.crop_region[1] + cx2 = seg.crop_region[2] + cy2 = seg.crop_region[3] + + bx1 = seg.bbox[0] + by1 = seg.bbox[1] + bx2 = seg.bbox[2] + by2 = seg.bbox[3] + + crop_left = min(crop_left, cx1) + crop_top = min(crop_top, cy1) + crop_right = max(crop_right, cx2) + crop_bottom = max(crop_bottom, cy2) + + bbox_left = min(bbox_left, bx1) + bbox_top = min(bbox_top, by1) + bbox_right = max(bbox_right, bx2) + bbox_bottom = max(bbox_bottom, by2) + + min_confidence = min(min_confidence, seg.confidence) + + combined_mask = core.segs_to_combined_mask(segs) + cropped_mask = combined_mask[crop_top:crop_bottom, crop_left:crop_right] + cropped_mask = cropped_mask.unsqueeze(0) + + crop_region = [crop_left, crop_top, crop_right, crop_bottom] + bbox = [bbox_left, bbox_top, bbox_right, bbox_bottom] + + seg = SEG(None, cropped_mask, min_confidence, crop_region, bbox, 'merged', None) + return ((segs[0], [seg]),) + + class SEGSConcat: @classmethod def INPUT_TYPES(s): diff --git a/pyproject.toml b/pyproject.toml index f026dc5..76ce266 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-impact-pack" description = "This extension offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details. And provide iterative upscaler." -version = "7.7.2" +version = "7.8" license = { file = "LICENSE.txt" } dependencies = ["segment-anything", "scikit-image", "piexif", "transformers", "opencv-python-headless", "GitPython", "scipy>=1.11.4"]