From 68999d0b15d612965e7bc7feb62d6b4d55e112fa Mon Sep 17 00:00:00 2001 From: space-nuko <24979496+space-nuko@users.noreply.github.com> Date: Sat, 25 Mar 2023 12:52:14 -0400 Subject: [PATCH 01/15] Add upscale slider to img2img --- javascript/ui.js | 25 +- modules/generation_parameters_copypaste.py | 3 + modules/img2img.py | 3 +- modules/processing.py | 18 +- modules/ui.py | 67 +- style.css | 814 ++++++++++++++------- 6 files changed, 644 insertions(+), 286 deletions(-) diff --git a/javascript/ui.js b/javascript/ui.js index fcaf5608a..8aa4a4592 100644 --- a/javascript/ui.js +++ b/javascript/ui.js @@ -8,8 +8,8 @@ function set_theme(theme){ } function selected_gallery_index(){ - var buttons = gradioApp().querySelectorAll('[style="display: block;"].tabitem div[id$=_gallery] .gallery-item') - var button = gradioApp().querySelector('[style="display: block;"].tabitem div[id$=_gallery] .gallery-item.\\!ring-2') + var buttons = gradioApp().querySelectorAll('[style="display: block;"].tabitem div[id$=_gallery] .thumbnails > .thumbnail-item') + var button = gradioApp().querySelector('[style="display: block;"].tabitem div[id$=_gallery] .thumbnails > .thumbnail-item.selected') var result = -1 buttons.forEach(function(v, i){ if(v==button) { result = i } }) @@ -111,6 +111,14 @@ function get_img2img_tab_index() { return res } +function get_img2img_tab_index_for_res_preview() { + let res = args_to_array(arguments) + res.splice(-1) // gradio also sends outputs to the arguments, pop them off + res[0] = get_tab_index('mode_img2img') + debugger; + return res +} + function create_submit_args(args){ res = [] for(var i=0;i 1) + setInactive(i2iHeight, scale > 1) + + return [init_img, width, height, scale, resize_mode] +} diff --git a/modules/generation_parameters_copypaste.py b/modules/generation_parameters_copypaste.py index 6df76858f..459de0803 100644 --- a/modules/generation_parameters_copypaste.py +++ b/modules/generation_parameters_copypaste.py @@ -282,6 +282,9 @@ Steps: 20, Sampler: Euler a, CFG scale: 7, Seed: 965400086, Size: 512x512, Model res["Hires resize-1"] = 0 res["Hires resize-2"] = 0 + if "Img2Img Upscale" not in res: + res["Img2Img Upscale"] = 1 + restore_old_hires_fix_params(res) return res diff --git a/modules/img2img.py b/modules/img2img.py index c973b7708..d05fa7501 100644 --- a/modules/img2img.py +++ b/modules/img2img.py @@ -78,7 +78,7 @@ def process_batch(p, input_dir, output_dir, inpaint_mask_dir, args): processed_image.save(os.path.join(output_dir, filename)) -def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_index: int, mask_blur: int, mask_alpha: float, inpainting_fill: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, denoising_strength: 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, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_input_dir: str, img2img_batch_output_dir: str, img2img_batch_inpaint_mask_dir: str, override_settings_texts, *args): +def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_index: int, mask_blur: int, mask_alpha: float, inpainting_fill: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, denoising_strength: 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, scale: float, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_input_dir: str, img2img_batch_output_dir: str, img2img_batch_inpaint_mask_dir: str, override_settings_texts, *args): override_settings = create_override_settings_dict(override_settings_texts) is_batch = mode == 5 @@ -149,6 +149,7 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s inpaint_full_res_padding=inpaint_full_res_padding, inpainting_mask_invert=inpainting_mask_invert, override_settings=override_settings, + scale=scale, ) p.scripts = modules.scripts.scripts_txt2img diff --git a/modules/processing.py b/modules/processing.py index 2e5a363f0..fc4b166c7 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -929,7 +929,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): sampler = None - def __init__(self, init_images: list = None, resize_mode: int = 0, denoising_strength: float = 0.75, image_cfg_scale: float = None, mask: Any = None, mask_blur: int = 4, inpainting_fill: int = 0, inpaint_full_res: bool = True, inpaint_full_res_padding: int = 0, inpainting_mask_invert: int = 0, initial_noise_multiplier: float = None, **kwargs): + def __init__(self, init_images: Optional[list] = None, resize_mode: int = 0, denoising_strength: float = 0.75, image_cfg_scale: Optional[float] = None, mask: Any = None, mask_blur: int = 4, inpainting_fill: int = 0, inpaint_full_res: bool = True, inpaint_full_res_padding: int = 0, inpainting_mask_invert: int = 0, initial_noise_multiplier: Optional[float] = None, scale: float = 0, **kwargs): super().__init__(**kwargs) self.init_images = init_images @@ -949,11 +949,27 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): self.mask = None self.nmask = None self.image_conditioning = None + self.scale = scale + + def get_final_size(self): + if self.scale > 1: + img = self.init_images[0] + width = int(img.width * self.scale) + height = int(img.height * self.scale) + return width, height + else: + return self.width, self.height + def init(self, all_prompts, all_seeds, all_subseeds): self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model) crop_region = None + if self.scale > 1: + self.extra_generation_params["Img2Img Upscale"] = self.scale + + self.width, self.height = self.get_final_size() + image_mask = self.image_mask if image_mask is not None: diff --git a/modules/ui.py b/modules/ui.py index af8546c29..bb548f92d 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -15,6 +15,7 @@ import warnings import gradio as gr import gradio.routes import gradio.utils +from gradio.events import Releaseable import numpy as np from PIL import Image, PngImagePlugin from modules.call_queue import wrap_gradio_gpu_call, wrap_queued_call, wrap_gradio_call @@ -138,6 +139,26 @@ def calc_resolution_hires(enable, width, height, hr_scale, hr_resize_x, hr_resiz return f"resize: from {p.width}x{p.height} to {p.hr_resize_x or p.hr_upscale_to_x}x{p.hr_resize_y or p.hr_upscale_to_y}" +def calc_resolution_img2img(mode, scale, resize_x, resize_y, resize_mode, *i2i_images): + init_img = None + if mode in {0, 1, 3, 4}: + init_img = i2i_images[mode] + elif mode == 2: + init_img = i2i_images[mode]["image"] + + if not init_img: + return "" + + if scale > 1: + width = int(init_img.width * scale) + height = int(init_img.height * scale) + else: + width = resize_x + height = resize_y + + return f"resize: from {init_img.width}x{init_img.height} to {width}x{height}" + + def apply_styles(prompt, prompt_neg, styles): prompt = shared.prompt_styles.apply_styles_to_prompt(prompt, styles) prompt_neg = shared.prompt_styles.apply_negative_styles_to_prompt(prompt_neg, styles) @@ -755,8 +776,13 @@ def create_ui(): elif category == "dimensions": with FormRow(): with gr.Column(elem_id="img2img_column_size", scale=4): - width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="img2img_width") - height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="img2img_height") + with FormRow(variant="compact"): + final_resolution = FormHTML(value="", elem_id="img2img_finalres", label="Upscaled resolution", interactive=False) + with FormRow(variant="compact"): + scale = gr.Slider(minimum=1.0, maximum=4.0, step=0.05, label="Upscale by", value=1.0, elem_id="img2img_scale") + with FormRow(variant="compact"): + width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="img2img_width") + height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="img2img_height") with gr.Column(elem_id="img2img_dimensions_row", scale=1, elem_classes="dimensions-tools"): res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="img2img_res_switch_btn") @@ -824,6 +850,41 @@ def create_ui(): outputs=[inpaint_controls, mask_alpha], ) + img2img_resolution_preview_inputs = [dummy_component, # filled in by selected img2img tab index in _js + scale, width, height, resize_mode, + init_img, sketch, init_img_with_mask, inpaint_color_sketch, init_img_inpaint] + for input in img2img_resolution_preview_inputs: + if isinstance(input, Releaseable): + input.release( + fn=calc_resolution_img2img, + _js="get_img2img_tab_index_for_res_preview", + inputs=img2img_resolution_preview_inputs, + outputs=[final_resolution], + show_progress=False, + ) + input.release( + None, + _js="onCalcResolutionImg2Img", + inputs=img2img_resolution_preview_inputs, + outputs=[], + show_progress=False, + ) + else: + input.change( + fn=calc_resolution_img2img, + _js="get_img2img_tab_index_for_res_preview", + inputs=img2img_resolution_preview_inputs, + outputs=[final_resolution], + show_progress=False, + ) + input.change( + None, + _js="onCalcResolutionImg2Img", + inputs=img2img_resolution_preview_inputs, + outputs=[], + show_progress=False, + ) + img2img_gallery, generation_info, html_info, html_log = create_output_panel("img2img", opts.outdir_img2img_samples) connect_reuse_seed(seed, reuse_seed, generation_info, dummy_component, is_subseed=False) @@ -872,6 +933,7 @@ def create_ui(): subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox, height, width, + scale, resize_mode, inpaint_full_res, inpaint_full_res_padding, @@ -957,6 +1019,7 @@ def create_ui(): (seed, "Seed"), (width, "Size-1"), (height, "Size-2"), + (scale, "Img2Img Upscale"), (batch_size, "Batch size"), (subseed, "Variation seed"), (subseed_strength, "Variation seed strength"), diff --git a/style.css b/style.css index 0dcc3e25d..7d58b3b27 100644 --- a/style.css +++ b/style.css @@ -1,196 +1,48 @@ - -/* general gradio fixes */ - -:root, .dark{ - --checkbox-label-gap: 0.25em 0.1em; - --section-header-text-size: 12pt; - --block-background-fill: transparent; +.container { + max-width: 100%; } -.block.padded{ - padding: 0 !important; -} - -div.gradio-container{ - max-width: unset !important; -} - -.hidden{ - display: none; -} - -.compact{ - background: transparent !important; - padding: 0 !important; -} - -div.form{ - border-width: 0; - box-shadow: none; - background: transparent; - overflow: visible; - gap: 0.5em; -} - -.block.gradio-dropdown, -.block.gradio-slider, -.block.gradio-checkbox, -.block.gradio-textbox, -.block.gradio-radio, -.block.gradio-checkboxgroup, -.block.gradio-number, -.block.gradio-colorpicker -{ - border-width: 0 !important; - box-shadow: none !important; -} - -.gap.compact{ - padding: 0; - gap: 0.2em 0; -} - -div.compact{ - gap: 1em; -} - -.gradio-dropdown ul.options{ - z-index: 3000; -} - -.gradio-dropdown label span:not(.has-info), -.gradio-textbox label span:not(.has-info), -.gradio-number label span:not(.has-info) -{ - margin-bottom: 0; -} - -.gradio-dropdown div.wrap.wrap.wrap.wrap{ - box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); -} - -.gradio-dropdown .wrap-inner.wrap-inner.wrap-inner{ - flex-wrap: unset; -} - -.gradio-dropdown .single-select{ - white-space: nowrap; - overflow: hidden; -} - -.gradio-dropdown .token-remove.remove-all.remove-all{ - display: none; -} - -.gradio-dropdown.multiselect .token-remove.remove-all.remove-all{ - display: flex; -} - -.gradio-slider input[type="number"]{ - width: 6em; -} - -.block.gradio-checkbox { - margin: 0.75em 1.5em 0 0; -} - -.gradio-html div.wrap{ - height: 100%; -} -div.gradio-html.min{ - min-height: 0; -} - -.block.gradio-gallery{ - background: var(--input-background-fill); -} - -.gradio-container .prose a, .gradio-container .prose a:visited{ - color: unset; - text-decoration: none; -} - - - -/* general styled components */ - -.gradio-button.tool{ - max-width: 2.2em; - min-width: 2.2em !important; - height: 2.4em; - align-self: end; - line-height: 1em; - border-radius: 0.5em; -} - -.checkboxes-row{ - margin-bottom: 0.5em; - margin-left: 0em; -} -.checkboxes-row > div{ - flex: 0; - white-space: nowrap; - min-width: auto; -} - -button.custom-button{ - border-radius: var(--button-large-radius); - padding: var(--button-large-padding); - font-weight: var(--button-large-text-weight); - border: var(--button-border-width) solid var(--button-secondary-border-color); - background: var(--button-secondary-background-fill); - color: var(--button-secondary-text-color); - font-size: var(--button-large-text-size); - display: inline-flex; - justify-content: center; - align-items: center; - transition: var(--button-transition); - box-shadow: var(--button-shadow); - text-align: center; -} - - -/* txt2img/img2img specific */ - -.block.token-counter{ +.token-counter{ position: absolute; display: inline-block; - right: 1em; + right: 2em; min-width: 0 !important; width: auto; z-index: 100; - top: -0.75em; } -.block.token-counter span{ - background: var(--input-background-fill) !important; - box-shadow: 0 0 0.0 0.3em rgba(192,192,192,0.15), inset 0 0 0.6em rgba(192,192,192,0.075); - border: 2px solid rgba(192,192,192,0.4) !important; - border-radius: 0.4em; -} - -.block.token-counter.error span{ +.token-counter.error span{ box-shadow: 0 0 0.0 0.3em rgba(255,0,0,0.15), inset 0 0 0.6em rgba(255,0,0,0.075); border: 2px solid rgba(255,0,0,0.4) !important; } -.block.token-counter div{ +.token-counter div{ display: inline; } -.block.token-counter span{ +.token-counter span{ padding: 0.1em 0.75em; } -[id$=_subseed_show]{ - min-width: auto !important; - flex-grow: 0 !important; - display: flex; +#sh{ + min-width: 2em; + min-height: 2em; + max-width: 2em; + max-height: 2em; + flex-grow: 0; + padding-left: 0.25em; + padding-right: 0.25em; + margin: 0.1em 0; + opacity: 0%; + cursor: default; } -[id$=_subseed_show] label{ - margin-bottom: 0.5em; - align-self: end; +.output-html p {margin: 0 0.5em;} + +.row > *, +.row > .gr-form > * { + min-width: min(120px, 100%); + flex: 1 1 0%; } .performance { @@ -223,94 +75,196 @@ button.custom-button{ object-fit: scale-down; } #txt2img_actions_column, #img2img_actions_column { - gap: 0.5em; + margin: 0.35rem 0.75rem 0.35rem 0; } +#script_list { + padding: .625rem .75rem 0 .625rem; +} +.justify-center.overflow-x-scroll { + justify-content: left; +} + +.justify-center.overflow-x-scroll button:first-of-type { + margin-left: auto; +} + +.justify-center.overflow-x-scroll button:last-of-type { + margin-right: auto; +} + +[id$=_random_seed], [id$=_random_subseed], [id$=_reuse_seed], [id$=_reuse_subseed], #open_folder{ + min-width: 2.3em; + height: 2.5em; + flex-grow: 0; + padding-left: 0.25em; + padding-right: 0.25em; +} + +#hidden_element{ + display: none; +} + +[id$=_seed_row], [id$=_subseed_row]{ + gap: 0.5rem; + padding: 0.6em; +} + +[id$=_subseed_show_box]{ + min-width: auto; + flex-grow: 0; +} + +[id$=_subseed_show_box] > div{ + border: 0; + height: 100%; +} + +[id$=_subseed_show]{ + min-width: auto; + flex-grow: 0; + padding: 0; +} + +[id$=_subseed_show] label{ + height: 100%; +} + +#txt2img_actions_column, #img2img_actions_column{ + gap: 0; + margin-right: .75rem; +} + #txt2img_tools, #img2img_tools{ gap: 0.4em; } -.interrogate-col{ +#interrogate_col{ min-width: 0 !important; - max-width: fit-content; - gap: 0.5em; + max-width: 8em !important; + margin-right: 1em; + gap: 0; } -.interrogate-col > button{ - flex: 1; +#interrogate, #deepbooru{ + margin: 0em 0.25em 0.5em 0.25em; + min-width: 8em; + max-width: 8em; } -.generate-box{ - position: relative; +#style_pos_col, #style_neg_col{ + min-width: 8em !important; } -.gradio-button.generate-box-skip, .gradio-button.generate-box-interrupt{ + +#txt2img_styles_row, #img2img_styles_row{ + gap: 0.25em; + margin-top: 0.3em; +} + +#txt2img_styles_row > button, #img2img_styles_row > button{ + margin: 0; +} + +#txt2img_styles, #img2img_styles{ + padding: 0; +} + +#txt2img_styles > label > div, #img2img_styles > label > div{ + min-height: 3.2em; +} + +ul.list-none{ + max-height: 35em; + z-index: 2000; +} + +.gr-form{ + background: transparent; +} + +.my-4{ + margin-top: 0; + margin-bottom: 0; +} + +#resize_mode{ + flex: 1.5; +} + +button{ + align-self: stretch !important; +} + +.overflow-hidden, .gr-panel{ + overflow: visible !important; +} + +#x_type, #y_type{ + max-width: 10em; +} + +#txt2img_preview, #img2img_preview, #ti_preview{ position: absolute; - width: 50%; - height: 100%; - display: none; - background: #b4c0cc; -} -.gradio-button.generate-box-skip:hover, .gradio-button.generate-box-interrupt:hover{ - background: #c2cfdb; -} -.gradio-button.generate-box-interrupt{ + width: 320px; left: 0; - border-radius: 0.5rem 0 0 0.5rem; -} -.gradio-button.generate-box-skip{ right: 0; - border-radius: 0 0.5rem 0.5rem 0; + margin-left: auto; + margin-right: auto; + margin-top: 34px; + z-index: 100; + border: none; + border-top-left-radius: 0; + border-top-right-radius: 0; } -#txtimg_hr_finalres{ - min-height: 0 !important; - padding: .625rem .75rem; - margin-left: -0.75em +@media screen and (min-width: 768px) { + #txt2img_preview, #img2img_preview, #ti_preview { + position: absolute; + } } -#txtimg_hr_finalres .resolution{ - font-weight: bold; +@media screen and (max-width: 767px) { + #txt2img_preview, #img2img_preview, #ti_preview { + position: relative; + } } -.inactive{ - opacity: 0.5; +#txt2img_preview div.left-0.top-0, #img2img_preview div.left-0.top-0, #ti_preview div.left-0.top-0{ + display: none; } -[id$=_column_batch]{ +fieldset span.text-gray-500, .gr-block.gr-box span.text-gray-500, label.block span{ + position: absolute; + top: -0.7em; + line-height: 1.2em; + padding: 0; + margin: 0 0.5em; + + background-color: white; + box-shadow: 6px 0 6px 0px white, -6px 0 6px 0px white; + + z-index: 300; +} + +.dark fieldset span.text-gray-500, .dark .gr-block.gr-box span.text-gray-500, .dark label.block span{ + background-color: rgb(31, 41, 55); + box-shadow: none; + border: 1px solid rgba(128, 128, 128, 0.1); + border-radius: 6px; + padding: 0.1em 0.5em; +} + +#txt2img_column_batch, #img2img_column_batch{ min-width: min(13.5em, 100%) !important; } -div.dimensions-tools{ - min-width: 0 !important; - max-width: fit-content; - flex-direction: row; - align-content: center; -} - -#mode_img2img .gradio-image > div.fixed-height, #mode_img2img .gradio-image > div.fixed-height img{ - height: 480px !important; - max-height: 480px !important; - min-height: 480px !important; -} - -.image-buttons button{ - min-width: auto; -} - -.infotext { - overflow-wrap: break-word; -} - -/* settings */ -#quicksettings { - width: fit-content; -} - -#quicksettings > div, #quicksettings > fieldset{ - max-width: 24em; - min-width: 24em; - padding: 0; +#settings fieldset span.text-gray-500, #settings .gr-block.gr-box span.text-gray-500, #settings label.block span{ + position: relative; border: none; - box-shadow: none; - background: none; + margin-right: 8em; +} + +#settings .gr-panel div.flex-col div.justify-between div{ + position: relative; + z-index: 200; } #settings{ @@ -322,18 +276,17 @@ div.dimensions-tools{ margin-left: 10em; } -#settings > div.tab-nav{ +#settings > div.flex-wrap{ float: left; display: block; margin-left: 0; width: 10em; } -#settings > div.tab-nav button{ +#settings > div.flex-wrap button{ display: block; border: none; text-align: left; - white-space: initial; } #settings_result{ @@ -341,8 +294,29 @@ div.dimensions-tools{ margin: 0 1.2em; } +input[type="range"]{ + margin: 0.5em 0 -0.3em 0; +} + +#mask_bug_info { + text-align: center; + display: block; + margin-top: -0.75em; + margin-bottom: -0.75em; +} + +#txt2img_negative_prompt, #img2img_negative_prompt{ +} + +/* gradio 3.8 adds opacity to progressbar which makes it blink; disable it here */ +.transition.opacity-20 { + opacity: 1 !important; +} + +/* more gradio's garbage cleanup */ +.min-h-\[4rem\] { min-height: unset !important; } +.min-h-\[6rem\] { min-height: unset !important; } -/* live preview */ .progressDiv{ position: relative; height: 20px; @@ -388,8 +362,6 @@ div.dimensions-tools{ height: 100%; } -/* fullscreen popup (ie in Lora's (i) button) */ - .popup-metadata{ color: black; background: white; @@ -430,54 +402,87 @@ div.dimensions-tools{ padding: 2em; } -/* fullpage image viewer */ - #lightboxModal{ - display: none; - position: fixed; - z-index: 1001; - left: 0; - top: 0; - width: 100%; - height: 100%; - overflow: auto; - background-color: rgba(20, 20, 20, 0.95); - user-select: none; - -webkit-user-select: none; - flex-direction: column; + display: none; + position: fixed; + z-index: 1001; + padding-top: 100px; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgba(20, 20, 20, 0.95); + user-select: none; + -webkit-user-select: none; } .modalControls { - display: flex; - gap: 1em; - padding: 1em; + display: grid; + grid-template-columns: 32px 32px 32px 1fr 32px; + grid-template-areas: "zoom tile save space close"; + position: absolute; + top: 0; + left: 0; + right: 0; + padding: 16px; + gap: 16px; background-color: rgba(0,0,0,0.2); } + .modalClose { - margin-left: auto; + grid-area: close; } -.modalControls span{ + +.modalZoom { + grid-area: zoom; +} + +.modalSave { + grid-area: save; +} + +.modalTileImage { + grid-area: tile; +} + +.modalClose, +.modalZoom, +.modalTileImage { + color: white; + font-size: 35px; + font-weight: bold; + cursor: pointer; +} + +.modalSave { color: white; - font-size: 35px; + font-size: 28px; + margin-top: 8px; font-weight: bold; cursor: pointer; - width: 1em; } -.modalControls span:hover, .modalControls span:focus{ - color: #999; - text-decoration: none; +.modalClose:hover, +.modalClose:focus, +.modalSave:hover, +.modalSave:focus, +.modalZoom:hover, +.modalZoom:focus { + color: #999; + text-decoration: none; + cursor: pointer; } -#lightboxModal > img { +#modalImage { display: block; margin: auto; width: auto; } -#lightboxModal > img.modalImageFullscreen{ +.modalImageFullscreen { object-fit: contain; - height: 100%; + height: 90%; } .modalPrev, @@ -507,7 +512,45 @@ div.dimensions-tools{ background-color: rgba(0, 0, 0, 0.8); } -/* context menu (ie for the generate button) */ +#imageARPreview{ + position:absolute; + top:0px; + left:0px; + border:2px solid red; + background:rgba(255, 0, 0, 0.3); + z-index: 900; + pointer-events:none; + display:none +} + +#txt2img_generate_box, #img2img_generate_box{ + position: relative; +} + +#txt2img_interrupt, #img2img_interrupt, #txt2img_skip, #img2img_skip{ + position: absolute; + width: 50%; + height: 100%; + background: #b4c0cc; + display: none; +} + +#txt2img_interrupt, #img2img_interrupt{ + left: 0; + border-radius: 0.5rem 0 0 0.5rem; +} +#txt2img_skip, #img2img_skip{ + right: 0; + border-radius: 0 0.5rem 0.5rem 0; +} + +.red { + color: red; +} + +.gallery-item { + --tw-bg-opacity: 0 !important; +} #context-menu{ z-index:9999; @@ -536,8 +579,61 @@ div.dimensions-tools{ background: #a55000; } +#quicksettings { + width: fit-content; +} -/* extensions */ +#quicksettings > div, #quicksettings > fieldset{ + max-width: 24em; + min-width: 24em; + padding: 0; + border: none; + box-shadow: none; + background: none; + margin-right: 10px; +} + +#quicksettings > div > div > div > label > span { + position: relative; + margin-right: 9em; + margin-bottom: -1em; +} + +canvas[key="mask"] { + z-index: 12 !important; + filter: invert(); + mix-blend-mode: multiply; + pointer-events: none; +} + + +/* gradio 3.4.1 stuff for editable scrollbar values */ +.gr-box > div > div > input.gr-text-input{ + position: absolute; + right: 0.5em; + top: -0.6em; + z-index: 400; + width: 6em; +} +#quicksettings .gr-box > div > div > input.gr-text-input { + top: -1.12em; +} + +.row.gr-compact{ + overflow: visible; +} + +#img2img_image, #img2img_image > .h-60, #img2img_image > .h-60 > div, #img2img_image > .h-60 > div > img, +#img2img_sketch, #img2img_sketch > .h-60, #img2img_sketch > .h-60 > div, #img2img_sketch > .h-60 > div > img, +#img2maskimg, #img2maskimg > .h-60, #img2maskimg > .h-60 > div, #img2maskimg > .h-60 > div > img, +#inpaint_sketch, #inpaint_sketch > .h-60, #inpaint_sketch > .h-60 > div, #inpaint_sketch > .h-60 > div > img +{ + height: 480px !important; + max-height: 480px !important; + min-height: 480px !important; +} + +/* Extensions */ #tab_extensions table{ border-collapse: collapse; @@ -550,7 +646,6 @@ div.dimensions-tools{ #tab_extensions table input[type="checkbox"]{ margin-right: 0.5em; - appearance: checkbox; } #tab_extensions button{ @@ -575,7 +670,74 @@ div.dimensions-tools{ font-size: 90%; } -/* replace original footer with ours */ +#image_buttons_txt2img button, #image_buttons_img2img button, #image_buttons_extras button{ + min-width: auto; + padding-left: 0.5em; + padding-right: 0.5em; +} + +.gr-form{ + background-color: white; +} + +.dark .gr-form{ + background-color: rgb(31 41 55 / var(--tw-bg-opacity)); +} + +.gr-button-tool, .gr-button-tool-top{ + max-width: 2.5em; + min-width: 2.5em !important; + height: 2.4em; +} + +.gr-button-tool{ + margin: 0.6em 0em 0.55em 0; +} + +.gr-button-tool-top, #settings .gr-button-tool{ + margin: 1.6em 0.7em 0.55em 0; +} + + +#modelmerger_results_container{ + margin-top: 1em; + overflow: visible; +} + +#modelmerger_models{ + gap: 0; +} + + +#quicksettings .gr-button-tool{ + margin: 0; + border-color: unset; + background-color: unset; +} + +#modelmerger_interp_description>p { + margin: 0!important; + text-align: center; +} +#modelmerger_interp_description { + margin: 0.35rem 0.75rem 1.23rem; +} +#img2img_settings > div.gr-form, #txt2img_settings > div.gr-form { + padding-top: 0.9em; + padding-bottom: 0.9em; +} +#txt2img_settings { + padding-top: 1.16em; + padding-bottom: 0.9em; +} +#img2img_settings { + padding-bottom: 0.9em; +} + +#img2img_settings div.gr-form .gr-form, #txt2img_settings div.gr-form .gr-form, #train_tabs div.gr-form .gr-form{ + border: none; + padding-bottom: 0.5em; +} footer { display: none !important; @@ -594,7 +756,99 @@ footer { opacity: 0.85; } -/* extra networks UI */ +#txtimg_hr_finalres{ + min-height: 0 !important; + padding: .625rem .75rem; + margin-left: -0.75em +} + +#txtimg_hr_finalres .resolution{ + font-weight: bold; +} + +#txt2img_checkboxes, #img2img_checkboxes{ + margin-bottom: 0.5em; + margin-left: 0em; +} +#txt2img_checkboxes > div, #img2img_checkboxes > div{ + flex: 0; + white-space: nowrap; + min-width: auto; +} + +#img2img_finalres{ + min-height: 0 !important; + padding: .625rem .75rem; + margin-left: -0.75em +} + +#img2img_finalres .resolution{ + font-weight: bold; +} + +#img2img_copy_to_img2img, #img2img_copy_to_sketch, #img2img_copy_to_inpaint, #img2img_copy_to_inpaint_sketch{ + margin-left: 0em; +} + +#axis_options { + margin-left: 0em; +} + +.inactive{ + opacity: 0.5; +} + +[id*='_prompt_container']{ + gap: 0; +} + +[id*='_prompt_container'] > div{ + margin: -0.4em 0 0 0; +} + +.gr-compact { + border: none; +} + +.dark .gr-compact{ + background-color: rgb(31 41 55 / var(--tw-bg-opacity)); + margin-left: 0; +} + +.gr-compact{ + overflow: visible; +} + +.gr-compact > *{ +} + +.gr-compact .gr-block, .gr-compact .gr-form{ + border: none; + box-shadow: none; +} + +.gr-compact .gr-box{ + border-radius: .5rem !important; + border-width: 1px !important; +} + +#mode_img2img > div > div{ + gap: 0 !important; +} + +[id*='img2img_copy_to_'] { + border: none; +} + +[id*='img2img_copy_to_'] > button { +} + +[id*='img2img_label_copy_to_'] { + font-size: 1.0em; + font-weight: bold; + text-align: center; + line-height: 2.4em; +} .extra-networks > div > [id *= '_extra_']{ margin: 0.3em; @@ -607,12 +861,12 @@ footer { .extra-network-subdirs button{ margin: 0 0.15em; } -.extra-networks .tab-nav .search{ + +#txt2img_extra_networks .search, #img2img_extra_networks .search{ display: inline-block; max-width: 16em; margin: 0.3em; align-self: center; - width: 16em; } #txt2img_extra_view, #img2img_extra_view { @@ -644,7 +898,6 @@ footer { text-shadow: 2px 2px 3px black; padding: 0.25em; font-size: 22pt; - width: 1.5em; } .extra-network-cards .card:hover .metadata-button, .extra-network-thumbs .card:hover .metadata-button{ display: inline-block; @@ -738,15 +991,12 @@ footer { left: 0; right: 0; padding: 0.5em; + color: white; background: rgba(0,0,0,0.5); box-shadow: 0 0 0.25em 0.25em rgba(0,0,0,0.5); text-shadow: 0 0 0.2em black; } -.extra-network-cards .card .actions *{ - color: white; -} - .extra-network-cards .card .actions:hover{ box-shadow: 0 0 0.75em 0.75em rgba(0,0,0,0.5) !important; } @@ -784,3 +1034,7 @@ footer { .extra-network-cards .card ul a:hover{ color: red; } + +[id*='_prompt_container'] > div { + margin: 0!important; +} From 7ea5d395c44be208f654b07ec7993aa2952f2510 Mon Sep 17 00:00:00 2001 From: space-nuko <24979496+space-nuko@users.noreply.github.com> Date: Sun, 19 Feb 2023 03:45:43 -0800 Subject: [PATCH 02/15] Add upscaler to img2img --- modules/generation_parameters_copypaste.py | 4 ++-- modules/img2img.py | 3 ++- modules/processing.py | 23 ++++++++++++++++------ modules/ui.py | 10 +++++++--- scripts/xyz_grid.py | 1 + style.css | 2 +- 6 files changed, 30 insertions(+), 13 deletions(-) diff --git a/modules/generation_parameters_copypaste.py b/modules/generation_parameters_copypaste.py index 459de0803..0ad2ad4f0 100644 --- a/modules/generation_parameters_copypaste.py +++ b/modules/generation_parameters_copypaste.py @@ -282,8 +282,8 @@ Steps: 20, Sampler: Euler a, CFG scale: 7, Seed: 965400086, Size: 512x512, Model res["Hires resize-1"] = 0 res["Hires resize-2"] = 0 - if "Img2Img Upscale" not in res: - res["Img2Img Upscale"] = 1 + if "Img2Img upscale" not in res: + res["Img2Img upscale"] = 1 restore_old_hires_fix_params(res) diff --git a/modules/img2img.py b/modules/img2img.py index d05fa7501..959dd96ea 100644 --- a/modules/img2img.py +++ b/modules/img2img.py @@ -78,7 +78,7 @@ def process_batch(p, input_dir, output_dir, inpaint_mask_dir, args): processed_image.save(os.path.join(output_dir, filename)) -def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_index: int, mask_blur: int, mask_alpha: float, inpainting_fill: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, denoising_strength: 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, scale: float, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_input_dir: str, img2img_batch_output_dir: str, img2img_batch_inpaint_mask_dir: str, override_settings_texts, *args): +def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_index: int, mask_blur: int, mask_alpha: float, inpainting_fill: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, denoising_strength: 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, scale: float, upscaler: str, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_input_dir: str, img2img_batch_output_dir: str, img2img_batch_inpaint_mask_dir: str, override_settings_texts, *args): override_settings = create_override_settings_dict(override_settings_texts) is_batch = mode == 5 @@ -150,6 +150,7 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s inpainting_mask_invert=inpainting_mask_invert, override_settings=override_settings, scale=scale, + upscaler=upscaler, ) p.scripts = modules.scripts.scripts_txt2img diff --git a/modules/processing.py b/modules/processing.py index fc4b166c7..afb8cfd1c 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -929,7 +929,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): sampler = None - def __init__(self, init_images: Optional[list] = None, resize_mode: int = 0, denoising_strength: float = 0.75, image_cfg_scale: Optional[float] = None, mask: Any = None, mask_blur: int = 4, inpainting_fill: int = 0, inpaint_full_res: bool = True, inpaint_full_res_padding: int = 0, inpainting_mask_invert: int = 0, initial_noise_multiplier: Optional[float] = None, scale: float = 0, **kwargs): + def __init__(self, init_images: Optional[list] = None, resize_mode: int = 0, denoising_strength: float = 0.75, image_cfg_scale: Optional[float] = None, mask: Any = None, mask_blur: int = 4, inpainting_fill: int = 0, inpaint_full_res: bool = True, inpaint_full_res_padding: int = 0, inpainting_mask_invert: int = 0, initial_noise_multiplier: Optional[float] = None, scale: float = 0, upscaler: Optional[str] = None, **kwargs): super().__init__(**kwargs) self.init_images = init_images @@ -950,6 +950,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): self.nmask = None self.image_conditioning = None self.scale = scale + self.upscaler = upscaler def get_final_size(self): if self.scale > 1: @@ -966,7 +967,16 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): crop_region = None if self.scale > 1: - self.extra_generation_params["Img2Img Upscale"] = self.scale + self.extra_generation_params["Img2Img upscale"] = self.scale + + # Non-latent upscalers are run before sampling + # Latent upscalers are run during sampling + init_upscaler = None + if self.upscaler is not None: + self.extra_generation_params["Img2Img upscaler"] = self.upscaler + if self.upscaler not in shared.latent_upscale_modes: + assert len([x for x in shared.sd_upscalers if x.name == self.upscaler]) > 0, f"could not find upscaler named {self.upscaler}" + init_upscaler = self.upscaler self.width, self.height = self.get_final_size() @@ -992,7 +1002,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): image_mask = images.resize_image(2, mask, self.width, self.height) self.paste_to = (x1, y1, x2-x1, y2-y1) else: - image_mask = images.resize_image(self.resize_mode, image_mask, self.width, self.height) + image_mask = images.resize_image(self.resize_mode, image_mask, self.width, self.height, init_upscaler) 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) @@ -1009,7 +1019,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): 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) + image = images.resize_image(self.resize_mode, image, self.width, self.height, init_upscaler) if image_mask is not None: image_masked = Image.new('RGBa', (image.width, image.height)) @@ -1054,8 +1064,9 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): self.init_latent = self.sd_model.get_first_stage_encoding(self.sd_model.encode_first_stage(image)) - if self.resize_mode == 3: - self.init_latent = torch.nn.functional.interpolate(self.init_latent, size=(self.height // opt_f, self.width // opt_f), mode="bilinear") + latent_scale_mode = shared.latent_upscale_modes.get(self.upscaler, None) if self.upscaler is not None else shared.latent_upscale_modes.get(shared.latent_upscale_default_mode, "nearest") + if latent_scale_mode is not None: + self.init_latent = torch.nn.functional.interpolate(self.init_latent, size=(self.height // opt_f, self.width // opt_f), mode=latent_scale_mode["mode"], antialias=latent_scale_mode["antialias"]) if image_mask is not None: init_mask = latent_mask diff --git a/modules/ui.py b/modules/ui.py index bb548f92d..24ab0af78 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -767,7 +767,7 @@ def create_ui(): ) with FormRow(): - resize_mode = gr.Radio(label="Resize mode", elem_id="resize_mode", choices=["Just resize", "Crop and resize", "Resize and fill", "Just resize (latent upscale)"], type="index", value="Just resize") + resize_mode = gr.Radio(label="Resize mode", elem_id="resize_mode", choices=["Just resize", "Crop and resize", "Resize and fill"], type="index", value="Just resize") for category in ordered_ui_categories(): if category == "sampler": @@ -797,7 +797,9 @@ def create_ui(): with FormRow(): cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='CFG Scale', value=7.0, elem_id="img2img_cfg_scale") image_cfg_scale = gr.Slider(minimum=0, maximum=3.0, step=0.05, label='Image CFG Scale', value=1.5, elem_id="img2img_image_cfg_scale", visible=shared.sd_model and shared.sd_model.cond_stage_key == "edit") - denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising strength', value=0.75, elem_id="img2img_denoising_strength") + with FormRow(): + upscaler = gr.Dropdown(label="Upscaler", elem_id="img2img_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.75, elem_id="img2img_denoising_strength") elif category == "seed": seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs('img2img') @@ -934,6 +936,7 @@ def create_ui(): height, width, scale, + upscaler, resize_mode, inpaint_full_res, inpaint_full_res_padding, @@ -1019,7 +1022,8 @@ def create_ui(): (seed, "Seed"), (width, "Size-1"), (height, "Size-2"), - (scale, "Img2Img Upscale"), + (scale, "Img2Img upscale"), + (upscaler, "Img2Img upscaler"), (batch_size, "Batch size"), (subseed, "Variation seed"), (subseed_strength, "Variation seed strength"), diff --git a/scripts/xyz_grid.py b/scripts/xyz_grid.py index 3895a795c..3f6c1997d 100644 --- a/scripts/xyz_grid.py +++ b/scripts/xyz_grid.py @@ -220,6 +220,7 @@ axis_options = [ AxisOption("Clip skip", int, apply_clip_skip), AxisOption("Denoising", float, apply_field("denoising_strength")), AxisOptionTxt2Img("Hires upscaler", str, apply_field("hr_upscaler"), choices=lambda: [*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]]), + AxisOptionImg2Img("Upscaler", str, apply_field("upscaler"), choices=lambda: [*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]]), AxisOptionImg2Img("Cond. Image Mask Weight", float, apply_field("inpainting_mask_weight")), AxisOption("VAE", str, apply_vae, cost=0.7, choices=lambda: list(sd_vae.vae_dict)), AxisOption("Styles", str, apply_styles, choices=lambda: list(shared.prompt_styles.styles)), diff --git a/style.css b/style.css index 7d58b3b27..e824256fa 100644 --- a/style.css +++ b/style.css @@ -779,7 +779,7 @@ footer { #img2img_finalres{ min-height: 0 !important; padding: .625rem .75rem; - margin-left: -0.75em + margin-left: 0.25em } #img2img_finalres .resolution{ From 75e7eb9172fb62eb6fbbcaf71bdd4273b44acc52 Mon Sep 17 00:00:00 2001 From: space-nuko <24979496+space-nuko@users.noreply.github.com> Date: Thu, 23 Mar 2023 13:36:15 -0400 Subject: [PATCH 03/15] img2img resolution preview should use currently selected tab's image --- javascript/ui.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/javascript/ui.js b/javascript/ui.js index 8aa4a4592..e564aabbb 100644 --- a/javascript/ui.js +++ b/javascript/ui.js @@ -106,7 +106,14 @@ function create_tab_index_args(tabId, args){ function get_img2img_tab_index() { let res = args_to_array(arguments) - res.splice(-2) + res.splice(-2) // gradio also sends outputs to the arguments, pop them off + res[0] = get_tab_index('mode_img2img') + return res +} + +function get_img2img_tab_index_for_res_preview() { + let res = args_to_array(arguments) + res.splice(-1) // gradio also sends outputs to the arguments, pop them off res[0] = get_tab_index('mode_img2img') return res } @@ -345,7 +352,7 @@ function selectCheckpoint(name){ } -function onCalcResolutionImg2Img(init_img, scale, width, height, resize_mode){ +function onCalcResolutionImg2Img(mode, scale, width, height, resize_mode, init_img, sketch, init_img_with_mask, inpaint_color_sketch, init_img_inpaint){ i2iScale = gradioApp().getElementById('img2img_scale') i2iWidth = gradioApp().getElementById('img2img_width') i2iHeight = gradioApp().getElementById('img2img_height') @@ -354,5 +361,5 @@ function onCalcResolutionImg2Img(init_img, scale, width, height, resize_mode){ setInactive(i2iWidth, scale > 1) setInactive(i2iHeight, scale > 1) - return [init_img, width, height, scale, resize_mode] + return []; } From c5f9f7c23759f9a74fa2b563451569c8926604ba Mon Sep 17 00:00:00 2001 From: space-nuko <24979496+space-nuko@users.noreply.github.com> Date: Sat, 25 Mar 2023 14:26:36 -0400 Subject: [PATCH 04/15] Use .success() callback on img2img preview inputs change --- javascript/ui.js | 8 - modules/ui.py | 8 +- style.css | 818 ++++++++++++++++------------------------------- 3 files changed, 285 insertions(+), 549 deletions(-) diff --git a/javascript/ui.js b/javascript/ui.js index e564aabbb..7aa30dc19 100644 --- a/javascript/ui.js +++ b/javascript/ui.js @@ -118,14 +118,6 @@ function get_img2img_tab_index_for_res_preview() { return res } -function get_img2img_tab_index_for_res_preview() { - let res = args_to_array(arguments) - res.splice(-1) // gradio also sends outputs to the arguments, pop them off - res[0] = get_tab_index('mode_img2img') - debugger; - return res -} - function create_submit_args(args){ res = [] for(var i=0;i div{ + flex: 0; + white-space: nowrap; + min-width: auto; +} + +button.custom-button{ + border-radius: var(--button-large-radius); + padding: var(--button-large-padding); + font-weight: var(--button-large-text-weight); + border: var(--button-border-width) solid var(--button-secondary-border-color); + background: var(--button-secondary-background-fill); + color: var(--button-secondary-text-color); + font-size: var(--button-large-text-size); + display: inline-flex; + justify-content: center; + align-items: center; + transition: var(--button-transition); + box-shadow: var(--button-shadow); + text-align: center; +} + + +/* txt2img/img2img specific */ + +.block.token-counter{ position: absolute; display: inline-block; - right: 2em; + right: 1em; min-width: 0 !important; width: auto; z-index: 100; + top: -0.75em; } -.token-counter.error span{ +.block.token-counter span{ + background: var(--input-background-fill) !important; + box-shadow: 0 0 0.0 0.3em rgba(192,192,192,0.15), inset 0 0 0.6em rgba(192,192,192,0.075); + border: 2px solid rgba(192,192,192,0.4) !important; + border-radius: 0.4em; +} + +.block.token-counter.error span{ box-shadow: 0 0 0.0 0.3em rgba(255,0,0,0.15), inset 0 0 0.6em rgba(255,0,0,0.075); border: 2px solid rgba(255,0,0,0.4) !important; } -.token-counter div{ +.block.token-counter div{ display: inline; } -.token-counter span{ +.block.token-counter span{ padding: 0.1em 0.75em; } -#sh{ - min-width: 2em; - min-height: 2em; - max-width: 2em; - max-height: 2em; - flex-grow: 0; - padding-left: 0.25em; - padding-right: 0.25em; - margin: 0.1em 0; - opacity: 0%; - cursor: default; +[id$=_subseed_show]{ + min-width: auto !important; + flex-grow: 0 !important; + display: flex; } -.output-html p {margin: 0 0.5em;} - -.row > *, -.row > .gr-form > * { - min-width: min(120px, 100%); - flex: 1 1 0%; +[id$=_subseed_show] label{ + margin-bottom: 0.5em; + align-self: end; } .performance { @@ -75,196 +223,94 @@ object-fit: scale-down; } #txt2img_actions_column, #img2img_actions_column { - margin: 0.35rem 0.75rem 0.35rem 0; + gap: 0.5em; } -#script_list { - padding: .625rem .75rem 0 .625rem; -} -.justify-center.overflow-x-scroll { - justify-content: left; -} - -.justify-center.overflow-x-scroll button:first-of-type { - margin-left: auto; -} - -.justify-center.overflow-x-scroll button:last-of-type { - margin-right: auto; -} - -[id$=_random_seed], [id$=_random_subseed], [id$=_reuse_seed], [id$=_reuse_subseed], #open_folder{ - min-width: 2.3em; - height: 2.5em; - flex-grow: 0; - padding-left: 0.25em; - padding-right: 0.25em; -} - -#hidden_element{ - display: none; -} - -[id$=_seed_row], [id$=_subseed_row]{ - gap: 0.5rem; - padding: 0.6em; -} - -[id$=_subseed_show_box]{ - min-width: auto; - flex-grow: 0; -} - -[id$=_subseed_show_box] > div{ - border: 0; - height: 100%; -} - -[id$=_subseed_show]{ - min-width: auto; - flex-grow: 0; - padding: 0; -} - -[id$=_subseed_show] label{ - height: 100%; -} - -#txt2img_actions_column, #img2img_actions_column{ - gap: 0; - margin-right: .75rem; -} - #txt2img_tools, #img2img_tools{ gap: 0.4em; } -#interrogate_col{ +.interrogate-col{ min-width: 0 !important; - max-width: 8em !important; - margin-right: 1em; - gap: 0; + max-width: fit-content; + gap: 0.5em; } -#interrogate, #deepbooru{ - margin: 0em 0.25em 0.5em 0.25em; - min-width: 8em; - max-width: 8em; +.interrogate-col > button{ + flex: 1; } -#style_pos_col, #style_neg_col{ - min-width: 8em !important; +.generate-box{ + position: relative; } - -#txt2img_styles_row, #img2img_styles_row{ - gap: 0.25em; - margin-top: 0.3em; -} - -#txt2img_styles_row > button, #img2img_styles_row > button{ - margin: 0; -} - -#txt2img_styles, #img2img_styles{ - padding: 0; -} - -#txt2img_styles > label > div, #img2img_styles > label > div{ - min-height: 3.2em; -} - -ul.list-none{ - max-height: 35em; - z-index: 2000; -} - -.gr-form{ - background: transparent; -} - -.my-4{ - margin-top: 0; - margin-bottom: 0; -} - -#resize_mode{ - flex: 1.5; -} - -button{ - align-self: stretch !important; -} - -.overflow-hidden, .gr-panel{ - overflow: visible !important; -} - -#x_type, #y_type{ - max-width: 10em; -} - -#txt2img_preview, #img2img_preview, #ti_preview{ +.gradio-button.generate-box-skip, .gradio-button.generate-box-interrupt{ position: absolute; - width: 320px; - left: 0; - right: 0; - margin-left: auto; - margin-right: auto; - margin-top: 34px; - z-index: 100; - border: none; - border-top-left-radius: 0; - border-top-right-radius: 0; -} - -@media screen and (min-width: 768px) { - #txt2img_preview, #img2img_preview, #ti_preview { - position: absolute; - } -} - -@media screen and (max-width: 767px) { - #txt2img_preview, #img2img_preview, #ti_preview { - position: relative; - } -} - -#txt2img_preview div.left-0.top-0, #img2img_preview div.left-0.top-0, #ti_preview div.left-0.top-0{ + width: 50%; + height: 100%; display: none; + background: #b4c0cc; +} +.gradio-button.generate-box-skip:hover, .gradio-button.generate-box-interrupt:hover{ + background: #c2cfdb; +} +.gradio-button.generate-box-interrupt{ + left: 0; + border-radius: 0.5rem 0 0 0.5rem; +} +.gradio-button.generate-box-skip{ + right: 0; + border-radius: 0 0.5rem 0.5rem 0; } -fieldset span.text-gray-500, .gr-block.gr-box span.text-gray-500, label.block span{ - position: absolute; - top: -0.7em; - line-height: 1.2em; - padding: 0; - margin: 0 0.5em; - - background-color: white; - box-shadow: 6px 0 6px 0px white, -6px 0 6px 0px white; - - z-index: 300; +#txtimg_hr_finalres, #img2img_finalres { + min-height: 0 !important; + padding: .625rem .75rem; + margin-left: -0.75em } -.dark fieldset span.text-gray-500, .dark .gr-block.gr-box span.text-gray-500, .dark label.block span{ - background-color: rgb(31, 41, 55); - box-shadow: none; - border: 1px solid rgba(128, 128, 128, 0.1); - border-radius: 6px; - padding: 0.1em 0.5em; +#txtimg_hr_finalres .resolution, #img2img_finalres .resolution{ + font-weight: bold; } -#txt2img_column_batch, #img2img_column_batch{ +.inactive{ + opacity: 0.5; +} + +[id$=_column_batch]{ min-width: min(13.5em, 100%) !important; } -#settings fieldset span.text-gray-500, #settings .gr-block.gr-box span.text-gray-500, #settings label.block span{ - position: relative; - border: none; - margin-right: 8em; +div.dimensions-tools{ + min-width: 0 !important; + max-width: fit-content; + flex-direction: row; + align-content: center; } -#settings .gr-panel div.flex-col div.justify-between div{ - position: relative; - z-index: 200; +#mode_img2img .gradio-image > div.fixed-height, #mode_img2img .gradio-image > div.fixed-height img{ + height: 480px !important; + max-height: 480px !important; + min-height: 480px !important; +} + +.image-buttons button{ + min-width: auto; +} + +.infotext { + overflow-wrap: break-word; +} + +/* settings */ +#quicksettings { + width: fit-content; +} + +#quicksettings > div, #quicksettings > fieldset{ + max-width: 24em; + min-width: 24em; + padding: 0; + border: none; + box-shadow: none; + background: none; } #settings{ @@ -276,17 +322,18 @@ fieldset span.text-gray-500, .gr-block.gr-box span.text-gray-500, label.block s margin-left: 10em; } -#settings > div.flex-wrap{ +#settings > div.tab-nav{ float: left; display: block; margin-left: 0; width: 10em; } -#settings > div.flex-wrap button{ +#settings > div.tab-nav button{ display: block; border: none; text-align: left; + white-space: initial; } #settings_result{ @@ -294,29 +341,8 @@ fieldset span.text-gray-500, .gr-block.gr-box span.text-gray-500, label.block s margin: 0 1.2em; } -input[type="range"]{ - margin: 0.5em 0 -0.3em 0; -} - -#mask_bug_info { - text-align: center; - display: block; - margin-top: -0.75em; - margin-bottom: -0.75em; -} - -#txt2img_negative_prompt, #img2img_negative_prompt{ -} - -/* gradio 3.8 adds opacity to progressbar which makes it blink; disable it here */ -.transition.opacity-20 { - opacity: 1 !important; -} - -/* more gradio's garbage cleanup */ -.min-h-\[4rem\] { min-height: unset !important; } -.min-h-\[6rem\] { min-height: unset !important; } +/* live preview */ .progressDiv{ position: relative; height: 20px; @@ -362,6 +388,8 @@ input[type="range"]{ height: 100%; } +/* fullscreen popup (ie in Lora's (i) button) */ + .popup-metadata{ color: black; background: white; @@ -402,87 +430,54 @@ input[type="range"]{ padding: 2em; } +/* fullpage image viewer */ + #lightboxModal{ - display: none; - position: fixed; - z-index: 1001; - padding-top: 100px; - left: 0; - top: 0; - width: 100%; - height: 100%; - overflow: auto; - background-color: rgba(20, 20, 20, 0.95); - user-select: none; - -webkit-user-select: none; + display: none; + position: fixed; + z-index: 1001; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgba(20, 20, 20, 0.95); + user-select: none; + -webkit-user-select: none; + flex-direction: column; } .modalControls { - display: grid; - grid-template-columns: 32px 32px 32px 1fr 32px; - grid-template-areas: "zoom tile save space close"; - position: absolute; - top: 0; - left: 0; - right: 0; - padding: 16px; - gap: 16px; + display: flex; + gap: 1em; + padding: 1em; background-color: rgba(0,0,0,0.2); } - .modalClose { - grid-area: close; + margin-left: auto; } - -.modalZoom { - grid-area: zoom; -} - -.modalSave { - grid-area: save; -} - -.modalTileImage { - grid-area: tile; -} - -.modalClose, -.modalZoom, -.modalTileImage { - color: white; - font-size: 35px; - font-weight: bold; - cursor: pointer; -} - -.modalSave { +.modalControls span{ color: white; - font-size: 28px; - margin-top: 8px; + font-size: 35px; font-weight: bold; cursor: pointer; + width: 1em; } -.modalClose:hover, -.modalClose:focus, -.modalSave:hover, -.modalSave:focus, -.modalZoom:hover, -.modalZoom:focus { - color: #999; - text-decoration: none; - cursor: pointer; +.modalControls span:hover, .modalControls span:focus{ + color: #999; + text-decoration: none; } -#modalImage { +#lightboxModal > img { display: block; margin: auto; width: auto; } -.modalImageFullscreen { +#lightboxModal > img.modalImageFullscreen{ object-fit: contain; - height: 90%; + height: 100%; } .modalPrev, @@ -512,45 +507,7 @@ input[type="range"]{ background-color: rgba(0, 0, 0, 0.8); } -#imageARPreview{ - position:absolute; - top:0px; - left:0px; - border:2px solid red; - background:rgba(255, 0, 0, 0.3); - z-index: 900; - pointer-events:none; - display:none -} - -#txt2img_generate_box, #img2img_generate_box{ - position: relative; -} - -#txt2img_interrupt, #img2img_interrupt, #txt2img_skip, #img2img_skip{ - position: absolute; - width: 50%; - height: 100%; - background: #b4c0cc; - display: none; -} - -#txt2img_interrupt, #img2img_interrupt{ - left: 0; - border-radius: 0.5rem 0 0 0.5rem; -} -#txt2img_skip, #img2img_skip{ - right: 0; - border-radius: 0 0.5rem 0.5rem 0; -} - -.red { - color: red; -} - -.gallery-item { - --tw-bg-opacity: 0 !important; -} +/* context menu (ie for the generate button) */ #context-menu{ z-index:9999; @@ -579,61 +536,8 @@ input[type="range"]{ background: #a55000; } -#quicksettings { - width: fit-content; -} -#quicksettings > div, #quicksettings > fieldset{ - max-width: 24em; - min-width: 24em; - padding: 0; - border: none; - box-shadow: none; - background: none; - margin-right: 10px; -} - -#quicksettings > div > div > div > label > span { - position: relative; - margin-right: 9em; - margin-bottom: -1em; -} - -canvas[key="mask"] { - z-index: 12 !important; - filter: invert(); - mix-blend-mode: multiply; - pointer-events: none; -} - - -/* gradio 3.4.1 stuff for editable scrollbar values */ -.gr-box > div > div > input.gr-text-input{ - position: absolute; - right: 0.5em; - top: -0.6em; - z-index: 400; - width: 6em; -} -#quicksettings .gr-box > div > div > input.gr-text-input { - top: -1.12em; -} - -.row.gr-compact{ - overflow: visible; -} - -#img2img_image, #img2img_image > .h-60, #img2img_image > .h-60 > div, #img2img_image > .h-60 > div > img, -#img2img_sketch, #img2img_sketch > .h-60, #img2img_sketch > .h-60 > div, #img2img_sketch > .h-60 > div > img, -#img2maskimg, #img2maskimg > .h-60, #img2maskimg > .h-60 > div, #img2maskimg > .h-60 > div > img, -#inpaint_sketch, #inpaint_sketch > .h-60, #inpaint_sketch > .h-60 > div, #inpaint_sketch > .h-60 > div > img -{ - height: 480px !important; - max-height: 480px !important; - min-height: 480px !important; -} - -/* Extensions */ +/* extensions */ #tab_extensions table{ border-collapse: collapse; @@ -646,6 +550,7 @@ canvas[key="mask"] { #tab_extensions table input[type="checkbox"]{ margin-right: 0.5em; + appearance: checkbox; } #tab_extensions button{ @@ -670,74 +575,7 @@ canvas[key="mask"] { font-size: 90%; } -#image_buttons_txt2img button, #image_buttons_img2img button, #image_buttons_extras button{ - min-width: auto; - padding-left: 0.5em; - padding-right: 0.5em; -} - -.gr-form{ - background-color: white; -} - -.dark .gr-form{ - background-color: rgb(31 41 55 / var(--tw-bg-opacity)); -} - -.gr-button-tool, .gr-button-tool-top{ - max-width: 2.5em; - min-width: 2.5em !important; - height: 2.4em; -} - -.gr-button-tool{ - margin: 0.6em 0em 0.55em 0; -} - -.gr-button-tool-top, #settings .gr-button-tool{ - margin: 1.6em 0.7em 0.55em 0; -} - - -#modelmerger_results_container{ - margin-top: 1em; - overflow: visible; -} - -#modelmerger_models{ - gap: 0; -} - - -#quicksettings .gr-button-tool{ - margin: 0; - border-color: unset; - background-color: unset; -} - -#modelmerger_interp_description>p { - margin: 0!important; - text-align: center; -} -#modelmerger_interp_description { - margin: 0.35rem 0.75rem 1.23rem; -} -#img2img_settings > div.gr-form, #txt2img_settings > div.gr-form { - padding-top: 0.9em; - padding-bottom: 0.9em; -} -#txt2img_settings { - padding-top: 1.16em; - padding-bottom: 0.9em; -} -#img2img_settings { - padding-bottom: 0.9em; -} - -#img2img_settings div.gr-form .gr-form, #txt2img_settings div.gr-form .gr-form, #train_tabs div.gr-form .gr-form{ - border: none; - padding-bottom: 0.5em; -} +/* replace original footer with ours */ footer { display: none !important; @@ -756,99 +594,7 @@ footer { opacity: 0.85; } -#txtimg_hr_finalres{ - min-height: 0 !important; - padding: .625rem .75rem; - margin-left: -0.75em -} - -#txtimg_hr_finalres .resolution{ - font-weight: bold; -} - -#txt2img_checkboxes, #img2img_checkboxes{ - margin-bottom: 0.5em; - margin-left: 0em; -} -#txt2img_checkboxes > div, #img2img_checkboxes > div{ - flex: 0; - white-space: nowrap; - min-width: auto; -} - -#img2img_finalres{ - min-height: 0 !important; - padding: .625rem .75rem; - margin-left: 0.25em -} - -#img2img_finalres .resolution{ - font-weight: bold; -} - -#img2img_copy_to_img2img, #img2img_copy_to_sketch, #img2img_copy_to_inpaint, #img2img_copy_to_inpaint_sketch{ - margin-left: 0em; -} - -#axis_options { - margin-left: 0em; -} - -.inactive{ - opacity: 0.5; -} - -[id*='_prompt_container']{ - gap: 0; -} - -[id*='_prompt_container'] > div{ - margin: -0.4em 0 0 0; -} - -.gr-compact { - border: none; -} - -.dark .gr-compact{ - background-color: rgb(31 41 55 / var(--tw-bg-opacity)); - margin-left: 0; -} - -.gr-compact{ - overflow: visible; -} - -.gr-compact > *{ -} - -.gr-compact .gr-block, .gr-compact .gr-form{ - border: none; - box-shadow: none; -} - -.gr-compact .gr-box{ - border-radius: .5rem !important; - border-width: 1px !important; -} - -#mode_img2img > div > div{ - gap: 0 !important; -} - -[id*='img2img_copy_to_'] { - border: none; -} - -[id*='img2img_copy_to_'] > button { -} - -[id*='img2img_label_copy_to_'] { - font-size: 1.0em; - font-weight: bold; - text-align: center; - line-height: 2.4em; -} +/* extra networks UI */ .extra-networks > div > [id *= '_extra_']{ margin: 0.3em; @@ -861,12 +607,12 @@ footer { .extra-network-subdirs button{ margin: 0 0.15em; } - -#txt2img_extra_networks .search, #img2img_extra_networks .search{ +.extra-networks .tab-nav .search{ display: inline-block; max-width: 16em; margin: 0.3em; align-self: center; + width: 16em; } #txt2img_extra_view, #img2img_extra_view { @@ -898,6 +644,7 @@ footer { text-shadow: 2px 2px 3px black; padding: 0.25em; font-size: 22pt; + width: 1.5em; } .extra-network-cards .card:hover .metadata-button, .extra-network-thumbs .card:hover .metadata-button{ display: inline-block; @@ -991,12 +738,15 @@ footer { left: 0; right: 0; padding: 0.5em; - color: white; background: rgba(0,0,0,0.5); box-shadow: 0 0 0.25em 0.25em rgba(0,0,0,0.5); text-shadow: 0 0 0.2em black; } +.extra-network-cards .card .actions *{ + color: white; +} + .extra-network-cards .card .actions:hover{ box-shadow: 0 0 0.75em 0.75em rgba(0,0,0,0.5) !important; } @@ -1034,7 +784,3 @@ footer { .extra-network-cards .card ul a:hover{ color: red; } - -[id*='_prompt_container'] > div { - margin: 0!important; -} From 8a34671fe91e142bce9e5556cca2258b3be9dd6e Mon Sep 17 00:00:00 2001 From: MrCheeze Date: Fri, 24 Mar 2023 22:48:16 -0400 Subject: [PATCH 05/15] Add support for the Variations models (unclip-h and unclip-l) --- launch.py | 2 +- models/karlo/ViT-L-14_stats.th | Bin 0 -> 7079 bytes modules/lowvram.py | 10 +++++--- modules/processing.py | 41 +++++++++++++++++++++--------- modules/sd_models.py | 5 ++++ modules/sd_models_config.py | 7 +++++ modules/sd_samplers_compvis.py | 31 +++++++++++++++++----- modules/sd_samplers_kdiffusion.py | 19 +++++++++----- 8 files changed, 85 insertions(+), 30 deletions(-) create mode 100644 models/karlo/ViT-L-14_stats.th diff --git a/launch.py b/launch.py index b943fed22..e70df7ba7 100644 --- a/launch.py +++ b/launch.py @@ -252,7 +252,7 @@ def prepare_environment(): codeformer_repo = os.environ.get('CODEFORMER_REPO', 'https://github.com/sczhou/CodeFormer.git') blip_repo = os.environ.get('BLIP_REPO', 'https://github.com/salesforce/BLIP.git') - stable_diffusion_commit_hash = os.environ.get('STABLE_DIFFUSION_COMMIT_HASH', "47b6b607fdd31875c9279cd2f4f16b92e4ea958e") + stable_diffusion_commit_hash = os.environ.get('STABLE_DIFFUSION_COMMIT_HASH', "cf1d67a6fd5ea1aa600c4df58e5b47da45f6bdbf") taming_transformers_commit_hash = os.environ.get('TAMING_TRANSFORMERS_COMMIT_HASH', "24268930bf1dce879235a7fddd0b2355b84d7ea6") k_diffusion_commit_hash = os.environ.get('K_DIFFUSION_COMMIT_HASH', "5b3af030dd83e0297272d861c19477735d0317ec") codeformer_commit_hash = os.environ.get('CODEFORMER_COMMIT_HASH', "c5b4593074ba6214284d6acd5f1719b6c5d739af") diff --git a/models/karlo/ViT-L-14_stats.th b/models/karlo/ViT-L-14_stats.th new file mode 100644 index 0000000000000000000000000000000000000000..a6a06e94ecaa4f2977972ff991f75db6c90403ea GIT binary patch literal 7079 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 J7yX~K{{h(9ncn~a literal 0 HcmV?d00001 diff --git a/modules/lowvram.py b/modules/lowvram.py index 042a0254a..e254cc131 100644 --- a/modules/lowvram.py +++ b/modules/lowvram.py @@ -55,12 +55,12 @@ def setup_for_low_vram(sd_model, use_medvram): if hasattr(sd_model.cond_stage_model, 'model'): sd_model.cond_stage_model.transformer = sd_model.cond_stage_model.model - # remove four big modules, cond, first_stage, depth (if applicable), and unet from the model and then + # remove several big modules: cond, first_stage, depth/embedder (if applicable), and unet from the model and then # send the model to GPU. Then put modules back. the modules will be in CPU. - stored = sd_model.cond_stage_model.transformer, sd_model.first_stage_model, getattr(sd_model, 'depth_model', None), sd_model.model - sd_model.cond_stage_model.transformer, sd_model.first_stage_model, sd_model.depth_model, sd_model.model = None, None, None, None + stored = sd_model.cond_stage_model.transformer, sd_model.first_stage_model, getattr(sd_model, 'depth_model', None), getattr(sd_model, 'embedder', None), sd_model.model + sd_model.cond_stage_model.transformer, sd_model.first_stage_model, sd_model.depth_model, sd_model.embedder, sd_model.model = None, None, None, None, None sd_model.to(devices.device) - sd_model.cond_stage_model.transformer, sd_model.first_stage_model, sd_model.depth_model, sd_model.model = stored + sd_model.cond_stage_model.transformer, sd_model.first_stage_model, sd_model.depth_model, sd_model.embedder, sd_model.model = stored # register hooks for those the first three models sd_model.cond_stage_model.transformer.register_forward_pre_hook(send_me_to_gpu) @@ -69,6 +69,8 @@ def setup_for_low_vram(sd_model, use_medvram): sd_model.first_stage_model.decode = first_stage_model_decode_wrap if sd_model.depth_model: sd_model.depth_model.register_forward_pre_hook(send_me_to_gpu) + if sd_model.embedder: + sd_model.embedder.register_forward_pre_hook(send_me_to_gpu) parents[sd_model.cond_stage_model.transformer] = sd_model.cond_stage_model if hasattr(sd_model.cond_stage_model, 'model'): diff --git a/modules/processing.py b/modules/processing.py index 59717b4c6..1451811ca 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -78,22 +78,28 @@ def apply_overlay(image, paste_loc, index, overlays): def txt2img_image_conditioning(sd_model, x, width, height): - if sd_model.model.conditioning_key not in {'hybrid', 'concat'}: - # Dummy zero conditioning if we're not using inpainting model. + if sd_model.model.conditioning_key in {'hybrid', 'concat'}: # Inpainting models + + # The "masked-image" in this case will just be all zeros since the entire image is masked. + image_conditioning = torch.zeros(x.shape[0], 3, height, width, device=x.device) + image_conditioning = sd_model.get_first_stage_encoding(sd_model.encode_first_stage(image_conditioning)) + + # Add the fake full 1s mask to the first dimension. + image_conditioning = torch.nn.functional.pad(image_conditioning, (0, 0, 0, 0, 1, 0), value=1.0) + image_conditioning = image_conditioning.to(x.dtype) + + return image_conditioning + + elif sd_model.model.conditioning_key == "crossattn-adm": # UnCLIP models + + return x.new_zeros(x.shape[0], 2*sd_model.noise_augmentor.time_embed.dim, dtype=x.dtype, device=x.device) + + else: + # Dummy zero conditioning if we're not using inpainting or unclip models. # Still takes up a bit of memory, but no encoder call. # Pretty sure we can just make this a 1x1 image since its not going to be used besides its batch size. return x.new_zeros(x.shape[0], 5, 1, 1, dtype=x.dtype, device=x.device) - # The "masked-image" in this case will just be all zeros since the entire image is masked. - image_conditioning = torch.zeros(x.shape[0], 3, height, width, device=x.device) - image_conditioning = sd_model.get_first_stage_encoding(sd_model.encode_first_stage(image_conditioning)) - - # Add the fake full 1s mask to the first dimension. - image_conditioning = torch.nn.functional.pad(image_conditioning, (0, 0, 0, 0, 1, 0), value=1.0) - image_conditioning = image_conditioning.to(x.dtype) - - return image_conditioning - class StableDiffusionProcessing: """ @@ -190,6 +196,14 @@ class StableDiffusionProcessing: return conditioning_image + def unclip_image_conditioning(self, source_image): + c_adm = self.sd_model.embedder(source_image) + if self.sd_model.noise_augmentor is not None: + noise_level = 0 # TODO: Allow other noise levels? + c_adm, noise_level_emb = self.sd_model.noise_augmentor(c_adm, noise_level=repeat(torch.tensor([noise_level]).to(c_adm.device), '1 -> b', b=c_adm.shape[0])) + c_adm = torch.cat((c_adm, noise_level_emb), 1) + return c_adm + def inpainting_image_conditioning(self, source_image, latent_image, image_mask=None): self.is_using_inpainting_conditioning = True @@ -241,6 +255,9 @@ class StableDiffusionProcessing: if self.sampler.conditioning_key in {'hybrid', 'concat'}: return self.inpainting_image_conditioning(source_image, latent_image, image_mask=image_mask) + if self.sampler.conditioning_key == "crossattn-adm": + return self.unclip_image_conditioning(source_image) + # Dummy zero conditioning if we're not using inpainting or depth model. return latent_image.new_zeros(latent_image.shape[0], 5, 1, 1) diff --git a/modules/sd_models.py b/modules/sd_models.py index f0cb12400..c1a80d828 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -383,6 +383,11 @@ def repair_config(sd_config): elif shared.cmd_opts.upcast_sampling: sd_config.model.params.unet_config.params.use_fp16 = True + # For UnCLIP-L, override the hardcoded karlo directory + if hasattr(sd_config.model.params, "noise_aug_config") and hasattr(sd_config.model.params.noise_aug_config.params, "clip_stats_path"): + karlo_path = os.path.join(paths.models_path, 'karlo') + sd_config.model.params.noise_aug_config.params.clip_stats_path = sd_config.model.params.noise_aug_config.params.clip_stats_path.replace("checkpoints/karlo_models", karlo_path) + sd1_clip_weight = 'cond_stage_model.transformer.text_model.embeddings.token_embedding.weight' sd2_clip_weight = 'cond_stage_model.model.transformer.resblocks.0.attn.in_proj_weight' diff --git a/modules/sd_models_config.py b/modules/sd_models_config.py index 91c217004..9398f5284 100644 --- a/modules/sd_models_config.py +++ b/modules/sd_models_config.py @@ -14,6 +14,8 @@ config_sd2 = os.path.join(sd_repo_configs_path, "v2-inference.yaml") config_sd2v = os.path.join(sd_repo_configs_path, "v2-inference-v.yaml") config_sd2_inpainting = os.path.join(sd_repo_configs_path, "v2-inpainting-inference.yaml") config_depth_model = os.path.join(sd_repo_configs_path, "v2-midas-inference.yaml") +config_unclip = os.path.join(sd_repo_configs_path, "v2-1-stable-unclip-l-inference.yaml") +config_unopenclip = os.path.join(sd_repo_configs_path, "v2-1-stable-unclip-h-inference.yaml") config_inpainting = os.path.join(sd_configs_path, "v1-inpainting-inference.yaml") config_instruct_pix2pix = os.path.join(sd_configs_path, "instruct-pix2pix.yaml") config_alt_diffusion = os.path.join(sd_configs_path, "alt-diffusion-inference.yaml") @@ -65,9 +67,14 @@ def is_using_v_parameterization_for_sd2(state_dict): def guess_model_config_from_state_dict(sd, filename): sd2_cond_proj_weight = sd.get('cond_stage_model.model.transformer.resblocks.0.attn.in_proj_weight', None) diffusion_model_input = sd.get('model.diffusion_model.input_blocks.0.0.weight', None) + sd2_variations_weight = sd.get('embedder.model.ln_final.weight', None) if sd.get('depth_model.model.pretrained.act_postprocess3.0.project.0.bias', None) is not None: return config_depth_model + elif sd2_variations_weight is not None and sd2_variations_weight.shape[0] == 768: + return config_unclip + elif sd2_variations_weight is not None and sd2_variations_weight.shape[0] == 1024: + return config_unopenclip if sd2_cond_proj_weight is not None and sd2_cond_proj_weight.shape[1] == 1024: if diffusion_model_input.shape[1] == 9: diff --git a/modules/sd_samplers_compvis.py b/modules/sd_samplers_compvis.py index 083da18ca..bfcc55749 100644 --- a/modules/sd_samplers_compvis.py +++ b/modules/sd_samplers_compvis.py @@ -70,8 +70,13 @@ class VanillaStableDiffusionSampler: # Have to unwrap the inpainting conditioning here to perform pre-processing image_conditioning = None + uc_image_conditioning = None if isinstance(cond, dict): - image_conditioning = cond["c_concat"][0] + if self.conditioning_key == "crossattn-adm": + image_conditioning = cond["c_adm"] + uc_image_conditioning = unconditional_conditioning["c_adm"] + else: + image_conditioning = cond["c_concat"][0] cond = cond["c_crossattn"][0] unconditional_conditioning = unconditional_conditioning["c_crossattn"][0] @@ -98,8 +103,12 @@ class VanillaStableDiffusionSampler: # Wrap the image conditioning back up since the DDIM code can accept the dict directly. # Note that they need to be lists because it just concatenates them later. if image_conditioning is not None: - cond = {"c_concat": [image_conditioning], "c_crossattn": [cond]} - unconditional_conditioning = {"c_concat": [image_conditioning], "c_crossattn": [unconditional_conditioning]} + if self.conditioning_key == "crossattn-adm": + cond = {"c_adm": image_conditioning, "c_crossattn": [cond]} + unconditional_conditioning = {"c_adm": uc_image_conditioning, "c_crossattn": [unconditional_conditioning]} + else: + cond = {"c_concat": [image_conditioning], "c_crossattn": [cond]} + unconditional_conditioning = {"c_concat": [image_conditioning], "c_crossattn": [unconditional_conditioning]} return x, ts, cond, unconditional_conditioning @@ -176,8 +185,12 @@ class VanillaStableDiffusionSampler: # Wrap the conditioning models with additional image conditioning for inpainting model if image_conditioning is not None: - conditioning = {"c_concat": [image_conditioning], "c_crossattn": [conditioning]} - unconditional_conditioning = {"c_concat": [image_conditioning], "c_crossattn": [unconditional_conditioning]} + if self.conditioning_key == "crossattn-adm": + conditioning = {"c_adm": image_conditioning, "c_crossattn": [conditioning]} + unconditional_conditioning = {"c_adm": torch.zeros_like(image_conditioning), "c_crossattn": [unconditional_conditioning]} + else: + conditioning = {"c_concat": [image_conditioning], "c_crossattn": [conditioning]} + unconditional_conditioning = {"c_concat": [image_conditioning], "c_crossattn": [unconditional_conditioning]} samples = self.launch_sampling(t_enc + 1, lambda: self.sampler.decode(x1, conditioning, t_enc, unconditional_guidance_scale=p.cfg_scale, unconditional_conditioning=unconditional_conditioning)) @@ -195,8 +208,12 @@ class VanillaStableDiffusionSampler: # Wrap the conditioning models with additional image conditioning for inpainting model # dummy_for_plms is needed because PLMS code checks the first item in the dict to have the right shape if image_conditioning is not None: - conditioning = {"dummy_for_plms": np.zeros((conditioning.shape[0],)), "c_crossattn": [conditioning], "c_concat": [image_conditioning]} - unconditional_conditioning = {"c_crossattn": [unconditional_conditioning], "c_concat": [image_conditioning]} + if self.conditioning_key == "crossattn-adm": + conditioning = {"dummy_for_plms": np.zeros((conditioning.shape[0],)), "c_crossattn": [conditioning], "c_adm": image_conditioning} + unconditional_conditioning = {"c_crossattn": [unconditional_conditioning], "c_adm": torch.zeros_like(image_conditioning)} + else: + conditioning = {"dummy_for_plms": np.zeros((conditioning.shape[0],)), "c_crossattn": [conditioning], "c_concat": [image_conditioning]} + unconditional_conditioning = {"c_crossattn": [unconditional_conditioning], "c_concat": [image_conditioning]} samples_ddim = self.launch_sampling(steps, lambda: self.sampler.sample(S=steps, conditioning=conditioning, batch_size=int(x.shape[0]), shape=x[0].shape, verbose=False, unconditional_guidance_scale=p.cfg_scale, unconditional_conditioning=unconditional_conditioning, x_T=x, eta=self.eta)[0]) diff --git a/modules/sd_samplers_kdiffusion.py b/modules/sd_samplers_kdiffusion.py index 93f0e55a0..e9f08518f 100644 --- a/modules/sd_samplers_kdiffusion.py +++ b/modules/sd_samplers_kdiffusion.py @@ -92,14 +92,21 @@ class CFGDenoiser(torch.nn.Module): batch_size = len(conds_list) repeats = [len(conds_list[i]) for i in range(batch_size)] + if shared.sd_model.model.conditioning_key == "crossattn-adm": + image_uncond = torch.zeros_like(image_cond) + make_condition_dict = lambda c_crossattn, c_adm: {"c_crossattn": c_crossattn, "c_adm": c_adm} + else: + image_uncond = image_cond + make_condition_dict = lambda c_crossattn, c_concat: {"c_crossattn": c_crossattn, "c_concat": [c_concat]} + if not is_edit_model: x_in = torch.cat([torch.stack([x[i] for _ in range(n)]) for i, n in enumerate(repeats)] + [x]) sigma_in = torch.cat([torch.stack([sigma[i] for _ in range(n)]) for i, n in enumerate(repeats)] + [sigma]) - image_cond_in = torch.cat([torch.stack([image_cond[i] for _ in range(n)]) for i, n in enumerate(repeats)] + [image_cond]) + image_cond_in = torch.cat([torch.stack([image_cond[i] for _ in range(n)]) for i, n in enumerate(repeats)] + [image_uncond]) else: x_in = torch.cat([torch.stack([x[i] for _ in range(n)]) for i, n in enumerate(repeats)] + [x] + [x]) sigma_in = torch.cat([torch.stack([sigma[i] for _ in range(n)]) for i, n in enumerate(repeats)] + [sigma] + [sigma]) - image_cond_in = torch.cat([torch.stack([image_cond[i] for _ in range(n)]) for i, n in enumerate(repeats)] + [image_cond] + [torch.zeros_like(self.init_latent)]) + image_cond_in = torch.cat([torch.stack([image_cond[i] for _ in range(n)]) for i, n in enumerate(repeats)] + [image_uncond] + [torch.zeros_like(self.init_latent)]) denoiser_params = CFGDenoiserParams(x_in, image_cond_in, sigma_in, state.sampling_step, state.sampling_steps, tensor, uncond) cfg_denoiser_callback(denoiser_params) @@ -116,13 +123,13 @@ class CFGDenoiser(torch.nn.Module): cond_in = torch.cat([tensor, uncond, uncond]) if shared.batch_cond_uncond: - x_out = self.inner_model(x_in, sigma_in, cond={"c_crossattn": [cond_in], "c_concat": [image_cond_in]}) + x_out = self.inner_model(x_in, sigma_in, cond=make_condition_dict([cond_in], image_cond_in)) else: x_out = torch.zeros_like(x_in) for batch_offset in range(0, x_out.shape[0], batch_size): a = batch_offset b = a + batch_size - x_out[a:b] = self.inner_model(x_in[a:b], sigma_in[a:b], cond={"c_crossattn": [cond_in[a:b]], "c_concat": [image_cond_in[a:b]]}) + x_out[a:b] = self.inner_model(x_in[a:b], sigma_in[a:b], cond=make_condition_dict([cond_in[a:b]], image_cond_in[a:b])) else: x_out = torch.zeros_like(x_in) batch_size = batch_size*2 if shared.batch_cond_uncond else batch_size @@ -135,9 +142,9 @@ class CFGDenoiser(torch.nn.Module): else: c_crossattn = torch.cat([tensor[a:b]], uncond) - x_out[a:b] = self.inner_model(x_in[a:b], sigma_in[a:b], cond={"c_crossattn": c_crossattn, "c_concat": [image_cond_in[a:b]]}) + x_out[a:b] = self.inner_model(x_in[a:b], sigma_in[a:b], cond=make_condition_dict(c_crossattn, image_cond_in[a:b])) - x_out[-uncond.shape[0]:] = self.inner_model(x_in[-uncond.shape[0]:], sigma_in[-uncond.shape[0]:], cond={"c_crossattn": [uncond], "c_concat": [image_cond_in[-uncond.shape[0]:]]}) + x_out[-uncond.shape[0]:] = self.inner_model(x_in[-uncond.shape[0]:], sigma_in[-uncond.shape[0]:], cond=make_condition_dict([uncond], image_cond_in[-uncond.shape[0]:])) denoised_params = CFGDenoisedParams(x_out, state.sampling_step, state.sampling_steps) cfg_denoised_callback(denoised_params) From 1f08600345298fac0bcb66cc215a81875a84d7b9 Mon Sep 17 00:00:00 2001 From: MrCheeze Date: Sun, 26 Mar 2023 16:55:29 -0400 Subject: [PATCH 06/15] overwrite xformers in the unclip model config if not available --- modules/sd_models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/sd_models.py b/modules/sd_models.py index c1a80d828..e741470a8 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -383,6 +383,9 @@ def repair_config(sd_config): elif shared.cmd_opts.upcast_sampling: sd_config.model.params.unet_config.params.use_fp16 = True + if getattr(sd_config.model.params.first_stage_config.params.ddconfig, "attn_type", None) == "vanilla-xformers" and not shared.xformers_available: + sd_config.model.params.first_stage_config.params.ddconfig.attn_type = "vanilla" + # For UnCLIP-L, override the hardcoded karlo directory if hasattr(sd_config.model.params, "noise_aug_config") and hasattr(sd_config.model.params.noise_aug_config.params, "clip_stats_path"): karlo_path = os.path.join(paths.models_path, 'karlo') From 77f9db3b080fafbc39c1b188777a93b5a1ab0f9e Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Mon, 27 Mar 2023 12:59:12 +0300 Subject: [PATCH 07/15] serve css as independent files --- modules/ui.py | 74 ++++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/modules/ui.py b/modules/ui.py index af8546c29..eb5fcd3fb 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -70,17 +70,6 @@ def gr_show(visible=True): sample_img2img = "assets/stable-samples/img2img/sketch-mountains-input.jpg" sample_img2img = sample_img2img if os.path.exists(sample_img2img) else None -css_hide_progressbar = """ -.wrap .m-12 svg { display:none!important; } -.wrap .m-12::before { content:"Loading..." } -.wrap .z-20 svg { display:none!important; } -.wrap .z-20::before { content:"Loading..." } -.wrap.cover-bg .z-20::before { content:"" } -.progress-bar { display:none!important; } -.meta-text { display:none!important; } -.meta-text-center { display:none!important; } -""" - # Using constants for these since the variation selector isn't visible. # Important that they exactly match script.js for tooltip to work. random_symbol = '\U0001f3b2\ufe0f' # 🎲️ @@ -1566,22 +1555,6 @@ def create_ui(): (train_interface, "Train", "ti"), ] - css = "" - - for cssfile in modules.scripts.list_files_with_name("style.css"): - if not os.path.isfile(cssfile): - continue - - with open(cssfile, "r", encoding="utf8") as file: - css += file.read() + "\n" - - if os.path.exists(os.path.join(data_path, "user.css")): - with open(os.path.join(data_path, "user.css"), "r", encoding="utf8") as file: - css += file.read() + "\n" - - if not cmd_opts.no_progressbar_hiding: - css += css_hide_progressbar - interfaces += script_callbacks.ui_tabs_callback() interfaces += [(settings_interface, "Settings", "settings")] @@ -1592,7 +1565,7 @@ def create_ui(): for _interface, label, _ifid in interfaces: shared.tab_names.append(label) - with gr.Blocks(css=css, analytics_enabled=False, title="Stable Diffusion") as demo: + with gr.Blocks(analytics_enabled=False, title="Stable Diffusion") as demo: with gr.Row(elem_id="quicksettings", variant="compact"): for i, k, item in sorted(quicksettings_list, key=lambda x: quicksettings_names.get(x[1], x[0])): component = create_setting_component(k, is_quicksettings=True) @@ -1777,25 +1750,60 @@ def create_ui(): return demo -def reload_javascript(): +def webpath(fn): + if fn.startswith(script_path): + web_path = os.path.relpath(fn, script_path).replace('\\', '/') + else: + web_path = os.path.abspath(fn) + + return f'file={web_path}?{os.path.getmtime(fn)}' + + +def javascript_html(): script_js = os.path.join(script_path, "script.js") - head = f'\n' + head = f'\n' inline = f"{localization.localization_js(shared.opts.localization)};" if cmd_opts.theme is not None: inline += f"set_theme('{cmd_opts.theme}');" for script in modules.scripts.list_scripts("javascript", ".js"): - head += f'\n' + head += f'\n' for script in modules.scripts.list_scripts("javascript", ".mjs"): - head += f'\n' + head += f'\n' head += f'\n' + return head + + +def css_html(): + head = "" + + def stylesheet(fn): + return f'' + + for cssfile in modules.scripts.list_files_with_name("style.css"): + if not os.path.isfile(cssfile): + continue + + head += stylesheet(cssfile) + + if os.path.exists(os.path.join(data_path, "user.css")): + head += stylesheet(os.path.join(data_path, "user.css")) + + return head + + +def reload_javascript(): + js = javascript_html() + css = css_html() + def template_response(*args, **kwargs): res = shared.GradioTemplateResponseOriginal(*args, **kwargs) - res.body = res.body.replace(b'', f'{head}'.encode("utf8")) + res.body = res.body.replace(b'', f'{js}'.encode("utf8")) + res.body = res.body.replace(b'', f'{css}'.encode("utf8")) res.init_headers() return res From 2a4d3d21242dcc8b2b9cef85aa8f4227e855dc96 Mon Sep 17 00:00:00 2001 From: space-nuko <24979496+space-nuko@users.noreply.github.com> Date: Mon, 27 Mar 2023 12:04:45 -0400 Subject: [PATCH 08/15] Add temporary "disable all extensions" option for debugging use --- launch.py | 4 ++++ modules/extensions.py | 4 ++++ modules/shared.py | 3 ++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/launch.py b/launch.py index c41ae82d2..1321b77ab 100644 --- a/launch.py +++ b/launch.py @@ -206,6 +206,10 @@ def list_extensions(settings_file): print(e, file=sys.stderr) disabled_extensions = set(settings.get('disabled_extensions', [])) + disable_all_extensions = settings.get('disable_all_extensions', False) + + if disable_all_extensions: + return [] return [x for x in os.listdir(extensions_dir) if x not in disabled_extensions] diff --git a/modules/extensions.py b/modules/extensions.py index 0d34b89ab..1493e8c81 100644 --- a/modules/extensions.py +++ b/modules/extensions.py @@ -97,6 +97,10 @@ def list_extensions(): if not os.path.isdir(extensions_dir): return + if shared.opts.disable_all_extensions: + print("*** \"Disable all extensions\" option was set, will not load any extensions ***") + return + extension_paths = [] for dirname in [extensions_dir, extensions_builtin_dir]: if not os.path.isdir(dirname): diff --git a/modules/shared.py b/modules/shared.py index 3ad0862b2..c79ec67b1 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -422,7 +422,8 @@ options_templates.update(options_section(('postprocessing', "Postprocessing"), { })) options_templates.update(options_section((None, "Hidden options"), { - "disabled_extensions": OptionInfo([], "Disable those extensions"), + "disabled_extensions": OptionInfo([], "Disable these extensions"), + "disable_all_extensions": OptionInfo(False, "Disable all extensions (preserves the list of disabled extensions)"), "sd_checkpoint_hash": OptionInfo("", "SHA256 hash of the current checkpoint"), })) From fc8e1008ea93f98554907f25aaf52f24ce661847 Mon Sep 17 00:00:00 2001 From: space-nuko <24979496+space-nuko@users.noreply.github.com> Date: Mon, 27 Mar 2023 12:44:49 -0400 Subject: [PATCH 09/15] Make disable configurable between builtin/extra extensions --- javascript/extensions.js | 6 +++--- launch.py | 4 ---- modules/extensions.py | 13 +++++++++---- modules/shared.py | 2 +- modules/ui_extensions.py | 21 +++++++++++++++++---- 5 files changed, 30 insertions(+), 16 deletions(-) diff --git a/javascript/extensions.js b/javascript/extensions.js index c593cd2e5..72924a28c 100644 --- a/javascript/extensions.js +++ b/javascript/extensions.js @@ -1,5 +1,5 @@ -function extensions_apply(_, _){ +function extensions_apply(_, _, disable_all){ var disable = [] var update = [] @@ -13,10 +13,10 @@ function extensions_apply(_, _){ restart_reload() - return [JSON.stringify(disable), JSON.stringify(update)] + return [JSON.stringify(disable), JSON.stringify(update), disable_all] } -function extensions_check(){ +function extensions_check(_, _){ var disable = [] gradioApp().querySelectorAll('#extensions input[type="checkbox"]').forEach(function(x){ diff --git a/launch.py b/launch.py index 1321b77ab..c41ae82d2 100644 --- a/launch.py +++ b/launch.py @@ -206,10 +206,6 @@ def list_extensions(settings_file): print(e, file=sys.stderr) disabled_extensions = set(settings.get('disabled_extensions', [])) - disable_all_extensions = settings.get('disable_all_extensions', False) - - if disable_all_extensions: - return [] return [x for x in os.listdir(extensions_dir) if x not in disabled_extensions] diff --git a/modules/extensions.py b/modules/extensions.py index 1493e8c81..3a7a03727 100644 --- a/modules/extensions.py +++ b/modules/extensions.py @@ -15,7 +15,12 @@ if not os.path.exists(extensions_dir): def active(): - return [x for x in extensions if x.enabled] + if shared.opts.disable_all_extensions == "all": + return [] + elif shared.opts.disable_all_extensions == "extra": + return [x for x in extensions if x.enabled and x.is_builtin] + else: + return [x for x in extensions if x.enabled] class Extension: @@ -97,9 +102,10 @@ def list_extensions(): if not os.path.isdir(extensions_dir): return - if shared.opts.disable_all_extensions: + if shared.opts.disable_all_extensions == "all": print("*** \"Disable all extensions\" option was set, will not load any extensions ***") - return + elif shared.opts.disable_all_extensions == "extra": + print("*** \"Disable all extensions\" option was set, will only load built-in extensions ***") extension_paths = [] for dirname in [extensions_dir, extensions_builtin_dir]: @@ -116,4 +122,3 @@ def list_extensions(): for dirname, path, is_builtin in extension_paths: extension = Extension(name=dirname, path=path, enabled=dirname not in shared.opts.disabled_extensions, is_builtin=is_builtin) extensions.append(extension) - diff --git a/modules/shared.py b/modules/shared.py index c79ec67b1..5fd0eecbd 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -423,7 +423,7 @@ options_templates.update(options_section(('postprocessing', "Postprocessing"), { options_templates.update(options_section((None, "Hidden options"), { "disabled_extensions": OptionInfo([], "Disable these extensions"), - "disable_all_extensions": OptionInfo(False, "Disable all extensions (preserves the list of disabled extensions)"), + "disable_all_extensions": OptionInfo("none", "Disable all extensions (preserves the list of disabled extensions)", gr.Radio, {"choices": ["none", "extra", "all"]}), "sd_checkpoint_hash": OptionInfo("", "SHA256 hash of the current checkpoint"), })) diff --git a/modules/ui_extensions.py b/modules/ui_extensions.py index b4a0d6ecf..efd6cda28 100644 --- a/modules/ui_extensions.py +++ b/modules/ui_extensions.py @@ -21,7 +21,7 @@ def check_access(): assert not shared.cmd_opts.disable_extension_access, "extension access disabled because of command line flags" -def apply_and_restart(disable_list, update_list): +def apply_and_restart(disable_list, update_list, disable_all): check_access() disabled = json.loads(disable_list) @@ -43,6 +43,7 @@ def apply_and_restart(disable_list, update_list): print(traceback.format_exc(), file=sys.stderr) shared.opts.disabled_extensions = disabled + shared.opts.disable_all_extensions = disable_all shared.opts.save(shared.config_filename) shared.state.interrupt() @@ -99,9 +100,13 @@ def extension_table(): else: ext_status = ext.status + style = "" + if shared.opts.disable_all_extensions == "extra" and not ext.is_builtin or shared.opts.disable_all_extensions == "all": + style = ' style="color: var(--primary-400)"' + code += f""" - + {html.escape(ext.name)} {remote} {ext.version} {ext_status} @@ -294,16 +299,24 @@ def create_ui(): with gr.Row(elem_id="extensions_installed_top"): apply = gr.Button(value="Apply and restart UI", variant="primary") check = gr.Button(value="Check for updates") + extensions_disable_all = gr.Radio(label="Disable all extensions", choices=["none", "extra", "all"], value=shared.opts.disable_all_extensions, elem_id="extensions_disable_all") extensions_disabled_list = gr.Text(elem_id="extensions_disabled_list", visible=False).style(container=False) extensions_update_list = gr.Text(elem_id="extensions_update_list", visible=False).style(container=False) - info = gr.HTML() + html = "" + if shared.opts.disable_all_extensions != "none": + html = """ + + "Disable all extensions" was set, change it to "none" to load all extensions again + + """ + info = gr.HTML(html) extensions_table = gr.HTML(lambda: extension_table()) apply.click( fn=apply_and_restart, _js="extensions_apply", - inputs=[extensions_disabled_list, extensions_update_list], + inputs=[extensions_disabled_list, extensions_update_list, extensions_disable_all], outputs=[], ) From 4b4902050684dc4db1bbd007a4f2e8f7c37bf1a4 Mon Sep 17 00:00:00 2001 From: zetclansu Date: Mon, 27 Mar 2023 21:05:56 +0300 Subject: [PATCH 10/15] Update style.css Fix for wide width image in img2img_sketch, img2maskimg, inpaint_sketch --- style.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/style.css b/style.css index 5e8fb5330..be6ceb1e4 100644 --- a/style.css +++ b/style.css @@ -318,6 +318,13 @@ div.dimensions-tools{ min-height: 480px !important; } +#img2img_sketch, #img2maskimg, #inpaint_sketch { + overflow: overlay !important; + resize: auto; + background: var(--panel-background-fill); + z-index: 5; +} + .image-buttons button{ min-width: auto; } From 56f62d3851ff08dc1574a9ff2a05271f3730f3f7 Mon Sep 17 00:00:00 2001 From: space-nuko <24979496+space-nuko@users.noreply.github.com> Date: Mon, 27 Mar 2023 17:23:20 -0400 Subject: [PATCH 11/15] Skip extension installers if all disabled --- launch.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/launch.py b/launch.py index c41ae82d2..2e3cd4c4b 100644 --- a/launch.py +++ b/launch.py @@ -206,6 +206,10 @@ def list_extensions(settings_file): print(e, file=sys.stderr) disabled_extensions = set(settings.get('disabled_extensions', [])) + disable_all_extensions = settings.get('disable_all_extensions', 'none') + + if disable_all_extensions != 'none': + return [] return [x for x in os.listdir(extensions_dir) if x not in disabled_extensions] From b3e593edcb72c0431a50b423fe7aa88a0daf2a90 Mon Sep 17 00:00:00 2001 From: missionfloyd Date: Mon, 27 Mar 2023 16:38:42 -0600 Subject: [PATCH 12/15] Fix quicksettings alignment --- style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/style.css b/style.css index 5e8fb5330..4827a9a18 100644 --- a/style.css +++ b/style.css @@ -329,6 +329,7 @@ div.dimensions-tools{ /* settings */ #quicksettings { width: fit-content; + align-items: end; } #quicksettings > div, #quicksettings > fieldset{ From 1b63afbedc7789c0eb9a4742b780ab304d7a9caf Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Tue, 28 Mar 2023 20:03:57 +0300 Subject: [PATCH 13/15] sort hypernetworks and checkpoints by name --- modules/hypernetworks/hypernetwork.py | 2 +- modules/sd_models.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/hypernetworks/hypernetwork.py b/modules/hypernetworks/hypernetwork.py index f6ef42d5a..1fc49537c 100644 --- a/modules/hypernetworks/hypernetwork.py +++ b/modules/hypernetworks/hypernetwork.py @@ -312,7 +312,7 @@ class Hypernetwork: def list_hypernetworks(path): res = {} - for filename in sorted(glob.iglob(os.path.join(path, '**/*.pt'), recursive=True)): + for filename in sorted(glob.iglob(os.path.join(path, '**/*.pt'), recursive=True), key=str.lower): name = os.path.splitext(os.path.basename(filename))[0] # Prevent a hypothetical "None.pt" from being listed. if name != "None": diff --git a/modules/sd_models.py b/modules/sd_models.py index c2b3405c5..6ea874dfc 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -122,7 +122,7 @@ def list_models(): elif cmd_ckpt is not None and cmd_ckpt != shared.default_sd_model_file: print(f"Checkpoint in --ckpt argument not found (Possible it was moved to {model_path}: {cmd_ckpt}", file=sys.stderr) - for filename in model_list: + for filename in sorted(model_list, key=str.lower): checkpoint_info = CheckpointInfo(filename) checkpoint_info.register() From 433b3ab7017556a19173a86d1215ed0a0b5b1396 Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Tue, 28 Mar 2023 20:36:57 +0300 Subject: [PATCH 14/15] Revert "Merge pull request #7931 from space-nuko/img2img-enhance" This reverts commit 426875937048e21305ac24bea53df06523bdaa81, reversing changes made to 1b63afbedc7789c0eb9a4742b780ab304d7a9caf. --- javascript/ui.js | 22 +------ modules/generation_parameters_copypaste.py | 3 - modules/img2img.py | 4 +- modules/processing.py | 37 ++--------- modules/ui.py | 73 ++-------------------- scripts/xyz_grid.py | 1 - style.css | 4 +- 7 files changed, 13 insertions(+), 131 deletions(-) diff --git a/javascript/ui.js b/javascript/ui.js index a73eeaa29..4a440193b 100644 --- a/javascript/ui.js +++ b/javascript/ui.js @@ -132,14 +132,7 @@ function create_tab_index_args(tabId, args){ function get_img2img_tab_index() { let res = args_to_array(arguments) - res.splice(-2) // gradio also sends outputs to the arguments, pop them off - res[0] = get_tab_index('mode_img2img') - return res -} - -function get_img2img_tab_index_for_res_preview() { - let res = args_to_array(arguments) - res.splice(-1) // gradio also sends outputs to the arguments, pop them off + res.splice(-2) res[0] = get_tab_index('mode_img2img') return res } @@ -368,16 +361,3 @@ function selectCheckpoint(name){ desiredCheckpointName = name; gradioApp().getElementById('change_checkpoint').click() } - - -function onCalcResolutionImg2Img(mode, scale, width, height, resize_mode, init_img, sketch, init_img_with_mask, inpaint_color_sketch, init_img_inpaint){ - i2iScale = gradioApp().getElementById('img2img_scale') - i2iWidth = gradioApp().getElementById('img2img_width') - i2iHeight = gradioApp().getElementById('img2img_height') - - setInactive(i2iScale, scale == 1) - setInactive(i2iWidth, scale > 1) - setInactive(i2iHeight, scale > 1) - - return []; -} diff --git a/modules/generation_parameters_copypaste.py b/modules/generation_parameters_copypaste.py index 0ad2ad4f0..6df76858f 100644 --- a/modules/generation_parameters_copypaste.py +++ b/modules/generation_parameters_copypaste.py @@ -282,9 +282,6 @@ Steps: 20, Sampler: Euler a, CFG scale: 7, Seed: 965400086, Size: 512x512, Model res["Hires resize-1"] = 0 res["Hires resize-2"] = 0 - if "Img2Img upscale" not in res: - res["Img2Img upscale"] = 1 - restore_old_hires_fix_params(res) return res diff --git a/modules/img2img.py b/modules/img2img.py index 959dd96ea..c973b7708 100644 --- a/modules/img2img.py +++ b/modules/img2img.py @@ -78,7 +78,7 @@ def process_batch(p, input_dir, output_dir, inpaint_mask_dir, args): processed_image.save(os.path.join(output_dir, filename)) -def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_index: int, mask_blur: int, mask_alpha: float, inpainting_fill: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, denoising_strength: 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, scale: float, upscaler: str, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_input_dir: str, img2img_batch_output_dir: str, img2img_batch_inpaint_mask_dir: str, override_settings_texts, *args): +def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_index: int, mask_blur: int, mask_alpha: float, inpainting_fill: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, denoising_strength: 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, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_input_dir: str, img2img_batch_output_dir: str, img2img_batch_inpaint_mask_dir: str, override_settings_texts, *args): override_settings = create_override_settings_dict(override_settings_texts) is_batch = mode == 5 @@ -149,8 +149,6 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s inpaint_full_res_padding=inpaint_full_res_padding, inpainting_mask_invert=inpainting_mask_invert, override_settings=override_settings, - scale=scale, - upscaler=upscaler, ) p.scripts = modules.scripts.scripts_txt2img diff --git a/modules/processing.py b/modules/processing.py index 509b80b9e..6d9c6a8de 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -946,7 +946,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): sampler = None - def __init__(self, init_images: Optional[list] = None, resize_mode: int = 0, denoising_strength: float = 0.75, image_cfg_scale: Optional[float] = None, mask: Any = None, mask_blur: int = 4, inpainting_fill: int = 0, inpaint_full_res: bool = True, inpaint_full_res_padding: int = 0, inpainting_mask_invert: int = 0, initial_noise_multiplier: Optional[float] = None, scale: float = 0, upscaler: Optional[str] = None, **kwargs): + def __init__(self, init_images: list = None, resize_mode: int = 0, denoising_strength: float = 0.75, image_cfg_scale: float = None, mask: Any = None, mask_blur: int = 4, inpainting_fill: int = 0, inpaint_full_res: bool = True, inpaint_full_res_padding: int = 0, inpainting_mask_invert: int = 0, initial_noise_multiplier: float = None, **kwargs): super().__init__(**kwargs) self.init_images = init_images @@ -966,37 +966,11 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): self.mask = None self.nmask = None self.image_conditioning = None - self.scale = scale - self.upscaler = upscaler - - def get_final_size(self): - if self.scale > 1: - img = self.init_images[0] - width = int(img.width * self.scale) - height = int(img.height * self.scale) - return width, height - else: - return self.width, self.height - def init(self, all_prompts, all_seeds, all_subseeds): self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model) crop_region = None - if self.scale > 1: - self.extra_generation_params["Img2Img upscale"] = self.scale - - # Non-latent upscalers are run before sampling - # Latent upscalers are run during sampling - init_upscaler = None - if self.upscaler is not None: - self.extra_generation_params["Img2Img upscaler"] = self.upscaler - if self.upscaler not in shared.latent_upscale_modes: - assert len([x for x in shared.sd_upscalers if x.name == self.upscaler]) > 0, f"could not find upscaler named {self.upscaler}" - init_upscaler = self.upscaler - - self.width, self.height = self.get_final_size() - image_mask = self.image_mask if image_mask is not None: @@ -1019,7 +993,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): image_mask = images.resize_image(2, mask, self.width, self.height) self.paste_to = (x1, y1, x2-x1, y2-y1) else: - image_mask = images.resize_image(self.resize_mode, image_mask, self.width, self.height, init_upscaler) + image_mask = images.resize_image(self.resize_mode, image_mask, self.width, self.height) 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) @@ -1036,7 +1010,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): 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, init_upscaler) + 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)) @@ -1081,9 +1055,8 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): self.init_latent = self.sd_model.get_first_stage_encoding(self.sd_model.encode_first_stage(image)) - latent_scale_mode = shared.latent_upscale_modes.get(self.upscaler, None) if self.upscaler is not None else shared.latent_upscale_modes.get(shared.latent_upscale_default_mode, "nearest") - if latent_scale_mode is not None: - self.init_latent = torch.nn.functional.interpolate(self.init_latent, size=(self.height // opt_f, self.width // opt_f), mode=latent_scale_mode["mode"], antialias=latent_scale_mode["antialias"]) + if self.resize_mode == 3: + self.init_latent = torch.nn.functional.interpolate(self.init_latent, size=(self.height // opt_f, self.width // opt_f), mode="bilinear") if image_mask is not None: init_mask = latent_mask diff --git a/modules/ui.py b/modules/ui.py index f22da16a5..eb5fcd3fb 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -15,7 +15,6 @@ import warnings import gradio as gr import gradio.routes import gradio.utils -from gradio.events import Releaseable import numpy as np from PIL import Image, PngImagePlugin from modules.call_queue import wrap_gradio_gpu_call, wrap_queued_call, wrap_gradio_call @@ -128,26 +127,6 @@ def calc_resolution_hires(enable, width, height, hr_scale, hr_resize_x, hr_resiz return f"resize: from {p.width}x{p.height} to {p.hr_resize_x or p.hr_upscale_to_x}x{p.hr_resize_y or p.hr_upscale_to_y}" -def calc_resolution_img2img(mode, scale, resize_x, resize_y, resize_mode, *i2i_images): - init_img = None - if mode in {0, 1, 3, 4}: - init_img = i2i_images[mode] - elif mode == 2: - init_img = i2i_images[mode]["image"] - - if not init_img: - return "" - - if scale > 1: - width = int(init_img.width * scale) - height = int(init_img.height * scale) - else: - width = resize_x - height = resize_y - - return f"resize: from {init_img.width}x{init_img.height} to {width}x{height}" - - def apply_styles(prompt, prompt_neg, styles): prompt = shared.prompt_styles.apply_styles_to_prompt(prompt, styles) prompt_neg = shared.prompt_styles.apply_negative_styles_to_prompt(prompt_neg, styles) @@ -756,7 +735,7 @@ def create_ui(): ) with FormRow(): - resize_mode = gr.Radio(label="Resize mode", elem_id="resize_mode", choices=["Just resize", "Crop and resize", "Resize and fill"], type="index", value="Just resize") + resize_mode = gr.Radio(label="Resize mode", elem_id="resize_mode", choices=["Just resize", "Crop and resize", "Resize and fill", "Just resize (latent upscale)"], type="index", value="Just resize") for category in ordered_ui_categories(): if category == "sampler": @@ -765,13 +744,8 @@ def create_ui(): elif category == "dimensions": with FormRow(): with gr.Column(elem_id="img2img_column_size", scale=4): - with FormRow(variant="compact"): - final_resolution = FormHTML(value="", elem_id="img2img_finalres", label="Upscaled resolution", interactive=False) - with FormRow(variant="compact"): - scale = gr.Slider(minimum=1.0, maximum=4.0, step=0.05, label="Upscale by", value=1.0, elem_id="img2img_scale") - with FormRow(variant="compact"): - width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="img2img_width") - height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="img2img_height") + width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="img2img_width") + height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="img2img_height") with gr.Column(elem_id="img2img_dimensions_row", scale=1, elem_classes="dimensions-tools"): res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="img2img_res_switch_btn") @@ -786,9 +760,7 @@ def create_ui(): with FormRow(): cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='CFG Scale', value=7.0, elem_id="img2img_cfg_scale") image_cfg_scale = gr.Slider(minimum=0, maximum=3.0, step=0.05, label='Image CFG Scale', value=1.5, elem_id="img2img_image_cfg_scale", visible=shared.sd_model and shared.sd_model.cond_stage_key == "edit") - with FormRow(): - upscaler = gr.Dropdown(label="Upscaler", elem_id="img2img_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.75, elem_id="img2img_denoising_strength") + denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising strength', value=0.75, elem_id="img2img_denoising_strength") elif category == "seed": seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs('img2img') @@ -841,39 +813,6 @@ def create_ui(): outputs=[inpaint_controls, mask_alpha], ) - img2img_resolution_preview_inputs = [dummy_component, # filled in by selected img2img tab index in _js - scale, width, height, resize_mode, - init_img, sketch, init_img_with_mask, inpaint_color_sketch, init_img_inpaint] - for input in img2img_resolution_preview_inputs[1:]: - if isinstance(input, Releaseable): - input.release( - fn=calc_resolution_img2img, - _js="get_img2img_tab_index_for_res_preview", - inputs=img2img_resolution_preview_inputs, - outputs=[final_resolution], - show_progress=False, - ).success( - None, - _js="onCalcResolutionImg2Img", - inputs=img2img_resolution_preview_inputs, - outputs=[], - show_progress=False, - ) - else: - input.change( - fn=calc_resolution_img2img, - _js="get_img2img_tab_index_for_res_preview", - inputs=img2img_resolution_preview_inputs, - outputs=[final_resolution], - show_progress=False, - ).success( - None, - _js="onCalcResolutionImg2Img", - inputs=img2img_resolution_preview_inputs, - outputs=[], - show_progress=False, - ) - img2img_gallery, generation_info, html_info, html_log = create_output_panel("img2img", opts.outdir_img2img_samples) connect_reuse_seed(seed, reuse_seed, generation_info, dummy_component, is_subseed=False) @@ -922,8 +861,6 @@ def create_ui(): subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox, height, width, - scale, - upscaler, resize_mode, inpaint_full_res, inpaint_full_res_padding, @@ -1009,8 +946,6 @@ def create_ui(): (seed, "Seed"), (width, "Size-1"), (height, "Size-2"), - (scale, "Img2Img upscale"), - (upscaler, "Img2Img upscaler"), (batch_size, "Batch size"), (subseed, "Variation seed"), (subseed_strength, "Variation seed strength"), diff --git a/scripts/xyz_grid.py b/scripts/xyz_grid.py index 3f6c1997d..3895a795c 100644 --- a/scripts/xyz_grid.py +++ b/scripts/xyz_grid.py @@ -220,7 +220,6 @@ axis_options = [ AxisOption("Clip skip", int, apply_clip_skip), AxisOption("Denoising", float, apply_field("denoising_strength")), AxisOptionTxt2Img("Hires upscaler", str, apply_field("hr_upscaler"), choices=lambda: [*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]]), - AxisOptionImg2Img("Upscaler", str, apply_field("upscaler"), choices=lambda: [*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]]), AxisOptionImg2Img("Cond. Image Mask Weight", float, apply_field("inpainting_mask_weight")), AxisOption("VAE", str, apply_vae, cost=0.7, choices=lambda: list(sd_vae.vae_dict)), AxisOption("Styles", str, apply_styles, choices=lambda: list(shared.prompt_styles.styles)), diff --git a/style.css b/style.css index 379a89dc8..de16a7f2f 100644 --- a/style.css +++ b/style.css @@ -287,13 +287,13 @@ button.custom-button{ border-radius: 0 0.5rem 0.5rem 0; } -#txtimg_hr_finalres, #img2img_finalres { +#txtimg_hr_finalres{ min-height: 0 !important; padding: .625rem .75rem; margin-left: -0.75em } -#txtimg_hr_finalres .resolution, #img2img_finalres .resolution{ +#txtimg_hr_finalres .resolution{ font-weight: bold; } From 3856ada5cc9ac4124e20ff311ce7aa77330845d9 Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Tue, 28 Mar 2023 22:20:31 +0300 Subject: [PATCH 15/15] do not add mask blur to infotext if there is no mask --- modules/img2img.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/img2img.py b/modules/img2img.py index c973b7708..953ac5d2d 100644 --- a/modules/img2img.py +++ b/modules/img2img.py @@ -157,7 +157,8 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s if shared.cmd_opts.enable_console_prompts: print(f"\nimg2img: {prompt}", file=shared.progress_print_out) - p.extra_generation_params["Mask blur"] = mask_blur + if mask: + p.extra_generation_params["Mask blur"] = mask_blur if is_batch: assert not shared.cmd_opts.hide_ui_dir_config, "Launched with --hide-ui-dir-config, batch img2img disabled"