From 91643f651d2794349876b12abbf2449cdc4f30b6 Mon Sep 17 00:00:00 2001 From: William Moorehouse Date: Sun, 25 Sep 2022 19:22:12 -0400 Subject: Add support for checkpoint merging --- modules/ui.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'modules/ui.py') diff --git a/modules/ui.py b/modules/ui.py index f7ca5588..6b3ba2f7 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -393,7 +393,7 @@ def setup_progressbar(progressbar, preview, id_part): ) -def create_ui(txt2img, img2img, run_extras, run_pnginfo): +def create_ui(txt2img, img2img, run_extras, run_pnginfo, run_modelmerger): with gr.Blocks(analytics_enabled=False) as txt2img_interface: txt2img_prompt, roll, txt2img_prompt_style, txt2img_negative_prompt, txt2img_prompt_style2, submit, _, txt2img_prompt_style_apply, txt2img_save_style, paste = create_toprow(is_img2img=False) dummy_component = gr.Label(visible=False) @@ -853,6 +853,31 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): outputs=[html, generation_info, html2], ) + with gr.Blocks() as modelmerger_interface: + with gr.Row().style(equal_height=False): + with gr.Column(variant='panel'): + gr.HTML(value="

A merger of the two checkpoints will be generated in your /models directory.

") + + modelname_0 = gr.Textbox(elem_id="modelmerger_modelname_0", label="Model Name (to)") + modelname_1 = gr.Textbox(elem_id="modelmerger_modelname_1", label="Model Name (from)") + alpha = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, label='Alpha', value=0.3) + submit = gr.Button(elem_id="modelmerger_merge", label="Merge", variant='primary') + + with gr.Column(variant='panel'): + submit_result = gr.HTML(elem_id="modelmerger_result") + + submit.click( + fn=run_modelmerger, + inputs=[ + modelname_0, + modelname_1, + alpha + ], + outputs=[ + submit_result, + ] + ) + def create_setting_component(key): def fun(): return opts.data[key] if key in opts.data else opts.data_labels[key].default @@ -950,6 +975,7 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): (img2img_interface, "img2img", "img2img"), (extras_interface, "Extras", "extras"), (pnginfo_interface, "PNG Info", "pnginfo"), + (modelmerger_interface, "Checkpoint Merger", "modelmerger"), (settings_interface, "Settings", "settings"), ] -- cgit v1.2.3 From db4ab47f09450cbeb454a6e02698cb636a456878 Mon Sep 17 00:00:00 2001 From: Liam Date: Sun, 25 Sep 2022 16:09:43 -0400 Subject: copy over fields when sending to img2img: https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/1029 --- modules/ui.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'modules/ui.py') diff --git a/modules/ui.py b/modules/ui.py index f7ca5588..d2402e28 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -978,18 +978,21 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): outputs=[result, text_settings], ) + paste_field_names = ['Prompt', 'Negative prompt', 'Steps', 'Face restoration', 'Seed', 'Size-1', 'Size-2'] + txt2img_fields = [field for field,name in txt2img_paste_fields if name in paste_field_names] + img2img_fields = [field for field,name in img2img_paste_fields if name in paste_field_names] send_to_img2img.click( - fn=lambda x: (image_from_url_text(x)), - _js="extract_image_from_gallery_img2img", - inputs=[txt2img_gallery], - outputs=[init_img], + fn=lambda img, *args: (image_from_url_text(img),*args), + _js="(gallery, ...args) => [extract_image_from_gallery_img2img(gallery), ...args]", + inputs=[txt2img_gallery] + txt2img_fields, + outputs=[init_img] + img2img_fields, ) send_to_inpaint.click( - fn=lambda x: (image_from_url_text(x)), - _js="extract_image_from_gallery_inpaint", - inputs=[txt2img_gallery], - outputs=[init_img_with_mask], + fn=lambda x, *args: (image_from_url_text(x), *args), + _js="(gallery, ...args) => [extract_image_from_gallery_inpaint(gallery), ...args]", + inputs=[txt2img_gallery] + txt2img_fields, + outputs=[init_img_with_mask] + img2img_fields, ) img2img_send_to_img2img.click( -- cgit v1.2.3 From dc11748dea36e7618a7cdad55526fa9d6faaa6cf Mon Sep 17 00:00:00 2001 From: William Moorehouse Date: Mon, 26 Sep 2022 10:50:21 -0400 Subject: Added smoothstep interpolation to checkpoint merging --- modules/extras.py | 19 +++++++++++++++++-- modules/ui.py | 6 ++++-- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'modules/ui.py') diff --git a/modules/extras.py b/modules/extras.py index 2c5b1fd6..a9788e7d 100644 --- a/modules/extras.py +++ b/modules/extras.py @@ -139,16 +139,31 @@ def run_pnginfo(image): return '', geninfo, info -def run_modelmerger(modelname_0, modelname_1, alpha): +def run_modelmerger(modelname_0, modelname_1, interp_method, interp_amount): + # Linear interpolation (https://en.wikipedia.org/wiki/Linear_interpolation) + def weighted_sum(theta0, theta1, alpha): + return ((1 - alpha) * theta0) + (alpha * theta1) + + # Smoothstep (https://en.wikipedia.org/wiki/Smoothstep) + def sigmoid(theta0, theta1, alpha): + alpha = alpha * alpha * (3 - (2 * alpha)) + return theta0 + ((theta1 - theta0) * alpha) + model_0 = torch.load('models/' + modelname_0 + '.ckpt') model_1 = torch.load('models/' + modelname_1 + '.ckpt') theta_0 = model_0['state_dict'] theta_1 = model_1['state_dict'] + theta_func = weighted_sum + + if interp_method == "Weighted Sum": + theta_func = weighted_sum + if interp_method == "Sigmoid": + theta_func = sigmoid for key in theta_0.keys(): if 'model' in key and key in theta_1: - theta_0[key] = (1 - alpha) * theta_0[key] + alpha * theta_1[key] + theta_0[key] = theta_func(theta_0[key], theta_1[key], interp_amount) for key in theta_1.keys(): if 'model' in key and key not in theta_0: diff --git a/modules/ui.py b/modules/ui.py index 6b3ba2f7..6525676c 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -860,7 +860,8 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo, run_modelmerger): modelname_0 = gr.Textbox(elem_id="modelmerger_modelname_0", label="Model Name (to)") modelname_1 = gr.Textbox(elem_id="modelmerger_modelname_1", label="Model Name (from)") - alpha = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, label='Alpha', value=0.3) + interp_method = gr.Radio(choices=["Weighted Sum", "Sigmoid"], value="Weighted Sum", label="Interpolation Method") + interp_amount = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, label='Interpolation Amount', value=0.3) submit = gr.Button(elem_id="modelmerger_merge", label="Merge", variant='primary') with gr.Column(variant='panel'): @@ -871,7 +872,8 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo, run_modelmerger): inputs=[ modelname_0, modelname_1, - alpha + interp_method, + interp_amount ], outputs=[ submit_result, -- cgit v1.2.3 From 2846ca57028cca1a9ce9cee66d2500b4ac38a9c6 Mon Sep 17 00:00:00 2001 From: Connum Date: Mon, 26 Sep 2022 22:57:31 +0200 Subject: adds support for a notification.mp3 in the root directory that will play upon completion (fixes #1013) --- .gitignore | 3 ++- javascript/notification.js | 3 +++ modules/ui.py | 9 ++++++--- 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'modules/ui.py') diff --git a/.gitignore b/.gitignore index 9d78853a..3e266baf 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ __pycache__ /webui-user.sh /interrogate /user.css -/.idea \ No newline at end of file +/.idea +notification.mp3 diff --git a/javascript/notification.js b/javascript/notification.js index e8159a7e..bdf614ad 100644 --- a/javascript/notification.js +++ b/javascript/notification.js @@ -25,6 +25,9 @@ onUiUpdate(function(){ lastHeadImg = headImg; + // play notification sound if available + gradioApp().querySelector('#audio_notification audio')?.play(); + if (document.hasFocus()) return; // Multiple copies of the images are in the DOM when one is selected. Dedup with a Set to get the real number generated. diff --git a/modules/ui.py b/modules/ui.py index d2402e28..efd46708 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -564,13 +564,13 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): with gr.TabItem('Inpaint', id='inpaint'): 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") - init_img_inpaint = gr.Image(label="Image for img2img", show_label=False, source="upload", interactive=True, type="pil", visible=False) - init_mask_inpaint = gr.Image(label="Mask", source="upload", interactive=True, type="pil", visible=False) + init_img_inpaint = gr.Image(label="Image for img2img", show_label=False, source="upload", interactive=True, type="pil", visible=False, elem_id="img_inpaint_base") + init_mask_inpaint = gr.Image(label="Mask", source="upload", interactive=True, type="pil", visible=False, elem_id="img_inpaint_mask") mask_blur = gr.Slider(label='Mask blur', minimum=0, maximum=64, step=1, value=4) with gr.Row(): - mask_mode = gr.Radio(label="Mask mode", show_label=False, choices=["Draw mask", "Upload mask"], type="index", value="Draw mask") + mask_mode = gr.Radio(label="Mask mode", show_label=False, choices=["Draw mask", "Upload mask"], type="index", value="Draw mask", elem_id="mask_mode") inpainting_mask_invert = gr.Radio(label='Masking mode', show_label=False, choices=['Inpaint masked', 'Inpaint not masked'], value='Inpaint masked', type="index") inpainting_fill = gr.Radio(label='Masked content', choices=['fill', 'original', 'latent noise', 'latent nothing'], value='fill', type="index") @@ -970,6 +970,9 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): for interface, label, ifid in interfaces: with gr.TabItem(label, id=ifid): interface.render() + + if os.path.exists(os.path.join(script_path, "notification.mp3")): + audio_notification = gr.Audio(interactive=False, value=os.path.join(script_path, "notification.mp3"), elem_id="audio_notification", visible=False) text_settings = gr.Textbox(elem_id="settings_json", value=lambda: opts.dumpjson(), visible=False) settings_submit.click( -- cgit v1.2.3 From ada901ed661a717c44281d640b8fc0a275d4cb48 Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Tue, 27 Sep 2022 10:44:00 +0300 Subject: added console outputs, more clear indication of progress, and ability to specify full filename to checkpoint merger restore "Loading..." text --- modules/extras.py | 48 +++++++++++++++++++++++++++++++++--------------- modules/ui.py | 3 ++- 2 files changed, 35 insertions(+), 16 deletions(-) (limited to 'modules/ui.py') diff --git a/modules/extras.py b/modules/extras.py index a9788e7d..15873204 100644 --- a/modules/extras.py +++ b/modules/extras.py @@ -4,6 +4,7 @@ import numpy as np from PIL import Image import torch +import tqdm from modules import processing, shared, images, devices from modules.shared import opts @@ -149,28 +150,45 @@ def run_modelmerger(modelname_0, modelname_1, interp_method, interp_amount): alpha = alpha * alpha * (3 - (2 * alpha)) return theta0 + ((theta1 - theta0) * alpha) - model_0 = torch.load('models/' + modelname_0 + '.ckpt') - model_1 = torch.load('models/' + modelname_1 + '.ckpt') + if os.path.exists(modelname_0): + model0_filename = modelname_0 + modelname_0 = os.path.splitext(os.path.basename(modelname_0))[0] + else: + model0_filename = 'models/' + modelname_0 + '.ckpt' + + if os.path.exists(modelname_1): + model1_filename = modelname_1 + modelname_1 = os.path.splitext(os.path.basename(modelname_1))[0] + else: + model1_filename = 'models/' + modelname_1 + '.ckpt' + + print(f"Loading {model0_filename}...") + model_0 = torch.load(model0_filename, map_location='cpu') + + print(f"Loading {model1_filename}...") + model_1 = torch.load(model1_filename, map_location='cpu') theta_0 = model_0['state_dict'] theta_1 = model_1['state_dict'] - theta_func = weighted_sum - - if interp_method == "Weighted Sum": - theta_func = weighted_sum - if interp_method == "Sigmoid": - theta_func = sigmoid - - for key in theta_0.keys(): + + theta_funcs = { + "Weighted Sum": weighted_sum, + "Sigmoid": sigmoid, + } + theta_func = theta_funcs[interp_method] + + print(f"Merging...") + for key in tqdm.tqdm(theta_0.keys()): if 'model' in key and key in theta_1: theta_0[key] = theta_func(theta_0[key], theta_1[key], interp_amount) for key in theta_1.keys(): if 'model' in key and key not in theta_0: theta_0[key] = theta_1[key] - - output_modelname = 'models/' + modelname_0 + '-' + modelname_1 + '-merged.ckpt'; - + + output_modelname = 'models/' + modelname_0 + '-' + modelname_1 + '-merged.ckpt' + print(f"Saving to {output_modelname}...") torch.save(model_0, output_modelname) - - return "

Model saved to " + output_modelname + "

" + + print(f"Checkpoint saved.") + return "Checkpoint saved to " + output_modelname diff --git a/modules/ui.py b/modules/ui.py index 5476c32f..e96109c9 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -49,6 +49,7 @@ 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..." } .progress-bar { display:none!important; } .meta-text { display:none!important; } """ @@ -865,7 +866,7 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo, run_modelmerger): submit = gr.Button(elem_id="modelmerger_merge", label="Merge", variant='primary') with gr.Column(variant='panel'): - submit_result = gr.HTML(elem_id="modelmerger_result") + submit_result = gr.Textbox(elem_id="modelmerger_result", show_label=False) submit.click( fn=run_modelmerger, -- cgit v1.2.3