mirror of
https://github.com/sd-webui/stable-diffusion-webui.git
synced 2024-12-15 23:31:59 +03:00
Add support for configuring defaults.
This commit is contained in:
parent
41dbcae10e
commit
844311fe7b
137
webui.py
137
webui.py
@ -59,6 +59,7 @@ parser.add_argument("--gfpgan-dir", type=str, help="GFPGAN directory", default=(
|
|||||||
parser.add_argument("--no-verify-input", action='store_true', help="do not verify input to check if it's too long")
|
parser.add_argument("--no-verify-input", action='store_true', help="do not verify input to check if it's too long")
|
||||||
parser.add_argument("--no-half", action='store_true', help="do not switch the model to 16-bit floats")
|
parser.add_argument("--no-half", action='store_true', help="do not switch the model to 16-bit floats")
|
||||||
parser.add_argument("--no-progressbar-hiding", action='store_true', help="do not hide progressbar in gradio UI (we hide it because it slows down ML if you have hardware accleration in browser)")
|
parser.add_argument("--no-progressbar-hiding", action='store_true', help="do not hide progressbar in gradio UI (we hide it because it slows down ML if you have hardware accleration in browser)")
|
||||||
|
parser.add_argument("--defaults", type=str, help="path to configuration file providing UI defaults, uses same format as cli parameter", default='configs/webui/webui.yaml')
|
||||||
parser.add_argument("--cli", type=str, help="don't launch web server, take Python function kwargs from this file.", default=None)
|
parser.add_argument("--cli", type=str, help="don't launch web server, take Python function kwargs from this file.", default=None)
|
||||||
opt = parser.parse_args()
|
opt = parser.parse_args()
|
||||||
|
|
||||||
@ -684,7 +685,7 @@ class Flagging(gr.FlaggingCallback):
|
|||||||
print("Logged:", filenames[0])
|
print("Logged:", filenames[0])
|
||||||
|
|
||||||
|
|
||||||
def img2img(prompt: str, image_editor_mode: str, cropped_image, image_with_mask, mask_mode: str, ddim_steps: int, sampler_name: str,
|
def img2img(prompt: str, image_editor_mode: str, cropped_image, image_with_mask, mask_mode: int, ddim_steps: int, sampler_name: str,
|
||||||
toggles: List[int], n_iter: int, batch_size: int, cfg_scale: float, denoising_strength: float,
|
toggles: List[int], n_iter: int, batch_size: int, cfg_scale: float, denoising_strength: float,
|
||||||
seed: int, height: int, width: int, resize_mode: int, fp):
|
seed: int, height: int, width: int, resize_mode: int, fp):
|
||||||
outpath = opt.outdir_img2img or opt.outdir or "outputs/img2img-samples"
|
outpath = opt.outdir_img2img or opt.outdir or "outputs/img2img-samples"
|
||||||
@ -723,7 +724,7 @@ def img2img(prompt: str, image_editor_mode: str, cropped_image, image_with_mask,
|
|||||||
init_mask = image_with_mask["mask"]
|
init_mask = image_with_mask["mask"]
|
||||||
init_mask = init_mask.convert("RGB")
|
init_mask = init_mask.convert("RGB")
|
||||||
init_mask = resize_image(resize_mode, init_mask, width, height)
|
init_mask = resize_image(resize_mode, init_mask, width, height)
|
||||||
keep_mask = mask_mode == "Keep masked area"
|
keep_mask = mask_mode == 0
|
||||||
init_mask = init_mask if keep_mask else ImageOps.invert(init_mask)
|
init_mask = init_mask if keep_mask else ImageOps.invert(init_mask)
|
||||||
else:
|
else:
|
||||||
init_img = cropped_image
|
init_img = cropped_image
|
||||||
@ -919,8 +920,16 @@ def run_GFPGAN(image, strength):
|
|||||||
css = "" if opt.no_progressbar_hiding else css_hide_progressbar
|
css = "" if opt.no_progressbar_hiding else css_hide_progressbar
|
||||||
css = css + '[data-testid="image"] {min-height: 512px !important}'
|
css = css + '[data-testid="image"] {min-height: 512px !important}'
|
||||||
|
|
||||||
sample_img2img = "assets/stable-samples/img2img/sketch-mountains-input.jpg"
|
if opt.defaults is not None and os.path.isfile(opt.defaults):
|
||||||
sample_img2img = sample_img2img if os.path.exists(sample_img2img) else None
|
try:
|
||||||
|
with open(opt.defaults, "r", encoding="utf8") as f:
|
||||||
|
user_defaults = yaml.safe_load(f)
|
||||||
|
except (OSError, yaml.YAMLError) as e:
|
||||||
|
print(f"Error loading defaults file {opt.defaults}:", e)
|
||||||
|
print("Falling back to program defaults.")
|
||||||
|
user_defaults = {}
|
||||||
|
else:
|
||||||
|
user_defaults = {}
|
||||||
|
|
||||||
# make sure these indicies line up at the top of txt2img()
|
# make sure these indicies line up at the top of txt2img()
|
||||||
txt2img_toggles = [
|
txt2img_toggles = [
|
||||||
@ -932,11 +941,28 @@ txt2img_toggles = [
|
|||||||
if GFPGAN is not None:
|
if GFPGAN is not None:
|
||||||
txt2img_toggles.append('Fix faces using GFPGAN')
|
txt2img_toggles.append('Fix faces using GFPGAN')
|
||||||
|
|
||||||
txt2img_toggle_defaults = [
|
txt2img_defaults = {
|
||||||
'Normalize Prompt Weights (ensure sum of weights add up to 1.0)',
|
'prompt': '',
|
||||||
'Save individual images',
|
'ddim_steps': 50,
|
||||||
'Save grid'
|
'toggles': [1, 2, 3],
|
||||||
]
|
'sampler_name': 'k_lms',
|
||||||
|
'ddim_eta': 0.0,
|
||||||
|
'n_iter': 1,
|
||||||
|
'batch_size': 1,
|
||||||
|
'cfg_scale': 7.5,
|
||||||
|
'seed': '',
|
||||||
|
'height': 512,
|
||||||
|
'width': 512,
|
||||||
|
'fp': None,
|
||||||
|
}
|
||||||
|
|
||||||
|
if 'txt2img' in user_defaults:
|
||||||
|
txt2img_defaults.update(user_defaults['txt2img'])
|
||||||
|
|
||||||
|
txt2img_toggle_defaults = [txt2img_toggles[i] for i in txt2img_defaults['toggles']]
|
||||||
|
|
||||||
|
sample_img2img = "assets/stable-samples/img2img/sketch-mountains-input.jpg"
|
||||||
|
sample_img2img = sample_img2img if os.path.exists(sample_img2img) else None
|
||||||
|
|
||||||
# make sure these indicies line up at the top of img2img()
|
# make sure these indicies line up at the top of img2img()
|
||||||
img2img_toggles = [
|
img2img_toggles = [
|
||||||
@ -950,11 +976,39 @@ img2img_toggles = [
|
|||||||
if GFPGAN is not None:
|
if GFPGAN is not None:
|
||||||
img2img_toggles.append('Fix faces using GFPGAN')
|
img2img_toggles.append('Fix faces using GFPGAN')
|
||||||
|
|
||||||
img2img_toggle_defaults = [
|
img2img_mask_modes = [
|
||||||
'Normalize Prompt Weights (ensure sum of weights add up to 1.0)',
|
"Keep masked area",
|
||||||
'Save individual images',
|
"Regenerate only masked area",
|
||||||
'Save grid',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
img2img_resize_modes = [
|
||||||
|
"Just resize",
|
||||||
|
"Crop and resize",
|
||||||
|
"Resize and fill",
|
||||||
|
]
|
||||||
|
|
||||||
|
img2img_defaults = {
|
||||||
|
'prompt': '',
|
||||||
|
'ddim_steps': 50,
|
||||||
|
'toggles': [1, 4, 5],
|
||||||
|
'sampler_name': 'k_lms',
|
||||||
|
'ddim_eta': 0.0,
|
||||||
|
'n_iter': 1,
|
||||||
|
'batch_size': 1,
|
||||||
|
'cfg_scale': 5.0,
|
||||||
|
'denoising_strength': 0.75,
|
||||||
|
'mask_mode': 0,
|
||||||
|
'resize_mode': 0,
|
||||||
|
'seed': '',
|
||||||
|
'height': 512,
|
||||||
|
'width': 512,
|
||||||
|
'fp': None,
|
||||||
|
}
|
||||||
|
|
||||||
|
if 'img2img' in user_defaults:
|
||||||
|
img2img_defaults.update(user_defaults['img2img'])
|
||||||
|
|
||||||
|
img2img_toggle_defaults = [img2img_toggles[i] for i in img2img_defaults['toggles']]
|
||||||
img2img_image_mode = 'sketch'
|
img2img_image_mode = 'sketch'
|
||||||
|
|
||||||
def change_image_editor_mode(choice, cropped_image, resize_mode, width, height):
|
def change_image_editor_mode(choice, cropped_image, resize_mode, width, height):
|
||||||
@ -981,18 +1035,18 @@ with gr.Blocks(css=css) as demo:
|
|||||||
with gr.Row().style(equal_height=False):
|
with gr.Row().style(equal_height=False):
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
gr.Markdown("Generate images from text with Stable Diffusion")
|
gr.Markdown("Generate images from text with Stable Diffusion")
|
||||||
txt2img_prompt = gr.Textbox(label="Prompt", placeholder="A corgi wearing a top hat as an oil painting.", lines=1)
|
txt2img_prompt = gr.Textbox(label="Prompt", placeholder="A corgi wearing a top hat as an oil painting.", lines=1, value=txt2img_defaults['prompt'])
|
||||||
txt2img_steps = gr.Slider(minimum=1, maximum=250, step=1, label="Sampling Steps", value=50)
|
txt2img_steps = gr.Slider(minimum=1, maximum=250, step=1, label="Sampling Steps", value=txt2img_defaults['ddim_steps'])
|
||||||
txt2img_sampling = gr.Radio(label='Sampling method (k_lms is default k-diffusion sampler)', choices=["DDIM", "PLMS", 'k_dpm_2_a', 'k_dpm_2', 'k_euler_a', 'k_euler', 'k_heun', 'k_lms'], value="k_lms")
|
txt2img_sampling = gr.Radio(label='Sampling method (k_lms is default k-diffusion sampler)', choices=["DDIM", "PLMS", 'k_dpm_2_a', 'k_dpm_2', 'k_euler_a', 'k_euler', 'k_heun', 'k_lms'], value=txt2img_defaults['sampler_name'])
|
||||||
txt2img_toggles = gr.CheckboxGroup(label='', choices=txt2img_toggles, value=txt2img_toggle_defaults, type="index")
|
txt2img_toggles = gr.CheckboxGroup(label='', choices=txt2img_toggles, value=txt2img_toggle_defaults, type="index")
|
||||||
txt2img_ddim_eta = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label="DDIM ETA", value=0.0, visible=False)
|
txt2img_ddim_eta = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label="DDIM ETA", value=txt2img_defaults['ddim_eta'], visible=False)
|
||||||
txt2img_batch_count = gr.Slider(minimum=1, maximum=250, step=1, label='Batch count (how many batches of images to generate)', value=1)
|
txt2img_batch_count = gr.Slider(minimum=1, maximum=250, step=1, label='Batch count (how many batches of images to generate)', value=txt2img_defaults['n_iter'])
|
||||||
txt2img_batch_size = gr.Slider(minimum=1, maximum=8, step=1, label='Batch size (how many images are in a batch; memory-hungry)', value=1)
|
txt2img_batch_size = gr.Slider(minimum=1, maximum=8, step=1, label='Batch size (how many images are in a batch; memory-hungry)', value=txt2img_defaults['batch_size'])
|
||||||
txt2img_cfg = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='Classifier Free Guidance Scale (how strongly the image should follow the prompt)', value=7.5)
|
txt2img_cfg = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='Classifier Free Guidance Scale (how strongly the image should follow the prompt)', value=txt2img_defaults['cfg_scale'])
|
||||||
txt2img_seed = gr.Textbox(label="Seed (blank to randomize)", lines=1, value="")
|
txt2img_seed = gr.Textbox(label="Seed (blank to randomize)", lines=1, value=txt2img_defaults['seed'])
|
||||||
txt2img_height = gr.Slider(minimum=64, maximum=2048, step=64, label="Height", value=512)
|
txt2img_height = gr.Slider(minimum=64, maximum=2048, step=64, label="Height", value=txt2img_defaults['height'])
|
||||||
txt2img_width = gr.Slider(minimum=64, maximum=2048, step=64, label="Width", value=512)
|
txt2img_width = gr.Slider(minimum=64, maximum=2048, step=64, label="Width", value=txt2img_defaults['width'])
|
||||||
txt2img_embeddings = gr.File(label = "Embeddings file for textual inversion", visible=hasattr(model, "embedding_manager"))
|
txt2img_embeddings = gr.File(label = "Embeddings file for textual inversion", visible=hasattr(model, "embedding_manager"), value=txt2img_defaults['fp'])
|
||||||
txt2img_btn = gr.Button("Generate")
|
txt2img_btn = gr.Button("Generate")
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
output_txt2img_gallery = gr.Gallery(label="Images")
|
output_txt2img_gallery = gr.Gallery(label="Images")
|
||||||
@ -1012,24 +1066,24 @@ with gr.Blocks(css=css) as demo:
|
|||||||
with gr.Row().style(equal_height=False):
|
with gr.Row().style(equal_height=False):
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
gr.Markdown("Generate images from images with Stable Diffusion")
|
gr.Markdown("Generate images from images with Stable Diffusion")
|
||||||
img2img_prompt = gr.Textbox(label="Prompt", placeholder="A fantasy landscape, trending on artstation.", lines=1)
|
img2img_prompt = gr.Textbox(label="Prompt", placeholder="A fantasy landscape, trending on artstation.", lines=1, value=img2img_defaults['prompt'])
|
||||||
img2img_image_editor_mode = gr.Radio(choices=["Mask", "Crop"], label="Image Editor Mode", value="Crop")
|
img2img_image_editor_mode = gr.Radio(choices=["Mask", "Crop"], label="Image Editor Mode", value="Crop")
|
||||||
gr.Markdown("The masking/cropping is very temperamental. It may take some time for the image to show when switching from Crop to Mask. If it doesn't work try switching modes again, switch tabs, clear the image or reload.")
|
gr.Markdown("The masking/cropping is very temperamental. It may take some time for the image to show when switching from Crop to Mask. If it doesn't work try switching modes again, switch tabs, clear the image or reload.")
|
||||||
img2img_image_editor = gr.Image(value=sample_img2img, source="upload", interactive=True, type="pil", tool="select")
|
img2img_image_editor = gr.Image(value=sample_img2img, source="upload", interactive=True, type="pil", tool="select")
|
||||||
img2img_image_mask = gr.Image(value=sample_img2img, source="upload", interactive=True, type="pil", tool="sketch", visible=False)
|
img2img_image_mask = gr.Image(value=sample_img2img, source="upload", interactive=True, type="pil", tool="sketch", visible=False)
|
||||||
img2img_mask = gr.Radio(choices=["Keep masked area", "Regenerate only masked area"], label="Mask Mode", value="Keep masked area")
|
img2img_mask = gr.Radio(choices=["Keep masked area", "Regenerate only masked area"], label="Mask Mode", type="index", value=img2img_mask_modes[img2img_defaults['mask_mode']])
|
||||||
img2img_steps = gr.Slider(minimum=1, maximum=250, step=1, label="Sampling Steps", value=50)
|
img2img_steps = gr.Slider(minimum=1, maximum=250, step=1, label="Sampling Steps", value=img2img_defaults['ddim_steps'])
|
||||||
img2img_sampling = gr.Radio(label='Sampling method (k_lms is default k-diffusion sampler)', choices=["DDIM", 'k_dpm_2_a', 'k_dpm_2', 'k_euler_a', 'k_euler', 'k_heun', 'k_lms'], value="k_lms")
|
img2img_sampling = gr.Radio(label='Sampling method (k_lms is default k-diffusion sampler)', choices=["DDIM", 'k_dpm_2_a', 'k_dpm_2', 'k_euler_a', 'k_euler', 'k_heun', 'k_lms'], value=img2img_defaults['sampler_name'])
|
||||||
img2img_toggles = gr.CheckboxGroup(label='', choices=img2img_toggles, value=img2img_toggle_defaults, type="index")
|
img2img_toggles = gr.CheckboxGroup(label='', choices=img2img_toggles, value=img2img_toggle_defaults, type="index")
|
||||||
img2img_batch_count = gr.Slider(minimum=1, maximum=250, step=1, label='Batch count (how many batches of images to generate)', value=1)
|
img2img_batch_count = gr.Slider(minimum=1, maximum=250, step=1, label='Batch count (how many batches of images to generate)', value=img2img_defaults['n_iter'])
|
||||||
img2img_batch_size = gr.Slider(minimum=1, maximum=8, step=1, label='Batch size (how many images are in a batch; memory-hungry)', value=1)
|
img2img_batch_size = gr.Slider(minimum=1, maximum=8, step=1, label='Batch size (how many images are in a batch; memory-hungry)', value=img2img_defaults['batch_size'])
|
||||||
img2img_cfg = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='Classifier Free Guidance Scale (how strongly the image should follow the prompt)', value=5.0)
|
img2img_cfg = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='Classifier Free Guidance Scale (how strongly the image should follow the prompt)', value=img2img_defaults['cfg_scale'])
|
||||||
img2img_denoising = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising Strength', value=0.75)
|
img2img_denoising = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising Strength', value=img2img_defaults['denoising_strength'])
|
||||||
img2img_seed = gr.Textbox(label="Seed (blank to randomize)", lines=1, value="")
|
img2img_seed = gr.Textbox(label="Seed (blank to randomize)", lines=1, value=img2img_defaults['seed'])
|
||||||
img2img_height = gr.Slider(minimum=64, maximum=2048, step=64, label="Height", value=512)
|
img2img_height = gr.Slider(minimum=64, maximum=2048, step=64, label="Height", value=img2img_defaults['height'])
|
||||||
img2img_width = gr.Slider(minimum=64, maximum=2048, step=64, label="Width", value=512)
|
img2img_width = gr.Slider(minimum=64, maximum=2048, step=64, label="Width", value=img2img_defaults['width'])
|
||||||
img2img_resize = gr.Radio(label="Resize mode", choices=["Just resize", "Crop and resize", "Resize and fill"], type="index", value="Just resize")
|
img2img_resize = gr.Radio(label="Resize mode", choices=["Just resize", "Crop and resize", "Resize and fill"], type="index", value=img2img_resize_modes[img2img_defaults['resize_mode']])
|
||||||
img2img_embeddings = gr.File(label = "Embeddings file for textual inversion", visible=hasattr(model, "embedding_manager"))
|
img2img_embeddings = gr.File(label = "Embeddings file for textual inversion", visible=hasattr(model, "embedding_manager"), value=img2img_defaults['fp'])
|
||||||
img2img_btn = gr.Button("Generate")
|
img2img_btn = gr.Button("Generate")
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
output_img2img_gallery = gr.Gallery(label="Images")
|
output_img2img_gallery = gr.Gallery(label="Images")
|
||||||
@ -1064,12 +1118,19 @@ with gr.Blocks(css=css) as demo:
|
|||||||
[output_img2img_gallery, output_img2img_seed, output_img2img_params, output_img2img_stats]
|
[output_img2img_gallery, output_img2img_seed, output_img2img_params, output_img2img_stats]
|
||||||
)
|
)
|
||||||
if GFPGAN is not None:
|
if GFPGAN is not None:
|
||||||
|
gfpgan_defaults = {
|
||||||
|
'strength': 100,
|
||||||
|
}
|
||||||
|
|
||||||
|
if 'gfpgan' in user_defaults:
|
||||||
|
gfpgan_defaults.update(user_defaults['gfpgan'])
|
||||||
|
|
||||||
with gr.TabItem("GFPGAN"):
|
with gr.TabItem("GFPGAN"):
|
||||||
gr.Markdown("Fix faces on images")
|
gr.Markdown("Fix faces on images")
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
gfpgan_source = gr.Image(label="Source", source="upload", interactive=True, type="pil")
|
gfpgan_source = gr.Image(label="Source", source="upload", interactive=True, type="pil")
|
||||||
gfpgan_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Effect strength", value=100)
|
gfpgan_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Effect strength", value=gfpgan_defaults['strength'])
|
||||||
gfpgan_btn = gr.Button("Generate")
|
gfpgan_btn = gr.Button("Generate")
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
gfpgan_output = gr.Image(label="Output")
|
gfpgan_output = gr.Image(label="Output")
|
||||||
|
58
webui.yaml
Normal file
58
webui.yaml
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# UI defaults configuration file. Is read automatically if located at configs/webui/webui.yaml, or specify path via --defaults.
|
||||||
|
|
||||||
|
txt2img:
|
||||||
|
prompt:
|
||||||
|
ddim_steps: 50
|
||||||
|
# Adding an int to toggles enables the corresponding feature.
|
||||||
|
# 0: Create prompt matrix (separate multiple prompts using |, and get all combinations of them)
|
||||||
|
# 1: Normalize Prompt Weights (ensure sum of weights add up to 1.0)
|
||||||
|
# 2: Save individual images
|
||||||
|
# 3: Save grid
|
||||||
|
# 4: Fix faces using GFPGAN
|
||||||
|
toggles: [1, 2, 3]
|
||||||
|
sampler_name: k_lms
|
||||||
|
ddim_eta: 0.0
|
||||||
|
n_iter: 1
|
||||||
|
batch_size: 1
|
||||||
|
cfg_scale: 7.5
|
||||||
|
# Leave blank for random seed
|
||||||
|
seed:
|
||||||
|
height: 512
|
||||||
|
width: 512
|
||||||
|
# Textual inversion embeddings file path
|
||||||
|
fp:
|
||||||
|
|
||||||
|
img2img:
|
||||||
|
prompt:
|
||||||
|
ddim_steps: 50
|
||||||
|
# Adding an int to toggles enables the corresponding feature.
|
||||||
|
# 0: Create prompt matrix (separate multiple prompts using |, and get all combinations of them)
|
||||||
|
# 1: Normalize Prompt Weights (ensure sum of weights add up to 1.0)
|
||||||
|
# 2: Loopback (use images from previous batch when creating next batch)
|
||||||
|
# 3: Random loopback seed
|
||||||
|
# 4: Save individual images
|
||||||
|
# 5: Save grid
|
||||||
|
# 6: Fix faces using GFPGAN
|
||||||
|
toggles: [1, 4, 5]
|
||||||
|
sampler_name: k_lms
|
||||||
|
ddim_eta: 0.0
|
||||||
|
n_iter: 1
|
||||||
|
batch_size: 1
|
||||||
|
cfg_scale: 5.0
|
||||||
|
denoising_strength: 0.75
|
||||||
|
# 0: Keep masked area
|
||||||
|
# 1: Regenerate only masked area
|
||||||
|
mask_mode: 0
|
||||||
|
# 0: Just resize
|
||||||
|
# 1: Crop and resize
|
||||||
|
# 2: Resize and fill
|
||||||
|
resize_mode: 0
|
||||||
|
# Leave blank for random seed
|
||||||
|
seed:
|
||||||
|
height: 512
|
||||||
|
width: 512
|
||||||
|
# Textual inversion embeddings file path
|
||||||
|
fp:
|
||||||
|
|
||||||
|
gfpgan:
|
||||||
|
strength: 100
|
Loading…
Reference in New Issue
Block a user