mirror of
https://github.com/lllyasviel/stable-diffusion-webui-forge.git
synced 2026-07-21 21:01:24 +08:00
Seed Variance Enhancer
https://github.com/ChangeTheConstants/SeedVarianceEnhancer
This commit is contained in:
parent
077c2d4d32
commit
eecfcc461e
77
extensions-builtin/seed-variance-enhancer/scripts/sve.py
Normal file
77
extensions-builtin/seed-variance-enhancer/scripts/sve.py
Normal file
@ -0,0 +1,77 @@
|
||||
# https://github.com/ChangeTheConstants/SeedVarianceEnhancer
|
||||
|
||||
import gradio as gr
|
||||
import torch
|
||||
|
||||
from modules import scripts
|
||||
from modules.infotext_utils import PasteField
|
||||
from modules.processing import StableDiffusionProcessingTxt2Img
|
||||
from modules.script_callbacks import CFGDenoiserParams, on_cfg_denoiser
|
||||
from modules.ui_components import InputAccordion
|
||||
|
||||
|
||||
class SeedVarianceEnhancer(scripts.Script):
|
||||
enable: bool
|
||||
steps: int
|
||||
percentage: float
|
||||
strength: float
|
||||
seed: int
|
||||
|
||||
def title(self):
|
||||
return "SeedVarianceEnhancer Integrated"
|
||||
|
||||
def show(self, is_img2img):
|
||||
return None if is_img2img else scripts.AlwaysVisible
|
||||
|
||||
def ui(self, is_img2img):
|
||||
with InputAccordion(value=False, label=self.title()) as enable:
|
||||
with gr.Row():
|
||||
steps = gr.Slider(value=3, minimum=0, maximum=8, step=1, label="Steps", info="the number of steps to inject random noise")
|
||||
percentage = gr.Slider(value=0.6, minimum=0.0, maximum=1.0, step=0.05, label="Percentage", info="the percentage of conditioning to inject random noise")
|
||||
strength = gr.Slider(value=32, minimum=0, maximum=64, step=1, label="Strength", info="the strength of the random noise")
|
||||
|
||||
self.infotext_fields = [
|
||||
PasteField(steps, "SVE Steps"),
|
||||
PasteField(percentage, "SVE Percentage"),
|
||||
PasteField(strength, "SVE Strength"),
|
||||
]
|
||||
|
||||
return [enable, steps, percentage, strength]
|
||||
|
||||
def before_process_batch(self, p: StableDiffusionProcessingTxt2Img, enable: bool, steps: int, percentage: float, strength: int, **kwargs):
|
||||
SeedVarianceEnhancer.enable = enable and isinstance(p, StableDiffusionProcessingTxt2Img)
|
||||
if not SeedVarianceEnhancer.enable:
|
||||
return
|
||||
|
||||
SeedVarianceEnhancer.steps = steps
|
||||
SeedVarianceEnhancer.percentage = percentage
|
||||
SeedVarianceEnhancer.strength = strength
|
||||
SeedVarianceEnhancer.seed = kwargs["seeds"][0]
|
||||
|
||||
p.extra_generation_params.update(
|
||||
{
|
||||
"SVE Steps": steps,
|
||||
"SVE Percentage": percentage,
|
||||
"SVE Strength": strength,
|
||||
}
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@torch.inference_mode()
|
||||
def on_cfg(cls, params: CFGDenoiserParams):
|
||||
if not cls.enable:
|
||||
return
|
||||
if cls.steps < params.sampling_step:
|
||||
return
|
||||
|
||||
cond: torch.Tensor = params.text_cond
|
||||
torch.manual_seed(cls.seed)
|
||||
|
||||
noise = torch.rand_like(cond) * 2.0 * cls.strength - cls.strength
|
||||
noise_mask = torch.bernoulli(torch.ones_like(cond) * cls.percentage).bool()
|
||||
|
||||
modified_noise = noise * noise_mask
|
||||
params.text_cond = cond + modified_noise
|
||||
|
||||
|
||||
on_cfg_denoiser(SeedVarianceEnhancer.on_cfg)
|
||||
@ -379,16 +379,6 @@ def forge_model_reload():
|
||||
script_callbacks.model_loaded_callback(sd_model)
|
||||
timer.record("scripts callbacks")
|
||||
|
||||
if opts.early_empty_prompt > 0:
|
||||
_cond = sd_model.get_learned_conditioning(SdConditioning([opts.empty_prompt_template]))
|
||||
if isinstance(_cond, dict):
|
||||
_cond = DictWithShape(_cond)
|
||||
elif isinstance(_cond, list):
|
||||
_cond = torch.stack(_cond)
|
||||
|
||||
sd_model.empty_cond = _cond.to(devices.cpu)
|
||||
timer.record("calculate empty prompt")
|
||||
|
||||
print(f"Model loaded in {timer.summary()}.")
|
||||
|
||||
model_data.forge_hash = current_hash
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import torch
|
||||
|
||||
import modules.shared as shared
|
||||
from backend.sampling.sampling_function import sampling_function
|
||||
from modules import processing, prompt_parser, sd_samplers_common
|
||||
from modules import prompt_parser, sd_samplers_common
|
||||
from modules.script_callbacks import AfterCFGCallbackParams, CFGDenoiserParams, cfg_after_cfg_callback, cfg_denoiser_callback
|
||||
from modules.shared import opts, state
|
||||
|
||||
@ -127,11 +126,6 @@ class CFGDenoiser(torch.nn.Module):
|
||||
noisy_initial_latent = predictor.noise_scaling(sigma[:, None, None, None], torch.randn_like(self.init_latent).to(self.init_latent), self.init_latent, max_denoise=False)
|
||||
x = x * self.nmask + noisy_initial_latent * self.mask
|
||||
|
||||
if 0 < self.step <= opts.early_empty_prompt:
|
||||
if isinstance(self.p, processing.StableDiffusionProcessingTxt2Img):
|
||||
cond = shared.sd_model.empty_cond.to(original_x_device)
|
||||
self.p.extra_generation_params["Empty Early CFG"] = opts.early_empty_prompt
|
||||
|
||||
denoiser_params = CFGDenoiserParams(x, image_cond, sigma, state.sampling_step, state.sampling_steps, cond, uncond, self)
|
||||
cfg_denoiser_callback(denoiser_params)
|
||||
|
||||
|
||||
@ -242,25 +242,6 @@ options_templates.update(
|
||||
gr.Textbox,
|
||||
{"lines": 3, "max_lines": 6, "placeholder": "<Prompt Start>"},
|
||||
),
|
||||
"divdistill": OptionDiv(),
|
||||
"early_empty_prompt": OptionInfo(
|
||||
0,
|
||||
"Steps to use Empty Prompt at the beginning",
|
||||
gr.Slider,
|
||||
{"minimum": 0, "maximum": 8, "step": 1},
|
||||
infotext="Empty Early CFG",
|
||||
)
|
||||
.info("improve variance for distilled models")
|
||||
.info("does not affect img2img")
|
||||
.needs_restart(),
|
||||
"empty_prompt_template": OptionInfo(
|
||||
"",
|
||||
"Prompt to Encode as the Empty Prompt",
|
||||
gr.Textbox,
|
||||
{"lines": 1, "max_lines": 3, "placeholder": "high quality"},
|
||||
)
|
||||
.info("default is empty")
|
||||
.needs_restart(),
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user