diff --git a/CHANGELOG.md b/CHANGELOG.md index 76324adc3..c77e2f486 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ And it also includes fixes for all reported issues so far - add **marigold** depth map processor this is state-of-the-art depth estimation model, but its quite heavy on resources - add **openpose xl** controlnet + - add blip/booru **interrogate** functionality to both input and output images - configurable output folder in settings - auto-refresh available models on tab activate - add image preview for override images set per-unit @@ -57,6 +58,8 @@ And it also includes fixes for all reported issues so far - **ui** - globally configurable font size will dynamically rescale ui depending on settings -> user interface + - modularized blip/booru interrogate + now appears as toolbuttons on image/gallery output - **server startup**: performance - faster extension load - faster json parsing diff --git a/html/locale_en.json b/html/locale_en.json index 91789b742..0807a2ab9 100644 --- a/html/locale_en.json +++ b/html/locale_en.json @@ -25,7 +25,9 @@ {"id":"","label":"🔎︎","localized":"","hint":"Scan CivitAI for missing metadata and previews"}, {"id":"","label":"☲","localized":"","hint":"Change view type"}, {"id":"","label":"📐","localized":"","hint":"Measure"}, - {"id":"","label":"🔍","localized":"","hint":"Search"} + {"id":"","label":"🔍","localized":"","hint":"Search"}, + {"id":"","label":"✎","localized":"","hint":"Interrogate image using BLIP model"}, + {"id":"","label":"✐","localized":"","hint":"Interrogate image using DeepBooru model"} ], "prompts": [ {"id":"","label":"Prompt","localized":"","hint":"Describe image you want to generate"}, diff --git a/javascript/black-teal.css b/javascript/black-teal.css index bc8073bd2..735f14f4b 100644 --- a/javascript/black-teal.css +++ b/javascript/black-teal.css @@ -102,10 +102,11 @@ svg.feather.feather-image, .feather .feather-image { display: none } /* gradio elements overrides */ #div.gradio-container { overflow-x: hidden; } #img2img_label_copy_to_img2img { font-weight: normal; } -#txt2img_prompt, #txt2img_neg_prompt, #img2img_prompt, #img2img_neg_prompt { background-color: var(--background-color); box-shadow: 4px 4px 4px 0px #333333 !important; } -#txt2img_prompt > label > textarea, #txt2img_neg_prompt > label > textarea, #img2img_prompt > label > textarea, #img2img_neg_prompt > label > textarea { font-size: 1.0em; line-height: 1.4em; } -#txt2img_styles, #img2img_styles { padding: 0; } -#txt2img_styles_refresh, #img2img_styles_refresh { padding: 0; margin-top: 1em; } + +#txt2img_prompt, #txt2img_neg_prompt, #img2img_prompt, #img2img_neg_prompt, #control_prompt, #control_neg_prompt { background-color: var(--background-color); box-shadow: 4px 4px 4px 0px #333333 !important; } +#txt2img_prompt > label > textarea, #txt2img_neg_prompt > label > textarea, #img2img_prompt > label > textarea, #img2img_neg_prompt > label > textarea, #control_prompt > label > textarea, #control_neg_prompt > label > textarea { font-size: 1.0em; line-height: 1.4em; } +#txt2img_styles, #img2img_styles, #control_styles { padding: 0; } +#txt2img_styles_refresh, #img2img_styles_refresh, #control_styles_refresh { padding: 0; margin-top: 1em; } #img2img_settings { min-width: calc(2 * var(--left-column)); max-width: calc(2 * var(--left-column)); background-color: #111111; padding-top: 16px; } #interrogate, #deepbooru { margin: 0 0px 10px 0px; max-width: 80px; max-height: 80px; font-weight: normal; font-size: 0.95em; } #quicksettings .gr-button-tool { font-size: 1.6rem; box-shadow: none; margin-left: -20px; margin-top: -2px; height: 2.4em; } @@ -116,14 +117,13 @@ svg.feather.feather-image, .feather .feather-image { display: none } #settings_search { margin-top: 1em; margin-left: 1em; } #settings_search textarea { padding: 0.5em; height: 2.2em !important; } #txt2img_cfg_scale { min-width: 200px; } -#txt2img_checkboxes, #img2img_checkboxes { background-color: transparent; } -#txt2img_checkboxes, #img2img_checkboxes { margin-bottom: 0.2em; } +#txt2img_checkboxes, #img2img_checkboxes, #control_checkboxes { background-color: transparent; margin-bottom: 0.2em; } textarea[rows="1"] { height: 33px !important; width: 99% !important; padding: 8px !important; } #extras_upscale { margin-top: 10px } #txt2img_progress_row > div { min-width: var(--left-column); max-width: var(--left-column); } #txt2img_settings { min-width: var(--left-column); max-width: var(--left-column); background-color: #111111; padding-top: 16px; } #pnginfo_html2_info { margin-top: -18px; background-color: var(--input-background-fill); padding: var(--input-padding) } -#txt2img_styles_row, #img2img_styles_row { margin-top: -6px; } +#txt2img_styles_row, #img2img_styles_row, #control_styles_row { margin-top: -6px; } /* based on gradio built-in dark theme */ :root, .light, .dark { diff --git a/javascript/light-teal.css b/javascript/light-teal.css index d77cb4ee4..7bfea1d38 100644 --- a/javascript/light-teal.css +++ b/javascript/light-teal.css @@ -100,10 +100,10 @@ svg.feather.feather-image, .feather .feather-image { display: none } /* gradio elements overrides */ #div.gradio-container { overflow-x: hidden; } #img2img_label_copy_to_img2img { font-weight: normal; } -#txt2img_prompt, #txt2img_neg_prompt, #img2img_prompt, #img2img_neg_prompt { background-color: var(--background-color); box-shadow: 4px 4px 4px 0px #333333 !important; } -#txt2img_prompt > label > textarea, #txt2img_neg_prompt > label > textarea, #img2img_prompt > label > textarea, #img2img_neg_prompt > label > textarea { font-size: 1.0em; line-height: 1.4em; } -#txt2img_styles, #img2img_styles { padding: 0; } -#txt2img_styles_refresh, #img2img_styles_refresh { padding: 0; margin-top: 1em; } +#txt2img_prompt, #txt2img_neg_prompt, #img2img_prompt, #img2img_neg_prompt, #control_prompt, #control_neg_prompt { background-color: var(--background-color); box-shadow: 4px 4px 4px 0px #333333 !important; } +#txt2img_prompt > label > textarea, #txt2img_neg_prompt > label > textarea, #img2img_prompt > label > textarea, #img2img_neg_prompt > label > textarea, #control_prompt > label > textarea, #control_neg_prompt > label > textarea { font-size: 1.0em; line-height: 1.4em; } +#txt2img_styles, #img2img_styles, #control_styles { padding: 0; } +#txt2img_styles_refresh, #img2img_styles_refresh, #control_styles_refresh { padding: 0; margin-top: 1em; } #img2img_settings { min-width: calc(2 * var(--left-column)); max-width: calc(2 * var(--left-column)); background-color: #111111; padding-top: 16px; } #interrogate, #deepbooru { margin: 0 0px 10px 0px; max-width: 80px; max-height: 80px; font-weight: normal; font-size: 0.95em; } #quicksettings .gr-button-tool { font-size: 1.6rem; box-shadow: none; margin-left: -20px; margin-top: -2px; height: 2.4em; } @@ -113,14 +113,13 @@ svg.feather.feather-image, .feather .feather-image { display: none } #settings > div.flex-wrap { width: 15em; } #tab_extensions table { background-color: #222222; } #txt2img_cfg_scale { min-width: 200px; } -#txt2img_checkboxes, #img2img_checkboxes { background-color: transparent; } -#txt2img_checkboxes, #img2img_checkboxes { margin-bottom: 0.2em; } +#txt2img_checkboxes, #img2img_checkboxes, #control_checkboxes { background-color: transparent; margin-bottom: 0.2em; } #extras_upscale { margin-top: 10px } #txt2img_progress_row > div { min-width: var(--left-column); max-width: var(--left-column); } #txt2img_settings { min-width: var(--left-column); max-width: var(--left-column); background-color: #111111; padding-top: 16px; } #pnginfo_html2_info { margin-top: -18px; background-color: var(--input-background-fill); padding: var(--input-padding) } -#txt2img_styles_row, #img2img_styles_row { margin-top: -6px; z-index: 200; } +#txt2img_styles_row, #img2img_styles_row, #control_styles_row { margin-top: -6px; } /* based on gradio built-in dark theme */ :root, .light, .dark { diff --git a/javascript/sdnext.css b/javascript/sdnext.css index 5b36464dd..fd93c6729 100644 --- a/javascript/sdnext.css +++ b/javascript/sdnext.css @@ -85,9 +85,12 @@ button.custom-button{ border-radius: var(--button-large-radius); padding: var(-- #txt2img_generate_line2>button, #img2img_generate_line2>button, #extras_generate_box>button, #control_generate_line2>button, #txt2img_tools>button, #img2img_tools>button, #control_tools>button { height: 2em; line-height: 0; font-size: var(--text-md); min-width: unset; display: block !important; } #txt2img_prompt, #txt2img_neg_prompt, #img2img_prompt, #img2img_neg_prompt, #control_prompt, #control_neg_prompt { display: contents; } -#txt2img_generate_box, #img2img_generate_box, #control_generate_box { min-width: unset; width: 48%; } +#txt2img_generate_box, #img2img_generate_box { min-width: unset; width: 48%; } +#control_generate_box { min-width: unset; width: 100%; } #txt2img_actions_column, #img2img_actions_column, #control_actions { flex-flow: wrap; justify-content: space-between; } #txt2img_enqueue_wrapper, #img2img_enqueue_wrapper, #control_enqueue_wrapper { min-width: unset !important; width: 48%; } +.interrogate-clip { position: absolute; right: 3em; top: -2.7em; max-width: fit-content; } +.interrogate-blip { position: absolute; right: 1em; top: -2.7em; max-width: fit-content; } .interrogate-col{ min-width: 0 !important; max-width: fit-content; margin-right: var(--spacing-xxl); } .interrogate-col>button{ flex: 1; width: 7em; max-height: 84px; } #sampler_selection_img2img { margin-top: 1em; } @@ -207,11 +210,11 @@ table.settings-value-table td { padding: 0.4em; border: 1px solid #ccc; max-widt .extra-network-cards .card:hover .overlay { background: rgba(0, 0, 0, 0.40); } .extra-network-cards .card .overlay .tags { display: none; overflow-wrap: break-word; } .extra-network-cards .card .overlay .tag { padding: 2px; margin: 2px; background: rgba(70, 70, 70, 0.60); font-size: var(--text-md); cursor: pointer; display: inline-block; } -.extra-network-cards .card .actions>span { padding: 4px; } +.extra-network-cards .card .actions>span { padding: 4px; font-size: 34px !important; } .extra-network-cards .card .actions>span:hover { color: var(--highlight-color); } .extra-network-cards .card:hover .actions { display: block; } .extra-network-cards .card:hover .overlay .tags { display: block; } -.extra-network-cards .card .actions { font-size: 3em; display: none; text-align-last: right; cursor: pointer; font-variant: unicase; position: absolute; z-index: 100; right: 0; height: 0.7em; width: 100%; background: rgba(0, 0, 0, 0.40); } +.extra-network-cards .card .actions { font-size: 3em; display: none; text-align-last: right; cursor: pointer; font-variant: unicase; position: absolute; z-index: 80; right: 0; height: 0.7em; width: 100%; background: rgba(0, 0, 0, 0.40); } .extra-network-cards .card-list { display: flex; margin: 0.3em; padding: 0.3em; background: var(--input-background-fill); cursor: pointer; border-radius: var(--button-large-radius); } .extra-network-cards .card-list .tag { color: var(--primary-500); margin-left: 0.8em; } .extra-details-close { position: fixed; top: 0.2em; right: 0.2em; z-index: 99; background: var(--button-secondary-background-fill) !important; } diff --git a/modules/deepbooru.py b/modules/deepbooru.py index 24f970a7d..8b822bf95 100644 --- a/modules/deepbooru.py +++ b/modules/deepbooru.py @@ -1,9 +1,8 @@ import os import re - import torch import numpy as np - +from PIL import Image from modules import modelloader, paths, deepbooru_model, devices, images, shared re_special = re.compile(r'([\\()])') @@ -54,6 +53,11 @@ class DeepDanbooru: alpha_sort = shared.opts.deepbooru_sort_alpha include_ranks = shared.opts.interrogate_return_ranks and not force_disable_ranks + if isinstance(pil_image, list): + pil_image = pil_image[0] + if isinstance(pil_image, dict) and 'name' in pil_image: + pil_image = Image.open(pil_image['name']) + pic = images.resize_image(2, pil_image.convert("RGB"), 512, 512) a = np.expand_dims(np.array(pic, dtype=np.float32), 0) / 255 diff --git a/modules/interrogate.py b/modules/interrogate.py index 1a60f728c..5a7b4ca18 100644 --- a/modules/interrogate.py +++ b/modules/interrogate.py @@ -5,6 +5,7 @@ from pathlib import Path import re import torch import torch.hub # pylint: disable=ungrouped-imports +from PIL import Image from torchvision import transforms from torchvision.transforms.functional import InterpolationMode from modules import devices, paths, shared, lowvram, modelloader, errors @@ -166,6 +167,11 @@ class InterrogateModels: lowvram.send_everything_to_cpu() devices.torch_gc() self.load() + if isinstance(pil_image, list): + pil_image = pil_image[0] + if isinstance(pil_image, dict) and 'name' in pil_image: + pil_image = Image.open(pil_image['name']) + pil_image = pil_image.convert("RGB") caption = self.generate_caption(pil_image) self.send_blip_to_ram() devices.torch_gc() diff --git a/modules/ui_common.py b/modules/ui_common.py index 9fb1a1902..4bd40b50a 100644 --- a/modules/ui_common.py +++ b/modules/ui_common.py @@ -7,7 +7,8 @@ import subprocess from functools import reduce import gradio as gr from modules import call_queue, shared, prompt_parser -from modules.generation_parameters_copypaste import image_from_url_text, parse_generation_parameters +from modules import generation_parameters_copypaste +from modules import ui_sections from modules.ui_components import FormRow, ToolButton import modules.ui_symbols as symbols import modules.images @@ -42,7 +43,7 @@ def plaintext_to_html(text): def infotext_to_html(text): - res = parse_generation_parameters(text) + res = generation_parameters_copypaste.parse_generation_parameters(text) prompt = res.get('Prompt', '') negative = res.get('Negative prompt', '') res.pop('Prompt', None) @@ -155,7 +156,7 @@ def save_files(js_data, images, html_info, index): shared.log.warning(f'Image description save failed: {filename_txt} {e}') modules.script_callbacks.image_save_btn_callback(tgt_filename) else: - image = image_from_url_text(filedata) + image = generation_parameters_copypaste.image_from_url_text(filedata) info = p.infotexts[i + 1] if len(p.infotexts) > len(p.all_seeds) else p.infotexts[i] # infotexts may be offset by 1 because the first image is the grid fullfn, txt_fullfn = modules.images.save_image(image, shared.opts.outdir_save, "", seed=p.all_seeds[i], prompt=p.all_prompts[i], info=info, extension=shared.opts.samples_format, grid=is_grid, p=p) if fullfn is None: @@ -203,15 +204,35 @@ def open_folder(result_gallery, gallery_index = 0): subprocess.Popen(["xdg-open", path]) # pylint: disable=consider-using-with -def create_output_panel(tabname, preview=True): - import modules.generation_parameters_copypaste as parameters_copypaste +def interrogate_clip(image): + if image is None: + shared.log.error("Interrogate: no image selected") + return gr.update() + prompt = shared.interrogator.interrogate(image) + return gr.update() if prompt is None else prompt + +def interrogate_booru(image): + if image is None: + shared.log.error("Interrogate: no image selected") + return gr.update() + from modules import deepbooru + prompt = deepbooru.model.tag(image) + return gr.update() if prompt is None else prompt + + +def create_output_panel(tabname, preview=True, prompt=None): with gr.Column(variant='panel', elem_id=f"{tabname}_results"): with gr.Group(elem_id=f"{tabname}_gallery_container"): if tabname == "txt2img": gr.HTML(value="", elem_id="main_info", visible=False, elem_classes=["main-info"]) # columns are for <576px, <768px, <992px, <1200px, <1400px, >1400px result_gallery = gr.Gallery(value=[], label='Output', show_label=False, show_download_button=True, allow_preview=True, elem_id=f"{tabname}_gallery", container=False, preview=preview, columns=5, object_fit='scale-down', height=shared.opts.gallery_height or None) + if prompt is not None: + interrogate_clip_btn, interrogate_booru_btn = ui_sections.create_interrogate_buttons('control') + interrogate_clip_btn.click(fn=interrogate_clip, inputs=[result_gallery], outputs=[prompt]) + interrogate_booru_btn.click(fn=interrogate_booru, inputs=[result_gallery], outputs=[prompt]) + with gr.Column(elem_id=f"{tabname}_footer", elem_classes="gallery_footer"): dummy_component = gr.Label(visible=False) @@ -225,9 +246,9 @@ def create_output_panel(tabname, preview=True): save = gr.Button('Save', elem_id=f'save_{tabname}') delete = gr.Button('Delete', elem_id=f'delete_{tabname}') if shared.backend == shared.Backend.ORIGINAL: - buttons = parameters_copypaste.create_buttons(["img2img", "inpaint", "extras"]) + buttons = generation_parameters_copypaste.create_buttons(["img2img", "inpaint", "extras"]) else: - buttons = parameters_copypaste.create_buttons(["img2img", "inpaint", "control", "extras"]) + buttons = generation_parameters_copypaste.create_buttons(["img2img", "inpaint", "control", "extras"]) download_files = gr.File(None, file_count="multiple", interactive=False, show_label=False, visible=False, elem_id=f'download_files_{tabname}') with gr.Group(): @@ -261,8 +282,8 @@ def create_output_panel(tabname, preview=True): paste_field_names = [] for paste_tabname, paste_button in buttons.items(): debug(f'Create output panel: button={paste_button} tabname={paste_tabname}') - bindings = parameters_copypaste.ParamBinding(paste_button=paste_button, tabname=paste_tabname, source_tabname=("txt2img" if tabname == "txt2img" else None), source_image_component=result_gallery, paste_field_names=paste_field_names) - parameters_copypaste.register_paste_params_button(bindings) + bindings = generation_parameters_copypaste.ParamBinding(paste_button=paste_button, tabname=paste_tabname, source_tabname=("txt2img" if tabname == "txt2img" else None), source_image_component=result_gallery, paste_field_names=paste_field_names) + generation_parameters_copypaste.register_paste_params_button(bindings) return result_gallery, generation_info, html_info, html_info_formatted, html_log diff --git a/modules/ui_control.py b/modules/ui_control.py index 0c81c5070..0d94c45d3 100644 --- a/modules/ui_control.py +++ b/modules/ui_control.py @@ -302,7 +302,7 @@ def create_ui(_blocks: gr.Blocks=None): return [(control_ui, 'Control', 'control')] with gr.Blocks(analytics_enabled = False) as control_ui: - prompt, styles, negative, btn_generate, _btn_interrogate, _btn_deepbooru, btn_paste, btn_extra, prompt_counter, btn_prompt_counter, negative_counter, btn_negative_counter = ui_sections.create_toprow(is_img2img=False, id_part='control') + prompt, styles, negative, btn_generate, btn_paste, btn_extra, prompt_counter, btn_prompt_counter, negative_counter, btn_negative_counter = ui_sections.create_toprow(is_img2img=False, id_part='control') with gr.Group(elem_id="control_interface", equal_height=False): with gr.Row(elem_id='control_settings'): @@ -367,6 +367,7 @@ def create_ui(_blocks: gr.Blocks=None): input_image = gr.Image(label="Input", show_label=False, type="pil", source="upload", interactive=True, tool="editor", height=gr_height, visible=True, image_mode='RGB', elem_id='control_input_select') input_resize = gr.Image(label="Input", show_label=False, type="pil", source="upload", interactive=True, tool="select", height=gr_height, visible=False, image_mode='RGB', elem_id='control_input_resize') input_inpaint = gr.Image(label="Input", show_label=False, type="pil", source="upload", interactive=True, tool="sketch", height=gr_height, visible=False, image_mode='RGB', elem_id='control_input_inpaint', brush_radius=64, mask_opacity=0.6) + interrogate_clip, interrogate_booru = ui_sections.create_interrogate_buttons('control') with gr.Row(): input_buttons = [gr.Button('Select', visible=True, interactive=False), gr.Button('Inpaint', visible=True, interactive=True), gr.Button('Outpaint', visible=True, interactive=True)] with gr.Tab('Video', id='in-video') as tab_video: @@ -390,7 +391,7 @@ def create_ui(_blocks: gr.Blocks=None): gr.HTML('Output

') with gr.Tabs(elem_classes=['control-tabs'], elem_id='control-tab-output') as output_tabs: with gr.Tab('Gallery', id='out-gallery'): - output_gallery, _output_gen_info, _output_html_info, _output_html_info_formatted, _output_html_log = ui_common.create_output_panel("control", preview=True) + output_gallery, _output_gen_info, _output_html_info, _output_html_info_formatted, _output_html_log = ui_common.create_output_panel("control", preview=True, prompt=prompt) with gr.Tab('Image', id='out-image'): output_image = gr.Image(label="Input", show_label=False, type="pil", interactive=False, tool="editor", height=gr_height) with gr.Tab('Video', id='out-video'): @@ -676,6 +677,8 @@ def create_ui(_blocks: gr.Blocks=None): input_type.change(fn=lambda x: gr.update(visible=x == 2), inputs=[input_type], outputs=[column_init]) btn_prompt_counter.click(fn=call_queue.wrap_queued_call(ui_common.update_token_counter), inputs=[prompt, steps], outputs=[prompt_counter]) btn_negative_counter.click(fn=call_queue.wrap_queued_call(ui_common.update_token_counter), inputs=[negative, steps], outputs=[negative_counter]) + interrogate_clip.click(fn=ui_common.interrogate_clip, inputs=[input_image], outputs=[prompt]) + interrogate_booru.click(fn=ui_common.interrogate_booru, inputs=[input_image], outputs=[prompt]) select_fields = [input_mode, input_image, init_image, input_type, input_resize, input_inpaint, input_video, input_batch, input_folder, mask_blur, mask_overlap] select_output = [output_tabs, result_txt] diff --git a/modules/ui_img2img.py b/modules/ui_img2img.py index f3d29065a..109f7606f 100644 --- a/modules/ui_img2img.py +++ b/modules/ui_img2img.py @@ -33,27 +33,13 @@ def process_interrogate(interrogation_function, mode, ii_input_files, ii_input_d return [gr.update(), None] -def interrogate(image): - if image is None: - shared.log.error("Interrogate: no image selected") - return gr.update() - prompt = shared.interrogator.interrogate(image.convert("RGB")) - return gr.update() if prompt is None else prompt - - -def interrogate_deepbooru(image): - from modules import deepbooru - prompt = deepbooru.model.tag(image) - return gr.update() if prompt is None else prompt - - def create_ui(): shared.log.debug('UI initialize: img2img') import modules.img2img # pylint: disable=redefined-outer-name modules.scripts.scripts_current = modules.scripts.scripts_img2img modules.scripts.scripts_img2img.initialize_scripts(is_img2img=True) with gr.Blocks(analytics_enabled=False) as _img2img_interface: - img2img_prompt, img2img_prompt_styles, img2img_negative_prompt, submit, img2img_interrogate, img2img_deepbooru, img2img_paste, img2img_extra_networks_button, img2img_token_counter, img2img_token_button, img2img_negative_token_counter, img2img_negative_token_button = ui_sections.create_toprow(is_img2img=True, id_part="img2img") + img2img_prompt, img2img_prompt_styles, img2img_negative_prompt, submit, img2img_paste, img2img_extra_networks_button, img2img_token_counter, img2img_token_button, img2img_negative_token_counter, img2img_negative_token_button = ui_sections.create_toprow(is_img2img=True, id_part="img2img") img2img_prompt_img = gr.File(label="", elem_id="img2img_prompt_image", file_count="single", type="binary", visible=False) with FormRow(variant='compact', elem_id="img2img_extra_networks", visible=False) as extra_networks_ui: @@ -70,7 +56,7 @@ def create_ui(): def add_copy_image_controls(tab_name, elem): with gr.Row(variant="compact", elem_id=f"img2img_copy_to_{tab_name}"): - for title, name in zip(['➠ Image', '➠ Sketch', '➠ Inpaint', '➠ Inpaint sketch'], ['img2img', 'sketch', 'inpaint', 'inpaint_sketch']): + for title, name in zip(['➠ Image', '➠ Sketch', '➠ Inpaint', '➠ Composite'], ['img2img', 'sketch', 'inpaint', 'inpaint_sketch']): if name == tab_name: gr.Button(title, interactive=False) copy_image_destinations[name] = elem @@ -82,6 +68,7 @@ def create_ui(): img2img_selected_tab = gr.State(0) # pylint: disable=abstract-class-instantiated with gr.TabItem('Image', id='img2img', elem_id="img2img_img2img_tab") as tab_img2img: init_img = gr.Image(label="Image for img2img", elem_id="img2img_image", show_label=False, source="upload", interactive=True, type="pil", tool="editor", image_mode="RGBA", height=512) + interrogate_clip, interrogate_booru = ui_sections.create_interrogate_buttons('img2img') add_copy_image_controls('img2img', init_img) with gr.TabItem('Sketch', id='img2img_sketch', elem_id="img2img_img2img_sketch_tab") as tab_sketch: @@ -92,7 +79,7 @@ def create_ui(): init_img_with_mask = gr.Image(label="Image for inpainting with mask", show_label=False, elem_id="img2maskimg", source="upload", interactive=True, type="pil", tool="sketch", image_mode="RGBA", height=512) add_copy_image_controls('inpaint', init_img_with_mask) - with gr.TabItem('Inpaint sketch', id='inpaint_sketch', elem_id="img2img_inpaint_sketch_tab") as tab_inpaint_color: + with gr.TabItem('Composite', id='inpaint_sketch', elem_id="img2img_inpaint_sketch_tab") as tab_inpaint_color: inpaint_color_sketch = gr.Image(label="Color sketch inpainting", show_label=False, elem_id="inpaint_sketch", source="upload", interactive=True, type="pil", tool="color-sketch", image_mode="RGBA", height=512) inpaint_color_sketch_orig = gr.State(None) # pylint: disable=abstract-class-instantiated add_copy_image_controls('inpaint_sketch', inpaint_color_sketch) @@ -107,7 +94,7 @@ def create_ui(): inpaint_color_sketch.change(update_orig, [inpaint_color_sketch, inpaint_color_sketch_orig], inpaint_color_sketch_orig) - with gr.TabItem('Inpaint upload', id='inpaint_upload', elem_id="img2img_inpaint_upload_tab") as tab_inpaint_upload: + with gr.TabItem('Upload', id='inpaint_upload', elem_id="img2img_inpaint_upload_tab") as tab_inpaint_upload: init_img_inpaint = gr.Image(label="Image for img2img", show_label=False, source="upload", interactive=True, type="pil", elem_id="img_inpaint_base") init_mask_inpaint = gr.Image(label="Mask", source="upload", interactive=True, type="pil", elem_id="img_inpaint_mask") @@ -172,7 +159,7 @@ def create_ui(): with FormGroup(elem_id="img2img_script_container"): img2img_script_inputs = modules.scripts.scripts_img2img.setup_ui(parent='img2img', accordion=True) - img2img_gallery, img2img_generation_info, img2img_html_info, _img2img_html_info_formatted, img2img_html_log = ui_common.create_output_panel("img2img") + img2img_gallery, img2img_generation_info, img2img_html_info, _img2img_html_info_formatted, img2img_html_log = ui_common.create_output_panel("img2img", prompt=None) ui_common.connect_reuse_seed(seed, reuse_seed, img2img_generation_info, is_subseed=False) ui_common.connect_reuse_seed(subseed, reuse_subseed, img2img_generation_info, is_subseed=True) @@ -242,8 +229,8 @@ def create_ui(): ], outputs=[img2img_prompt, dummy_component], ) - img2img_interrogate.click(fn=lambda *args: process_interrogate(interrogate, *args), **interrogate_args) - img2img_deepbooru.click(fn=lambda *args: process_interrogate(interrogate_deepbooru, *args), **interrogate_args) + interrogate_clip.click(fn=lambda *args: process_interrogate(ui_common.interrogate_clip, *args), **interrogate_args) + interrogate_booru.click(fn=lambda *args: process_interrogate(ui_common.interrogate_booru, *args), **interrogate_args) img2img_token_button.click(fn=wrap_queued_call(ui_common.update_token_counter), inputs=[img2img_prompt, steps], outputs=[img2img_token_counter]) img2img_negative_token_button.click(fn=wrap_queued_call(ui_common.update_token_counter), inputs=[img2img_negative_prompt, steps], outputs=[img2img_negative_token_counter]) diff --git a/modules/ui_sections.py b/modules/ui_sections.py index 44f0df1ea..d33190c59 100644 --- a/modules/ui_sections.py +++ b/modules/ui_sections.py @@ -25,12 +25,6 @@ def create_toprow(is_img2img: bool = False, id_part: str = None): with gr.Column(scale=80): with gr.Row(): negative_prompt = gr.Textbox(elem_id=f"{id_part}_neg_prompt", label="Negative prompt", show_label=False, lines=3, placeholder="Negative prompt", elem_classes=["prompt"]) - button_interrogate = None - button_deepbooru = None - if is_img2img: - with gr.Column(scale=1, elem_classes="interrogate-col"): - button_interrogate = gr.Button('Interrogate\nCLIP', elem_id=f"{id_part}_interrogate") - button_deepbooru = gr.Button('Interrogate\nDeepBooru', elem_id=f"{id_part}_deepbooru") with gr.Column(scale=1, elem_id=f"{id_part}_actions_column"): with gr.Row(elem_id=f"{id_part}_generate_box"): submit = gr.Button('Generate', elem_id=f"{id_part}_generate", variant='primary') @@ -60,7 +54,13 @@ def create_toprow(is_img2img: bool = False, id_part: str = None): styles_btn_select.click(_js="applyStyles", fn=parse_style, inputs=[styles], outputs=[styles]) styles_btn_apply = ToolButton(ui_symbols.apply, elem_id=f"{id_part}_extra_apply", visible=False) styles_btn_apply.click(fn=apply_styles, inputs=[prompt, negative_prompt, styles], outputs=[prompt, negative_prompt, styles]) - return prompt, styles, negative_prompt, submit, button_interrogate, button_deepbooru, button_paste, button_extra, token_counter, token_button, negative_token_counter, negative_token_button + return prompt, styles, negative_prompt, submit, button_paste, button_extra, token_counter, token_button, negative_token_counter, negative_token_button + + +def create_interrogate_buttons(tab): + button_interrogate = gr.Button(ui_symbols.int_clip, elem_id=f"{tab}_interrogate", elem_classes=['interrogate-clip']) + button_deepbooru = gr.Button(ui_symbols.int_blip, elem_id=f"{tab}_deepbooru", elem_classes=['interrogate-blip']) + return button_interrogate, button_deepbooru def create_sampler_inputs(tab, accordion=True): diff --git a/modules/ui_txt2img.py b/modules/ui_txt2img.py index 224443f10..d03010fcf 100644 --- a/modules/ui_txt2img.py +++ b/modules/ui_txt2img.py @@ -21,7 +21,7 @@ def create_ui(): modules.scripts.scripts_current = modules.scripts.scripts_txt2img modules.scripts.scripts_txt2img.initialize_scripts(is_img2img=False) with gr.Blocks(analytics_enabled=False) as _txt2img_interface: - txt2img_prompt, txt2img_prompt_styles, txt2img_negative_prompt, txt2img_submit, _interrogate, _deepbooru, txt2img_paste, txt2img_extra_networks_button, txt2img_token_counter, txt2img_token_button, txt2img_negative_token_counter, txt2img_negative_token_button = ui_sections.create_toprow(is_img2img=False, id_part="txt2img") + txt2img_prompt, txt2img_prompt_styles, txt2img_negative_prompt, txt2img_submit, txt2img_paste, txt2img_extra_networks_button, txt2img_token_counter, txt2img_token_button, txt2img_negative_token_counter, txt2img_negative_token_button = ui_sections.create_toprow(is_img2img=False, id_part="txt2img") txt_prompt_img = gr.File(label="", elem_id="txt2img_prompt_image", file_count="single", type="binary", visible=False) txt_prompt_img.change(fn=modules.images.image_data, inputs=[txt_prompt_img], outputs=[txt2img_prompt, txt_prompt_img]) @@ -61,7 +61,7 @@ def create_ui(): show_progress=False, ) - txt2img_gallery, txt2img_generation_info, txt2img_html_info, _txt2img_html_info_formatted, txt2img_html_log = ui_common.create_output_panel("txt2img") + txt2img_gallery, txt2img_generation_info, txt2img_html_info, _txt2img_html_info_formatted, txt2img_html_log = ui_common.create_output_panel("txt2img", preview=True, prompt=None) ui_common.connect_reuse_seed(seed, reuse_seed, txt2img_generation_info, is_subseed=False) ui_common.connect_reuse_seed(subseed, reuse_subseed, txt2img_generation_info, is_subseed=True)