diff --git a/README.md b/README.md index 050ec2d..edfb988 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,8 @@ This takes latent as input and outputs latent as the result. * You need to install the [BlenderNeko/ComfyUI_TiledKSampler](https://github.com/BlenderNeko/ComfyUI_TiledKSampler) node extension. * TwoAdvancedSamplersForMask - TwoSamplersForMask is similar to TwoAdvancedSamplersForMask, but they differ in their operation. TwoSamplersForMask performs sampling in the mask area only after all the samples in the base area are finished. On the other hand, TwoAdvancedSamplersForMask performs sampling in both the base area and the mask area sequentially at each step. -* KSamplerAdvancedProvider - This is a wrapper that enables KSampler to be used in TwoAdvancedSamplersForMask. +* KSamplerAdvancedProvider - This is a wrapper that enables KSampler to be used in TwoAdvancedSamplersForMask, RegionalSampler. + * sigma_factor: By multiplying the noise schedule by the sigma_factor, you can adjust the amount of denoising based on the configured denoise. * TwoSamplersForMaskUpscalerProvider - This is an Upscaler that extends TwoSamplersForMask to be used in Iterative Upscale. * TwoSamplersForMaskUpscalerProviderPipe - pipe version of TwoSamplersForMaskUpscalerProvider. diff --git a/modules/impact/config.py b/modules/impact/config.py index b71ae1c..9154fc5 100644 --- a/modules/impact/config.py +++ b/modules/impact/config.py @@ -2,7 +2,7 @@ import configparser import os -version_code = [4, 75, 1] +version_code = [4, 76] version = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '') dependency_version = 20 diff --git a/modules/impact/impact_sampling.py b/modules/impact/impact_sampling.py index 2eec530..8ff6f52 100644 --- a/modules/impact/impact_sampling.py +++ b/modules/impact/impact_sampling.py @@ -119,10 +119,10 @@ def separated_sample(model, add_noise, seed, steps, cfg, sampler_name, scheduler 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): + refiner_ratio=None, refiner_model=None, refiner_clip=None, refiner_positive=None, refiner_negative=None, sigma_factor=1.0): 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: - refined_latent = nodes.KSampler().sample(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise)[0] + refined_latent = nodes.KSampler().sample(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise * sigma_factor)[0] else: advanced_steps = math.floor(steps / denoise) start_at_step = advanced_steps - steps @@ -130,7 +130,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) + positive, negative, latent_image, start_at_step, end_at_step, True, sigma_ratio=sigma_factor) if 'noise_mask' in latent_image: # noise_latent = \ @@ -143,7 +143,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) + refiner_positive, refiner_negative, temp_latent, end_at_step, advanced_steps + 1, False, sigma_ratio=sigma_factor) return refined_latent @@ -151,18 +151,19 @@ def ksampler_wrapper(model, seed, steps, cfg, sampler_name, scheduler, positive, class KSamplerAdvancedWrapper: params = None - def __init__(self, model, cfg, sampler_name, scheduler, positive, negative, sampler_opt=None): - self.params = model, cfg, sampler_name, scheduler, positive, negative + def __init__(self, model, cfg, sampler_name, scheduler, positive, negative, sampler_opt=None, sigma_factor=1.0): + self.params = model, cfg, sampler_name, scheduler, positive, negative, sigma_factor self.sampler_opt = sampler_opt def clone_with_conditionings(self, positive, negative): - model, cfg, sampler_name, scheduler, _, _ = self.params + model, cfg, sampler_name, scheduler, _, _, _ = self.params return KSamplerAdvancedWrapper(model, cfg, sampler_name, scheduler, positive, negative, self.sampler_opt) def sample_advanced(self, add_noise, seed, steps, latent_image, start_at_step, end_at_step, return_with_leftover_noise, hook=None, recovery_mode="ratio additional", recovery_sampler="AUTO", recovery_sigma_ratio=1.0): - model, cfg, sampler_name, scheduler, positive, negative = self.params + model, cfg, sampler_name, scheduler, positive, negative, sigma_factor = self.params + # steps, start_at_step, end_at_step = self.compensate_denoise(steps, start_at_step, end_at_step) if hook is not None: model, seed, steps, cfg, sampler_name, scheduler, positive, negative, upscaled_latent = hook.pre_ksample_advanced(model, add_noise, seed, steps, cfg, sampler_name, scheduler, @@ -183,7 +184,7 @@ class KSamplerAdvancedWrapper: if sigma_ratio > 0: latent_image = separated_sample(model, add_noise, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, start_at_step, end_at_step, - return_with_leftover_noise, sigma_ratio=sigma_ratio, sampler_opt=self.sampler_opt) + return_with_leftover_noise, sigma_ratio=sigma_ratio * sigma_factor, sampler_opt=self.sampler_opt) except ValueError as e: if str(e) == 'sigma_min and sigma_max must not be 0': print(f"\nWARN: sampling skipped - sigma_min and sigma_max are 0") @@ -207,7 +208,7 @@ class KSamplerAdvancedWrapper: try: latent_image = separated_sample(model, add_noise, seed, steps, cfg, recovery_sampler, scheduler, positive, negative, latent_image, start_at_step-compensate, end_at_step, - return_with_leftover_noise, sigma_ratio=recovery_sigma_ratio, sampler_opt=self.sampler_opt) + return_with_leftover_noise, sigma_ratio=recovery_sigma_ratio * sigma_factor, sampler_opt=self.sampler_opt) except ValueError as e: if str(e) == 'sigma_min and sigma_max must not be 0': print(f"\nWARN: sampling skipped - sigma_min and sigma_max are 0") diff --git a/modules/impact/special_samplers.py b/modules/impact/special_samplers.py index 7670cbe..d2dec47 100644 --- a/modules/impact/special_samplers.py +++ b/modules/impact/special_samplers.py @@ -67,6 +67,7 @@ class KSamplerAdvancedProvider: "cfg": ("FLOAT", {"default": 8.0, "min": 0.0, "max": 100.0}), "sampler_name": (comfy.samplers.KSampler.SAMPLERS, ), "scheduler": (comfy.samplers.KSampler.SCHEDULERS, ), + "sigma_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}), "basic_pipe": ("BASIC_PIPE", ) }, "optional": { @@ -79,9 +80,9 @@ class KSamplerAdvancedProvider: CATEGORY = "ImpactPack/Sampler" - def doit(self, cfg, sampler_name, scheduler, basic_pipe, sampler_opt=None): + def doit(self, cfg, sampler_name, scheduler, basic_pipe, sigma_factor=1.0, sampler_opt=None): model, _, _, positive, negative = basic_pipe - sampler = KSamplerAdvancedWrapper(model, cfg, sampler_name, scheduler, positive, negative, sampler_opt=sampler_opt) + sampler = KSamplerAdvancedWrapper(model, cfg, sampler_name, scheduler, positive, negative, sampler_opt=sampler_opt, sigma_factor=sigma_factor) return (sampler, )