Files
blepping a7855cde42 Add ensure_model_mode parameter and alt strategies for ensure model
Allow passing advanced noise sampler parameters
Fix masks not being respected in sharpen operation
2025-01-09 03:07:26 -07:00

118 lines
3.7 KiB
Python

from __future__ import annotations
from typing import TYPE_CHECKING
from .tensor_image_ops import BLENDING_MODES
from .utils import ensure_model, sigma_to_float
if TYPE_CHECKING:
import torch
class JankDiffuseHighModelWrapper:
def __init__(self, guided_model):
self.__guided_model = guided_model
def __getattr__(self, key):
try:
return getattr(self.__guided_model.dhso.model, key)
except AttributeError:
raise AttributeError(key) from None
def __call__(self, *args: list, **kwargs: dict) -> torch.Tensor:
return self.__guided_model(*args, **kwargs)
class GuidedModel:
def __init__(
self,
dh_sampler_object,
guidance_sigmas: torch.Tensor,
guidance_steps: int,
):
self.dhso = dh_sampler_object
self.allow_guidance = True
self.force_guidance: int | None = None
self.set_guidance_range(guidance_sigmas, guidance_steps)
def set_guidance_range(self, guidance_sigmas, guidance_steps):
if len(guidance_sigmas) >= 2:
self.guidance_start_sigma = sigma_to_float(guidance_sigmas[0]) + 1e-05
self.guidance_end_sigma = sigma_to_float(guidance_sigmas[-1]) + 1e-05
else:
self.guidance_start_sigma = None
self.guidance_end_sigma = None
self.guidance_sigmas_list = tuple(guidance_sigmas.detach().cpu().tolist())
self.guidance_steps = guidance_steps
def get_guidance_step(self, sigma: torch.Tensor) -> int | None:
sigma_float = sigma_to_float(sigma)
if not self.allow_guidance:
return None
sigma_float = sigma_to_float(sigma)
if self.force_guidance is None and (
self.guidance_start_sigma is None or sigma_float < self.guidance_end_sigma
):
return None
if self.force_guidance is not None and self.force_guidance >= 0:
return self.force_guidance
step_idx = (
next(
(
idx
for idx, gsigma in enumerate(self.guidance_sigmas_list)
if gsigma <= sigma_float
),
None,
)
if sigma_float <= self.guidance_start_sigma
else 0
)
if step_idx is None:
if not self.force_guidance:
return None
step_idx = max(0, self.guidance_steps - 1)
return min(step_idx, self.guidance_steps - 1)
def make_wrapper(self):
return JankDiffuseHighModelWrapper(self)
def __call__(
self,
x: torch.Tensor,
sigma: torch.Tensor,
**extra_args: dict,
) -> torch.Tensor:
dhso = self.dhso
model = dhso.model
dhso.seed_offset += 1
ensure_model(model, mode=dhso.ensure_model_mode)
guidance_step = self.get_guidance_step(sigma)
# Sigma offset trick from https://github.com/muerrilla/sd-webui-detail-daemon
sigma_offset = max(
1e-05,
1.0
+ (
dhso.sigma_dishonesty_factor_guidance
if guidance_step is not None
else dhso.sigma_dishonesty_factor
),
)
denoised = model(
x,
sigma * sigma_offset if sigma_offset != 1 else sigma,
**extra_args,
)
result = (
denoised
if guidance_step is None
else dhso.apply_guidance(guidance_step, denoised)
)
if dhso.mask is not None:
result = BLENDING_MODES[dhso.mask_blend_mode](
dhso.orig_latent,
result,
dhso.mask,
)
return result