diff --git a/extensions-builtin/multidiffusion-upscaler-for-automatic1111 b/extensions-builtin/multidiffusion-upscaler-for-automatic1111 index 5da750b9d..7253cb449 160000 --- a/extensions-builtin/multidiffusion-upscaler-for-automatic1111 +++ b/extensions-builtin/multidiffusion-upscaler-for-automatic1111 @@ -1 +1 @@ -Subproject commit 5da750b9de930b0e28883423f697c5ea82457c24 +Subproject commit 7253cb449c85e2d2317ba541bf770ef372a807a4 diff --git a/html/extra-networks-card.html b/html/extra-networks-card.html index cb4720f14..6825a2752 100644 --- a/html/extra-networks-card.html +++ b/html/extra-networks-card.html @@ -4,9 +4,9 @@
@@ -14,4 +14,3 @@ {description}
- diff --git a/modules/processing.py b/modules/processing.py index a83d9fa12..1c6c36d32 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -971,9 +971,8 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): img2img_sampler_name = self.sampler_name force_latent_upscaler = shared.opts.data.get('xyz_fallback_sampler') - if self.sampler_name in ['PLMS'] or force_latent_upscaler is not None: - # PLMS does not support img2img, use fallback instead - img2img_sampler_name = force_latent_upscaler or shared.opts.fallback_sampler + if self.sampler_name in ['PLMS'] or (force_latent_upscaler is not None and force_latent_upscaler != 'None'): + img2img_sampler_name = force_latent_upscaler or shared.opts.fallback_sampler # PLMS does not support img2img, use fallback instead self.sampler = sd_samplers.create_sampler(img2img_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] @@ -1026,29 +1025,24 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): self.image_conditioning = None def init(self, all_prompts, all_seeds, all_subseeds): - if self.sampler_name in ['PLMS', 'UniPC']: # PLMS/UniPC do not support img2img so we just silently switch to DDIM - self.sampler_name = shared.opts.fallback_sampler + force_latent_upscaler = shared.opts.data.get('xyz_fallback_sampler') + if self.sampler_name in ['PLMS'] or (force_latent_upscaler is not None and force_latent_upscaler != 'None'): + self.sampler_name = force_latent_upscaler or shared.opts.fallback_sampler # PLMS does not support img2img, use fallback instead self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model) crop_region = None - image_mask = self.image_mask - if image_mask is not None: image_mask = image_mask.convert('L') - if self.inpainting_mask_invert: image_mask = ImageOps.invert(image_mask) - if self.mask_blur > 0: image_mask = image_mask.filter(ImageFilter.GaussianBlur(self.mask_blur)) - if self.inpaint_full_res: self.mask_for_overlay = image_mask mask = image_mask.convert('L') crop_region = masking.get_crop_region(np.array(mask), self.inpaint_full_res_padding) crop_region = masking.expand_crop_region(crop_region, self.width, self.height, mask.width, mask.height) x1, y1, x2, y2 = crop_region - mask = mask.crop(crop_region) image_mask = images.resize_image(2, mask, self.width, self.height) self.paste_to = (x1, y1, x2-x1, y2-y1) @@ -1057,42 +1051,31 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): np_mask = np.array(image_mask) np_mask = np.clip((np_mask.astype(np.float32)) * 2, 0, 255).astype(np.uint8) self.mask_for_overlay = Image.fromarray(np_mask) - self.overlay_images = [] - latent_mask = self.latent_mask if self.latent_mask is not None else image_mask - add_color_corrections = opts.img2img_color_correction and self.color_corrections is None if add_color_corrections: self.color_corrections = [] imgs = [] for img in self.init_images: image = images.flatten(img, opts.img2img_background_color) - if crop_region is None and self.resize_mode != 3: image = images.resize_image(self.resize_mode, image, self.width, self.height) - if image_mask is not None: image_masked = Image.new('RGBa', (image.width, image.height)) image_masked.paste(image.convert("RGBA").convert("RGBa"), mask=ImageOps.invert(self.mask_for_overlay.convert('L'))) - self.overlay_images.append(image_masked.convert('RGBA')) - # crop_region is not None if we are doing inpaint full res if crop_region is not None: image = image.crop(crop_region) image = images.resize_image(2, image, self.width, self.height) - if image_mask is not None: if self.inpainting_fill != 1: image = masking.fill(image, latent_mask) - if add_color_corrections: self.color_corrections.append(setup_color_correction(image)) - image = np.array(image).astype(np.float32) / 255.0 image = np.moveaxis(image, 2, 0) - imgs.append(image) if len(imgs) == 1: diff --git a/modules/shared.py b/modules/shared.py index 5c94bc4ff..c18e31021 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -417,7 +417,7 @@ options_templates.update(options_section(('ui', "Live previews"), { options_templates.update(options_section(('sampler-params', "Sampler parameters"), { "show_samplers": OptionInfo(["Euler a", "UniPC", "DDIM", "DPM++ SDE", "DPM++ SDE", "DPM2 Karras", "DPM++ 2M Karras"], "Show samplers in user interface", gr.CheckboxGroup, lambda: {"choices": [x.name for x in list_samplers()]}), - "fallback_sampler": OptionInfo("Euler a", "Fallback sampler if primary sampler is not compatible", gr.Dropdown, lambda: {"choices": [x.name for x in list_samplers()]}), + "fallback_sampler": OptionInfo("Euler a", "Fallback sampler if primary sampler is not compatible", gr.Dropdown, lambda: {"choices": ["None"] + [x.name for x in list_samplers()]}), "eta_ancestral": OptionInfo(1.0, "Noise multiplier for ancestral samplers (eta)", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), "eta_ddim": OptionInfo(0.0, "Noise multiplier for DDIM (eta)", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), "ddim_discretize": OptionInfo('uniform', "DDIM discretize img2img", gr.Radio, {"choices": ['uniform', 'quad']}), diff --git a/modules/ui_common.py b/modules/ui_common.py index 12908005e..cb9870196 100644 --- a/modules/ui_common.py +++ b/modules/ui_common.py @@ -66,10 +66,12 @@ def save_files(js_data, images, do_make_zip, index): for image_index, filedata in enumerate(images, start_index): image = image_from_url_text(filedata) - is_grid = image_index < p.index_of_first_image i = 0 if is_grid else (image_index - p.index_of_first_image) - + if len(p.all_seeds) <= i: + p.all_seeds.append(p.seed) + if len(p.all_prompts) <= i: + p.all_prompts.append(p.prompt) fullfn, txt_fullfn = modules.images.save_image(image, path, "", seed=p.all_seeds[i], prompt=p.all_prompts[i], extension=extension, info=p.infotexts[image_index], grid=is_grid, p=p, save_to_dirs=save_to_dirs) filename = os.path.relpath(fullfn, path) diff --git a/scripts/xyz_grid.py b/scripts/xyz_grid.py index 9a5a67241..95fa9ac95 100644 --- a/scripts/xyz_grid.py +++ b/scripts/xyz_grid.py @@ -1,26 +1,18 @@ +import re +import csv +import random from collections import namedtuple from copy import copy from itertools import permutations, chain -import random -import csv from io import StringIO from PIL import Image import numpy as np - -import modules.scripts as scripts import gradio as gr - -from modules import images, paths, sd_samplers, processing, sd_models, sd_vae -from modules.processing import process_images, Processed, StableDiffusionProcessingTxt2Img -from modules.shared import opts, cmd_opts, state +import modules.scripts as scripts import modules.shared as shared -import modules.sd_samplers -import modules.sd_models -import modules.sd_vae -import glob -import os -import re - +from modules import images, sd_samplers, processing, sd_models, sd_vae +from modules.processing import process_images, Processed, StableDiffusionProcessingTxt2Img +from modules.shared import opts, state from modules.ui_components import ToolButton fill_values_symbol = "\U0001f4d2" # 📒 @@ -83,15 +75,15 @@ def confirm_samplers(p, xs): def apply_checkpoint(p, x, xs): - info = modules.sd_models.get_closet_checkpoint_match(x) + info = sd_models.get_closet_checkpoint_match(x) if info is None: raise RuntimeError(f"Unknown checkpoint: {x}") - modules.sd_models.reload_model_weights(shared.sd_model, info) + sd_models.reload_model_weights(shared.sd_model, info) def confirm_checkpoints(p, xs): for x in xs: - if modules.sd_models.get_closet_checkpoint_match(x) is None: + if sd_models.get_closet_checkpoint_match(x) is None: raise RuntimeError(f"Unknown checkpoint: {x}") @@ -108,20 +100,20 @@ def apply_upscale_latent_space(p, x, xs): def find_vae(name: str): if name.lower() in ['auto', 'automatic']: - return modules.sd_vae.unspecified + return sd_vae.unspecified if name.lower() == 'none': return None else: - choices = [x for x in sorted(modules.sd_vae.vae_dict, key=lambda x: len(x)) if name.lower().strip() in x.lower()] + choices = [x for x in sorted(sd_vae.vae_dict, key=lambda x: len(x)) if name.lower().strip() in x.lower()] if len(choices) == 0: print(f"No VAE found for {name}; using automatic") - return modules.sd_vae.unspecified + return sd_vae.unspecified else: - return modules.sd_vae.vae_dict[choices[0]] + return sd_vae.vae_dict[choices[0]] def apply_vae(p, x, xs): - modules.sd_vae.reload_vae_weights(shared.sd_model, vae_file=find_vae(x)) + sd_vae.reload_vae_weights(shared.sd_model, vae_file=find_vae(x)) def apply_styles(p: StableDiffusionProcessingTxt2Img, x: str, _): @@ -341,7 +333,6 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend if draw_legend: z_grid = images.draw_grid_annotations(z_grid, sub_grid_size[0], sub_grid_size[1], title_texts, [[images.GridAnnotation()]]) processed_result.images.insert(0, z_grid) - #TODO: Deeper aspects of the program rely on grid info being misaligned between metadata arrays, which is not ideal. #processed_result.all_prompts.insert(0, processed_result.all_prompts[0]) #processed_result.all_seeds.insert(0, processed_result.all_seeds[0]) processed_result.infotexts.insert(0, processed_result.infotexts[0]) @@ -354,12 +345,12 @@ class SharedSettingsStackHelper(object): self.CLIP_stop_at_last_layers = opts.CLIP_stop_at_last_layers self.vae = opts.sd_vae self.uni_pc_order = opts.uni_pc_order - + def __exit__(self, exc_type, exc_value, tb): opts.data["sd_vae"] = self.vae opts.data["uni_pc_order"] = self.uni_pc_order - modules.sd_models.reload_model_weights() - modules.sd_vae.reload_vae_weights() + sd_models.reload_model_weights() + sd_vae.reload_vae_weights() opts.data["CLIP_stop_at_last_layers"] = self.CLIP_stop_at_last_layers @@ -407,7 +398,7 @@ class Script(scripts.Script): include_sub_grids = gr.Checkbox(label='Include Sub Grids', value=False, elem_id=self.elem_id("include_sub_grids")) with gr.Column(): margin_size = gr.Slider(label="Grid margins (px)", minimum=0, maximum=500, value=0, step=2, elem_id=self.elem_id("margin_size")) - + with gr.Row(variant="compact", elem_id="swap_axes"): swap_xy_axes_button = gr.Button(value="Swap X/Y axes", elem_id="xy_grid_swap_axes_button") swap_yz_axes_button = gr.Button(value="Swap Y/Z axes", elem_id="yz_grid_swap_axes_button") @@ -468,7 +459,7 @@ class Script(scripts.Script): def run(self, p, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, draw_legend, include_lone_images, include_sub_grids, no_fixed_seeds, margin_size): if not no_fixed_seeds: - modules.processing.fix_seed(p) + processing.fix_seed(p) if not opts.return_grid: p.batch_size = 1 @@ -498,7 +489,7 @@ class Script(scripts.Script): start = int(mc.group(1)) end = int(mc.group(2)) num = int(mc.group(3)) if mc.group(3) is not None else 1 - + valslist_ext += [int(x) for x in np.linspace(start=start, stop=end, num=num).tolist()] else: valslist_ext.append(val) @@ -520,7 +511,7 @@ class Script(scripts.Script): start = float(mc.group(1)) end = float(mc.group(2)) num = int(mc.group(3)) if mc.group(3) is not None else 1 - + valslist_ext += np.linspace(start=start, stop=end, num=num).tolist() else: valslist_ext.append(val) @@ -708,13 +699,12 @@ class Script(scripts.Script): # Auto-save main and sub-grids: grid_count = z_count + 1 if z_count > 1 else 1 for g in range(grid_count): - #TODO: See previous comment about intentional data misalignment. adj_g = g-1 if g > 0 else g images.save_image(processed.images[g], p.outpath_grids, "xyz_grid", info=processed.infotexts[g], extension=opts.grid_format, prompt=processed.all_prompts[adj_g], seed=processed.all_seeds[adj_g], grid=True, p=processed) if not include_sub_grids: # Done with sub-grids, drop all related information: - for sg in range(z_count): + for _sg in range(z_count): del processed.images[1] del processed.all_prompts[1] del processed.all_seeds[1] diff --git a/style.css b/style.css index 55c571d6f..4f5449a61 100644 --- a/style.css +++ b/style.css @@ -679,10 +679,6 @@ footer { margin-left: 0.5em; } - -.extra-network-cards .card .metadata-button:before, .extra-network-thumbs .card .metadata-button:before{ - content: "🛈"; -} .extra-network-cards .card .metadata-button, .extra-network-thumbs .card .metadata-button{ display: none; position: absolute; @@ -696,11 +692,11 @@ footer { .extra-network-cards .card:hover .metadata-button, .extra-network-thumbs .card:hover .metadata-button{ display: inline-block; } + .extra-network-cards .card .metadata-button:hover, .extra-network-thumbs .card .metadata-button:hover{ color: red; } - .extra-network-thumbs { display: flex; flex-flow: row wrap; @@ -708,8 +704,9 @@ footer { } .extra-network-thumbs .card { - height: 6em; - width: 6em; + display: inline-block; + height: 9em; + width: 9em; cursor: pointer; background-image: url('./file=html/card-no-preview.png'); background-size: cover; @@ -717,23 +714,13 @@ footer { position: relative; } -.extra-network-thumbs .card:hover .additional a { - display: inline-block; +.extra-network-thumbs .card .additional, .extra-network-thumbs .card .additional { + white-space: nowrap; + overflow: hidden; } -.extra-network-thumbs .actions .additional a { - background-image: url('./file=html/image-update.svg'); - background-repeat: no-repeat; - background-size: cover; - background-position: center center; - position: absolute; - top: 0; - left: 0; - width: 24px; - height: 24px; - display: none; - font-size: 0; - text-align: -9999; +.extra-network-thumbs .card:hover .additional a { + display: inline-block; } .extra-network-thumbs .actions .name { @@ -762,12 +749,10 @@ footer { box-shadow: 0 0 5px rgba(128, 128, 128, 0.5); border-radius: 0.2em; position: relative; - background-size: auto 100%; background-position: center; overflow: hidden; cursor: pointer; - background-image: url('./file=html/card-no-preview.png') }