feat: MaskToSEGS for AnimateDiff allows batch mask
refactor: change some doit functions to staticmethod update README.md https://github.com/ltdrdata/ComfyUI-extension-tutorials/issues/44
This commit is contained in:
@@ -72,7 +72,9 @@ This custom node helps to conveniently enhance images through Detector, Detailer
|
||||
* `DetailerDebug (SEGS)` - Refines the image based on SEGS. Additionally, it provides the ability to monitor the cropped image and the refined image of the cropped image.
|
||||
* To prevent regeneration caused by the seed that does not change every time when using 'external_seed', please disable the 'seed random generate' option in the 'Detailer...' node.
|
||||
* `MASK to SEGS` - Generates SEGS based on the mask.
|
||||
* `MASK to SEGS For AnimateDiff` - Generates SEGS based on the mask for AnimateDiff.
|
||||
* `MASK to SEGS For AnimateDiff` - Generates SEGS based on the mask for AnimateDiff.
|
||||
* When using a single mask, convert it to SEGS to apply it to the entire frame.
|
||||
* When using a batch mask, the contour fill feature is disabled.
|
||||
* `MediaPipe FaceMesh to SEGS` - Separate each landmark from the mediapipe facemesh image to create labeled SEGS.
|
||||
* Usually, the size of images created through the MediaPipe facemesh preprocessor is downscaled. It resizes the MediaPipe facemesh image to the original size given as reference_image_opt for matching sizes during processing.
|
||||
* `ToBinaryMask` - Separates the mask generated with alpha values between 0 and 255 into 0 and 255. The non-zero parts are always set to 255.
|
||||
|
||||
@@ -2,7 +2,7 @@ import configparser
|
||||
import os
|
||||
|
||||
|
||||
version_code = [5, 6]
|
||||
version_code = [5, 7]
|
||||
version = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
||||
|
||||
dependency_version = 20
|
||||
|
||||
@@ -1013,6 +1013,21 @@ class ONNXDetector:
|
||||
pass
|
||||
|
||||
|
||||
def batch_mask_to_segs(mask, combined, crop_factor, bbox_fill, drop_size=1, label='A', crop_min_size=None, detailer_hook=None):
|
||||
combined_mask = mask.max(dim=0).values
|
||||
|
||||
segs = mask_to_segs(combined_mask, combined, crop_factor, bbox_fill, drop_size, label, crop_min_size, detailer_hook)
|
||||
|
||||
new_segs = []
|
||||
for seg in segs[1]:
|
||||
x1, y1, x2, y2 = seg.crop_region
|
||||
cropped_mask = mask[:, y1:y2, x1:x2]
|
||||
item = SEG(None, cropped_mask, 1.0, seg.crop_region, seg.bbox, label, None)
|
||||
new_segs.append(item)
|
||||
|
||||
return segs[0], new_segs
|
||||
|
||||
|
||||
def mask_to_segs(mask, combined, crop_factor, bbox_fill, drop_size=1, label='A', crop_min_size=None, detailer_hook=None, is_contour=True):
|
||||
drop_size = max(drop_size, 1)
|
||||
if mask is None:
|
||||
|
||||
@@ -410,7 +410,7 @@ class SimpleDetectorForAnimateDiff:
|
||||
return segs_by_frames[0][1]
|
||||
else:
|
||||
merged_mask = get_whole_merged_mask()
|
||||
return segs_nodes.MaskToSEGS().doit(merged_mask, False, crop_factor, False, drop_size, contour_fill=True)[0]
|
||||
return segs_nodes.MaskToSEGS.doit(merged_mask, False, crop_factor, False, drop_size, contour_fill=True)[0]
|
||||
|
||||
def get_merged_neighboring_segs():
|
||||
pivot_segs = get_pivot_segs()
|
||||
|
||||
@@ -1141,10 +1141,11 @@ class MaskToSEGS:
|
||||
|
||||
CATEGORY = "ImpactPack/Operation"
|
||||
|
||||
def doit(self, mask, combined, crop_factor, bbox_fill, drop_size, contour_fill=False):
|
||||
@staticmethod
|
||||
def doit(mask, combined, crop_factor, bbox_fill, drop_size, contour_fill=False):
|
||||
mask = make_2d_mask(mask)
|
||||
|
||||
result = core.mask_to_segs(mask, combined, crop_factor, bbox_fill, drop_size, is_contour=contour_fill)
|
||||
|
||||
return (result, )
|
||||
|
||||
|
||||
@@ -1166,11 +1167,17 @@ class MaskToSEGS_for_AnimateDiff:
|
||||
|
||||
CATEGORY = "ImpactPack/Operation"
|
||||
|
||||
def doit(self, mask, combined, crop_factor, bbox_fill, drop_size, contour_fill=False):
|
||||
@staticmethod
|
||||
def doit(mask, combined, crop_factor, bbox_fill, drop_size, contour_fill=False):
|
||||
if (len(mask.shape) == 4 and mask.shape[1] > 1) or (len(mask.shape) == 3 and mask.shape[0] > 1):
|
||||
mask = make_3d_mask(mask)
|
||||
if contour_fill:
|
||||
print(f"[Impact Pack] MaskToSEGS_for_AnimateDiff: 'contour_fill' is ignored because batch mask 'contour_fill' is not supported.")
|
||||
result = core.batch_mask_to_segs(mask, combined, crop_factor, bbox_fill, drop_size)
|
||||
return (result, )
|
||||
|
||||
mask = make_2d_mask(mask)
|
||||
|
||||
segs = core.mask_to_segs(mask, combined, crop_factor, bbox_fill, drop_size, is_contour=contour_fill)
|
||||
|
||||
all_masks = SEGSToMaskList().doit(segs)[0]
|
||||
|
||||
result_mask = (all_masks[0] * 255).to(torch.uint8)
|
||||
@@ -1180,7 +1187,7 @@ class MaskToSEGS_for_AnimateDiff:
|
||||
result_mask = (result_mask/255.0).to(torch.float32)
|
||||
result_mask = utils.to_binary_mask(result_mask, 0.1)[0]
|
||||
|
||||
return MaskToSEGS().doit(result_mask, False, crop_factor, False, drop_size, contour_fill)
|
||||
return MaskToSEGS.doit(result_mask, False, crop_factor, False, drop_size, contour_fill)
|
||||
|
||||
|
||||
class IPAdapterApplySEGS:
|
||||
@@ -1211,7 +1218,8 @@ class IPAdapterApplySEGS:
|
||||
|
||||
CATEGORY = "ImpactPack/Util"
|
||||
|
||||
def doit(self, segs, ipadapter_pipe, weight, noise, weight_type, start_at, end_at, unfold_batch, faceid_v2, weight_v2, context_crop_factor, reference_image, combine_embeds="concat", neg_image=None):
|
||||
@staticmethod
|
||||
def doit(segs, ipadapter_pipe, weight, noise, weight_type, start_at, end_at, unfold_batch, faceid_v2, weight_v2, context_crop_factor, reference_image, combine_embeds="concat", neg_image=None):
|
||||
|
||||
if len(ipadapter_pipe) == 4:
|
||||
print(f"[Impact Pack] IPAdapterApplySEGS: Installed Inspire Pack is outdated.")
|
||||
@@ -1255,7 +1263,8 @@ class ControlNetApplySEGS:
|
||||
|
||||
CATEGORY = "ImpactPack/Util"
|
||||
|
||||
def doit(self, segs, control_net, strength, segs_preprocessor=None, control_image=None):
|
||||
@staticmethod
|
||||
def doit(segs, control_net, strength, segs_preprocessor=None, control_image=None):
|
||||
new_segs = []
|
||||
|
||||
for seg in segs[1]:
|
||||
@@ -1288,7 +1297,8 @@ class ControlNetApplyAdvancedSEGS:
|
||||
|
||||
CATEGORY = "ImpactPack/Util"
|
||||
|
||||
def doit(self, segs, control_net, strength, start_percent, end_percent, segs_preprocessor=None, control_image=None):
|
||||
@staticmethod
|
||||
def doit(segs, control_net, strength, start_percent, end_percent, segs_preprocessor=None, control_image=None):
|
||||
new_segs = []
|
||||
|
||||
for seg in segs[1]:
|
||||
@@ -1311,7 +1321,8 @@ class ControlNetClearSEGS:
|
||||
|
||||
CATEGORY = "ImpactPack/Util"
|
||||
|
||||
def doit(self, segs):
|
||||
@staticmethod
|
||||
def doit(segs):
|
||||
new_segs = []
|
||||
|
||||
for seg in segs[1]:
|
||||
@@ -1369,7 +1380,8 @@ class SEGSPicker:
|
||||
|
||||
CATEGORY = "ImpactPack/Util"
|
||||
|
||||
def doit(self, picks, segs, fallback_image_opt=None, unique_id=None):
|
||||
@staticmethod
|
||||
def doit(picks, segs, fallback_image_opt=None, unique_id=None):
|
||||
if fallback_image_opt is not None:
|
||||
segs = core.segs_scale_match(segs, fallback_image_opt.shape)
|
||||
|
||||
@@ -1424,7 +1436,8 @@ class DefaultImageForSEGS:
|
||||
|
||||
CATEGORY = "ImpactPack/Util"
|
||||
|
||||
def doit(self, segs, image, override):
|
||||
@staticmethod
|
||||
def doit(segs, image, override):
|
||||
results = []
|
||||
|
||||
segs = core.segs_scale_match(segs, image.shape)
|
||||
@@ -1468,7 +1481,8 @@ class RemoveImageFromSEGS:
|
||||
|
||||
CATEGORY = "ImpactPack/Util"
|
||||
|
||||
def doit(self, segs):
|
||||
@staticmethod
|
||||
def doit(segs):
|
||||
results = []
|
||||
|
||||
if len(segs[1]) > 0:
|
||||
@@ -1505,7 +1519,8 @@ class MakeTileSEGS:
|
||||
|
||||
CATEGORY = "ImpactPack/__for_testing"
|
||||
|
||||
def doit(self, images, bbox_size, crop_factor, min_overlap, filter_segs_dilation, mask_irregularity=0, irregular_mask_mode="Reuse fast", filter_in_segs_opt=None, filter_out_segs_opt=None):
|
||||
@staticmethod
|
||||
def doit(images, bbox_size, crop_factor, min_overlap, filter_segs_dilation, mask_irregularity=0, irregular_mask_mode="Reuse fast", filter_in_segs_opt=None, filter_out_segs_opt=None):
|
||||
if bbox_size <= 2*min_overlap:
|
||||
new_min_overlap = bbox_size / 2
|
||||
print(f"[MakeTileSEGS] min_overlap should be greater than bbox_size. (value changed: {min_overlap} => {new_min_overlap})")
|
||||
|
||||
+2
-2
@@ -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 = "5.6"
|
||||
version = "5.7"
|
||||
license = "LICENSE"
|
||||
dependencies = ["segment-anything", "scikit-image", "piexif", "transformers", "opencv-python-headless", "GitPython", "scipy>=1.11.4"]
|
||||
|
||||
@@ -11,5 +11,5 @@ Repository = "https://github.com/ltdrdata/ComfyUI-Impact-Pack"
|
||||
|
||||
[tool.comfy]
|
||||
PublisherId = "drltdata"
|
||||
DisplayName = "ComfyUI-Impact-Pack"
|
||||
DisplayName = "ComfyUI Impact Pack"
|
||||
Icon = ""
|
||||
|
||||
Reference in New Issue
Block a user