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:
Dr.Lt.Data
2024-05-30 00:50:58 +09:00
parent 0985a88707
commit ebaf54e2b6
6 changed files with 51 additions and 19 deletions
+3 -1
View File
@@ -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.
+1 -1
View File
@@ -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
+15
View File
@@ -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:
+1 -1
View File
@@ -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()
+29 -14
View File
@@ -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
View File
@@ -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 = ""