diff --git a/backend/args.py b/backend/args.py index 5057795e..7c8da50a 100644 --- a/backend/args.py +++ b/backend/args.py @@ -168,7 +168,7 @@ class dynamic_args(metaclass=_DynamicArgsMeta): """Reference Latent(s) for Flux Kontext / Qwen-Image-Edit / Flux.2 Klein""" concat_latent: "torch.Tensor" = None """Input Latent for Wan 2.2 I2V""" - lq_latent: tuple["torch.Tensor", "torch.Tensor"] = None + lq_latent: list["torch.Tensor", "torch.Tensor"] = [None, None] """lq_latent & degrade_sigma for PiD""" is_referencing: bool = False """Appending Reference Latent(s) (by. ImageStitch)""" diff --git a/backend/diffusion_engine/pid.py b/backend/diffusion_engine/pid.py index 784197f2..be7cc5ab 100644 --- a/backend/diffusion_engine/pid.py +++ b/backend/diffusion_engine/pid.py @@ -51,8 +51,6 @@ class PiD(ForgeDiffusionEngine): self.use_shift = True - self.degrade_sigma: float = None - @torch.inference_mode() def get_learned_conditioning(self, prompt: list[str]): memory_management.load_model_gpu(self.forge_objects.clip.patcher) @@ -65,15 +63,12 @@ class PiD(ForgeDiffusionEngine): @torch.inference_mode() def encode_first_stage(self, x): - if not dynamic_args.is_referencing: - raise SystemError("PiD only supports txt2img") - sample = self.forge_objects.vae.encode(x.movedim(1, -1) * 0.5 + 0.5) sample = self.forge_objects.vae.first_stage_model.process_in(sample) sample = sample.squeeze(2) + dynamic_args.lq_latent[0] = sample.detach().clone() - dynamic_args.lq_latent = (sample, torch.tensor([float(self.degrade_sigma)], dtype=torch.float32)) - return None + return sample @torch.inference_mode() def decode_first_stage(self, x): diff --git a/backend/nn/pixeldit/pid.py b/backend/nn/pixeldit/pid.py index c9321b68..61cd3693 100644 --- a/backend/nn/pixeldit/pid.py +++ b/backend/nn/pixeldit/pid.py @@ -191,7 +191,7 @@ class PidNet(PixDiT_T2I): Hs = -(-x.shape[2] // self.patch_size) Ws = -(-x.shape[3] // self.patch_size) - degrade_sigma = degrade_sigma.to(device=x.device, dtype=torch.float32).reshape(-1) + degrade_sigma = degrade_sigma.to(device=x.device).reshape(-1) if degrade_sigma.numel() == 1 and B > 1: degrade_sigma = degrade_sigma.expand(B).contiguous() diff --git a/extensions-builtin/sd_forge_image_stitch/scripts/image_stitch.py b/extensions-builtin/sd_forge_image_stitch/scripts/image_stitch.py index 3fd7f023..5f50b122 100644 --- a/extensions-builtin/sd_forge_image_stitch/scripts/image_stitch.py +++ b/extensions-builtin/sd_forge_image_stitch/scripts/image_stitch.py @@ -6,11 +6,7 @@ from PIL import Image from backend.args import dynamic_args from modules import images, scripts, sd_models from modules.api import api -from modules.processing import ( - StableDiffusionProcessing, - StableDiffusionProcessingTxt2Img, - logger, -) +from modules.processing import StableDiffusionProcessing, StableDiffusionProcessingTxt2Img, logger from modules.sd_samplers_common import images_tensor_to_samples from modules.shared import device, opts from modules.ui_components import FormRow, InputAccordion @@ -18,7 +14,6 @@ from modules.ui_components import FormRow, InputAccordion t2i_info = """ For Flux.1-Kontext / Flux.2-Klein / Qwen-Image-Edit: Use in txt2img to achieve the effect of empty latent with custom resolution
For Wan 2.2 I2V: Use in txt2img to set as the Last Frame to achieve LastFrameToVideo
-For PiD: Use in txt2img to set as the lq_latent
Note: This doesn't actually stitch the images ; Tip: Use the "Image to Upload" to paste images """ @@ -97,15 +92,6 @@ class ImageStitch(scripts.Script): info="reduce VRAM usage during encoding ; apply to all reference images ; set to 0 for no limit", ) - degrade_sigma = gr.Slider( - minimum=0.0, - maximum=1.0, - value=0.0, - step=0.05, - label="Degrade Sigma", - info="denoising strength ; for PiD only", - ) - def _upload(gallery: list[tuple[Image.Image, str]], image: Image.Image): if not image: return [gr.skip(), gr.skip()] @@ -158,7 +144,7 @@ class ImageStitch(scripts.Script): show_progress=False, ) - return [enable, references, max_dim, degrade_sigma] + return [enable, references, max_dim] @staticmethod def reset_references(p: StableDiffusionProcessing): @@ -166,8 +152,8 @@ class ImageStitch(scripts.Script): p.clear_prompt_cache() p.sd_model.clear_references() - def process(self, p: StableDiffusionProcessing, enable: bool, references: list[str | tuple[Image.Image, str]], max_dim: int, degrade_sigma: float): - if not (enable and references and any(getattr(dynamic_args, key) for key in ("kontext", "edit", "klein", "wan", "pid"))): + def process(self, p: StableDiffusionProcessing, enable: bool, references: list[str | tuple[Image.Image, str]], max_dim: int): + if not (enable and references and any(getattr(dynamic_args, key) for key in ("kontext", "edit", "klein", "wan"))): if ImageStitch.cached_parameters is None: return @@ -198,16 +184,6 @@ class ImageStitch(scripts.Script): logger.warning("Wan 2.2 only uses the first reference image...") references = [references[0]] - if dynamic_args.pid: - if not isinstance(p, StableDiffusionProcessingTxt2Img): - logger.error("PiD only supports txt2img...") - return - if len(references) > 1: - logger.warning("PiD only uses the first reference image...") - references = [references[0]] - - p.sd_model.degrade_sigma = degrade_sigma - dynamic_args.is_referencing = True for reference in references: diff --git a/modules/processing.py b/modules/processing.py index 5316bae3..40c5937b 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -1691,6 +1691,12 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): if (args.dynamic_args.kontext or args.dynamic_args.edit) and self.denoising_strength < 0.9: logger.warning("Edit Models require High Denoising Strength") + if args.dynamic_args.pid: + args.dynamic_args.lq_latent[1] = torch.tensor([self.denoising_strength], dtype=torch.float32) + self.denoising_strength = 1.0 + self.resize_mode = 3 # skip resize image + assert self.image_mask is None + self.image_cfg_scale: float = None self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model) @@ -1868,6 +1874,9 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): if shared.sd_model.is_wan and args.dynamic_args.wan: # enforce batch_size of 1 x = x[0].unsqueeze(0) + if args.dynamic_args.pid: + self.init_latent = x.detach().clone() + if self.initial_noise_multiplier != 1.0: self.extra_generation_params["Noise multiplier"] = self.initial_noise_multiplier x *= self.initial_noise_multiplier