Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f57d309932 | ||
|
|
6ccf9bab68 | ||
|
|
ac3668d946 | ||
|
|
78d3793a77 |
@@ -189,6 +189,7 @@ NOTE: The UltralyticsDetectorProvider node is not part of the ComfyUI-Impact-Pac
|
||||
* `PreviewDetailerHook` - Connecting this hook node helps provide assistance for viewing previews whenever SEGS Detailing tasks are completed. When working with a large number of SEGS, such as Make Tile SEGS, it allows for monitoring the situation as improvements progress incrementally.
|
||||
* Since this is the hook applied when pasting onto the original image, it has no effect on nodes like `SEGSDetailer`.
|
||||
* `VariationNoiseDetailerHookProvider` - Apply variation seed to the detailer. It can be applied in multiple stages through combine.
|
||||
* `CustomSamplerDetailerHookProvider` - Apply a hook that allows you to use a custom sampler in the Detailer nodes. When using `DetailerHookCombine`, the sampler from the first hook is applied.
|
||||
|
||||
### Iterative Upscale nodes
|
||||
* `Iterative Upscale (Latent/on Pixel Space)` - The upscaler takes the input upscaler and splits the scale_factor into steps, then iteratively performs upscaling.
|
||||
|
||||
@@ -122,6 +122,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
"UnsamplerHookProvider": UnsamplerHookProvider,
|
||||
"CoreMLDetailerHookProvider": CoreMLDetailerHookProvider,
|
||||
"PreviewDetailerHookProvider": PreviewDetailerHookProvider,
|
||||
"CustomSamplerDetailerHookProvider": CustomSamplerDetailerHookProvider,
|
||||
|
||||
"DetailerHookCombine": DetailerHookCombine,
|
||||
"NoiseInjectionDetailerHookProvider": NoiseInjectionDetailerHookProvider,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import configparser
|
||||
import os
|
||||
|
||||
version_code = [8, 15, 3]
|
||||
version_code = [8, 16, 1]
|
||||
version = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
||||
|
||||
dependency_version = 24
|
||||
|
||||
+12
-3
@@ -344,6 +344,10 @@ def enhance_detail(image, model, clip, vae, guide_size, guide_size_for_bbox, max
|
||||
|
||||
refined_latent = latent_image
|
||||
|
||||
sampler_opt=None
|
||||
if detailer_hook is not None:
|
||||
sampler_opt = detailer_hook.get_custom_sampler()
|
||||
|
||||
# ksampler
|
||||
for i in range(0, cycle):
|
||||
if detailer_hook is not None:
|
||||
@@ -364,7 +368,7 @@ def enhance_detail(image, model, clip, vae, guide_size, guide_size_for_bbox, max
|
||||
|
||||
refined_latent = impact_sampling.ksampler_wrapper(model2, seed2, steps2, cfg2, sampler_name2, scheduler2, positive2, negative2,
|
||||
refined_latent, denoise2, refiner_ratio, refiner_model, refiner_clip, refiner_positive, refiner_negative,
|
||||
noise=noise, scheduler_func=scheduler_func)
|
||||
noise=noise, scheduler_func=scheduler_func, sampler_opt=sampler_opt)
|
||||
|
||||
if detailer_hook is not None:
|
||||
refined_latent = detailer_hook.pre_decode(refined_latent)
|
||||
@@ -513,11 +517,16 @@ def enhance_detail_for_animatediff(image_frames, model, clip, vae, guide_size, g
|
||||
'samples': latent_frames
|
||||
}
|
||||
|
||||
|
||||
sampler_opt=None
|
||||
if detailer_hook is not None:
|
||||
sampler_opt = detailer_hook.get_custom_sampler()
|
||||
|
||||
if detailer_hook is not None:
|
||||
latent = detailer_hook.post_encode(latent)
|
||||
|
||||
refined_latent = impact_sampling.ksampler_wrapper(model, seed, steps, cfg, sampler_name, scheduler, positive, negative,
|
||||
latent, denoise, refiner_ratio, refiner_model, refiner_clip, refiner_positive, refiner_negative, scheduler_func=scheduler_func)
|
||||
latent, denoise, refiner_ratio, refiner_model, refiner_clip, refiner_positive, refiner_negative, scheduler_func=scheduler_func, sampler_opt=sampler_opt)
|
||||
|
||||
if detailer_hook is not None:
|
||||
refined_latent = detailer_hook.pre_decode(refined_latent)
|
||||
@@ -1077,7 +1086,7 @@ class ONNXDetector:
|
||||
def detect(self, image, threshold, dilation, crop_factor, drop_size=1, detailer_hook=None):
|
||||
drop_size = max(drop_size, 1)
|
||||
try:
|
||||
import impact.onnx as onnx
|
||||
import impact.impact_onnx as onnx
|
||||
|
||||
h = image.shape[1]
|
||||
w = image.shape[2]
|
||||
|
||||
@@ -163,7 +163,7 @@ class SegmDetectorCombined:
|
||||
mask = segm_detector.detect_combined(image, threshold, dilation)
|
||||
|
||||
if mask is None:
|
||||
mask = torch.zeros((image.shape[2], image.shape[1]), dtype=torch.float32, device="cpu")
|
||||
mask = torch.zeros((image.shape[1], image.shape[2]), dtype=torch.float32, device="cpu")
|
||||
|
||||
return (mask.unsqueeze(0),)
|
||||
|
||||
@@ -183,7 +183,7 @@ class BboxDetectorCombined(SegmDetectorCombined):
|
||||
mask = bbox_detector.detect_combined(image, threshold, dilation)
|
||||
|
||||
if mask is None:
|
||||
mask = torch.zeros((image.shape[2], image.shape[1]), dtype=torch.float32, device="cpu")
|
||||
mask = torch.zeros((image.shape[1], image.shape[2]), dtype=torch.float32, device="cpu")
|
||||
|
||||
return (mask.unsqueeze(0),)
|
||||
|
||||
|
||||
@@ -109,6 +109,12 @@ class DetailerHookCombine(PixelKSampleHookCombine):
|
||||
noise_2nd, is_touched = self.hook2.get_custom_noise(seed, noise, is_touched)
|
||||
return noise, is_touched
|
||||
|
||||
def get_custom_sampler():
|
||||
if self.hook1.get_custom_sampler() is not None:
|
||||
return self.hook1.get_custom_sampler()
|
||||
else:
|
||||
return self.hook2.get_custom_sampler()
|
||||
|
||||
|
||||
class SimpleCfgScheduleHook(PixelKSampleHook):
|
||||
target_cfg = 0
|
||||
@@ -173,6 +179,18 @@ class DetailerHook(PixelKSampleHook):
|
||||
def get_custom_noise(self, seed, noise, is_touched):
|
||||
return noise, is_touched
|
||||
|
||||
def get_custom_sampler(self):
|
||||
return None
|
||||
|
||||
|
||||
class CustomSamplerDetailerHookProvider(DetailerHook):
|
||||
def __init__(self, sampler):
|
||||
super().__init__()
|
||||
self.sampler = sampler
|
||||
|
||||
def get_custom_sampler(self):
|
||||
return self.sampler
|
||||
|
||||
|
||||
# class CustomNoiseDetailerHookProvider(DetailerHook):
|
||||
# def __init__(self, noise):
|
||||
|
||||
@@ -811,6 +811,26 @@ class CoreMLDetailerHookProvider:
|
||||
return (hook, )
|
||||
|
||||
|
||||
class CustomSamplerDetailerHookProvider:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"sampler": ("SAMPLER", ),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DETAILER_HOOK",)
|
||||
FUNCTION = "doit"
|
||||
|
||||
CATEGORY = "ImpactPack/Detailer"
|
||||
|
||||
DESCRIPTION = "Apply a hook that allows you to use a custom sampler in the Detailer nodes. When using `DetailerHookCombine`, the sampler from the first hook is applied."
|
||||
|
||||
def doit(self, sampler):
|
||||
hook = hooks.CustomSamplerDetailerHookProvider(sampler)
|
||||
return (hook, )
|
||||
|
||||
|
||||
class CfgScheduleHookProvider:
|
||||
schedules = ["simple"]
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ def impact_sample(model, seed, steps, cfg, sampler_name, scheduler, positive, ne
|
||||
|
||||
|
||||
def ksampler_wrapper(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise,
|
||||
refiner_ratio=None, refiner_model=None, refiner_clip=None, refiner_positive=None, refiner_negative=None, sigma_factor=1.0, noise=None, scheduler_func=None):
|
||||
refiner_ratio=None, refiner_model=None, refiner_clip=None, refiner_positive=None, refiner_negative=None, sigma_factor=1.0, noise=None, scheduler_func=None, sampler_opt=None):
|
||||
|
||||
if refiner_ratio is None or refiner_model is None or refiner_clip is None or refiner_positive is None or refiner_negative is None:
|
||||
# Use separated_sample instead of KSampler for `AYS scheduler`
|
||||
@@ -206,7 +206,7 @@ def ksampler_wrapper(model, seed, steps, cfg, sampler_name, scheduler, positive,
|
||||
|
||||
refined_latent = separated_sample(model, True, seed, advanced_steps, cfg, sampler_name, scheduler,
|
||||
positive, negative, latent_image, start_at_step, end_at_step, False,
|
||||
sigma_ratio=sigma_factor, noise=noise, scheduler_func=scheduler_func)
|
||||
sigma_ratio=sigma_factor, sampler_opt=sampler_opt, noise=noise, scheduler_func=scheduler_func)
|
||||
else:
|
||||
advanced_steps = math.floor(steps / denoise)
|
||||
start_at_step = advanced_steps - steps
|
||||
@@ -215,7 +215,7 @@ def ksampler_wrapper(model, seed, steps, cfg, sampler_name, scheduler, positive,
|
||||
# print(f"pre: {start_at_step} .. {end_at_step} / {advanced_steps}")
|
||||
temp_latent = separated_sample(model, True, seed, advanced_steps, cfg, sampler_name, scheduler,
|
||||
positive, negative, latent_image, start_at_step, end_at_step, True,
|
||||
sigma_ratio=sigma_factor, noise=noise, scheduler_func=scheduler_func)
|
||||
sigma_ratio=sigma_factor, sampler_opt=sampler_opt, noise=noise, scheduler_func=scheduler_func)
|
||||
|
||||
if 'noise_mask' in latent_image:
|
||||
# noise_latent = \
|
||||
@@ -229,7 +229,7 @@ def ksampler_wrapper(model, seed, steps, cfg, sampler_name, scheduler, positive,
|
||||
# print(f"post: {end_at_step} .. {advanced_steps + 1} / {advanced_steps}")
|
||||
refined_latent = separated_sample(refiner_model, False, seed, advanced_steps, cfg, sampler_name, scheduler,
|
||||
refiner_positive, refiner_negative, temp_latent, end_at_step, advanced_steps + 1, False,
|
||||
sigma_ratio=sigma_factor, scheduler_func=scheduler_func)
|
||||
sigma_ratio=sigma_factor, sampler_opt=sampler_opt, scheduler_func=scheduler_func)
|
||||
|
||||
return refined_latent
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ def process(text, seed=None):
|
||||
selected_items = random_gen.choice(options, p=normalized_probabilities, size=select_count, replace=False)
|
||||
|
||||
# x may be numpy.int32, convert to string
|
||||
selected_items2 = [re.sub(r'^\s*[0-9.]+::', '', str(x), 1) for x in selected_items]
|
||||
selected_items2 = [re.sub(r'^\s*[0-9.]+::', '', str(x), count=1) for x in selected_items]
|
||||
replacement = select_sep.join(selected_items2)
|
||||
if '::' in replacement:
|
||||
pass
|
||||
@@ -279,7 +279,7 @@ def process(text, seed=None):
|
||||
|
||||
normalized_probabilities = [prob / total_prob for prob in adjusted_probabilities]
|
||||
selected_item = random_gen.choice(options, p=normalized_probabilities, replace=False)
|
||||
replacement = re.sub(r'^\s*[0-9.]+::', '', selected_item, 1)
|
||||
replacement = re.sub(r'^\s*[0-9.]+::', '', selected_item, count=1)
|
||||
replacements_found = True
|
||||
string = string.replace(f"__{match}__", replacement, 1)
|
||||
elif '*' in keyword:
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui-impact-pack"
|
||||
description = "This node pack offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details. And provide iterative upscaler."
|
||||
version = "8.15.3"
|
||||
version = "8.16.1"
|
||||
license = { file = "LICENSE.txt" }
|
||||
dependencies = ["segment-anything", "scikit-image", "piexif", "transformers", "opencv-python-headless", "GitPython", "scipy>=1.11.4"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user