added the option to specify target resolution with possibility of truncating for hires fix; also sampling steps
This commit is contained in:
parent
24d4a0841d
commit
8149078094
5 changed files with 81 additions and 19 deletions
|
@ -81,9 +81,6 @@ titles = {
|
||||||
|
|
||||||
"vram": "Torch active: Peak amount of VRAM used by Torch during generation, excluding cached data.\nTorch reserved: Peak amount of VRAM allocated by Torch, including all active and cached data.\nSys VRAM: Peak amount of VRAM allocation across all applications / total GPU VRAM (peak utilization%).",
|
"vram": "Torch active: Peak amount of VRAM used by Torch during generation, excluding cached data.\nTorch reserved: Peak amount of VRAM allocated by Torch, including all active and cached data.\nSys VRAM: Peak amount of VRAM allocation across all applications / total GPU VRAM (peak utilization%).",
|
||||||
|
|
||||||
"Highres. fix": "Use a two step process to partially create an image at smaller resolution, upscale, and then improve details in it without changing composition",
|
|
||||||
"Scale latent": "Uscale the image in latent space. Alternative is to produce the full image from latent representation, upscale that, and then move it back to latent space.",
|
|
||||||
|
|
||||||
"Eta noise seed delta": "If this values is non-zero, it will be added to seed and used to initialize RNG for noises when using samplers with Eta. You can use this to produce even more variation of images, or you can use this to match images of other software if you know what you are doing.",
|
"Eta noise seed delta": "If this values is non-zero, it will be added to seed and used to initialize RNG for noises when using samplers with Eta. You can use this to produce even more variation of images, or you can use this to match images of other software if you know what you are doing.",
|
||||||
"Do not add watermark to images": "If this option is enabled, watermark will not be added to created images. Warning: if you do not add watermark, you may be behaving in an unethical manner.",
|
"Do not add watermark to images": "If this option is enabled, watermark will not be added to created images. Warning: if you do not add watermark, you may be behaving in an unethical manner.",
|
||||||
|
|
||||||
|
@ -100,7 +97,13 @@ titles = {
|
||||||
"Clip skip": "Early stopping parameter for CLIP model; 1 is stop at last layer as usual, 2 is stop at penultimate layer, etc.",
|
"Clip skip": "Early stopping parameter for CLIP model; 1 is stop at last layer as usual, 2 is stop at penultimate layer, etc.",
|
||||||
|
|
||||||
"Approx NN": "Cheap neural network approximation. Very fast compared to VAE, but produces pictures with 4 times smaller horizontal/vertical resoluton and lower quality.",
|
"Approx NN": "Cheap neural network approximation. Very fast compared to VAE, but produces pictures with 4 times smaller horizontal/vertical resoluton and lower quality.",
|
||||||
"Approx cheap": "Very cheap approximation. Very fast compared to VAE, but produces pictures with 8 times smaller horizontal/vertical resoluton and extremely low quality."
|
"Approx cheap": "Very cheap approximation. Very fast compared to VAE, but produces pictures with 8 times smaller horizontal/vertical resoluton and extremely low quality.",
|
||||||
|
|
||||||
|
"Hires. fix": "Use a two step process to partially create an image at smaller resolution, upscale, and then improve details in it without changing composition",
|
||||||
|
"Hires steps": "Number of sampling steps for upscaled picture. If 0, uses same as for original.",
|
||||||
|
"Upscale by": "Adjusts the size of the image by multiplying the original width and height by the selected value. Ignored if either Resize width to or Resize height to are non-zero.",
|
||||||
|
"Resize width to": "Resizes image to this width. If 0, width is inferred from either of two nearby sliders.",
|
||||||
|
"Resize height to": "Resizes image to this height. If 0, height is inferred from either of two nearby sliders."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -212,11 +212,10 @@ def restore_old_hires_fix_params(res):
|
||||||
firstpass_width = math.ceil(scale * width / 64) * 64
|
firstpass_width = math.ceil(scale * width / 64) * 64
|
||||||
firstpass_height = math.ceil(scale * height / 64) * 64
|
firstpass_height = math.ceil(scale * height / 64) * 64
|
||||||
|
|
||||||
hr_scale = width / firstpass_width if firstpass_width > 0 else height / firstpass_height
|
|
||||||
|
|
||||||
res['Size-1'] = firstpass_width
|
res['Size-1'] = firstpass_width
|
||||||
res['Size-2'] = firstpass_height
|
res['Size-2'] = firstpass_height
|
||||||
res['Hires upscale'] = hr_scale
|
res['Hires resize-1'] = width
|
||||||
|
res['Hires resize-2'] = height
|
||||||
|
|
||||||
|
|
||||||
def parse_generation_parameters(x: str):
|
def parse_generation_parameters(x: str):
|
||||||
|
@ -276,6 +275,10 @@ Steps: 20, Sampler: Euler a, CFG scale: 7, Seed: 965400086, Size: 512x512, Model
|
||||||
hypernet_hash = res.get("Hypernet hash", None)
|
hypernet_hash = res.get("Hypernet hash", None)
|
||||||
res["Hypernet"] = find_hypernetwork_key(hypernet_name, hypernet_hash)
|
res["Hypernet"] = find_hypernetwork_key(hypernet_name, hypernet_hash)
|
||||||
|
|
||||||
|
if "Hires resize-1" not in res:
|
||||||
|
res["Hires resize-1"] = 0
|
||||||
|
res["Hires resize-2"] = 0
|
||||||
|
|
||||||
restore_old_hires_fix_params(res)
|
restore_old_hires_fix_params(res)
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
|
@ -662,12 +662,17 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||||
class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
|
class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
|
||||||
sampler = None
|
sampler = None
|
||||||
|
|
||||||
def __init__(self, enable_hr: bool = False, denoising_strength: float = 0.75, firstphase_width: int = 0, firstphase_height: int = 0, hr_scale: float = 2.0, hr_upscaler: str = None, **kwargs):
|
def __init__(self, enable_hr: bool = False, denoising_strength: float = 0.75, firstphase_width: int = 0, firstphase_height: int = 0, hr_scale: float = 2.0, hr_upscaler: str = None, hr_second_pass_steps: int = 0, hr_resize_x: int = 0, hr_resize_y: int = 0, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.enable_hr = enable_hr
|
self.enable_hr = enable_hr
|
||||||
self.denoising_strength = denoising_strength
|
self.denoising_strength = denoising_strength
|
||||||
self.hr_scale = hr_scale
|
self.hr_scale = hr_scale
|
||||||
self.hr_upscaler = hr_upscaler
|
self.hr_upscaler = hr_upscaler
|
||||||
|
self.hr_second_pass_steps = hr_second_pass_steps
|
||||||
|
self.hr_resize_x = hr_resize_x
|
||||||
|
self.hr_resize_y = hr_resize_y
|
||||||
|
self.hr_upscale_to_x = hr_resize_x
|
||||||
|
self.hr_upscale_to_y = hr_resize_y
|
||||||
|
|
||||||
if firstphase_width != 0 or firstphase_height != 0:
|
if firstphase_width != 0 or firstphase_height != 0:
|
||||||
print("firstphase_width/firstphase_height no longer supported; use hr_scale", file=sys.stderr)
|
print("firstphase_width/firstphase_height no longer supported; use hr_scale", file=sys.stderr)
|
||||||
|
@ -675,6 +680,9 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
|
||||||
self.width = firstphase_width
|
self.width = firstphase_width
|
||||||
self.height = firstphase_height
|
self.height = firstphase_height
|
||||||
|
|
||||||
|
self.truncate_x = 0
|
||||||
|
self.truncate_y = 0
|
||||||
|
|
||||||
def init(self, all_prompts, all_seeds, all_subseeds):
|
def init(self, all_prompts, all_seeds, all_subseeds):
|
||||||
if self.enable_hr:
|
if self.enable_hr:
|
||||||
if state.job_count == -1:
|
if state.job_count == -1:
|
||||||
|
@ -682,7 +690,38 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
|
||||||
else:
|
else:
|
||||||
state.job_count = state.job_count * 2
|
state.job_count = state.job_count * 2
|
||||||
|
|
||||||
self.extra_generation_params["Hires upscale"] = self.hr_scale
|
if self.hr_resize_x == 0 and self.hr_resize_y == 0:
|
||||||
|
self.extra_generation_params["Hires upscale"] = self.hr_scale
|
||||||
|
self.hr_upscale_to_x = int(self.width * self.hr_scale)
|
||||||
|
self.hr_upscale_to_y = int(self.height * self.hr_scale)
|
||||||
|
else:
|
||||||
|
self.extra_generation_params["Hires resize"] = f"{self.hr_resize_x}x{self.hr_resize_y}"
|
||||||
|
|
||||||
|
if self.hr_resize_y == 0:
|
||||||
|
self.hr_upscale_to_x = self.hr_resize_x
|
||||||
|
self.hr_upscale_to_y = self.hr_resize_x * self.height // self.width
|
||||||
|
elif self.hr_resize_x == 0:
|
||||||
|
self.hr_upscale_to_x = self.hr_resize_y * self.width // self.height
|
||||||
|
self.hr_upscale_to_y = self.hr_resize_y
|
||||||
|
else:
|
||||||
|
target_w = self.hr_resize_x
|
||||||
|
target_h = self.hr_resize_y
|
||||||
|
src_ratio = self.width / self.height
|
||||||
|
dst_ratio = self.hr_resize_x / self.hr_resize_y
|
||||||
|
|
||||||
|
if src_ratio < dst_ratio:
|
||||||
|
self.hr_upscale_to_x = self.hr_resize_x
|
||||||
|
self.hr_upscale_to_y = self.hr_resize_x * self.height // self.width
|
||||||
|
else:
|
||||||
|
self.hr_upscale_to_x = self.hr_resize_y * self.width // self.height
|
||||||
|
self.hr_upscale_to_y = self.hr_resize_y
|
||||||
|
|
||||||
|
self.truncate_x = (self.hr_upscale_to_x - target_w) // opt_f
|
||||||
|
self.truncate_y = (self.hr_upscale_to_y - target_h) // opt_f
|
||||||
|
|
||||||
|
if self.hr_second_pass_steps:
|
||||||
|
self.extra_generation_params["Hires steps"] = self.hr_second_pass_steps
|
||||||
|
|
||||||
if self.hr_upscaler is not None:
|
if self.hr_upscaler is not None:
|
||||||
self.extra_generation_params["Hires upscaler"] = self.hr_upscaler
|
self.extra_generation_params["Hires upscaler"] = self.hr_upscaler
|
||||||
|
|
||||||
|
@ -699,8 +738,8 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
|
||||||
if not self.enable_hr:
|
if not self.enable_hr:
|
||||||
return samples
|
return samples
|
||||||
|
|
||||||
target_width = int(self.width * self.hr_scale)
|
target_width = self.hr_upscale_to_x
|
||||||
target_height = int(self.height * self.hr_scale)
|
target_height = self.hr_upscale_to_y
|
||||||
|
|
||||||
def save_intermediate(image, index):
|
def save_intermediate(image, index):
|
||||||
"""saves image before applying hires fix, if enabled in options; takes as an argument either an image or batch with latent space images"""
|
"""saves image before applying hires fix, if enabled in options; takes as an argument either an image or batch with latent space images"""
|
||||||
|
@ -755,13 +794,15 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
|
||||||
|
|
||||||
self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model)
|
self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model)
|
||||||
|
|
||||||
|
samples = samples[:, :, self.truncate_y//2:samples.shape[2]-(self.truncate_y+1)//2, self.truncate_x//2:samples.shape[3]-(self.truncate_x+1)//2]
|
||||||
|
|
||||||
noise = create_random_tensors(samples.shape[1:], seeds=seeds, subseeds=subseeds, subseed_strength=subseed_strength, p=self)
|
noise = create_random_tensors(samples.shape[1:], seeds=seeds, subseeds=subseeds, subseed_strength=subseed_strength, p=self)
|
||||||
|
|
||||||
# GC now before running the next img2img to prevent running out of memory
|
# GC now before running the next img2img to prevent running out of memory
|
||||||
x = None
|
x = None
|
||||||
devices.torch_gc()
|
devices.torch_gc()
|
||||||
|
|
||||||
samples = self.sampler.sample_img2img(self, samples, noise, conditioning, unconditional_conditioning, steps=self.steps, image_conditioning=image_conditioning)
|
samples = self.sampler.sample_img2img(self, samples, noise, conditioning, unconditional_conditioning, steps=self.hr_second_pass_steps or self.steps, image_conditioning=image_conditioning)
|
||||||
|
|
||||||
return samples
|
return samples
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import modules.processing as processing
|
||||||
from modules.ui import plaintext_to_html
|
from modules.ui import plaintext_to_html
|
||||||
|
|
||||||
|
|
||||||
def txt2img(prompt: str, negative_prompt: str, prompt_style: str, prompt_style2: str, steps: int, sampler_index: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, seed_enable_extras: bool, height: int, width: int, enable_hr: bool, denoising_strength: float, hr_scale: float, hr_upscaler: str, *args):
|
def txt2img(prompt: str, negative_prompt: str, prompt_style: str, prompt_style2: str, steps: int, sampler_index: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, seed_enable_extras: bool, height: int, width: int, enable_hr: bool, denoising_strength: float, hr_scale: float, hr_upscaler: str, hr_second_pass_steps: int, hr_resize_x: int, hr_resize_y: int, *args):
|
||||||
p = StableDiffusionProcessingTxt2Img(
|
p = StableDiffusionProcessingTxt2Img(
|
||||||
sd_model=shared.sd_model,
|
sd_model=shared.sd_model,
|
||||||
outpath_samples=opts.outdir_samples or opts.outdir_txt2img_samples,
|
outpath_samples=opts.outdir_samples or opts.outdir_txt2img_samples,
|
||||||
|
@ -35,6 +35,9 @@ def txt2img(prompt: str, negative_prompt: str, prompt_style: str, prompt_style2:
|
||||||
denoising_strength=denoising_strength if enable_hr else None,
|
denoising_strength=denoising_strength if enable_hr else None,
|
||||||
hr_scale=hr_scale,
|
hr_scale=hr_scale,
|
||||||
hr_upscaler=hr_upscaler,
|
hr_upscaler=hr_upscaler,
|
||||||
|
hr_second_pass_steps=hr_second_pass_steps,
|
||||||
|
hr_resize_x=hr_resize_x,
|
||||||
|
hr_resize_y=hr_resize_y,
|
||||||
)
|
)
|
||||||
|
|
||||||
p.scripts = modules.scripts.scripts_txt2img
|
p.scripts = modules.scripts.scripts_txt2img
|
||||||
|
|
|
@ -637,10 +637,10 @@ def create_sampler_and_steps_selection(choices, tabname):
|
||||||
with FormRow(elem_id=f"sampler_selection_{tabname}"):
|
with FormRow(elem_id=f"sampler_selection_{tabname}"):
|
||||||
sampler_index = gr.Dropdown(label='Sampling method', elem_id=f"{tabname}_sampling", choices=[x.name for x in choices], value=choices[0].name, type="index")
|
sampler_index = gr.Dropdown(label='Sampling method', elem_id=f"{tabname}_sampling", choices=[x.name for x in choices], value=choices[0].name, type="index")
|
||||||
sampler_index.save_to_config = True
|
sampler_index.save_to_config = True
|
||||||
steps = gr.Slider(minimum=1, maximum=150, step=1, elem_id=f"{tabname}_steps", label="Sampling Steps", value=20)
|
steps = gr.Slider(minimum=1, maximum=150, step=1, elem_id=f"{tabname}_steps", label="Sampling steps", value=20)
|
||||||
else:
|
else:
|
||||||
with FormGroup(elem_id=f"sampler_selection_{tabname}"):
|
with FormGroup(elem_id=f"sampler_selection_{tabname}"):
|
||||||
steps = gr.Slider(minimum=1, maximum=150, step=1, elem_id=f"{tabname}_steps", label="Sampling Steps", value=20)
|
steps = gr.Slider(minimum=1, maximum=150, step=1, elem_id=f"{tabname}_steps", label="Sampling steps", value=20)
|
||||||
sampler_index = gr.Radio(label='Sampling method', elem_id=f"{tabname}_sampling", choices=[x.name for x in choices], value=choices[0].name, type="index")
|
sampler_index = gr.Radio(label='Sampling method', elem_id=f"{tabname}_sampling", choices=[x.name for x in choices], value=choices[0].name, type="index")
|
||||||
|
|
||||||
return steps, sampler_index
|
return steps, sampler_index
|
||||||
|
@ -709,10 +709,16 @@ def create_ui():
|
||||||
enable_hr = gr.Checkbox(label='Hires. fix', value=False, elem_id="txt2img_enable_hr")
|
enable_hr = gr.Checkbox(label='Hires. fix', value=False, elem_id="txt2img_enable_hr")
|
||||||
|
|
||||||
elif category == "hires_fix":
|
elif category == "hires_fix":
|
||||||
with FormRow(visible=False, elem_id="txt2img_hires_fix") as hr_options:
|
with FormGroup(visible=False, elem_id="txt2img_hires_fix") as hr_options:
|
||||||
hr_upscaler = gr.Dropdown(label="Upscaler", elem_id="txt2img_hr_upscaler", choices=[*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]], value=shared.latent_upscale_default_mode)
|
with FormRow(elem_id="txt2img_hires_fix_row1"):
|
||||||
hr_scale = gr.Slider(minimum=1.0, maximum=4.0, step=0.05, label="Upscale by", value=2.0, elem_id="txt2img_hr_scale")
|
hr_upscaler = gr.Dropdown(label="Upscaler", elem_id="txt2img_hr_upscaler", choices=[*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]], value=shared.latent_upscale_default_mode)
|
||||||
denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising strength', value=0.7, elem_id="txt2img_denoising_strength")
|
hr_second_pass_steps = gr.Slider(minimum=0, maximum=150, step=1, label='Hires steps', value=0, elem_id="txt2img_hires_steps")
|
||||||
|
denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising strength', value=0.7, elem_id="txt2img_denoising_strength")
|
||||||
|
|
||||||
|
with FormRow(elem_id="txt2img_hires_fix_row2"):
|
||||||
|
hr_scale = gr.Slider(minimum=1.0, maximum=4.0, step=0.05, label="Upscale by", value=2.0, elem_id="txt2img_hr_scale")
|
||||||
|
hr_resize_x = gr.Slider(minimum=0, maximum=2048, step=8, label="Resize width to", value=0, elem_id="txt2img_hr_resize_x")
|
||||||
|
hr_resize_y = gr.Slider(minimum=0, maximum=2048, step=8, label="Resize height to", value=0, elem_id="txt2img_hr_resize_y")
|
||||||
|
|
||||||
elif category == "batch":
|
elif category == "batch":
|
||||||
if not opts.dimensions_and_batch_together:
|
if not opts.dimensions_and_batch_together:
|
||||||
|
@ -753,6 +759,9 @@ def create_ui():
|
||||||
denoising_strength,
|
denoising_strength,
|
||||||
hr_scale,
|
hr_scale,
|
||||||
hr_upscaler,
|
hr_upscaler,
|
||||||
|
hr_second_pass_steps,
|
||||||
|
hr_resize_x,
|
||||||
|
hr_resize_y,
|
||||||
] + custom_inputs,
|
] + custom_inputs,
|
||||||
|
|
||||||
outputs=[
|
outputs=[
|
||||||
|
@ -804,6 +813,9 @@ def create_ui():
|
||||||
(hr_options, lambda d: gr.Row.update(visible="Denoising strength" in d)),
|
(hr_options, lambda d: gr.Row.update(visible="Denoising strength" in d)),
|
||||||
(hr_scale, "Hires upscale"),
|
(hr_scale, "Hires upscale"),
|
||||||
(hr_upscaler, "Hires upscaler"),
|
(hr_upscaler, "Hires upscaler"),
|
||||||
|
(hr_second_pass_steps, "Hires steps"),
|
||||||
|
(hr_resize_x, "Hires resize-1"),
|
||||||
|
(hr_resize_y, "Hires resize-2"),
|
||||||
*modules.scripts.scripts_txt2img.infotext_fields
|
*modules.scripts.scripts_txt2img.infotext_fields
|
||||||
]
|
]
|
||||||
parameters_copypaste.add_paste_fields("txt2img", None, txt2img_paste_fields)
|
parameters_copypaste.add_paste_fields("txt2img", None, txt2img_paste_fields)
|
||||||
|
|
Loading…
Reference in a new issue