diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/extras.py | 25 | ||||
-rw-r--r-- | modules/images_history.py | 18 | ||||
-rw-r--r-- | modules/ngrok.py | 8 | ||||
-rw-r--r-- | modules/processing.py | 15 | ||||
-rw-r--r-- | modules/shared.py | 1 | ||||
-rw-r--r-- | modules/textual_inversion/textual_inversion.py | 1 | ||||
-rw-r--r-- | modules/ui.py | 75 |
7 files changed, 93 insertions, 50 deletions
diff --git a/modules/extras.py b/modules/extras.py index f2f5a7b0..0819ed37 100644 --- a/modules/extras.py +++ b/modules/extras.py @@ -20,26 +20,40 @@ import gradio as gr cached_images = {}
-def run_extras(extras_mode, resize_mode, image, image_folder, gfpgan_visibility, codeformer_visibility, codeformer_weight, upscaling_resize, upscaling_resize_w, upscaling_resize_h, upscaling_crop, extras_upscaler_1, extras_upscaler_2, extras_upscaler_2_visibility):
+def run_extras(extras_mode, resize_mode, image, image_folder, input_dir, output_dir, show_extras_results, gfpgan_visibility, codeformer_visibility, codeformer_weight, upscaling_resize, upscaling_resize_w, upscaling_resize_h, upscaling_crop, extras_upscaler_1, extras_upscaler_2, extras_upscaler_2_visibility):
devices.torch_gc()
imageArr = []
# Also keep track of original file names
imageNameArr = []
-
+ outputs = []
+
if extras_mode == 1:
#convert file to pillow image
for img in image_folder:
image = Image.open(img)
imageArr.append(image)
imageNameArr.append(os.path.splitext(img.orig_name)[0])
+ elif extras_mode == 2:
+ assert not shared.cmd_opts.hide_ui_dir_config, '--hide-ui-dir-config option must be disabled'
+
+ if input_dir == '':
+ return outputs, "Please select an input directory.", ''
+ image_list = [file for file in [os.path.join(input_dir, x) for x in os.listdir(input_dir)] if os.path.isfile(file)]
+ for img in image_list:
+ image = Image.open(img)
+ imageArr.append(image)
+ imageNameArr.append(img)
else:
imageArr.append(image)
imageNameArr.append(None)
- outpath = opts.outdir_samples or opts.outdir_extras_samples
+ if extras_mode == 2 and output_dir != '':
+ outpath = output_dir
+ else:
+ outpath = opts.outdir_samples or opts.outdir_extras_samples
- outputs = []
+
for image, image_name in zip(imageArr, imageNameArr):
if image is None:
return outputs, "Please select an input image.", ''
@@ -112,7 +126,8 @@ def run_extras(extras_mode, resize_mode, image, image_folder, gfpgan_visibility, image.info = existing_pnginfo
image.info["extras"] = info
- outputs.append(image)
+ if extras_mode != 2 or show_extras_results :
+ outputs.append(image)
devices.torch_gc()
diff --git a/modules/images_history.py b/modules/images_history.py index 9260df8a..46b23e56 100644 --- a/modules/images_history.py +++ b/modules/images_history.py @@ -1,6 +1,6 @@ import os import shutil - +import sys def traverse_all_files(output_dir, image_list, curr_dir=None): curr_path = output_dir if curr_dir is None else os.path.join(output_dir, curr_dir) @@ -24,10 +24,14 @@ def traverse_all_files(output_dir, image_list, curr_dir=None): def get_recent_images(dir_name, page_index, step, image_index, tabname): page_index = int(page_index) - f_list = os.listdir(dir_name) image_list = [] - image_list = traverse_all_files(dir_name, image_list) - image_list = sorted(image_list, key=lambda file: -os.path.getctime(os.path.join(dir_name, file))) + if not os.path.exists(dir_name): + pass + elif os.path.isdir(dir_name): + image_list = traverse_all_files(dir_name, image_list) + image_list = sorted(image_list, key=lambda file: -os.path.getctime(os.path.join(dir_name, file))) + else: + print(f'ERROR: "{dir_name}" is not a directory. Check the path in the settings.', file=sys.stderr) num = 48 if tabname != "extras" else 12 max_page_index = len(image_list) // num + 1 page_index = max_page_index if page_index == -1 else page_index + step @@ -105,10 +109,8 @@ def show_images_history(gr, opts, tabname, run_pnginfo, switch_dict): dir_name = opts.outdir_img2img_samples elif tabname == "extras": dir_name = opts.outdir_extras_samples - d = dir_name.split("/") - dir_name = "/" if dir_name.startswith("/") else d[0] - for p in d[1:]: - dir_name = os.path.join(dir_name, p) + else: + return with gr.Row(): renew_page = gr.Button('Renew Page', elem_id=tabname + "_images_history_renew_page") first_page = gr.Button('First Page') diff --git a/modules/ngrok.py b/modules/ngrok.py index 7d03a6df..5c5f349a 100644 --- a/modules/ngrok.py +++ b/modules/ngrok.py @@ -1,12 +1,14 @@ from pyngrok import ngrok, conf, exception -def connect(token, port): +def connect(token, port, region): if token == None: token = 'None' - conf.get_default().auth_token = token + config = conf.PyngrokConfig( + auth_token=token, region=region + ) try: - public_url = ngrok.connect(port).public_url + public_url = ngrok.connect(port, pyngrok_config=config).public_url except exception.PyngrokNgrokError: print(f'Invalid ngrok authtoken, ngrok connection aborted.\n' f'Your token: {token}, get the right one on https://dashboard.ngrok.com/get-started/your-authtoken') diff --git a/modules/processing.py b/modules/processing.py index 685f9fcd..6c4bde6e 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -53,11 +53,7 @@ def get_correct_sampler(p): class StableDiffusionProcessing:
- def __init__(self, sd_model=None, outpath_samples=None, outpath_grids=None, prompt="", styles=None, seed=-1,
- subseed=-1, subseed_strength=0, seed_resize_from_h=-1, seed_resize_from_w=-1, seed_enable_extras=True,
- sampler_index=0, batch_size=1, n_iter=1, steps=50, cfg_scale=7.0, width=512, height=512,
- restore_faces=False, tiling=False, do_not_save_samples=False, do_not_save_grid=False,
- extra_generation_params=None, overlay_images=None, negative_prompt=None, eta=None):
+ def __init__(self, sd_model=None, outpath_samples=None, outpath_grids=None, prompt="", styles=None, seed=-1, subseed=-1, subseed_strength=0, seed_resize_from_h=-1, seed_resize_from_w=-1, seed_enable_extras=True, sampler_index=0, batch_size=1, n_iter=1, steps=50, cfg_scale=7.0, width=512, height=512, restore_faces=False, tiling=False, do_not_save_samples=False, do_not_save_grid=False, extra_generation_params=None, overlay_images=None, negative_prompt=None, eta=None, do_not_reload_embeddings=False):
self.sd_model = sd_model
self.outpath_samples: str = outpath_samples
self.outpath_grids: str = outpath_grids
@@ -84,6 +80,7 @@ class StableDiffusionProcessing: self.extra_generation_params: dict = extra_generation_params or {}
self.overlay_images = overlay_images
self.eta = eta
+ self.do_not_reload_embeddings = do_not_reload_embeddings
self.paste_to = None
self.color_corrections = None
self.denoising_strength: float = 0
@@ -350,12 +347,6 @@ def process_images(p: StableDiffusionProcessing) -> Processed: seed = get_fixed_seed(p.seed)
subseed = get_fixed_seed(p.subseed)
- if p.outpath_samples is not None:
- os.makedirs(p.outpath_samples, exist_ok=True)
-
- if p.outpath_grids is not None:
- os.makedirs(p.outpath_grids, exist_ok=True)
-
modules.sd_hijack.model_hijack.apply_circular(p.tiling)
modules.sd_hijack.model_hijack.clear_comments()
@@ -381,7 +372,7 @@ def process_images(p: StableDiffusionProcessing) -> Processed: def infotext(iteration=0, position_in_batch=0):
return create_infotext(p, all_prompts, all_seeds, all_subseeds, comments, iteration, position_in_batch)
- if os.path.exists(cmd_opts.embeddings_dir):
+ if os.path.exists(cmd_opts.embeddings_dir) and not p.do_not_reload_embeddings:
model_hijack.embedding_db.load_textual_inversion_embeddings()
infotexts = []
diff --git a/modules/shared.py b/modules/shared.py index e19ca779..7946d603 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -43,6 +43,7 @@ parser.add_argument("--unload-gfpgan", action='store_true', help="does not do an parser.add_argument("--precision", type=str, help="evaluate at this precision", choices=["full", "autocast"], default="autocast")
parser.add_argument("--share", action='store_true', help="use share=True for gradio and make the UI accessible through their site (doesn't work for me but you might have better luck)")
parser.add_argument("--ngrok", type=str, help="ngrok authtoken, alternative to gradio --share", default=None)
+parser.add_argument("--ngrok-region", type=str, help="The region in which ngrok should start.", default="us")
parser.add_argument("--codeformer-models-path", type=str, help="Path to directory with codeformer model file(s).", default=os.path.join(models_path, 'Codeformer'))
parser.add_argument("--gfpgan-models-path", type=str, help="Path to directory with GFPGAN model file(s).", default=os.path.join(models_path, 'GFPGAN'))
parser.add_argument("--esrgan-models-path", type=str, help="Path to directory with ESRGAN model file(s).", default=os.path.join(models_path, 'ESRGAN'))
diff --git a/modules/textual_inversion/textual_inversion.py b/modules/textual_inversion/textual_inversion.py index d2a389c9..34c46efb 100644 --- a/modules/textual_inversion/textual_inversion.py +++ b/modules/textual_inversion/textual_inversion.py @@ -298,6 +298,7 @@ def train_embedding(embedding_name, learn_rate, batch_size, data_root, log_direc sd_model=shared.sd_model,
do_not_save_grid=True,
do_not_save_samples=True,
+ do_not_reload_embeddings=True,
)
if preview_from_txt2img:
diff --git a/modules/ui.py b/modules/ui.py index 0e5d73f0..32536b2d 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -60,7 +60,7 @@ if not cmd_opts.share and not cmd_opts.listen: if cmd_opts.ngrok != None:
import modules.ngrok as ngrok
print('ngrok authtoken detected, trying to connect...')
- ngrok.connect(cmd_opts.ngrok, cmd_opts.port if cmd_opts.port != None else 7860)
+ ngrok.connect(cmd_opts.ngrok, cmd_opts.port if cmd_opts.port != None else 7860, cmd_opts.ngrok_region)
def gr_show(visible=True):
@@ -512,9 +512,11 @@ def create_toprow(is_img2img): with gr.Row():
with gr.Column(scale=1, elem_id="style_pos_col"):
prompt_style = gr.Dropdown(label="Style 1", elem_id=f"{id_part}_style_index", choices=[k for k, v in shared.prompt_styles.styles.items()], value=next(iter(shared.prompt_styles.styles.keys())))
+ prompt_style.save_to_config = True
with gr.Column(scale=1, elem_id="style_neg_col"):
prompt_style2 = gr.Dropdown(label="Style 2", elem_id=f"{id_part}_style2_index", choices=[k for k, v in shared.prompt_styles.styles.items()], value=next(iter(shared.prompt_styles.styles.keys())))
+ prompt_style2.save_to_config = True
return prompt, roll, prompt_style, negative_prompt, prompt_style2, submit, button_interrogate, button_deepbooru, prompt_style_apply, save_style, paste, token_counter, token_button
@@ -570,6 +572,24 @@ def create_ui(wrap_gradio_gpu_call): import modules.img2img
import modules.txt2img
+ def create_refresh_button(refresh_component, refresh_method, refreshed_args, elem_id):
+ def refresh():
+ refresh_method()
+ args = refreshed_args() if callable(refreshed_args) else refreshed_args
+
+ for k, v in args.items():
+ setattr(refresh_component, k, v)
+
+ return gr.update(**(args or {}))
+
+ refresh_button = gr.Button(value=refresh_symbol, elem_id=elem_id)
+ refresh_button.click(
+ fn = refresh,
+ inputs = [],
+ outputs = [refresh_component]
+ )
+ return refresh_button
+
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, txt2img_paste, token_counter, token_button = create_toprow(is_img2img=False)
dummy_component = gr.Label(visible=False)
@@ -1061,6 +1081,15 @@ def create_ui(wrap_gradio_gpu_call): with gr.TabItem('Batch Process'):
image_batch = gr.File(label="Batch Process", file_count="multiple", interactive=True, type="file")
+ with gr.TabItem('Batch from Directory'):
+ extras_batch_input_dir = gr.Textbox(label="Input directory", **shared.hide_dirs,
+ placeholder="A directory on the same machine where the server is running."
+ )
+ extras_batch_output_dir = gr.Textbox(label="Output directory", **shared.hide_dirs,
+ placeholder="Leave blank to save images to the default path."
+ )
+ show_extras_results = gr.Checkbox(label='Show result images', value=True)
+
with gr.Tabs(elem_id="extras_resize_mode"):
with gr.TabItem('Scale by'):
upscaling_resize = gr.Slider(minimum=1.0, maximum=4.0, step=0.05, label="Resize", value=2)
@@ -1105,6 +1134,9 @@ def create_ui(wrap_gradio_gpu_call): dummy_component,
extras_image,
image_batch,
+ extras_batch_input_dir,
+ extras_batch_output_dir,
+ show_extras_results,
gfpgan_visibility,
codeformer_visibility,
codeformer_weight,
@@ -1248,8 +1280,12 @@ def create_ui(wrap_gradio_gpu_call): with gr.Tab(label="Train"):
gr.HTML(value="<p style='margin-bottom: 0.7em'>Train an embedding; must specify a directory with a set of 1:1 ratio images</p>")
- train_embedding_name = gr.Dropdown(label='Embedding', choices=sorted(sd_hijack.model_hijack.embedding_db.word_embeddings.keys()))
- train_hypernetwork_name = gr.Dropdown(label='Hypernetwork', choices=[x for x in shared.hypernetworks.keys()])
+ with gr.Row():
+ train_embedding_name = gr.Dropdown(label='Embedding', choices=sorted(sd_hijack.model_hijack.embedding_db.word_embeddings.keys()))
+ create_refresh_button(train_embedding_name, sd_hijack.model_hijack.embedding_db.load_textual_inversion_embeddings, lambda: {"choices": sorted(sd_hijack.model_hijack.embedding_db.word_embeddings.keys())}, "refresh_train_embedding_name")
+ with gr.Row():
+ train_hypernetwork_name = gr.Dropdown(label='Hypernetwork', choices=[x for x in shared.hypernetworks.keys()])
+ create_refresh_button(train_hypernetwork_name, shared.reload_hypernetworks, lambda: {"choices": sorted([x for x in shared.hypernetworks.keys()])}, "refresh_train_hypernetwork_name")
learn_rate = gr.Textbox(label='Learning rate', placeholder="Learning rate", value="0.005")
batch_size = gr.Number(label='Batch size', value=1, precision=0)
dataset_directory = gr.Textbox(label='Dataset directory', placeholder="Path to directory with input images")
@@ -1418,26 +1454,11 @@ def create_ui(wrap_gradio_gpu_call): if info.refresh is not None:
if is_quicksettings:
res = comp(label=info.label, value=fun, **(args or {}))
- refresh_button = gr.Button(value=refresh_symbol, elem_id="refresh_"+key)
+ refresh_button = create_refresh_button(res, info.refresh, info.component_args, "refresh_" + key)
else:
with gr.Row(variant="compact"):
res = comp(label=info.label, value=fun, **(args or {}))
- refresh_button = gr.Button(value=refresh_symbol, elem_id="refresh_" + key)
-
- def refresh():
- info.refresh()
- refreshed_args = info.component_args() if callable(info.component_args) else info.component_args
-
- for k, v in refreshed_args.items():
- setattr(res, k, v)
-
- return gr.update(**(refreshed_args or {}))
-
- refresh_button.click(
- fn=refresh,
- inputs=[],
- outputs=[res],
- )
+ refresh_button = create_refresh_button(res, info.refresh, info.component_args, "refresh_" + key)
else:
res = comp(label=info.label, value=fun, **(args or {}))
@@ -1448,7 +1469,10 @@ def create_ui(wrap_gradio_gpu_call): component_dict = {}
def open_folder(f):
- if not os.path.isdir(f):
+ if not os.path.exists(f):
+ print(f'Folder "{f}" does not exist. After you create an image, the folder will be created.')
+ return
+ elif not os.path.isdir(f):
print(f"""
WARNING
An open_folder request was made with an argument that is not a folder.
@@ -1778,7 +1802,9 @@ Requested path was: {f} saved_value = ui_settings.get(key, None)
if saved_value is None:
ui_settings[key] = getattr(obj, field)
- elif condition is None or condition(saved_value):
+ elif condition and not condition(saved_value):
+ print(f'Warning: Bad ui setting value: {key}: {saved_value}; Default value "{getattr(obj, field)}" will be used instead.')
+ else:
setattr(obj, field, saved_value)
if type(x) in [gr.Slider, gr.Radio, gr.Checkbox, gr.Textbox, gr.Number] and x.visible:
@@ -1802,6 +1828,11 @@ Requested path was: {f} if type(x) == gr.Number:
apply_field(x, 'value')
+ # Since there are many dropdowns that shouldn't be saved,
+ # we only mark dropdowns that should be saved.
+ if type(x) == gr.Dropdown and getattr(x, 'save_to_config', False):
+ apply_field(x, 'value', lambda val: val in x.choices)
+
visit(txt2img_interface, loadsave, "txt2img")
visit(img2img_interface, loadsave, "img2img")
visit(extras_interface, loadsave, "extras")
|