From 33b85391474098b021946a5f1d8e07f8a6d27aa2 Mon Sep 17 00:00:00 2001 From: James Railton Date: Tue, 21 Mar 2023 21:07:33 -0400 Subject: Loopback Script Updates - Improved user experience. You can now pick the denoising strength of the final loop and one of three curves. Previously you picked a multiplier such as 0.98 or 1.03 to define the change to the denoising strength for each loop. You had to do a ton of math in your head to visualize what was happening. The new UX makes it very easy to understand what's going on and tweak. - For batch sizes over 1, intermediate images no longer returned. For a batch size of 1, intermediate images from each loop will continue to be returned. When more than 1 image is returned, a grid will also be generated. Previously for larger jobs, you'd get back a mess of many grids and potentially hundreds of images with no organization. To make large jobs usable, only final images are returned. - Added support for skipping current image. Fixed interrupt to cleanly end and return images. Previously these would throw. - Improved tooltip descriptions - Fix some edge cases --- scripts/loopback.py | 93 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 26 deletions(-) (limited to 'scripts') diff --git a/scripts/loopback.py b/scripts/loopback.py index ec1f85e5..81577888 100644 --- a/scripts/loopback.py +++ b/scripts/loopback.py @@ -1,14 +1,10 @@ -import numpy as np -from tqdm import trange +import math -import modules.scripts as scripts import gradio as gr - -from modules import processing, shared, sd_samplers, images +import modules.scripts as scripts +from modules import deepbooru, images, processing, shared from modules.processing import Processed -from modules.sd_samplers import samplers -from modules.shared import opts, cmd_opts, state -from modules import deepbooru +from modules.shared import opts, state class Script(scripts.Script): @@ -20,24 +16,27 @@ class Script(scripts.Script): def ui(self, is_img2img): loops = gr.Slider(minimum=1, maximum=32, step=1, label='Loops', value=4, elem_id=self.elem_id("loops")) - denoising_strength_change_factor = gr.Slider(minimum=0.9, maximum=1.1, step=0.01, label='Denoising strength change factor', value=1, elem_id=self.elem_id("denoising_strength_change_factor")) + final_denoising_strength = gr.Slider(minimum=0, maximum=1, step=0.01, label='Final denoising strength', value=0.5, elem_id=self.elem_id("final_denoising_strength")) + denoising_curve = gr.Dropdown(label="Denoising strength curve", choices=["Aggressive", "Linear", "Lazy"], value="Linear") append_interrogation = gr.Dropdown(label="Append interrogated prompt at each iteration", choices=["None", "CLIP", "DeepBooru"], value="None") - return [loops, denoising_strength_change_factor, append_interrogation] + return [loops, final_denoising_strength, denoising_curve, append_interrogation] - def run(self, p, loops, denoising_strength_change_factor, append_interrogation): + def run(self, p, loops, final_denoising_strength, denoising_curve, append_interrogation): processing.fix_seed(p) batch_count = p.n_iter p.extra_generation_params = { - "Denoising strength change factor": denoising_strength_change_factor, + "Final denoising strength": final_denoising_strength, + "Denoising curve": denoising_curve } p.batch_size = 1 p.n_iter = 1 - output_images, info = None, None + info = None initial_seed = None initial_info = None + initial_denoising_strength = p.denoising_strength grids = [] all_images = [] @@ -47,12 +46,37 @@ class Script(scripts.Script): initial_color_corrections = [processing.setup_color_correction(p.init_images[0])] - for n in range(batch_count): - history = [] + def calculate_denoising_strength(loop): + strength = initial_denoising_strength + + if loops == 1: + return strength + + progress = loop / (loops - 1) + match denoising_curve: + case "Aggressive": + strength = math.sin((progress) * math.pi * 0.5) + + case "Lazy": + strength = 1 - math.cos((progress) * math.pi * 0.5) + + case _: + strength = progress + + change = (final_denoising_strength - initial_denoising_strength) * strength + return initial_denoising_strength + change + history = [] + + for n in range(batch_count): # Reset to original init image at the start of each batch p.init_images = original_init_image + # Reset to original denoising strength + p.denoising_strength = initial_denoising_strength + + last_image = None + for i in range(loops): p.n_iter = 1 p.batch_size = 1 @@ -72,26 +96,43 @@ class Script(scripts.Script): processed = processing.process_images(p) + # Generation cancelled. + if state.interrupted: + break + if initial_seed is None: initial_seed = processed.seed initial_info = processed.info - init_img = processed.images[0] - - p.init_images = [init_img] p.seed = processed.seed + 1 - p.denoising_strength = min(max(p.denoising_strength * denoising_strength_change_factor, 0.1), 1) - history.append(processed.images[0]) - + p.denoising_strength = calculate_denoising_strength(i + 1) + + if state.skipped: + break + + last_image = processed.images[0] + p.init_images = [last_image] + + if batch_count == 1: + history.append(last_image) + all_images.append(last_image) + + if batch_count > 1 and not state.skipped and not state.interrupted: + history.append(last_image) + all_images.append(last_image) + + if state.interrupted: + break + + if len(history) > 1: grid = images.image_grid(history, rows=1) if opts.grid_save: images.save_image(grid, p.outpath_grids, "grid", initial_seed, p.prompt, opts.grid_format, info=info, short_filename=not opts.grid_extended_filename, grid=True, p=p) - grids.append(grid) - all_images += history - - if opts.return_grid: - all_images = grids + all_images + if opts.return_grid: + grids.append(grid) + + all_images = grids + all_images processed = Processed(p, all_images, initial_seed, initial_info) -- cgit v1.2.1 From e7ac09b25a885a66d3e789b1c175885ad3165e92 Mon Sep 17 00:00:00 2001 From: EllangoK Date: Wed, 22 Mar 2023 02:11:38 -0400 Subject: fixes xyz extra_generation_params not being saved --- scripts/xyz_grid.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/xyz_grid.py b/scripts/xyz_grid.py index ce584981..3551aca0 100644 --- a/scripts/xyz_grid.py +++ b/scripts/xyz_grid.py @@ -247,7 +247,7 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend state.job = f"{index(ix, iy, iz) + 1} out of {list_size}" - processed: Processed = cell(x, y, z) + processed: Processed = cell(x, y, z, ix, iy, iz) if processed_result is None: # Use our first processed result object as a template container to hold our full results @@ -558,8 +558,6 @@ class Script(scripts.Script): print(f"X/Y/Z plot will create {len(xs) * len(ys) * len(zs) * image_cell_count} images on {len(zs)} {len(xs)}x{len(ys)} grid{plural_s}{cell_console_text}. (Total steps to process: {total_steps})") shared.total_tqdm.updateTotal(total_steps) - grid_infotext = [None] - state.xyz_plot_x = AxisInfo(x_opt, xs) state.xyz_plot_y = AxisInfo(y_opt, ys) state.xyz_plot_z = AxisInfo(z_opt, zs) @@ -588,7 +586,9 @@ class Script(scripts.Script): else: second_axes_processed = 'y' - def cell(x, y, z): + grid_infotext = [None] * (1 + len(zs)) + + def cell(x, y, z, ix, iy, iz): if shared.state.interrupted: return Processed(p, [], p.seed, "") @@ -600,7 +600,9 @@ class Script(scripts.Script): res = process_images(pc) - if grid_infotext[0] is None: + # Sets subgrid infotexts + subgrid_index = 1 + iz + if grid_infotext[subgrid_index] is None and ix == 0 and iy == 0: pc.extra_generation_params = copy(pc.extra_generation_params) pc.extra_generation_params['Script'] = self.title() @@ -616,6 +618,12 @@ class Script(scripts.Script): if y_opt.label in ["Seed", "Var. seed"] and not no_fixed_seeds: pc.extra_generation_params["Fixed Y Values"] = ", ".join([str(y) for y in ys]) + grid_infotext[subgrid_index] = processing.create_infotext(pc, pc.all_prompts, pc.all_seeds, pc.all_subseeds) + + # Sets main grid infotext + if grid_infotext[0] is None and ix == 0 and iy == 0 and iz == 0: + pc.extra_generation_params = copy(pc.extra_generation_params) + if z_opt.label != 'Nothing': pc.extra_generation_params["Z Type"] = z_opt.label pc.extra_generation_params["Z Values"] = z_values @@ -650,6 +658,9 @@ class Script(scripts.Script): z_count = len(zs) + # Set the grid infotexts to the real ones with extra_generation_params (1 main grid + z_count sub-grids) + processed.infotexts[:1+z_count] = grid_infotext[:1+z_count] + if not include_lone_images: # Don't need sub-images anymore, drop from list: processed.images = processed.images[:z_count+1] -- cgit v1.2.1 From a9eef1fbb1dcdce4f0eb0b8e0f79dcd4c96713e1 Mon Sep 17 00:00:00 2001 From: James Railton Date: Thu, 23 Mar 2023 10:44:25 -0400 Subject: Fix "masked content" in loopback script The loopback script did not set masked content to original after first loop. So each loop would apply a fill, or latent mask. This would essentially reset progress each loop. The desired behavior is to use the mask for the first loop, then continue to iterate on the results of the previous loop. --- scripts/loopback.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'scripts') diff --git a/scripts/loopback.py b/scripts/loopback.py index 81577888..9c388aa8 100644 --- a/scripts/loopback.py +++ b/scripts/loopback.py @@ -42,6 +42,7 @@ class Script(scripts.Script): all_images = [] original_init_image = p.init_images original_prompt = p.prompt + original_inpainting_fill = p.inpainting_fill state.job_count = loops * batch_count initial_color_corrections = [processing.setup_color_correction(p.init_images[0])] @@ -112,6 +113,7 @@ class Script(scripts.Script): last_image = processed.images[0] p.init_images = [last_image] + p.inpainting_fill = 1 # Set "masked content" to "original" for next loop. if batch_count == 1: history.append(last_image) @@ -120,6 +122,8 @@ class Script(scripts.Script): if batch_count > 1 and not state.skipped and not state.interrupted: history.append(last_image) all_images.append(last_image) + + p.inpainting_fill = original_inpainting_fill if state.interrupted: break -- cgit v1.2.1 From 9f0da9f6edfb9be1d69ba3492a61d96db769307b Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Mon, 20 Mar 2023 16:09:36 +0300 Subject: initial gradio 3.22 support --- scripts/postprocessing_upscale.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'scripts') diff --git a/scripts/postprocessing_upscale.py b/scripts/postprocessing_upscale.py index 8842bd91..11eab31a 100644 --- a/scripts/postprocessing_upscale.py +++ b/scripts/postprocessing_upscale.py @@ -17,22 +17,24 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing): def ui(self): selected_tab = gr.State(value=0) - with gr.Tabs(elem_id="extras_resize_mode"): - with gr.TabItem('Scale by', elem_id="extras_scale_by_tab") as tab_scale_by: - upscaling_resize = gr.Slider(minimum=1.0, maximum=8.0, step=0.05, label="Resize", value=4, elem_id="extras_upscaling_resize") - - with gr.TabItem('Scale to', elem_id="extras_scale_to_tab") as tab_scale_to: - with FormRow(): - upscaling_resize_w = gr.Number(label="Width", value=512, precision=0, elem_id="extras_upscaling_resize_w") - upscaling_resize_h = gr.Number(label="Height", value=512, precision=0, elem_id="extras_upscaling_resize_h") - upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop") - - with FormRow(): - extras_upscaler_1 = gr.Dropdown(label='Upscaler 1', elem_id="extras_upscaler_1", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name) - - with FormRow(): - extras_upscaler_2 = gr.Dropdown(label='Upscaler 2', elem_id="extras_upscaler_2", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name) - extras_upscaler_2_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Upscaler 2 visibility", value=0.0, elem_id="extras_upscaler_2_visibility") + with gr.Column(): + with FormRow(): + with gr.Tabs(elem_id="extras_resize_mode"): + with gr.TabItem('Scale by', elem_id="extras_scale_by_tab") as tab_scale_by: + upscaling_resize = gr.Slider(minimum=1.0, maximum=8.0, step=0.05, label="Resize", value=4, elem_id="extras_upscaling_resize") + + with gr.TabItem('Scale to', elem_id="extras_scale_to_tab") as tab_scale_to: + with FormRow(): + upscaling_resize_w = gr.Number(label="Width", value=512, precision=0, elem_id="extras_upscaling_resize_w") + upscaling_resize_h = gr.Number(label="Height", value=512, precision=0, elem_id="extras_upscaling_resize_h") + upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop") + + with FormRow(): + extras_upscaler_1 = gr.Dropdown(label='Upscaler 1', elem_id="extras_upscaler_1", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name) + + with FormRow(): + extras_upscaler_2 = gr.Dropdown(label='Upscaler 2', elem_id="extras_upscaler_2", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name) + extras_upscaler_2_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Upscaler 2 visibility", value=0.0, elem_id="extras_upscaler_2_visibility") tab_scale_by.select(fn=lambda: 0, inputs=[], outputs=[selected_tab]) tab_scale_to.select(fn=lambda: 1, inputs=[], outputs=[selected_tab]) -- cgit v1.2.1