Compare commits
55
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4145c8453 | ||
|
|
c0b1177a32 | ||
|
|
8dcac9ac81 | ||
|
|
258a2d4f06 | ||
|
|
c74becca23 | ||
|
|
16e7ac09df | ||
|
|
2846ca5702 | ||
|
|
78d6aef302 | ||
|
|
b39f06cea7 | ||
|
|
e61da308ba | ||
|
|
b8a8f749ef | ||
|
|
db4ab47f09 | ||
|
|
ca3e5519e8 | ||
|
|
ff107845b4 | ||
|
|
1877a3767e | ||
|
|
4c3d4aad60 | ||
|
|
e13912dfde | ||
|
|
ba34b790d3 | ||
|
|
40166dbf08 | ||
|
|
073f6eac22 | ||
|
|
50ae19acf6 | ||
|
|
31a0fbf1ad | ||
|
|
615b2fc9ce | ||
|
|
b8eae5de93 | ||
|
|
600cc0342d | ||
|
|
72e2a96284 | ||
|
|
ab5a472556 | ||
|
|
ca13264609 | ||
|
|
b1320d79b5 | ||
|
|
714dcda068 | ||
|
|
5194a58278 | ||
|
|
53be15c204 | ||
|
|
b5d705e263 | ||
|
|
a2bea2f97a | ||
|
|
410bef0853 | ||
|
|
31ac0baba0 | ||
|
|
ed8b8b3b8c | ||
|
|
7aec029423 | ||
|
|
e94ec98102 | ||
|
|
db341bd0d8 | ||
|
|
3e4b7fb869 | ||
|
|
910a3d9427 | ||
|
|
0f77e1852f | ||
|
|
74f940e818 | ||
|
|
71cfb9ebac | ||
|
|
b04a36be37 | ||
|
|
e1d49c5262 | ||
|
|
6cd613811b | ||
|
|
e560eb8b60 | ||
|
|
e12793e937 | ||
|
|
c8c662901b | ||
|
|
39ce23f42d | ||
|
|
9c92a1a9aa | ||
|
|
8ffc07b7b1 | ||
|
|
0065327726 |
+3
-1
@@ -19,4 +19,6 @@ __pycache__
|
||||
/webui-user.sh
|
||||
/interrogate
|
||||
/user.css
|
||||
/.idea
|
||||
/.idea
|
||||
notification.mp3
|
||||
/SwinIR
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Stable Diffusion web UI
|
||||
A browser interface based on Gradio library for Stable Diffusion.
|
||||
|
||||

|
||||

|
||||
|
||||
## Features
|
||||
[Detailed feature showcase with images](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features):
|
||||
@@ -51,7 +51,10 @@ A browser interface based on Gradio library for Stable Diffusion.
|
||||
## Installation and Running
|
||||
Make sure the required [dependencies](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Dependencies) are met and follow the instructions available for both [NVidia](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-NVidia-GPUs) (recommended) and [AMD](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-AMD-GPUs) GPUs.
|
||||
|
||||
Alternatively, use [Google Colab](https://colab.research.google.com/drive/1Iy-xW9t1-OQWhb0hNxueGij8phCyluOh).
|
||||
Alternatively, use Google Colab:
|
||||
|
||||
- [Colab, maintained by Akaibu](https://colab.research.google.com/drive/1kw3egmSn-KgWsikYvOMjJkVDsPLjEMzl)
|
||||
- [Colab, original by me, outdated](https://colab.research.google.com/drive/1Iy-xW9t1-OQWhb0hNxueGij8phCyluOh).
|
||||
|
||||
### Automatic Installation on Windows
|
||||
1. Install [Python 3.10.6](https://www.python.org/downloads/windows/), checking "Add Python to PATH"
|
||||
|
||||
Vendored
+15
-9
@@ -68,13 +68,19 @@ window.addEventListener('paste', e => {
|
||||
if ( ! isValidImageList( files ) ) {
|
||||
return;
|
||||
}
|
||||
[...gradioApp().querySelectorAll('input[type=file][accept="image/x-png,image/gif,image/jpeg"]')]
|
||||
.filter(input => !input.matches('.\\!hidden input[type=file]'))
|
||||
.forEach(input => {
|
||||
input.files = files;
|
||||
input.dispatchEvent(new Event('change'))
|
||||
});
|
||||
[...gradioApp().querySelectorAll('[data-testid="image"]')]
|
||||
.filter(imgWrap => !imgWrap.closest('.\\!hidden'))
|
||||
.forEach(imgWrap => dropReplaceImage( imgWrap, files ));
|
||||
|
||||
const visibleImageFields = [...gradioApp().querySelectorAll('[data-testid="image"]')]
|
||||
.filter(el => uiElementIsVisible(el));
|
||||
if ( ! visibleImageFields.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const firstFreeImageField = visibleImageFields
|
||||
.filter(el => el.querySelector('input[type=file]'))?.[0];
|
||||
|
||||
dropReplaceImage(
|
||||
firstFreeImageField ?
|
||||
firstFreeImageField :
|
||||
visibleImageFields[visibleImageFields.length - 1]
|
||||
, files );
|
||||
});
|
||||
|
||||
+4
-5
@@ -13,6 +13,8 @@ titles = {
|
||||
"Seed": "A value that determines the output of random number generator - if you create an image with same parameters and seed as another image, you'll get the same result",
|
||||
"\u{1f3b2}\ufe0f": "Set seed to -1, which will cause a new random number to be used every time",
|
||||
"\u267b\ufe0f": "Reuse seed from last generation, mostly useful if it was randomed",
|
||||
"\u{1f3a8}": "Add a random artist to the prompt.",
|
||||
"\u2199\ufe0f": "Read generation parameters from prompt into user interface.",
|
||||
|
||||
"Inpaint a part of image": "Draw a mask over an image, and the script will regenerate the masked area with content according to prompt",
|
||||
"SD upscale": "Upscale image normally, split result into tiles, improve each tile using img2img, merge whole image back",
|
||||
@@ -48,8 +50,6 @@ titles = {
|
||||
"Tiling": "Produce an image that can be tiled.",
|
||||
"Tile overlap": "For SD upscale, how much overlap in pixels should there be between tiles. Tiles overlap so that when they are merged back into one picture, there is no clearly visible seam.",
|
||||
|
||||
"Roll": "Add a random artist to the prompt.",
|
||||
|
||||
"Variation seed": "Seed of a different picture to be mixed into the generation.",
|
||||
"Variation strength": "How strong of a variation to produce. At 0, there will be no effect. At 1, you will get the complete picture with variation seed (except for ancestral samplers, where you will just get something).",
|
||||
"Resize seed from height": "Make an attempt to produce a picture similar to what would have been produced with same seed at specified resolution",
|
||||
@@ -57,14 +57,13 @@ titles = {
|
||||
|
||||
"Interrogate": "Reconstruct prompt from existing image and put it into the prompt field.",
|
||||
|
||||
"Images filename pattern": "Use following tags to define how filenames for images are chosen: [steps], [cfg], [prompt], [prompt_spaces], [width], [height], [sampler], [seed], [model_hash], [prompt_words], [date]; leave empty for default.",
|
||||
"Directory name pattern": "Use following tags to define how subdirectories for images and grids are chosen: [steps], [cfg], [prompt], [prompt_spaces], [width], [height], [sampler], [seed], [model_hash], [prompt_words], [date]; leave empty for default.",
|
||||
"Images filename pattern": "Use following tags to define how filenames for images are chosen: [steps], [cfg], [prompt], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [prompt_words], [date], [datetime], [job_timestamp]; leave empty for default.",
|
||||
"Directory name pattern": "Use following tags to define how subdirectories for images and grids are chosen: [steps], [cfg], [prompt], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [prompt_words], [date], [datetime], [job_timestamp]; leave empty for default.",
|
||||
"Max prompt words": "Set the maximum number of words to be used in the [prompt_words] option; ATTENTION: If the words are too long, they may exceed the maximum length of the file path that the system can handle",
|
||||
|
||||
"Loopback": "Process an image, use it as an input, repeat.",
|
||||
"Loops": "How many times to repeat processing an image and using it as input for the next iteration",
|
||||
|
||||
|
||||
"Style 1": "Style to apply; styles have components for both positive and negative prompts and apply to both",
|
||||
"Style 2": "Style to apply; styles have components for both positive and negative prompts and apply to both",
|
||||
"Apply style": "Insert selected styles into prompt fields",
|
||||
|
||||
@@ -22,10 +22,22 @@ function negmod(n, m) {
|
||||
}
|
||||
|
||||
function modalImageSwitch(offset){
|
||||
var galleryButtons = gradioApp().querySelectorAll(".gallery-item.transition-all")
|
||||
var allgalleryButtons = gradioApp().querySelectorAll(".gallery-item.transition-all")
|
||||
var galleryButtons = []
|
||||
allgalleryButtons.forEach(function(elem){
|
||||
if(elem.parentElement.offsetParent){
|
||||
galleryButtons.push(elem);
|
||||
}
|
||||
})
|
||||
|
||||
if(galleryButtons.length>1){
|
||||
var currentButton = gradioApp().querySelector(".gallery-item.transition-all.\\!ring-2")
|
||||
var allcurrentButtons = gradioApp().querySelectorAll(".gallery-item.transition-all.\\!ring-2")
|
||||
var currentButton = null
|
||||
allcurrentButtons.forEach(function(elem){
|
||||
if(elem.parentElement.offsetParent){
|
||||
currentButton = elem;
|
||||
}
|
||||
})
|
||||
|
||||
var result = -1
|
||||
galleryButtons.forEach(function(v, i){ if(v==currentButton) { result = i } })
|
||||
|
||||
@@ -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.
|
||||
|
||||
+27
-29
@@ -1,53 +1,51 @@
|
||||
// code related to showing and updating progressbar shown as the image is being made
|
||||
global_progressbar = null
|
||||
global_progressbars = {}
|
||||
|
||||
onUiUpdate(function(){
|
||||
progressbar = gradioApp().getElementById('progressbar')
|
||||
progressDiv = gradioApp().querySelectorAll('#progressSpan').length > 0;
|
||||
interrupt = gradioApp().getElementById('interrupt')
|
||||
if(progressbar!= null && progressbar != global_progressbar){
|
||||
global_progressbar = progressbar
|
||||
function check_progressbar(id_part, id_progressbar, id_progressbar_span, id_interrupt, id_preview, id_gallery){
|
||||
var progressbar = gradioApp().getElementById(id_progressbar)
|
||||
var interrupt = gradioApp().getElementById(id_interrupt)
|
||||
if(progressbar!= null && progressbar != global_progressbars[id_progressbar]){
|
||||
global_progressbars[id_progressbar] = progressbar
|
||||
|
||||
var mutationObserver = new MutationObserver(function(m){
|
||||
txt2img_preview = gradioApp().getElementById('txt2img_preview')
|
||||
txt2img_gallery = gradioApp().getElementById('txt2img_gallery')
|
||||
img2img_preview = gradioApp().getElementById('img2img_preview')
|
||||
img2img_gallery = gradioApp().getElementById('img2img_gallery')
|
||||
preview = gradioApp().getElementById(id_preview)
|
||||
gallery = gradioApp().getElementById(id_gallery)
|
||||
|
||||
if(txt2img_preview != null && txt2img_gallery != null){
|
||||
txt2img_preview.style.width = txt2img_gallery.clientWidth + "px"
|
||||
txt2img_preview.style.height = txt2img_gallery.clientHeight + "px"
|
||||
if(preview != null && gallery != null){
|
||||
preview.style.width = gallery.clientWidth + "px"
|
||||
preview.style.height = gallery.clientHeight + "px"
|
||||
|
||||
var progressDiv = gradioApp().querySelectorAll('#' + id_progressbar_span).length > 0;
|
||||
if(!progressDiv){
|
||||
interrupt.style.display = "none"
|
||||
}
|
||||
}
|
||||
|
||||
if(img2img_preview != null && img2img_gallery != null){
|
||||
img2img_preview.style.width = img2img_gallery.clientWidth + "px"
|
||||
img2img_preview.style.height = img2img_gallery.clientHeight + "px"
|
||||
if(!progressDiv){
|
||||
interrupt.style.display = "none"
|
||||
}
|
||||
}
|
||||
|
||||
window.setTimeout(requestMoreProgress, 500)
|
||||
window.setTimeout(function(){ requestMoreProgress(id_part, id_progressbar_span, id_interrupt) }, 500)
|
||||
});
|
||||
mutationObserver.observe( progressbar, { childList:true, subtree:true })
|
||||
}
|
||||
}
|
||||
|
||||
onUiUpdate(function(){
|
||||
check_progressbar('txt2img', 'txt2img_progressbar', 'txt2img_progress_span', 'txt2img_interrupt', 'txt2img_preview', 'txt2img_gallery')
|
||||
check_progressbar('img2img', 'img2img_progressbar', 'img2img_progress_span', 'img2img_interrupt', 'img2img_preview', 'img2img_gallery')
|
||||
})
|
||||
function requestMoreProgress(){
|
||||
btn = gradioApp().getElementById("check_progress");
|
||||
|
||||
function requestMoreProgress(id_part, id_progressbar_span, id_interrupt){
|
||||
btn = gradioApp().getElementById(id_part+"_check_progress");
|
||||
if(btn==null) return;
|
||||
|
||||
btn.click();
|
||||
progressDiv = gradioApp().querySelectorAll('#progressSpan').length > 0;
|
||||
if(progressDiv){
|
||||
var progressDiv = gradioApp().querySelectorAll('#' + id_progressbar_span).length > 0;
|
||||
var interrupt = gradioApp().getElementById(id_interrupt)
|
||||
if(progressDiv && interrupt){
|
||||
interrupt.style.display = "block"
|
||||
}
|
||||
}
|
||||
|
||||
function requestProgress(){
|
||||
btn = gradioApp().getElementById("check_progress_initial");
|
||||
function requestProgress(id_part){
|
||||
btn = gradioApp().getElementById(id_part+"_check_progress_initial");
|
||||
if(btn==null) return;
|
||||
|
||||
btn.click();
|
||||
|
||||
+50
-7
@@ -1,9 +1,8 @@
|
||||
// various functions for interation with ui.py not large enough to warrant putting them in separate files
|
||||
|
||||
function selected_gallery_index(){
|
||||
var gr = gradioApp()
|
||||
var buttons = gradioApp().querySelectorAll(".gallery-item")
|
||||
var button = gr.querySelector(".gallery-item.\\!ring-2")
|
||||
var buttons = gradioApp().querySelectorAll('[style="display: block;"].tabitem .gallery-item')
|
||||
var button = gradioApp().querySelector('[style="display: block;"].tabitem .gallery-item.\\!ring-2')
|
||||
|
||||
var result = -1
|
||||
buttons.forEach(function(v, i){ if(v==button) { result = i } })
|
||||
@@ -25,13 +24,57 @@ function extract_image_from_gallery(gallery){
|
||||
return gallery[index];
|
||||
}
|
||||
|
||||
function extract_image_from_gallery_img2img(gallery){
|
||||
function args_to_array(args){
|
||||
res = []
|
||||
for(var i=0;i<args.length;i++){
|
||||
res.push(args[i])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
function switch_to_txt2img(){
|
||||
gradioApp().querySelectorAll('button')[0].click();
|
||||
|
||||
return args_to_array(arguments);
|
||||
}
|
||||
|
||||
function switch_to_img2img_img2img(){
|
||||
gradioApp().querySelectorAll('button')[1].click();
|
||||
gradioApp().getElementById('mode_img2img').querySelectorAll('button')[0].click();
|
||||
|
||||
return args_to_array(arguments);
|
||||
}
|
||||
|
||||
function switch_to_img2img_inpaint(){
|
||||
gradioApp().querySelectorAll('button')[1].click();
|
||||
gradioApp().getElementById('mode_img2img').querySelectorAll('button')[1].click();
|
||||
|
||||
return args_to_array(arguments);
|
||||
}
|
||||
|
||||
function switch_to_extras(){
|
||||
gradioApp().querySelectorAll('button')[2].click();
|
||||
|
||||
return args_to_array(arguments);
|
||||
}
|
||||
|
||||
function extract_image_from_gallery_txt2img(gallery){
|
||||
switch_to_txt2img()
|
||||
return extract_image_from_gallery(gallery);
|
||||
}
|
||||
|
||||
function extract_image_from_gallery_img2img(gallery){
|
||||
switch_to_img2img_img2img()
|
||||
return extract_image_from_gallery(gallery);
|
||||
}
|
||||
|
||||
function extract_image_from_gallery_inpaint(gallery){
|
||||
switch_to_img2img_inpaint()
|
||||
return extract_image_from_gallery(gallery);
|
||||
}
|
||||
|
||||
function extract_image_from_gallery_extras(gallery){
|
||||
gradioApp().querySelectorAll('button')[2].click();
|
||||
switch_to_extras()
|
||||
return extract_image_from_gallery(gallery);
|
||||
}
|
||||
|
||||
@@ -79,13 +122,13 @@ function create_submit_args(args){
|
||||
}
|
||||
|
||||
function submit(){
|
||||
requestProgress()
|
||||
requestProgress('txt2img')
|
||||
|
||||
return create_submit_args(arguments)
|
||||
}
|
||||
|
||||
function submit_img2img(){
|
||||
requestProgress()
|
||||
requestProgress('img2img')
|
||||
|
||||
res = create_submit_args(arguments)
|
||||
|
||||
|
||||
+4
-2
@@ -102,6 +102,7 @@ def run_pnginfo(image):
|
||||
return '', '', ''
|
||||
|
||||
items = image.info
|
||||
geninfo = ''
|
||||
|
||||
if "exif" in image.info:
|
||||
exif = piexif.load(image.info["exif"])
|
||||
@@ -111,13 +112,14 @@ def run_pnginfo(image):
|
||||
except ValueError:
|
||||
exif_comment = exif_comment.decode('utf8', errors="ignore")
|
||||
|
||||
|
||||
items['exif comment'] = exif_comment
|
||||
geninfo = exif_comment
|
||||
|
||||
for field in ['jfif', 'jfif_version', 'jfif_unit', 'jfif_density', 'dpi', 'exif',
|
||||
'loop', 'background', 'timestamp', 'duration']:
|
||||
items.pop(field, None)
|
||||
|
||||
geninfo = items.get('parameters', geninfo)
|
||||
|
||||
info = ''
|
||||
for key, text in items.items():
|
||||
@@ -132,4 +134,4 @@ def run_pnginfo(image):
|
||||
message = "Nothing found in the image."
|
||||
info = f"<div><p>{message}<p></div>"
|
||||
|
||||
return '', '', info
|
||||
return '', geninfo, info
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import re
|
||||
import gradio as gr
|
||||
|
||||
re_param_code = r"\s*([\w ]+):\s*([^,]+)(?:,|$)"
|
||||
re_param = re.compile(re_param_code)
|
||||
re_params = re.compile(r"^(?:" + re_param_code + "){3,}$")
|
||||
re_imagesize = re.compile(r"^(\d+)x(\d+)$")
|
||||
type_of_gr_update = type(gr.update())
|
||||
|
||||
|
||||
def parse_generation_parameters(x: str):
|
||||
"""parses generation parameters string, the one you see in text field under the picture in UI:
|
||||
```
|
||||
girl with an artist's beret, determined, blue eyes, desert scene, computer monitors, heavy makeup, by Alphonse Mucha and Charlie Bowater, ((eyeshadow)), (coquettish), detailed, intricate
|
||||
Negative prompt: ugly, fat, obese, chubby, (((deformed))), [blurry], bad anatomy, disfigured, poorly drawn face, mutation, mutated, (extra_limb), (ugly), (poorly drawn hands), messy drawing
|
||||
Steps: 20, Sampler: Euler a, CFG scale: 7, Seed: 965400086, Size: 512x512, Model hash: 45dee52b
|
||||
```
|
||||
|
||||
returns a dict with field values
|
||||
"""
|
||||
|
||||
res = {}
|
||||
|
||||
prompt = ""
|
||||
negative_prompt = ""
|
||||
|
||||
done_with_prompt = False
|
||||
|
||||
*lines, lastline = x.strip().split("\n")
|
||||
if not re_params.match(lastline):
|
||||
lines.append(lastline)
|
||||
lastline = ''
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
line = line.strip()
|
||||
if line.startswith("Negative prompt:"):
|
||||
done_with_prompt = True
|
||||
line = line[16:].strip()
|
||||
|
||||
if done_with_prompt:
|
||||
negative_prompt += ("" if negative_prompt == "" else "\n") + line
|
||||
else:
|
||||
prompt += ("" if prompt == "" else "\n") + line
|
||||
|
||||
if len(prompt) > 0:
|
||||
res["Prompt"] = prompt
|
||||
|
||||
if len(negative_prompt) > 0:
|
||||
res["Negative prompt"] = negative_prompt
|
||||
|
||||
for k, v in re_param.findall(lastline):
|
||||
m = re_imagesize.match(v)
|
||||
if m is not None:
|
||||
res[k+"-1"] = m.group(1)
|
||||
res[k+"-2"] = m.group(2)
|
||||
else:
|
||||
res[k] = v
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def connect_paste(button, paste_fields, input_comp, js=None):
|
||||
def paste_func(prompt):
|
||||
params = parse_generation_parameters(prompt)
|
||||
res = []
|
||||
|
||||
for output, key in paste_fields:
|
||||
if callable(key):
|
||||
v = key(params)
|
||||
else:
|
||||
v = params.get(key, None)
|
||||
|
||||
if v is None:
|
||||
res.append(gr.update())
|
||||
elif isinstance(v, type_of_gr_update):
|
||||
res.append(v)
|
||||
else:
|
||||
try:
|
||||
valtype = type(output.value)
|
||||
val = valtype(v)
|
||||
res.append(gr.update(value=val))
|
||||
except Exception:
|
||||
res.append(gr.update())
|
||||
|
||||
return res
|
||||
|
||||
button.click(
|
||||
fn=paste_func,
|
||||
_js=js,
|
||||
inputs=[input_comp],
|
||||
outputs=[x[0] for x in paste_fields],
|
||||
)
|
||||
+4
-1
@@ -210,7 +210,7 @@ def draw_prompt_matrix(im, width, height, all_prompts):
|
||||
|
||||
def resize_image(resize_mode, im, width, height):
|
||||
def resize(im, w, h):
|
||||
if opts.upscaler_for_img2img is None or opts.upscaler_for_img2img == "None":
|
||||
if opts.upscaler_for_img2img is None or opts.upscaler_for_img2img == "None" or im.mode == 'L':
|
||||
return im.resize((w, h), resample=LANCZOS)
|
||||
|
||||
upscaler = [x for x in shared.sd_upscalers if x.name == opts.upscaler_for_img2img][0]
|
||||
@@ -290,10 +290,13 @@ def apply_filename_pattern(x, p, seed, prompt):
|
||||
x = x.replace("[cfg]", str(p.cfg_scale))
|
||||
x = x.replace("[width]", str(p.width))
|
||||
x = x.replace("[height]", str(p.height))
|
||||
x = x.replace("[styles]", sanitize_filename_part(", ".join(p.styles), replace_spaces=False))
|
||||
x = x.replace("[sampler]", sanitize_filename_part(sd_samplers.samplers[p.sampler_index].name, replace_spaces=False))
|
||||
|
||||
x = x.replace("[model_hash]", shared.sd_model.sd_model_hash)
|
||||
x = x.replace("[date]", datetime.date.today().isoformat())
|
||||
x = x.replace("[datetime]", datetime.datetime.now().strftime("%Y%m%d%H%M%S"))
|
||||
x = x.replace("[job_timestamp]", shared.state.job_timestamp)
|
||||
|
||||
if cmd_opts.hide_ui_dir_config:
|
||||
x = re.sub(r'^[\\/]+|\.{2,}[\\/]+|[\\/]+\.{2,}', '', x)
|
||||
|
||||
@@ -108,6 +108,8 @@ def img2img(mode: int, prompt: str, negative_prompt: str, prompt_style: str, pro
|
||||
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"
|
||||
|
||||
process_batch(p, img2img_batch_input_dir, img2img_batch_output_dir, args)
|
||||
|
||||
processed = Processed(p, [], p.seed, "")
|
||||
|
||||
@@ -406,7 +406,7 @@ def process_images(p: StableDiffusionProcessing) -> Processed:
|
||||
index_of_first_image = 1
|
||||
|
||||
if opts.grid_save:
|
||||
images.save_image(grid, p.outpath_grids, "grid", all_seeds[0], all_prompts[0], opts.grid_format, info=infotext(), short_filename=not opts.grid_extended_filename, p=p)
|
||||
images.save_image(grid, p.outpath_grids, "grid", all_seeds[0], all_prompts[0], opts.grid_format, info=infotext(), short_filename=not opts.grid_extended_filename, p=p, grid=True)
|
||||
|
||||
devices.torch_gc()
|
||||
return Processed(p, output_images, all_seeds[0], infotext(), subseed=all_subseeds[0], all_prompts=all_prompts, all_seeds=all_seeds, all_subseeds=all_subseeds, index_of_first_image=index_of_first_image)
|
||||
@@ -488,6 +488,11 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
|
||||
|
||||
self.sampler = samplers[self.sampler_index].constructor(self.sd_model)
|
||||
noise = create_random_tensors(samples.shape[1:], seeds=seeds, subseeds=subseeds, subseed_strength=subseed_strength, seed_resize_from_h=self.seed_resize_from_h, seed_resize_from_w=self.seed_resize_from_w, p=self)
|
||||
|
||||
# GC now before running the next img2img to prevent running out of memory
|
||||
x = None
|
||||
devices.torch_gc()
|
||||
|
||||
samples = self.sampler.sample_img2img(self, samples, noise, conditioning, unconditional_conditioning, steps=self.steps)
|
||||
|
||||
return samples
|
||||
|
||||
@@ -119,6 +119,7 @@ class ScriptRunner:
|
||||
continue
|
||||
|
||||
for control in controls:
|
||||
control.custom_script_source = os.path.basename(script.filename)
|
||||
control.visible = False
|
||||
|
||||
inputs += controls
|
||||
|
||||
@@ -201,7 +201,7 @@ class StableDiffusionModelHijack:
|
||||
def process_file(path, filename):
|
||||
name = os.path.splitext(filename)[0]
|
||||
|
||||
data = torch.load(path)
|
||||
data = torch.load(path, map_location="cpu")
|
||||
|
||||
# textual inversion embeddings
|
||||
if 'string_to_param' in data:
|
||||
@@ -217,7 +217,7 @@ class StableDiffusionModelHijack:
|
||||
if len(emb.shape) == 1:
|
||||
emb = emb.unsqueeze(0)
|
||||
|
||||
self.word_embeddings[name] = emb.detach()
|
||||
self.word_embeddings[name] = emb.detach().to(device)
|
||||
self.word_embeddings_checksums[name] = f'{const_hash(emb.reshape(-1)*100)&0xffff:04x}'
|
||||
|
||||
ids = tokenizer([name], add_special_tokens=False)['input_ids'][0]
|
||||
@@ -300,7 +300,7 @@ class FrozenCLIPEmbedderWithCustomWords(torch.nn.Module):
|
||||
remade_batch_tokens = []
|
||||
id_start = self.wrapped.tokenizer.bos_token_id
|
||||
id_end = self.wrapped.tokenizer.eos_token_id
|
||||
maxlen = self.wrapped.max_length - 2
|
||||
maxlen = self.wrapped.max_length
|
||||
used_custom_terms = []
|
||||
|
||||
cache = {}
|
||||
|
||||
+13
-1
@@ -4,6 +4,7 @@ import json
|
||||
import os
|
||||
import gradio as gr
|
||||
import tqdm
|
||||
import datetime
|
||||
|
||||
import modules.artists
|
||||
from modules.paths import script_path, sd_path
|
||||
@@ -65,6 +66,7 @@ class State:
|
||||
job = ""
|
||||
job_no = 0
|
||||
job_count = 0
|
||||
job_timestamp = '0'
|
||||
sampling_step = 0
|
||||
sampling_steps = 0
|
||||
current_latent = None
|
||||
@@ -78,6 +80,9 @@ class State:
|
||||
self.job_no += 1
|
||||
self.sampling_step = 0
|
||||
self.current_image_sampling_step = 0
|
||||
|
||||
def get_job_timestamp(self):
|
||||
return datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
||||
|
||||
|
||||
state = State()
|
||||
@@ -116,7 +121,7 @@ def options_section(section_identifer, options_dict):
|
||||
return options_dict
|
||||
|
||||
|
||||
hide_dirs = {"visible": False} if cmd_opts.hide_ui_dir_config else None
|
||||
hide_dirs = {"visible": not cmd_opts.hide_ui_dir_config}
|
||||
|
||||
options_templates = {}
|
||||
|
||||
@@ -307,6 +312,13 @@ class TotalTQDM:
|
||||
self.reset()
|
||||
self._tqdm.update()
|
||||
|
||||
def updateTotal(self, new_total):
|
||||
if not opts.multiple_tqdm:
|
||||
return
|
||||
if self._tqdm is None:
|
||||
self.reset()
|
||||
self._tqdm.total=new_total
|
||||
|
||||
def clear(self):
|
||||
if self._tqdm is not None:
|
||||
self._tqdm.close()
|
||||
|
||||
+162
-107
@@ -27,6 +27,7 @@ import modules.scripts
|
||||
import modules.gfpgan_model
|
||||
import modules.codeformer_model
|
||||
import modules.styles
|
||||
import modules.generation_parameters_copypaste
|
||||
|
||||
# this is a fix for Windows users. Without it, javascript files will be served with text/html content-type and the bowser will not show any UI
|
||||
mimetypes.init()
|
||||
@@ -48,7 +49,6 @@ 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; }
|
||||
"""
|
||||
@@ -57,6 +57,8 @@ css_hide_progressbar = """
|
||||
# Important that they exactly match script.js for tooltip to work.
|
||||
random_symbol = '\U0001f3b2\ufe0f' # 🎲️
|
||||
reuse_symbol = '\u267b\ufe0f' # ♻️
|
||||
art_symbol = '\U0001f3a8' # 🎨
|
||||
paste_symbol = '\u2199\ufe0f' # ↙
|
||||
|
||||
|
||||
def plaintext_to_html(text):
|
||||
@@ -166,7 +168,7 @@ def wrap_gradio_call(func):
|
||||
return f
|
||||
|
||||
|
||||
def check_progress_call():
|
||||
def check_progress_call(id_part):
|
||||
if shared.state.job_count == 0:
|
||||
return "", gr_show(False), gr_show(False)
|
||||
|
||||
@@ -195,20 +197,20 @@ def check_progress_call():
|
||||
|
||||
image = shared.state.current_image
|
||||
|
||||
if image is None or progress >= 1:
|
||||
if image is None:
|
||||
image = gr.update(value=None)
|
||||
else:
|
||||
preview_visibility = gr_show(True)
|
||||
|
||||
return f"<span id='progressSpan' style='display: none'>{time.time()}</span><p>{progressbar}</p>", preview_visibility, image
|
||||
return f"<span id='{id_part}_progress_span' style='display: none'>{time.time()}</span><p>{progressbar}</p>", preview_visibility, image
|
||||
|
||||
|
||||
def check_progress_call_initial():
|
||||
def check_progress_call_initial(id_part):
|
||||
shared.state.job_count = -1
|
||||
shared.state.current_latent = None
|
||||
shared.state.current_image = None
|
||||
|
||||
return check_progress_call()
|
||||
return check_progress_call(id_part)
|
||||
|
||||
|
||||
def roll_artist(prompt):
|
||||
@@ -236,8 +238,7 @@ def add_style(name: str, prompt: str, negative_prompt: str):
|
||||
# reserialize all styles every time we save them
|
||||
shared.prompt_styles.save_styles(shared.styles_filename)
|
||||
|
||||
update = {"visible": True, "choices": list(shared.prompt_styles.styles), "__type__": "update"}
|
||||
return [update, update, update, update]
|
||||
return [gr.Dropdown.update(visible=True, choices=list(shared.prompt_styles.styles)) for _ in range(4)]
|
||||
|
||||
|
||||
def apply_styles(prompt, prompt_neg, style1_name, style2_name):
|
||||
@@ -329,27 +330,32 @@ def connect_reuse_seed(seed: gr.Number, reuse_seed: gr.Button, generation_info:
|
||||
|
||||
|
||||
def create_toprow(is_img2img):
|
||||
id_part = "img2img" if is_img2img else "txt2img"
|
||||
|
||||
with gr.Row(elem_id="toprow"):
|
||||
with gr.Column(scale=4):
|
||||
with gr.Row():
|
||||
with gr.Column(scale=8):
|
||||
with gr.Column(scale=80):
|
||||
with gr.Row():
|
||||
prompt = gr.Textbox(label="Prompt", elem_id="prompt", show_label=False, placeholder="Prompt", lines=2)
|
||||
roll = gr.Button('Roll', elem_id="roll", visible=len(shared.artist_db.artists) > 0)
|
||||
|
||||
with gr.Column(scale=1, elem_id="style_pos_col"):
|
||||
prompt_style = gr.Dropdown(label="Style 1", elem_id="style_index", choices=[k for k, v in shared.prompt_styles.styles.items()], value=next(iter(shared.prompt_styles.styles.keys())), visible=len(shared.prompt_styles.styles) > 1)
|
||||
with gr.Column(scale=1, elem_id="roll_col"):
|
||||
roll = gr.Button(value=art_symbol, elem_id="roll", visible=len(shared.artist_db.artists) > 0)
|
||||
paste = gr.Button(value=paste_symbol, elem_id="paste")
|
||||
|
||||
with gr.Column(scale=10, 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())), visible=len(shared.prompt_styles.styles) > 1)
|
||||
|
||||
with gr.Row():
|
||||
with gr.Column(scale=8):
|
||||
negative_prompt = gr.Textbox(label="Negative prompt", elem_id="negative_prompt", show_label=False, placeholder="Negative prompt", lines=2)
|
||||
|
||||
with gr.Column(scale=1, elem_id="style_neg_col"):
|
||||
prompt_style2 = gr.Dropdown(label="Style 2", elem_id="style2_index", choices=[k for k, v in shared.prompt_styles.styles.items()], value=next(iter(shared.prompt_styles.styles.keys())), visible=len(shared.prompt_styles.styles) > 1)
|
||||
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())), visible=len(shared.prompt_styles.styles) > 1)
|
||||
|
||||
with gr.Column(scale=1):
|
||||
with gr.Row():
|
||||
interrupt = gr.Button('Interrupt', elem_id="interrupt")
|
||||
interrupt = gr.Button('Interrupt', elem_id=f"{id_part}_interrupt")
|
||||
submit = gr.Button('Generate', elem_id="generate", variant='primary')
|
||||
|
||||
interrupt.click(
|
||||
@@ -366,21 +372,21 @@ def create_toprow(is_img2img):
|
||||
prompt_style_apply = gr.Button('Apply style', elem_id="style_apply")
|
||||
save_style = gr.Button('Create style', elem_id="style_create")
|
||||
|
||||
return prompt, roll, prompt_style, negative_prompt, prompt_style2, submit, interrogate, prompt_style_apply, save_style
|
||||
return prompt, roll, prompt_style, negative_prompt, prompt_style2, submit, interrogate, prompt_style_apply, save_style, paste
|
||||
|
||||
|
||||
def setup_progressbar(progressbar, preview):
|
||||
check_progress = gr.Button('Check progress', elem_id="check_progress", visible=False)
|
||||
def setup_progressbar(progressbar, preview, id_part):
|
||||
check_progress = gr.Button('Check progress', elem_id=f"{id_part}_check_progress", visible=False)
|
||||
check_progress.click(
|
||||
fn=check_progress_call,
|
||||
fn=lambda: check_progress_call(id_part),
|
||||
show_progress=False,
|
||||
inputs=[],
|
||||
outputs=[progressbar, preview, preview],
|
||||
)
|
||||
|
||||
check_progress_initial = gr.Button('Check progress (first)', elem_id="check_progress_initial", visible=False)
|
||||
check_progress_initial = gr.Button('Check progress (first)', elem_id=f"{id_part}_check_progress_initial", visible=False)
|
||||
check_progress_initial.click(
|
||||
fn=check_progress_call_initial,
|
||||
fn=lambda: check_progress_call_initial(id_part),
|
||||
show_progress=False,
|
||||
inputs=[],
|
||||
outputs=[progressbar, preview, preview],
|
||||
@@ -389,23 +395,27 @@ def setup_progressbar(progressbar, preview):
|
||||
|
||||
def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
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 = create_toprow(is_img2img=False)
|
||||
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)
|
||||
|
||||
with gr.Row(elem_id='progressRow'):
|
||||
with gr.Column(scale=1):
|
||||
columnEmpty = "Empty"
|
||||
with gr.Row(elem_id='txt2img_progress_row'):
|
||||
with gr.Column(scale=1):
|
||||
pass
|
||||
|
||||
with gr.Column(scale=1):
|
||||
progressbar = gr.HTML(elem_id="progressbar")
|
||||
with gr.Column(scale=1):
|
||||
progressbar = gr.HTML(elem_id="txt2img_progressbar")
|
||||
txt2img_preview = gr.Image(elem_id='txt2img_preview', visible=False)
|
||||
setup_progressbar(progressbar, txt2img_preview)
|
||||
setup_progressbar(progressbar, txt2img_preview, 'txt2img')
|
||||
|
||||
with gr.Row().style(equal_height=False):
|
||||
with gr.Column(variant='panel'):
|
||||
steps = gr.Slider(minimum=1, maximum=150, step=1, label="Sampling Steps", value=20)
|
||||
sampler_index = gr.Radio(label='Sampling method', elem_id="txt2img_sampling", choices=[x.name for x in samplers], value=samplers[0].name, type="index")
|
||||
|
||||
with gr.Group():
|
||||
width = gr.Slider(minimum=64, maximum=2048, step=64, label="Width", value=512)
|
||||
height = gr.Slider(minimum=64, maximum=2048, step=64, label="Height", value=512)
|
||||
|
||||
with gr.Row():
|
||||
restore_faces = gr.Checkbox(label='Restore faces', value=False, visible=len(shared.face_restorers) > 1)
|
||||
tiling = gr.Checkbox(label='Tiling', value=False)
|
||||
@@ -421,10 +431,6 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
|
||||
cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='CFG Scale', value=7.0)
|
||||
|
||||
with gr.Group():
|
||||
width = gr.Slider(minimum=64, maximum=2048, step=64, label="Width", value=512)
|
||||
height = gr.Slider(minimum=64, maximum=2048, step=64, label="Height", value=512)
|
||||
|
||||
seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs()
|
||||
|
||||
with gr.Group():
|
||||
@@ -515,36 +521,56 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
]
|
||||
)
|
||||
|
||||
txt2img_paste_fields = [
|
||||
(txt2img_prompt, "Prompt"),
|
||||
(txt2img_negative_prompt, "Negative prompt"),
|
||||
(steps, "Steps"),
|
||||
(sampler_index, "Sampler"),
|
||||
(restore_faces, "Face restoration"),
|
||||
(cfg_scale, "CFG scale"),
|
||||
(seed, "Seed"),
|
||||
(width, "Size-1"),
|
||||
(height, "Size-2"),
|
||||
(batch_size, "Batch size"),
|
||||
(subseed, "Variation seed"),
|
||||
(subseed_strength, "Variation seed strength"),
|
||||
(seed_resize_from_w, "Seed resize from-1"),
|
||||
(seed_resize_from_h, "Seed resize from-2"),
|
||||
(denoising_strength, "Denoising strength"),
|
||||
(enable_hr, lambda d: "Denoising strength" in d),
|
||||
(hr_options, lambda d: gr.Row.update(visible="Denoising strength" in d)),
|
||||
]
|
||||
modules.generation_parameters_copypaste.connect_paste(paste, txt2img_paste_fields, txt2img_prompt)
|
||||
|
||||
with gr.Blocks(analytics_enabled=False) as img2img_interface:
|
||||
img2img_prompt, roll, img2img_prompt_style, img2img_negative_prompt, img2img_prompt_style2, submit, img2img_interrogate, img2img_prompt_style_apply, img2img_save_style = create_toprow(is_img2img=True)
|
||||
img2img_prompt, roll, img2img_prompt_style, img2img_negative_prompt, img2img_prompt_style2, submit, img2img_interrogate, img2img_prompt_style_apply, img2img_save_style, paste = create_toprow(is_img2img=True)
|
||||
|
||||
with gr.Row(elem_id='progressRow'):
|
||||
with gr.Column(scale=1):
|
||||
columnEmpty = "Empty"
|
||||
with gr.Row(elem_id='img2img_progress_row'):
|
||||
with gr.Column(scale=1):
|
||||
pass
|
||||
|
||||
with gr.Column(scale=1):
|
||||
progressbar = gr.HTML(elem_id="progressbar")
|
||||
with gr.Column(scale=1):
|
||||
progressbar = gr.HTML(elem_id="img2img_progressbar")
|
||||
img2img_preview = gr.Image(elem_id='img2img_preview', visible=False)
|
||||
setup_progressbar(progressbar, img2img_preview)
|
||||
setup_progressbar(progressbar, img2img_preview, 'img2img')
|
||||
|
||||
with gr.Row().style(equal_height=False):
|
||||
with gr.Column(variant='panel'):
|
||||
|
||||
with gr.Tabs(elem_id="mode_img2img") as tabs_img2img_mode:
|
||||
with gr.TabItem('img2img'):
|
||||
with gr.TabItem('img2img', id='img2img'):
|
||||
init_img = gr.Image(label="Image for img2img", show_label=False, source="upload", interactive=True, type="pil")
|
||||
|
||||
with gr.TabItem('Inpaint'):
|
||||
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_with_mask_comment = gr.HTML(elem_id="mask_bug_info", value="<small>if the editor shows ERROR, switch to another tab and back, then to \"Upload mask\" mode above and back</small>")
|
||||
|
||||
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")
|
||||
@@ -553,10 +579,11 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
inpaint_full_res = gr.Checkbox(label='Inpaint at full resolution', value=False)
|
||||
inpaint_full_res_padding = gr.Slider(label='Inpaint at full resolution padding, pixels', minimum=0, maximum=256, step=4, value=32)
|
||||
|
||||
with gr.TabItem('Batch img2img'):
|
||||
gr.HTML("<p class=\"text-gray-500\">Process images in a directory on the same machine where the server is running.</p>")
|
||||
img2img_batch_input_dir = gr.Textbox(label="Input directory")
|
||||
img2img_batch_output_dir = gr.Textbox(label="Output directory")
|
||||
with gr.TabItem('Batch img2img', id='batch'):
|
||||
hidden = '<br>Disabled when launched with --hide-ui-dir-config.' if shared.cmd_opts.hide_ui_dir_config else ''
|
||||
gr.HTML(f"<p class=\"text-gray-500\">Process images in a directory on the same machine where the server is running.{hidden}</p>")
|
||||
img2img_batch_input_dir = gr.Textbox(label="Input directory", **shared.hide_dirs)
|
||||
img2img_batch_output_dir = gr.Textbox(label="Output directory", **shared.hide_dirs)
|
||||
|
||||
with gr.Row():
|
||||
resize_mode = gr.Radio(label="Resize mode", elem_id="resize_mode", show_label=False, choices=["Just resize", "Crop and resize", "Resize and fill"], type="index", value="Just resize")
|
||||
@@ -564,6 +591,10 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
steps = gr.Slider(minimum=1, maximum=150, step=1, label="Sampling Steps", value=20)
|
||||
sampler_index = gr.Radio(label='Sampling method', choices=[x.name for x in samplers_for_img2img], value=samplers_for_img2img[0].name, type="index")
|
||||
|
||||
with gr.Group():
|
||||
width = gr.Slider(minimum=64, maximum=2048, step=64, label="Width", value=512)
|
||||
height = gr.Slider(minimum=64, maximum=2048, step=64, label="Height", value=512)
|
||||
|
||||
with gr.Row():
|
||||
restore_faces = gr.Checkbox(label='Restore faces', value=False, visible=len(shared.face_restorers) > 1)
|
||||
tiling = gr.Checkbox(label='Tiling', value=False)
|
||||
@@ -576,10 +607,6 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='CFG Scale', value=7.0)
|
||||
denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising strength', value=0.75)
|
||||
|
||||
with gr.Group():
|
||||
width = gr.Slider(minimum=64, maximum=2048, step=64, label="Width", value=512)
|
||||
height = gr.Slider(minimum=64, maximum=2048, step=64, label="Height", value=512)
|
||||
|
||||
seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs()
|
||||
|
||||
with gr.Group():
|
||||
@@ -597,7 +624,6 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
img2img_send_to_img2img = gr.Button('Send to img2img')
|
||||
img2img_send_to_inpaint = gr.Button('Send to inpaint')
|
||||
img2img_send_to_extras = gr.Button('Send to extras')
|
||||
img2img_save_style = gr.Button('Save prompt as style')
|
||||
|
||||
with gr.Group():
|
||||
html_info = gr.HTML()
|
||||
@@ -608,16 +634,13 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
|
||||
mask_mode.change(
|
||||
lambda mode, img: {
|
||||
#init_img_with_mask: gr.Image.update(visible=mode == 0, value=img["image"]),
|
||||
init_img_with_mask: gr_show(mode == 0),
|
||||
init_img_with_mask_comment: gr_show(mode == 0),
|
||||
init_img_inpaint: gr_show(mode == 1),
|
||||
init_mask_inpaint: gr_show(mode == 1),
|
||||
},
|
||||
inputs=[mask_mode, init_img_with_mask],
|
||||
outputs=[
|
||||
init_img_with_mask,
|
||||
init_img_with_mask_comment,
|
||||
init_img_inpaint,
|
||||
init_mask_inpaint,
|
||||
],
|
||||
@@ -720,12 +743,31 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
outputs=[prompt, negative_prompt, style1, style2],
|
||||
)
|
||||
|
||||
img2img_paste_fields = [
|
||||
(img2img_prompt, "Prompt"),
|
||||
(img2img_negative_prompt, "Negative prompt"),
|
||||
(steps, "Steps"),
|
||||
(sampler_index, "Sampler"),
|
||||
(restore_faces, "Face restoration"),
|
||||
(cfg_scale, "CFG scale"),
|
||||
(seed, "Seed"),
|
||||
(width, "Size-1"),
|
||||
(height, "Size-2"),
|
||||
(batch_size, "Batch size"),
|
||||
(subseed, "Variation seed"),
|
||||
(subseed_strength, "Variation seed strength"),
|
||||
(seed_resize_from_w, "Seed resize from-1"),
|
||||
(seed_resize_from_h, "Seed resize from-2"),
|
||||
(denoising_strength, "Denoising strength"),
|
||||
]
|
||||
modules.generation_parameters_copypaste.connect_paste(paste, img2img_paste_fields, img2img_prompt)
|
||||
|
||||
with gr.Blocks(analytics_enabled=False) as extras_interface:
|
||||
with gr.Row().style(equal_height=False):
|
||||
with gr.Column(variant='panel'):
|
||||
with gr.Tabs(elem_id="mode_extras"):
|
||||
with gr.TabItem('Single Image'):
|
||||
image = gr.Image(label="Source", source="upload", interactive=True, type="pil")
|
||||
extras_image = gr.Image(label="Source", source="upload", interactive=True, type="pil")
|
||||
|
||||
with gr.TabItem('Batch Process'):
|
||||
image_batch = gr.File(label="Batch Process", file_count="multiple", interactive=True, type="file")
|
||||
@@ -760,7 +802,7 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
_js="get_extras_tab_index",
|
||||
inputs=[
|
||||
dummy_component,
|
||||
image,
|
||||
extras_image,
|
||||
image_batch,
|
||||
gfpgan_visibility,
|
||||
codeformer_visibility,
|
||||
@@ -791,20 +833,25 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
outputs=[init_img_with_mask],
|
||||
)
|
||||
|
||||
pnginfo_interface = gr.Interface(
|
||||
wrap_gradio_call(run_pnginfo),
|
||||
inputs=[
|
||||
gr.Image(elem_id="pnginfo_image", label="Source", source="upload", interactive=True, type="pil"),
|
||||
],
|
||||
outputs=[
|
||||
gr.HTML(),
|
||||
gr.HTML(),
|
||||
gr.HTML(),
|
||||
],
|
||||
allow_flagging="never",
|
||||
analytics_enabled=False,
|
||||
live=True,
|
||||
)
|
||||
with gr.Blocks(analytics_enabled=False) as pnginfo_interface:
|
||||
with gr.Row().style(equal_height=False):
|
||||
with gr.Column(variant='panel'):
|
||||
image = gr.Image(elem_id="pnginfo_image", label="Source", source="upload", interactive=True, type="pil")
|
||||
|
||||
with gr.Column(variant='panel'):
|
||||
html = gr.HTML()
|
||||
generation_info = gr.Textbox(visible=False)
|
||||
html2 = gr.HTML()
|
||||
|
||||
with gr.Row():
|
||||
pnginfo_send_to_txt2img = gr.Button('Send to txt2img')
|
||||
pnginfo_send_to_img2img = gr.Button('Send to img2img')
|
||||
|
||||
image.change(
|
||||
fn=wrap_gradio_call(run_pnginfo),
|
||||
inputs=[image],
|
||||
outputs=[html, generation_info, html2],
|
||||
)
|
||||
|
||||
def create_setting_component(key):
|
||||
def fun():
|
||||
@@ -853,7 +900,7 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
|
||||
opts.save(shared.config_filename)
|
||||
|
||||
return f'{changed} settings changed.'
|
||||
return f'{changed} settings changed.', opts.dumpjson()
|
||||
|
||||
with gr.Blocks(analytics_enabled=False) as settings_interface:
|
||||
settings_submit = gr.Button(value="Apply settings", variant='primary')
|
||||
@@ -898,12 +945,6 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
if column is not None:
|
||||
column.__exit__()
|
||||
|
||||
settings_submit.click(
|
||||
fn=run_settings,
|
||||
inputs=components,
|
||||
outputs=[result]
|
||||
)
|
||||
|
||||
interfaces = [
|
||||
(txt2img_interface, "txt2img", "txt2img"),
|
||||
(img2img_interface, "img2img", "img2img"),
|
||||
@@ -929,51 +970,44 @@ 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(
|
||||
fn=lambda: opts.dumpjson(),
|
||||
inputs=[],
|
||||
outputs=[text_settings],
|
||||
)
|
||||
|
||||
tabs.change(
|
||||
fn=lambda x: x,
|
||||
inputs=[init_img_with_mask],
|
||||
outputs=[init_img_with_mask],
|
||||
)
|
||||
|
||||
tabs_img2img_mode.change(
|
||||
fn=lambda x: x,
|
||||
inputs=[init_img_with_mask],
|
||||
outputs=[init_img_with_mask],
|
||||
fn=run_settings,
|
||||
inputs=components,
|
||||
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_img2img",
|
||||
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(
|
||||
fn=lambda x: image_from_url_text(x),
|
||||
_js="extract_image_from_gallery",
|
||||
_js="extract_image_from_gallery_img2img",
|
||||
inputs=[img2img_gallery],
|
||||
outputs=[init_img],
|
||||
)
|
||||
|
||||
img2img_send_to_inpaint.click(
|
||||
fn=lambda x: image_from_url_text(x),
|
||||
_js="extract_image_from_gallery",
|
||||
_js="extract_image_from_gallery_inpaint",
|
||||
inputs=[img2img_gallery],
|
||||
outputs=[init_img_with_mask],
|
||||
)
|
||||
@@ -982,16 +1016,19 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
fn=lambda x: image_from_url_text(x),
|
||||
_js="extract_image_from_gallery_extras",
|
||||
inputs=[txt2img_gallery],
|
||||
outputs=[image],
|
||||
outputs=[extras_image],
|
||||
)
|
||||
|
||||
img2img_send_to_extras.click(
|
||||
fn=lambda x: image_from_url_text(x),
|
||||
_js="extract_image_from_gallery_extras",
|
||||
inputs=[img2img_gallery],
|
||||
outputs=[image],
|
||||
outputs=[extras_image],
|
||||
)
|
||||
|
||||
modules.generation_parameters_copypaste.connect_paste(pnginfo_send_to_txt2img, txt2img_paste_fields, generation_info, 'switch_to_txt2img')
|
||||
modules.generation_parameters_copypaste.connect_paste(pnginfo_send_to_img2img, img2img_paste_fields, generation_info, 'switch_to_img2img_img2img')
|
||||
|
||||
ui_config_file = cmd_opts.ui_config_file
|
||||
ui_settings = {}
|
||||
settings_count = len(ui_settings)
|
||||
@@ -1010,12 +1047,21 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
def apply_field(obj, field, condition=None):
|
||||
key = path + "/" + field
|
||||
|
||||
if getattr(obj,'custom_script_source',None) is not None:
|
||||
key = 'customscript/' + obj.custom_script_source + '/' + key
|
||||
|
||||
if getattr(obj, 'do_not_save_to_config', False):
|
||||
return
|
||||
|
||||
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):
|
||||
setattr(obj, field, saved_value)
|
||||
|
||||
if type(x) in [gr.Slider, gr.Radio, gr.Checkbox, gr.Textbox, gr.Number] and x.visible:
|
||||
apply_field(x, 'visible')
|
||||
|
||||
if type(x) == gr.Slider:
|
||||
apply_field(x, 'value')
|
||||
apply_field(x, 'minimum')
|
||||
@@ -1025,6 +1071,15 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
|
||||
if type(x) == gr.Radio:
|
||||
apply_field(x, 'value', lambda val: val in x.choices)
|
||||
|
||||
if type(x) == gr.Checkbox:
|
||||
apply_field(x, 'value')
|
||||
|
||||
if type(x) == gr.Textbox:
|
||||
apply_field(x, 'value')
|
||||
|
||||
if type(x) == gr.Number:
|
||||
apply_field(x, 'value')
|
||||
|
||||
visit(txt2img_interface, loadsave, "txt2img")
|
||||
visit(img2img_interface, loadsave, "img2img")
|
||||
visit(extras_interface, loadsave, "extras")
|
||||
|
||||
+13
-15
@@ -1,22 +1,20 @@
|
||||
transformers
|
||||
diffusers
|
||||
basicsr
|
||||
gfpgan
|
||||
gradio
|
||||
numpy
|
||||
Pillow
|
||||
realesrgan
|
||||
torch
|
||||
transformers
|
||||
omegaconf
|
||||
pytorch_lightning
|
||||
diffusers
|
||||
invisible-watermark
|
||||
scikit-image>=0.19
|
||||
fairscale==0.4.4
|
||||
fonts
|
||||
font-roboto
|
||||
gfpgan
|
||||
gradio
|
||||
invisible-watermark
|
||||
git+https://github.com/crowsonkb/k-diffusion.git
|
||||
numpy
|
||||
omegaconf
|
||||
piexif
|
||||
Pillow
|
||||
pytorch_lightning
|
||||
realesrgan
|
||||
scikit-image>=0.19
|
||||
git+https://github.com/TencentARC/GFPGAN.git@8d2447a2d918f8eba5a4a01463fd48e45126a379
|
||||
timm==0.4.12
|
||||
fairscale==0.4.4
|
||||
piexif
|
||||
transformers
|
||||
torch
|
||||
|
||||
@@ -2,7 +2,7 @@ transformers==4.19.2
|
||||
diffusers==0.3.0
|
||||
basicsr==1.4.2
|
||||
gfpgan==1.3.8
|
||||
gradio==3.3.1
|
||||
gradio==3.4b3
|
||||
numpy==1.23.3
|
||||
Pillow==9.2.0
|
||||
realesrgan==0.3.0
|
||||
|
||||
@@ -2,24 +2,61 @@ function gradioApp(){
|
||||
return document.getElementsByTagName('gradio-app')[0].shadowRoot;
|
||||
}
|
||||
|
||||
function get_uiCurrentTab() {
|
||||
return gradioApp().querySelector('.tabs button:not(.border-transparent)')
|
||||
}
|
||||
|
||||
uiUpdateCallbacks = []
|
||||
uiTabChangeCallbacks = []
|
||||
let uiCurrentTab = null
|
||||
|
||||
function onUiUpdate(callback){
|
||||
uiUpdateCallbacks.push(callback)
|
||||
}
|
||||
function onUiTabChange(callback){
|
||||
uiTabChangeCallbacks.push(callback)
|
||||
}
|
||||
|
||||
function uiUpdate(root){
|
||||
uiUpdateCallbacks.forEach(function(x){
|
||||
try {
|
||||
x()
|
||||
} catch (e) {
|
||||
(console.error || console.log).call(console, e.message, e);
|
||||
}
|
||||
})
|
||||
function runCallback(x){
|
||||
try {
|
||||
x()
|
||||
} catch (e) {
|
||||
(console.error || console.log).call(console, e.message, e);
|
||||
}
|
||||
}
|
||||
function executeCallbacks(queue) {
|
||||
queue.forEach(runCallback)
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var mutationObserver = new MutationObserver(function(m){
|
||||
uiUpdate(gradioApp());
|
||||
executeCallbacks(uiUpdateCallbacks);
|
||||
const newTab = get_uiCurrentTab();
|
||||
if ( newTab && ( newTab !== uiCurrentTab ) ) {
|
||||
uiCurrentTab = newTab;
|
||||
executeCallbacks(uiTabChangeCallbacks);
|
||||
}
|
||||
});
|
||||
mutationObserver.observe( gradioApp(), { childList:true, subtree:true })
|
||||
});
|
||||
|
||||
/**
|
||||
* checks that a UI element is not in another hidden element or tab content
|
||||
*/
|
||||
function uiElementIsVisible(el) {
|
||||
let isVisible = !el.closest('.\\!hidden');
|
||||
if ( ! isVisible ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while( isVisible = el.closest('.tabitem')?.style.display !== 'none' ) {
|
||||
if ( ! isVisible ) {
|
||||
return false;
|
||||
} else if ( el.parentElement ) {
|
||||
el = el.parentElement
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isVisible;
|
||||
}
|
||||
+62
-6
@@ -59,7 +59,55 @@ def find_noise_for_image(p, cond, uncond, cfg_scale, steps):
|
||||
return x / x.std()
|
||||
|
||||
|
||||
Cached = namedtuple("Cached", ["noise", "cfg_scale", "steps", "latent", "original_prompt", "original_negative_prompt"])
|
||||
Cached = namedtuple("Cached", ["noise", "cfg_scale", "steps", "latent", "original_prompt", "original_negative_prompt", "sigma_adjustment"])
|
||||
|
||||
|
||||
# Based on changes suggested by briansemrau in https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/736
|
||||
def find_noise_for_image_sigma_adjustment(p, cond, uncond, cfg_scale, steps):
|
||||
x = p.init_latent
|
||||
|
||||
s_in = x.new_ones([x.shape[0]])
|
||||
dnw = K.external.CompVisDenoiser(shared.sd_model)
|
||||
sigmas = dnw.get_sigmas(steps).flip(0)
|
||||
|
||||
shared.state.sampling_steps = steps
|
||||
|
||||
for i in trange(1, len(sigmas)):
|
||||
shared.state.sampling_step += 1
|
||||
|
||||
x_in = torch.cat([x] * 2)
|
||||
sigma_in = torch.cat([sigmas[i - 1] * s_in] * 2)
|
||||
cond_in = torch.cat([uncond, cond])
|
||||
|
||||
c_out, c_in = [K.utils.append_dims(k, x_in.ndim) for k in dnw.get_scalings(sigma_in)]
|
||||
|
||||
if i == 1:
|
||||
t = dnw.sigma_to_t(torch.cat([sigmas[i] * s_in] * 2))
|
||||
else:
|
||||
t = dnw.sigma_to_t(sigma_in)
|
||||
|
||||
eps = shared.sd_model.apply_model(x_in * c_in, t, cond=cond_in)
|
||||
denoised_uncond, denoised_cond = (x_in + eps * c_out).chunk(2)
|
||||
|
||||
denoised = denoised_uncond + (denoised_cond - denoised_uncond) * cfg_scale
|
||||
|
||||
if i == 1:
|
||||
d = (x - denoised) / (2 * sigmas[i])
|
||||
else:
|
||||
d = (x - denoised) / sigmas[i - 1]
|
||||
|
||||
dt = sigmas[i] - sigmas[i - 1]
|
||||
x = x + d * dt
|
||||
|
||||
sd_samplers.store_latent(x)
|
||||
|
||||
# This shouldn't be necessary, but solved some VRAM issues
|
||||
del x_in, sigma_in, cond_in, c_out, c_in, t,
|
||||
del eps, denoised_uncond, denoised_cond, denoised, d, dt
|
||||
|
||||
shared.state.nextjob()
|
||||
|
||||
return x / sigmas[-1]
|
||||
|
||||
|
||||
class Script(scripts.Script):
|
||||
@@ -78,9 +126,10 @@ class Script(scripts.Script):
|
||||
cfg = gr.Slider(label="Decode CFG scale", minimum=0.0, maximum=15.0, step=0.1, value=1.0)
|
||||
st = gr.Slider(label="Decode steps", minimum=1, maximum=150, step=1, value=50)
|
||||
randomness = gr.Slider(label="Randomness", minimum=0.0, maximum=1.0, step=0.01, value=0.0)
|
||||
return [original_prompt, original_negative_prompt, cfg, st, randomness]
|
||||
sigma_adjustment = gr.Checkbox(label="Sigma adjustment for finding noise for image", value=False)
|
||||
return [original_prompt, original_negative_prompt, cfg, st, randomness, sigma_adjustment]
|
||||
|
||||
def run(self, p, original_prompt, original_negative_prompt, cfg, st, randomness):
|
||||
def run(self, p, original_prompt, original_negative_prompt, cfg, st, randomness, sigma_adjustment):
|
||||
p.batch_size = 1
|
||||
p.batch_count = 1
|
||||
|
||||
@@ -88,7 +137,10 @@ class Script(scripts.Script):
|
||||
def sample_extra(conditioning, unconditional_conditioning, seeds, subseeds, subseed_strength):
|
||||
lat = (p.init_latent.cpu().numpy() * 10).astype(int)
|
||||
|
||||
same_params = self.cache is not None and self.cache.cfg_scale == cfg and self.cache.steps == st and self.cache.original_prompt == original_prompt and self.cache.original_negative_prompt == original_negative_prompt
|
||||
same_params = self.cache is not None and self.cache.cfg_scale == cfg and self.cache.steps == st \
|
||||
and self.cache.original_prompt == original_prompt \
|
||||
and self.cache.original_negative_prompt == original_negative_prompt \
|
||||
and self.cache.sigma_adjustment == sigma_adjustment
|
||||
same_everything = same_params and self.cache.latent.shape == lat.shape and np.abs(self.cache.latent-lat).sum() < 100
|
||||
|
||||
if same_everything:
|
||||
@@ -97,8 +149,11 @@ class Script(scripts.Script):
|
||||
shared.state.job_count += 1
|
||||
cond = p.sd_model.get_learned_conditioning(p.batch_size * [original_prompt])
|
||||
uncond = p.sd_model.get_learned_conditioning(p.batch_size * [original_negative_prompt])
|
||||
rec_noise = find_noise_for_image(p, cond, uncond, cfg, st)
|
||||
self.cache = Cached(rec_noise, cfg, st, lat, original_prompt, original_negative_prompt)
|
||||
if sigma_adjustment:
|
||||
rec_noise = find_noise_for_image_sigma_adjustment(p, cond, uncond, cfg, st)
|
||||
else:
|
||||
rec_noise = find_noise_for_image(p, cond, uncond, cfg, st)
|
||||
self.cache = Cached(rec_noise, cfg, st, lat, original_prompt, original_negative_prompt, sigma_adjustment)
|
||||
|
||||
rand_noise = processing.create_random_tensors(p.init_latent.shape[1:], [p.seed + x + 1 for x in range(p.init_latent.shape[0])])
|
||||
|
||||
@@ -121,6 +176,7 @@ class Script(scripts.Script):
|
||||
p.extra_generation_params["Decode CFG scale"] = cfg
|
||||
p.extra_generation_params["Decode steps"] = st
|
||||
p.extra_generation_params["Randomness"] = randomness
|
||||
p.extra_generation_params["Sigma Adjustment"] = sigma_adjustment
|
||||
|
||||
processed = processing.process_images(p)
|
||||
|
||||
|
||||
+26
-5
@@ -141,10 +141,11 @@ class Script(scripts.Script):
|
||||
y_values = gr.Textbox(label="Y values", visible=False, lines=1)
|
||||
|
||||
draw_legend = gr.Checkbox(label='Draw legend', value=True)
|
||||
|
||||
return [x_type, x_values, y_type, y_values, draw_legend]
|
||||
no_fixed_seeds = gr.Checkbox(label='Keep -1 for seeds', value=False)
|
||||
|
||||
def run(self, p, x_type, x_values, y_type, y_values, draw_legend):
|
||||
return [x_type, x_values, y_type, y_values, draw_legend, no_fixed_seeds]
|
||||
|
||||
def run(self, p, x_type, x_values, y_type, y_values, draw_legend, no_fixed_seeds):
|
||||
modules.processing.fix_seed(p)
|
||||
p.batch_size = 1
|
||||
|
||||
@@ -169,7 +170,7 @@ class Script(scripts.Script):
|
||||
end = int(mc.group(2))
|
||||
num = int(mc.group(3)) if mc.group(3) is not None else 1
|
||||
|
||||
valslist_ext += [int(x) for x in np.linspace(start = start, stop = end, num = num).tolist()]
|
||||
valslist_ext += [int(x) for x in np.linspace(start=start, stop=end, num=num).tolist()]
|
||||
else:
|
||||
valslist_ext.append(val)
|
||||
|
||||
@@ -191,7 +192,7 @@ class Script(scripts.Script):
|
||||
end = float(mc.group(2))
|
||||
num = int(mc.group(3)) if mc.group(3) is not None else 1
|
||||
|
||||
valslist_ext += np.linspace(start = start, stop = end, num = num).tolist()
|
||||
valslist_ext += np.linspace(start=start, stop=end, num=num).tolist()
|
||||
else:
|
||||
valslist_ext.append(val)
|
||||
|
||||
@@ -207,6 +208,26 @@ class Script(scripts.Script):
|
||||
y_opt = axis_options[y_type]
|
||||
ys = process_axis(y_opt, y_values)
|
||||
|
||||
def fix_axis_seeds(axis_opt, axis_list):
|
||||
if axis_opt.label == 'Seed':
|
||||
return [int(random.randrange(4294967294)) if val is None or val == '' or val == -1 else val for val in axis_list]
|
||||
else:
|
||||
return axis_list
|
||||
|
||||
if not no_fixed_seeds:
|
||||
xs = fix_axis_seeds(x_opt, xs)
|
||||
ys = fix_axis_seeds(y_opt, ys)
|
||||
|
||||
if x_opt.label == 'Steps':
|
||||
total_steps = sum(xs) * len(ys)
|
||||
elif y_opt.label == 'Steps':
|
||||
total_steps = sum(ys) * len(xs)
|
||||
else:
|
||||
total_steps = p.steps * len(xs) * len(ys)
|
||||
|
||||
print(f"X/Y plot will create {len(xs) * len(ys) * p.n_iter} images on a {len(xs)}x{len(ys)} grid. (Total steps to process: {total_steps * p.n_iter})")
|
||||
shared.total_tqdm.updateTotal(total_steps * p.n_iter)
|
||||
|
||||
def cell(x, y):
|
||||
pc = copy(p)
|
||||
x_opt.apply(pc, x, xs)
|
||||
|
||||
@@ -74,10 +74,21 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#roll{
|
||||
min-width: 1em;
|
||||
max-width: 4em;
|
||||
margin: 0.5em;
|
||||
#roll_col{
|
||||
min-width: unset !important;
|
||||
flex-grow: 0 !important;
|
||||
padding: 0.4em 0;
|
||||
}
|
||||
|
||||
#roll, #paste{
|
||||
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;
|
||||
}
|
||||
|
||||
#style_apply, #style_create, #interrogate{
|
||||
@@ -89,7 +100,7 @@
|
||||
min-width: 8em !important;
|
||||
}
|
||||
|
||||
#style_index, #style2_index{
|
||||
#txt2img_style_index, #txt2img_style2_index, #img2img_style_index, #img2img_style2_index{
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
@@ -143,7 +154,23 @@ button{
|
||||
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 {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
#txt2img_preview, #img2img_preview {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
#txt2img_preview div.left-0.top-0, #img2img_preview div.left-0.top-0{
|
||||
@@ -210,7 +237,7 @@ input[type="range"]{
|
||||
#txt2img_negative_prompt, #img2img_negative_prompt{
|
||||
}
|
||||
|
||||
#progressbar{
|
||||
#txt2img_progressbar, #img2img_progressbar{
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
right: 0;
|
||||
@@ -219,7 +246,7 @@ input[type="range"]{
|
||||
display: block;
|
||||
}
|
||||
|
||||
#progressRow{
|
||||
#txt2img_progress_row, #img2img_progress_row{
|
||||
margin-bottom: 10px;
|
||||
margin-top: -18px;
|
||||
}
|
||||
@@ -354,7 +381,7 @@ input[type="range"]{
|
||||
display:none
|
||||
}
|
||||
|
||||
#interrupt{
|
||||
#txt2img_interrupt, #img2img_interrupt{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 72px;
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 526 KiB |
@@ -3,6 +3,8 @@
|
||||
if not defined PYTHON (set PYTHON=python)
|
||||
if not defined VENV_DIR (set VENV_DIR=venv)
|
||||
|
||||
set ERROR_REPORTING=FALSE
|
||||
|
||||
mkdir tmp 2>NUL
|
||||
|
||||
%PYTHON% -c "" >tmp/stdout.txt 2>tmp/stderr.txt
|
||||
|
||||
@@ -50,6 +50,7 @@ def wrap_gradio_gpu_call(func):
|
||||
shared.state.sampling_step = 0
|
||||
shared.state.job_count = -1
|
||||
shared.state.job_no = 0
|
||||
shared.state.job_timestamp = shared.state.get_job_timestamp()
|
||||
shared.state.current_latent = None
|
||||
shared.state.current_image = None
|
||||
shared.state.current_image_sampling_step = 0
|
||||
|
||||
Reference in New Issue
Block a user