Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9bc3332d86 | |||
| f8395750f4 |
+12
-1
@@ -1 +1,12 @@
|
|||||||
* @AUTOMATIC1111 @w-e-w @catboxanon
|
* @AUTOMATIC1111
|
||||||
|
|
||||||
|
# if you were managing a localization and were removed from this file, this is because
|
||||||
|
# the intended way to do localizations now is via extensions. See:
|
||||||
|
# https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Developing-extensions
|
||||||
|
# Make a repo with your localization and since you are still listed as a collaborator
|
||||||
|
# you can add it to the wiki page yourself. This change is because some people complained
|
||||||
|
# the git commit log is cluttered with things unrelated to almost everyone and
|
||||||
|
# because I believe this is the best overall for the project to handle localizations almost
|
||||||
|
# entirely without my oversight.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,6 @@ python_cmd="python3.11"
|
|||||||
2. Navigate to the directory you would like the webui to be installed and execute the following command:
|
2. Navigate to the directory you would like the webui to be installed and execute the following command:
|
||||||
```bash
|
```bash
|
||||||
wget -q https://raw.githubusercontent.com/AUTOMATIC1111/stable-diffusion-webui/master/webui.sh
|
wget -q https://raw.githubusercontent.com/AUTOMATIC1111/stable-diffusion-webui/master/webui.sh
|
||||||
chmod +x webui.sh
|
|
||||||
```
|
```
|
||||||
Or just clone the repo wherever you want:
|
Or just clone the repo wherever you want:
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -1,98 +0,0 @@
|
|||||||
model:
|
|
||||||
target: sgm.models.diffusion.DiffusionEngine
|
|
||||||
params:
|
|
||||||
scale_factor: 0.13025
|
|
||||||
disable_first_stage_autocast: True
|
|
||||||
|
|
||||||
denoiser_config:
|
|
||||||
target: sgm.modules.diffusionmodules.denoiser.DiscreteDenoiser
|
|
||||||
params:
|
|
||||||
num_idx: 1000
|
|
||||||
|
|
||||||
weighting_config:
|
|
||||||
target: sgm.modules.diffusionmodules.denoiser_weighting.VWeighting
|
|
||||||
scaling_config:
|
|
||||||
target: sgm.modules.diffusionmodules.denoiser_scaling.VScaling
|
|
||||||
discretization_config:
|
|
||||||
target: sgm.modules.diffusionmodules.discretizer.LegacyDDPMDiscretization
|
|
||||||
|
|
||||||
network_config:
|
|
||||||
target: sgm.modules.diffusionmodules.openaimodel.UNetModel
|
|
||||||
params:
|
|
||||||
adm_in_channels: 2816
|
|
||||||
num_classes: sequential
|
|
||||||
use_checkpoint: False
|
|
||||||
in_channels: 4
|
|
||||||
out_channels: 4
|
|
||||||
model_channels: 320
|
|
||||||
attention_resolutions: [4, 2]
|
|
||||||
num_res_blocks: 2
|
|
||||||
channel_mult: [1, 2, 4]
|
|
||||||
num_head_channels: 64
|
|
||||||
use_spatial_transformer: True
|
|
||||||
use_linear_in_transformer: True
|
|
||||||
transformer_depth: [1, 2, 10] # note: the first is unused (due to attn_res starting at 2) 32, 16, 8 --> 64, 32, 16
|
|
||||||
context_dim: 2048
|
|
||||||
spatial_transformer_attn_type: softmax-xformers
|
|
||||||
legacy: False
|
|
||||||
|
|
||||||
conditioner_config:
|
|
||||||
target: sgm.modules.GeneralConditioner
|
|
||||||
params:
|
|
||||||
emb_models:
|
|
||||||
# crossattn cond
|
|
||||||
- is_trainable: False
|
|
||||||
input_key: txt
|
|
||||||
target: sgm.modules.encoders.modules.FrozenCLIPEmbedder
|
|
||||||
params:
|
|
||||||
layer: hidden
|
|
||||||
layer_idx: 11
|
|
||||||
# crossattn and vector cond
|
|
||||||
- is_trainable: False
|
|
||||||
input_key: txt
|
|
||||||
target: sgm.modules.encoders.modules.FrozenOpenCLIPEmbedder2
|
|
||||||
params:
|
|
||||||
arch: ViT-bigG-14
|
|
||||||
version: laion2b_s39b_b160k
|
|
||||||
freeze: True
|
|
||||||
layer: penultimate
|
|
||||||
always_return_pooled: True
|
|
||||||
legacy: False
|
|
||||||
# vector cond
|
|
||||||
- is_trainable: False
|
|
||||||
input_key: original_size_as_tuple
|
|
||||||
target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
|
|
||||||
params:
|
|
||||||
outdim: 256 # multiplied by two
|
|
||||||
# vector cond
|
|
||||||
- is_trainable: False
|
|
||||||
input_key: crop_coords_top_left
|
|
||||||
target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
|
|
||||||
params:
|
|
||||||
outdim: 256 # multiplied by two
|
|
||||||
# vector cond
|
|
||||||
- is_trainable: False
|
|
||||||
input_key: target_size_as_tuple
|
|
||||||
target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
|
|
||||||
params:
|
|
||||||
outdim: 256 # multiplied by two
|
|
||||||
|
|
||||||
first_stage_config:
|
|
||||||
target: sgm.models.autoencoder.AutoencoderKLInferenceWrapper
|
|
||||||
params:
|
|
||||||
embed_dim: 4
|
|
||||||
monitor: val/rec_loss
|
|
||||||
ddconfig:
|
|
||||||
attn_type: vanilla-xformers
|
|
||||||
double_z: true
|
|
||||||
z_channels: 4
|
|
||||||
resolution: 256
|
|
||||||
in_channels: 3
|
|
||||||
out_ch: 3
|
|
||||||
ch: 128
|
|
||||||
ch_mult: [1, 2, 4, 4]
|
|
||||||
num_res_blocks: 2
|
|
||||||
attn_resolutions: []
|
|
||||||
dropout: 0.0
|
|
||||||
lossconfig:
|
|
||||||
target: torch.nn.Identity
|
|
||||||
@@ -816,7 +816,7 @@ onUiLoaded(async() => {
|
|||||||
// Increase or decrease brush size based on scroll direction
|
// Increase or decrease brush size based on scroll direction
|
||||||
adjustBrushSize(elemId, e.deltaY);
|
adjustBrushSize(elemId, e.deltaY);
|
||||||
}
|
}
|
||||||
}, {passive: false});
|
});
|
||||||
|
|
||||||
// Handle the move event for pan functionality. Updates the panX and panY variables and applies the new transform to the target element.
|
// Handle the move event for pan functionality. Updates the panX and panY variables and applies the new transform to the target element.
|
||||||
function handleMoveKeyDown(e) {
|
function handleMoveKeyDown(e) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Hypertile module for splitting attention layers in SD-1.5 U-Net and SD-1.5 VAE
|
Hypertile module for splitting attention layers in SD-1.5 U-Net and SD-1.5 VAE
|
||||||
Warn: The patch works well only if the input image has a width and height that are multiples of 128
|
Warn: The patch works well only if the input image has a width and height that are multiples of 128
|
||||||
Original author: @tfernd GitHub: https://github.com/tfernd/HyperTile
|
Original author: @tfernd Github: https://github.com/tfernd/HyperTile
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|||||||
+6
-6
@@ -34,14 +34,14 @@ class ScriptPostprocessingAutosizedCrop(scripts_postprocessing.ScriptPostprocess
|
|||||||
with ui_components.InputAccordion(False, label="Auto-sized crop") as enable:
|
with ui_components.InputAccordion(False, label="Auto-sized crop") as enable:
|
||||||
gr.Markdown('Each image is center-cropped with an automatically chosen width and height.')
|
gr.Markdown('Each image is center-cropped with an automatically chosen width and height.')
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
mindim = gr.Slider(minimum=64, maximum=2048, step=8, label="Dimension lower bound", value=384, elem_id=self.elem_id_suffix("postprocess_multicrop_mindim"))
|
mindim = gr.Slider(minimum=64, maximum=2048, step=8, label="Dimension lower bound", value=384, elem_id="postprocess_multicrop_mindim")
|
||||||
maxdim = gr.Slider(minimum=64, maximum=2048, step=8, label="Dimension upper bound", value=768, elem_id=self.elem_id_suffix("postprocess_multicrop_maxdim"))
|
maxdim = gr.Slider(minimum=64, maximum=2048, step=8, label="Dimension upper bound", value=768, elem_id="postprocess_multicrop_maxdim")
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
minarea = gr.Slider(minimum=64 * 64, maximum=2048 * 2048, step=1, label="Area lower bound", value=64 * 64, elem_id=self.elem_id_suffix("postprocess_multicrop_minarea"))
|
minarea = gr.Slider(minimum=64 * 64, maximum=2048 * 2048, step=1, label="Area lower bound", value=64 * 64, elem_id="postprocess_multicrop_minarea")
|
||||||
maxarea = gr.Slider(minimum=64 * 64, maximum=2048 * 2048, step=1, label="Area upper bound", value=640 * 640, elem_id=self.elem_id_suffix("postprocess_multicrop_maxarea"))
|
maxarea = gr.Slider(minimum=64 * 64, maximum=2048 * 2048, step=1, label="Area upper bound", value=640 * 640, elem_id="postprocess_multicrop_maxarea")
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
objective = gr.Radio(["Maximize area", "Minimize error"], value="Maximize area", label="Resizing objective", elem_id=self.elem_id_suffix("postprocess_multicrop_objective"))
|
objective = gr.Radio(["Maximize area", "Minimize error"], value="Maximize area", label="Resizing objective", elem_id="postprocess_multicrop_objective")
|
||||||
threshold = gr.Slider(minimum=0, maximum=1, step=0.01, label="Error threshold", value=0.1, elem_id=self.elem_id_suffix("postprocess_multicrop_threshold"))
|
threshold = gr.Slider(minimum=0, maximum=1, step=0.01, label="Error threshold", value=0.1, elem_id="postprocess_multicrop_threshold")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"enable": enable,
|
"enable": enable,
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ class ScriptPostprocessingFocalCrop(scripts_postprocessing.ScriptPostprocessing)
|
|||||||
|
|
||||||
def ui(self):
|
def ui(self):
|
||||||
with ui_components.InputAccordion(False, label="Auto focal point crop") as enable:
|
with ui_components.InputAccordion(False, label="Auto focal point crop") as enable:
|
||||||
face_weight = gr.Slider(label='Focal point face weight', value=0.9, minimum=0.0, maximum=1.0, step=0.05, elem_id=self.elem_id_suffix("postprocess_focal_crop_face_weight"))
|
face_weight = gr.Slider(label='Focal point face weight', value=0.9, minimum=0.0, maximum=1.0, step=0.05, elem_id="postprocess_focal_crop_face_weight")
|
||||||
entropy_weight = gr.Slider(label='Focal point entropy weight', value=0.15, minimum=0.0, maximum=1.0, step=0.05, elem_id=self.elem_id_suffix("postprocess_focal_crop_entropy_weight"))
|
entropy_weight = gr.Slider(label='Focal point entropy weight', value=0.15, minimum=0.0, maximum=1.0, step=0.05, elem_id="postprocess_focal_crop_entropy_weight")
|
||||||
edges_weight = gr.Slider(label='Focal point edges weight', value=0.5, minimum=0.0, maximum=1.0, step=0.05, elem_id=self.elem_id_suffix("postprocess_focal_crop_edges_weight"))
|
edges_weight = gr.Slider(label='Focal point edges weight', value=0.5, minimum=0.0, maximum=1.0, step=0.05, elem_id="postprocess_focal_crop_edges_weight")
|
||||||
debug = gr.Checkbox(label='Create debug image', elem_id=self.elem_id_suffix("train_process_focal_crop_debug"))
|
debug = gr.Checkbox(label='Create debug image', elem_id="train_process_focal_crop_debug")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"enable": enable,
|
"enable": enable,
|
||||||
|
|||||||
+2
-2
@@ -35,8 +35,8 @@ class ScriptPostprocessingSplitOversized(scripts_postprocessing.ScriptPostproces
|
|||||||
def ui(self):
|
def ui(self):
|
||||||
with ui_components.InputAccordion(False, label="Split oversized images") as enable:
|
with ui_components.InputAccordion(False, label="Split oversized images") as enable:
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
split_threshold = gr.Slider(label='Threshold', value=0.5, minimum=0.0, maximum=1.0, step=0.05, elem_id=self.elem_id_suffix("postprocess_split_threshold"))
|
split_threshold = gr.Slider(label='Threshold', value=0.5, minimum=0.0, maximum=1.0, step=0.05, elem_id="postprocess_split_threshold")
|
||||||
overlap_ratio = gr.Slider(label='Overlap ratio', value=0.2, minimum=0.0, maximum=0.9, step=0.05, elem_id=self.elem_id_suffix("postprocess_overlap_ratio"))
|
overlap_ratio = gr.Slider(label='Overlap ratio', value=0.2, minimum=0.0, maximum=0.9, step=0.05, elem_id="postprocess_overlap_ratio")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"enable": enable,
|
"enable": enable,
|
||||||
|
|||||||
@@ -1,69 +1,36 @@
|
|||||||
// Stable Diffusion WebUI - Bracket Checker
|
// Stable Diffusion WebUI - Bracket checker
|
||||||
// By @Bwin4L, @akx, @w-e-w, @Haoming02
|
// By Hingashi no Florin/Bwin4L & @akx
|
||||||
// Counts open and closed brackets (round, square, curly) in the prompt and negative prompt text boxes in the txt2img and img2img tabs.
|
// Counts open and closed brackets (round, square, curly) in the prompt and negative prompt text boxes in the txt2img and img2img tabs.
|
||||||
// If there's a mismatch, the keyword counter turns red, and if you hover on it, a tooltip tells you what's wrong.
|
// If there's a mismatch, the keyword counter turns red and if you hover on it, a tooltip tells you what's wrong.
|
||||||
|
|
||||||
function checkBrackets(textArea, counterElem) {
|
function checkBrackets(textArea, counterElt) {
|
||||||
const pairs = [
|
var counts = {};
|
||||||
['(', ')', 'round brackets'],
|
(textArea.value.match(/[(){}[\]]/g) || []).forEach(bracket => {
|
||||||
['[', ']', 'square brackets'],
|
counts[bracket] = (counts[bracket] || 0) + 1;
|
||||||
['{', '}', 'curly brackets']
|
});
|
||||||
];
|
var errors = [];
|
||||||
|
|
||||||
const counts = {};
|
function checkPair(open, close, kind) {
|
||||||
const errors = new Set();
|
if (counts[open] !== counts[close]) {
|
||||||
let i = 0;
|
errors.push(
|
||||||
|
`${open}...${close} - Detected ${counts[open] || 0} opening and ${counts[close] || 0} closing ${kind}.`
|
||||||
while (i < textArea.value.length) {
|
);
|
||||||
let char = textArea.value[i];
|
|
||||||
let escaped = false;
|
|
||||||
while (char === '\\' && i + 1 < textArea.value.length) {
|
|
||||||
escaped = !escaped;
|
|
||||||
i++;
|
|
||||||
char = textArea.value[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (escaped) {
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [open, close, label] of pairs) {
|
|
||||||
if (char === open) {
|
|
||||||
counts[label] = (counts[label] || 0) + 1;
|
|
||||||
} else if (char === close) {
|
|
||||||
counts[label] = (counts[label] || 0) - 1;
|
|
||||||
if (counts[label] < 0) {
|
|
||||||
errors.add(`Incorrect order of ${label}.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [open, close, label] of pairs) {
|
|
||||||
if (counts[label] == undefined) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (counts[label] > 0) {
|
|
||||||
errors.add(`${open} ... ${close} - Detected ${counts[label]} more opening than closing ${label}.`);
|
|
||||||
} else if (counts[label] < 0) {
|
|
||||||
errors.add(`${open} ... ${close} - Detected ${-counts[label]} more closing than opening ${label}.`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
counterElem.title = [...errors].join('\n');
|
checkPair('(', ')', 'round brackets');
|
||||||
counterElem.classList.toggle('error', errors.size !== 0);
|
checkPair('[', ']', 'square brackets');
|
||||||
|
checkPair('{', '}', 'curly brackets');
|
||||||
|
counterElt.title = errors.join('\n');
|
||||||
|
counterElt.classList.toggle('error', errors.length !== 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupBracketChecking(id_prompt, id_counter) {
|
function setupBracketChecking(id_prompt, id_counter) {
|
||||||
const textarea = gradioApp().querySelector(`#${id_prompt} > label > textarea`);
|
var textarea = gradioApp().querySelector("#" + id_prompt + " > label > textarea");
|
||||||
const counter = gradioApp().getElementById(id_counter);
|
var counter = gradioApp().getElementById(id_counter);
|
||||||
|
|
||||||
if (textarea && counter) {
|
if (textarea && counter) {
|
||||||
onEdit(`${id_prompt}_BracketChecking`, textarea, 400, () => checkBrackets(textarea, counter));
|
textarea.addEventListener("input", () => checkBrackets(textarea, counter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<a href="{api_docs}">API</a>
|
<a href="{api_docs}">API</a>
|
||||||
•
|
•
|
||||||
<a href="https://github.com/AUTOMATIC1111/stable-diffusion-webui">GitHub</a>
|
<a href="https://github.com/AUTOMATIC1111/stable-diffusion-webui">Github</a>
|
||||||
•
|
•
|
||||||
<a href="https://gradio.app">Gradio</a>
|
<a href="https://gradio.app">Gradio</a>
|
||||||
•
|
•
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ var contextMenuInit = function() {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, {passive: false});
|
});
|
||||||
});
|
});
|
||||||
eventListenerApplied = true;
|
eventListenerApplied = true;
|
||||||
|
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ function setupExtraNetworks() {
|
|||||||
setupExtraNetworksForTab('img2img');
|
setupExtraNetworksForTab('img2img');
|
||||||
}
|
}
|
||||||
|
|
||||||
var re_extranet = /<([^:^>]+:[^:]+):[\d.]+>(.*)/s;
|
var re_extranet = /<([^:^>]+:[^:]+):[\d.]+>(.*)/;
|
||||||
var re_extranet_g = /<([^:^>]+:[^:]+):[\d.]+>/g;
|
var re_extranet_g = /<([^:^>]+:[^:]+):[\d.]+>/g;
|
||||||
|
|
||||||
var re_extranet_neg = /\(([^:^>]+:[\d.]+)\)/;
|
var re_extranet_neg = /\(([^:^>]+:[\d.]+)\)/;
|
||||||
|
|||||||
+12
-18
@@ -13,7 +13,6 @@ function showModal(event) {
|
|||||||
if (modalImage.style.display === 'none') {
|
if (modalImage.style.display === 'none') {
|
||||||
lb.style.setProperty('background-image', 'url(' + source.src + ')');
|
lb.style.setProperty('background-image', 'url(' + source.src + ')');
|
||||||
}
|
}
|
||||||
updateModalImage();
|
|
||||||
lb.style.display = "flex";
|
lb.style.display = "flex";
|
||||||
lb.focus();
|
lb.focus();
|
||||||
|
|
||||||
@@ -32,26 +31,21 @@ function negmod(n, m) {
|
|||||||
return ((n % m) + m) % m;
|
return ((n % m) + m) % m;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateModalImage() {
|
|
||||||
const modalImage = gradioApp().getElementById("modalImage");
|
|
||||||
let currentButton = selected_gallery_button();
|
|
||||||
let preview = gradioApp().querySelectorAll('.livePreview > img');
|
|
||||||
if (opts.js_live_preview_in_modal_lightbox && preview.length > 0) {
|
|
||||||
// show preview image if available
|
|
||||||
modalImage.src = preview[preview.length - 1].src;
|
|
||||||
} else if (currentButton?.children?.length > 0 && modalImage.src != currentButton.children[0].src) {
|
|
||||||
modalImage.src = currentButton.children[0].src;
|
|
||||||
if (modalImage.style.display === 'none') {
|
|
||||||
const modal = gradioApp().getElementById("lightboxModal");
|
|
||||||
modal.style.setProperty('background-image', `url(${modalImage.src})`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateOnBackgroundChange() {
|
function updateOnBackgroundChange() {
|
||||||
const modalImage = gradioApp().getElementById("modalImage");
|
const modalImage = gradioApp().getElementById("modalImage");
|
||||||
if (modalImage && modalImage.offsetParent) {
|
if (modalImage && modalImage.offsetParent) {
|
||||||
updateModalImage();
|
let currentButton = selected_gallery_button();
|
||||||
|
let preview = gradioApp().querySelectorAll('.livePreview > img');
|
||||||
|
if (opts.js_live_preview_in_modal_lightbox && preview.length > 0) {
|
||||||
|
// show preview image if available
|
||||||
|
modalImage.src = preview[preview.length - 1].src;
|
||||||
|
} else if (currentButton?.children?.length > 0 && modalImage.src != currentButton.children[0].src) {
|
||||||
|
modalImage.src = currentButton.children[0].src;
|
||||||
|
if (modalImage.style.display === 'none') {
|
||||||
|
const modal = gradioApp().getElementById("lightboxModal");
|
||||||
|
modal.style.setProperty('background-image', `url(${modalImage.src})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,12 +79,11 @@ function requestProgress(id_task, progressbarContainer, gallery, atEnd, onProgre
|
|||||||
var wakeLock = null;
|
var wakeLock = null;
|
||||||
|
|
||||||
var requestWakeLock = async function() {
|
var requestWakeLock = async function() {
|
||||||
if (!opts.prevent_screen_sleep_during_generation || wakeLock !== null) return;
|
if (!opts.prevent_screen_sleep_during_generation || wakeLock) return;
|
||||||
try {
|
try {
|
||||||
wakeLock = await navigator.wakeLock.request('screen');
|
wakeLock = await navigator.wakeLock.request('screen');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Wake Lock is not supported.');
|
console.error('Wake Lock is not supported.');
|
||||||
wakeLock = false;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,7 @@
|
|||||||
} else {
|
} else {
|
||||||
R.screenX = evt.changedTouches[0].screenX;
|
R.screenX = evt.changedTouches[0].screenX;
|
||||||
}
|
}
|
||||||
}, {passive: false});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
resizeHandle.addEventListener('dblclick', onDoubleClick);
|
resizeHandle.addEventListener('dblclick', onDoubleClick);
|
||||||
|
|||||||
+1
-10
@@ -122,7 +122,7 @@ def encode_pil_to_base64(image):
|
|||||||
if opts.samples_format.lower() in ("jpg", "jpeg"):
|
if opts.samples_format.lower() in ("jpg", "jpeg"):
|
||||||
image.save(output_bytes, format="JPEG", exif = exif_bytes, quality=opts.jpeg_quality)
|
image.save(output_bytes, format="JPEG", exif = exif_bytes, quality=opts.jpeg_quality)
|
||||||
else:
|
else:
|
||||||
image.save(output_bytes, format="WEBP", exif = exif_bytes, quality=opts.jpeg_quality, lossless=opts.webp_lossless)
|
image.save(output_bytes, format="WEBP", exif = exif_bytes, quality=opts.jpeg_quality)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise HTTPException(status_code=500, detail="Invalid image format")
|
raise HTTPException(status_code=500, detail="Invalid image format")
|
||||||
@@ -249,8 +249,6 @@ class Api:
|
|||||||
self.add_api_route("/sdapi/v1/server-kill", self.kill_webui, methods=["POST"])
|
self.add_api_route("/sdapi/v1/server-kill", self.kill_webui, methods=["POST"])
|
||||||
self.add_api_route("/sdapi/v1/server-restart", self.restart_webui, methods=["POST"])
|
self.add_api_route("/sdapi/v1/server-restart", self.restart_webui, methods=["POST"])
|
||||||
self.add_api_route("/sdapi/v1/server-stop", self.stop_webui, methods=["POST"])
|
self.add_api_route("/sdapi/v1/server-stop", self.stop_webui, methods=["POST"])
|
||||||
self.add_api_route("/sdapi/v1/server-reload-ui", self.reload_webui, methods=["POST"])
|
|
||||||
self.add_api_route("/sdapi/v1/server-reload-script-bodies", self.reload_script_bodies, methods=["POST"])
|
|
||||||
|
|
||||||
self.default_script_arg_txt2img = []
|
self.default_script_arg_txt2img = []
|
||||||
self.default_script_arg_img2img = []
|
self.default_script_arg_img2img = []
|
||||||
@@ -928,10 +926,3 @@ class Api:
|
|||||||
shared.state.server_command = "stop"
|
shared.state.server_command = "stop"
|
||||||
return Response("Stopping.")
|
return Response("Stopping.")
|
||||||
|
|
||||||
def reload_webui(self):
|
|
||||||
shared.state.request_restart()
|
|
||||||
return Response("Reloading.")
|
|
||||||
|
|
||||||
def reload_script_bodies(self):
|
|
||||||
scripts.reload_script_body_only()
|
|
||||||
return Response("Reload script bodies.")
|
|
||||||
|
|||||||
+4
-18
@@ -1,7 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from modules import modelloader, errors
|
from modules import modelloader, errors
|
||||||
from modules.shared import cmd_opts, opts, hf_endpoint
|
from modules.shared import cmd_opts, opts
|
||||||
from modules.upscaler import Upscaler, UpscalerData
|
from modules.upscaler import Upscaler, UpscalerData
|
||||||
from modules.upscaler_utils import upscale_with_model
|
from modules.upscaler_utils import upscale_with_model
|
||||||
|
|
||||||
@@ -49,18 +49,7 @@ class UpscalerDAT(Upscaler):
|
|||||||
scaler.local_data_path = modelloader.load_file_from_url(
|
scaler.local_data_path = modelloader.load_file_from_url(
|
||||||
scaler.data_path,
|
scaler.data_path,
|
||||||
model_dir=self.model_download_path,
|
model_dir=self.model_download_path,
|
||||||
hash_prefix=scaler.sha256,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if os.path.getsize(scaler.local_data_path) < 200:
|
|
||||||
# Re-download if the file is too small, probably an LFS pointer
|
|
||||||
scaler.local_data_path = modelloader.load_file_from_url(
|
|
||||||
scaler.data_path,
|
|
||||||
model_dir=self.model_download_path,
|
|
||||||
hash_prefix=scaler.sha256,
|
|
||||||
re_download=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
if not os.path.exists(scaler.local_data_path):
|
if not os.path.exists(scaler.local_data_path):
|
||||||
raise FileNotFoundError(f"DAT data missing: {scaler.local_data_path}")
|
raise FileNotFoundError(f"DAT data missing: {scaler.local_data_path}")
|
||||||
return scaler
|
return scaler
|
||||||
@@ -71,23 +60,20 @@ def get_dat_models(scaler):
|
|||||||
return [
|
return [
|
||||||
UpscalerData(
|
UpscalerData(
|
||||||
name="DAT x2",
|
name="DAT x2",
|
||||||
path=f"{hf_endpoint}/w-e-w/DAT/resolve/main/experiments/pretrained_models/DAT/DAT_x2.pth",
|
path="https://github.com/n0kovo/dat_upscaler_models/raw/main/DAT/DAT_x2.pth",
|
||||||
scale=2,
|
scale=2,
|
||||||
upscaler=scaler,
|
upscaler=scaler,
|
||||||
sha256='7760aa96e4ee77e29d4f89c3a4486200042e019461fdb8aa286f49aa00b89b51',
|
|
||||||
),
|
),
|
||||||
UpscalerData(
|
UpscalerData(
|
||||||
name="DAT x3",
|
name="DAT x3",
|
||||||
path=f"{hf_endpoint}/w-e-w/DAT/resolve/main/experiments/pretrained_models/DAT/DAT_x3.pth",
|
path="https://github.com/n0kovo/dat_upscaler_models/raw/main/DAT/DAT_x3.pth",
|
||||||
scale=3,
|
scale=3,
|
||||||
upscaler=scaler,
|
upscaler=scaler,
|
||||||
sha256='581973e02c06f90d4eb90acf743ec9604f56f3c2c6f9e1e2c2b38ded1f80d197',
|
|
||||||
),
|
),
|
||||||
UpscalerData(
|
UpscalerData(
|
||||||
name="DAT x4",
|
name="DAT x4",
|
||||||
path=f"{hf_endpoint}/w-e-w/DAT/resolve/main/experiments/pretrained_models/DAT/DAT_x4.pth",
|
path="https://github.com/n0kovo/dat_upscaler_models/raw/main/DAT/DAT_x4.pth",
|
||||||
scale=4,
|
scale=4,
|
||||||
upscaler=scaler,
|
upscaler=scaler,
|
||||||
sha256='391a6ce69899dff5ea3214557e9d585608254579217169faf3d4c353caff049e',
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ def run_pnginfo(image):
|
|||||||
info = ''
|
info = ''
|
||||||
for key, text in items.items():
|
for key, text in items.items():
|
||||||
info += f"""
|
info += f"""
|
||||||
<div class="infotext">
|
<div>
|
||||||
<p><b>{plaintext_to_html(str(key))}</b></p>
|
<p><b>{plaintext_to_html(str(key))}</b></p>
|
||||||
<p>{plaintext_to_html(str(text))}</p>
|
<p>{plaintext_to_html(str(text))}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+24
-1
@@ -10,7 +10,6 @@ import torch
|
|||||||
|
|
||||||
from modules import shared
|
from modules import shared
|
||||||
from modules.upscaler import Upscaler, UpscalerLanczos, UpscalerNearest, UpscalerNone
|
from modules.upscaler import Upscaler, UpscalerLanczos, UpscalerNearest, UpscalerNone
|
||||||
from modules.util import load_file_from_url # noqa, backwards compatibility
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
import spandrel
|
import spandrel
|
||||||
@@ -18,6 +17,30 @@ if TYPE_CHECKING:
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def load_file_from_url(
|
||||||
|
url: str,
|
||||||
|
*,
|
||||||
|
model_dir: str,
|
||||||
|
progress: bool = True,
|
||||||
|
file_name: str | None = None,
|
||||||
|
hash_prefix: str | None = None,
|
||||||
|
) -> str:
|
||||||
|
"""Download a file from `url` into `model_dir`, using the file present if possible.
|
||||||
|
|
||||||
|
Returns the path to the downloaded file.
|
||||||
|
"""
|
||||||
|
os.makedirs(model_dir, exist_ok=True)
|
||||||
|
if not file_name:
|
||||||
|
parts = urlparse(url)
|
||||||
|
file_name = os.path.basename(parts.path)
|
||||||
|
cached_file = os.path.abspath(os.path.join(model_dir, file_name))
|
||||||
|
if not os.path.exists(cached_file):
|
||||||
|
print(f'Downloading: "{url}" to {cached_file}\n')
|
||||||
|
from torch.hub import download_url_to_file
|
||||||
|
download_url_to_file(url, cached_file, progress=progress, hash_prefix=hash_prefix)
|
||||||
|
return cached_file
|
||||||
|
|
||||||
|
|
||||||
def load_models(model_path: str, model_url: str = None, command_path: str = None, ext_filter=None, download_name=None, ext_blacklist=None, hash_prefix=None) -> list:
|
def load_models(model_path: str, model_url: str = None, command_path: str = None, ext_filter=None, download_name=None, ext_blacklist=None, hash_prefix=None) -> list:
|
||||||
"""
|
"""
|
||||||
A one-and done loader to try finding the desired models in specified directories.
|
A one-and done loader to try finding the desired models in specified directories.
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class SafetensorsMapping(typing.Mapping):
|
|||||||
return self.file.get_tensor(key)
|
return self.file.get_tensor(key)
|
||||||
|
|
||||||
|
|
||||||
CLIPL_URL = f"{shared.hf_endpoint}/AUTOMATIC/stable-diffusion-3-medium-text-encoders/resolve/main/clip_l.safetensors"
|
CLIPL_URL = "https://huggingface.co/AUTOMATIC/stable-diffusion-3-medium-text-encoders/resolve/main/clip_l.safetensors"
|
||||||
CLIPL_CONFIG = {
|
CLIPL_CONFIG = {
|
||||||
"hidden_act": "quick_gelu",
|
"hidden_act": "quick_gelu",
|
||||||
"hidden_size": 768,
|
"hidden_size": 768,
|
||||||
@@ -33,7 +33,7 @@ CLIPL_CONFIG = {
|
|||||||
"num_hidden_layers": 12,
|
"num_hidden_layers": 12,
|
||||||
}
|
}
|
||||||
|
|
||||||
CLIPG_URL = f"{shared.hf_endpoint}/AUTOMATIC/stable-diffusion-3-medium-text-encoders/resolve/main/clip_g.safetensors"
|
CLIPG_URL = "https://huggingface.co/AUTOMATIC/stable-diffusion-3-medium-text-encoders/resolve/main/clip_g.safetensors"
|
||||||
CLIPG_CONFIG = {
|
CLIPG_CONFIG = {
|
||||||
"hidden_act": "gelu",
|
"hidden_act": "gelu",
|
||||||
"hidden_size": 1280,
|
"hidden_size": 1280,
|
||||||
@@ -43,7 +43,7 @@ CLIPG_CONFIG = {
|
|||||||
"textual_inversion_key": "clip_g",
|
"textual_inversion_key": "clip_g",
|
||||||
}
|
}
|
||||||
|
|
||||||
T5_URL = f"{shared.hf_endpoint}/AUTOMATIC/stable-diffusion-3-medium-text-encoders/resolve/main/t5xxl_fp16.safetensors"
|
T5_URL = "https://huggingface.co/AUTOMATIC/stable-diffusion-3-medium-text-encoders/resolve/main/t5xxl_fp16.safetensors"
|
||||||
T5_CONFIG = {
|
T5_CONFIG = {
|
||||||
"d_ff": 10240,
|
"d_ff": 10240,
|
||||||
"d_model": 4096,
|
"d_model": 4096,
|
||||||
|
|||||||
@@ -1259,10 +1259,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
|
|||||||
if self.hr_checkpoint_info is None:
|
if self.hr_checkpoint_info is None:
|
||||||
raise Exception(f'Could not find checkpoint with name {self.hr_checkpoint_name}')
|
raise Exception(f'Could not find checkpoint with name {self.hr_checkpoint_name}')
|
||||||
|
|
||||||
if shared.sd_model.sd_checkpoint_info == self.hr_checkpoint_info:
|
self.extra_generation_params["Hires checkpoint"] = self.hr_checkpoint_info.short_title
|
||||||
self.hr_checkpoint_info = None
|
|
||||||
else:
|
|
||||||
self.extra_generation_params["Hires checkpoint"] = self.hr_checkpoint_info.short_title
|
|
||||||
|
|
||||||
if self.hr_sampler_name is not None and self.hr_sampler_name != self.sampler_name:
|
if self.hr_sampler_name is not None and self.hr_sampler_name != self.sampler_name:
|
||||||
self.extra_generation_params["Hires sampler"] = self.hr_sampler_name
|
self.extra_generation_params["Hires sampler"] = self.hr_sampler_name
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ class ScriptPostprocessingForMainUI(scripts.Script):
|
|||||||
return scripts.AlwaysVisible
|
return scripts.AlwaysVisible
|
||||||
|
|
||||||
def ui(self, is_img2img):
|
def ui(self, is_img2img):
|
||||||
self.script.tab_name = '_img2img' if is_img2img else '_txt2img'
|
|
||||||
self.postprocessing_controls = self.script.ui()
|
self.postprocessing_controls = self.script.ui()
|
||||||
return self.postprocessing_controls.values()
|
return self.postprocessing_controls.values()
|
||||||
|
|
||||||
@@ -34,7 +33,7 @@ def create_auto_preprocessing_script_data():
|
|||||||
|
|
||||||
for name in shared.opts.postprocessing_enable_in_main_ui:
|
for name in shared.opts.postprocessing_enable_in_main_ui:
|
||||||
script = next(iter([x for x in scripts.postprocessing_scripts_data if x.script_class.name == name]), None)
|
script = next(iter([x for x in scripts.postprocessing_scripts_data if x.script_class.name == name]), None)
|
||||||
if script is None or script.script_class.extra_only:
|
if script is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
constructor = lambda s=script: ScriptPostprocessingForMainUI(s.script_class())
|
constructor = lambda s=script: ScriptPostprocessingForMainUI(s.script_class())
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import re
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import os
|
import os
|
||||||
import gradio as gr
|
import gradio as gr
|
||||||
@@ -60,10 +59,6 @@ class ScriptPostprocessing:
|
|||||||
args_from = None
|
args_from = None
|
||||||
args_to = None
|
args_to = None
|
||||||
|
|
||||||
# define if the script should be used only in extras or main UI
|
|
||||||
extra_only = None
|
|
||||||
main_ui_only = None
|
|
||||||
|
|
||||||
order = 1000
|
order = 1000
|
||||||
"""scripts will be ordred by this value in postprocessing UI"""
|
"""scripts will be ordred by this value in postprocessing UI"""
|
||||||
|
|
||||||
@@ -102,31 +97,6 @@ class ScriptPostprocessing:
|
|||||||
def image_changed(self):
|
def image_changed(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
tab_name = '' # used by ScriptPostprocessingForMainUI
|
|
||||||
replace_pattern = re.compile(r'\s')
|
|
||||||
rm_pattern = re.compile(r'[^a-z_0-9]')
|
|
||||||
|
|
||||||
def elem_id(self, item_id):
|
|
||||||
"""
|
|
||||||
Helper function to generate id for a HTML element
|
|
||||||
constructs final id out of script name and user-supplied item_id
|
|
||||||
'script_extras_{self.name.lower()}_{item_id}'
|
|
||||||
{tab_name} will append to the end of the id if set
|
|
||||||
tab_name will be set to '_img2img' or '_txt2img' if use by ScriptPostprocessingForMainUI
|
|
||||||
|
|
||||||
Extensions should use this function to generate element IDs
|
|
||||||
"""
|
|
||||||
return self.elem_id_suffix(f'extras_{self.name.lower()}_{item_id}')
|
|
||||||
|
|
||||||
def elem_id_suffix(self, base_id):
|
|
||||||
"""
|
|
||||||
Append tab_name to the base_id
|
|
||||||
|
|
||||||
Extensions that already have specific there element IDs and wish to keep their IDs the same when possible should use this function
|
|
||||||
"""
|
|
||||||
base_id = self.rm_pattern.sub('', self.replace_pattern.sub('_', base_id))
|
|
||||||
return f'{base_id}{self.tab_name}'
|
|
||||||
|
|
||||||
|
|
||||||
def wrap_call(func, filename, funcname, *args, default=None, **kwargs):
|
def wrap_call(func, filename, funcname, *args, default=None, **kwargs):
|
||||||
try:
|
try:
|
||||||
@@ -149,6 +119,10 @@ class ScriptPostprocessingRunner:
|
|||||||
for script_data in scripts_data:
|
for script_data in scripts_data:
|
||||||
script: ScriptPostprocessing = script_data.script_class()
|
script: ScriptPostprocessing = script_data.script_class()
|
||||||
script.filename = script_data.path
|
script.filename = script_data.path
|
||||||
|
|
||||||
|
if script.name == "Simple Upscale":
|
||||||
|
continue
|
||||||
|
|
||||||
self.scripts.append(script)
|
self.scripts.append(script)
|
||||||
|
|
||||||
def create_script_ui(self, script, inputs):
|
def create_script_ui(self, script, inputs):
|
||||||
@@ -178,7 +152,7 @@ class ScriptPostprocessingRunner:
|
|||||||
|
|
||||||
return len(self.scripts)
|
return len(self.scripts)
|
||||||
|
|
||||||
filtered_scripts = [script for script in self.scripts if script.name not in scripts_filter_out and not script.main_ui_only]
|
filtered_scripts = [script for script in self.scripts if script.name not in scripts_filter_out]
|
||||||
script_scores = {script.name: (script_score(script.name), script.order, script.name, original_index) for original_index, script in enumerate(filtered_scripts)}
|
script_scores = {script.name: (script_score(script.name), script.order, script.name, original_index) for original_index, script in enumerate(filtered_scripts)}
|
||||||
|
|
||||||
return sorted(filtered_scripts, key=lambda x: script_scores[x.name])
|
return sorted(filtered_scripts, key=lambda x: script_scores[x.name])
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class DisableInitialization(ReplaceHelper):
|
|||||||
def transformers_utils_hub_get_file_from_cache(original, url, *args, **kwargs):
|
def transformers_utils_hub_get_file_from_cache(original, url, *args, **kwargs):
|
||||||
|
|
||||||
# this file is always 404, prevent making request
|
# this file is always 404, prevent making request
|
||||||
if url == f'{shared.hf_endpoint}/openai/clip-vit-large-patch14/resolve/main/added_tokens.json' or url == 'openai/clip-vit-large-patch14' and args[0] == 'added_tokens.json':
|
if url == 'https://huggingface.co/openai/clip-vit-large-patch14/resolve/main/added_tokens.json' or url == 'openai/clip-vit-large-patch14' and args[0] == 'added_tokens.json':
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
+5
-10
@@ -159,7 +159,7 @@ def list_models():
|
|||||||
model_url = None
|
model_url = None
|
||||||
expected_sha256 = None
|
expected_sha256 = None
|
||||||
else:
|
else:
|
||||||
model_url = f"{shared.hf_endpoint}/stable-diffusion-v1-5/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.safetensors"
|
model_url = f"{shared.hf_endpoint}/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.safetensors"
|
||||||
expected_sha256 = '6ce0161689b3853acaa03779ec93eafe75a02f4ced659bee03f50797806fa2fa'
|
expected_sha256 = '6ce0161689b3853acaa03779ec93eafe75a02f4ced659bee03f50797806fa2fa'
|
||||||
|
|
||||||
model_list = modelloader.load_models(model_path=model_path, model_url=model_url, command_path=shared.cmd_opts.ckpt_dir, ext_filter=[".ckpt", ".safetensors"], download_name="v1-5-pruned-emaonly.safetensors", ext_blacklist=[".vae.ckpt", ".vae.safetensors"], hash_prefix=expected_sha256)
|
model_list = modelloader.load_models(model_path=model_path, model_url=model_url, command_path=shared.cmd_opts.ckpt_dir, ext_filter=[".ckpt", ".safetensors"], download_name="v1-5-pruned-emaonly.safetensors", ext_blacklist=[".vae.ckpt", ".vae.safetensors"], hash_prefix=expected_sha256)
|
||||||
@@ -423,10 +423,6 @@ def load_model_weights(model, checkpoint_info: CheckpointInfo, state_dict, timer
|
|||||||
|
|
||||||
set_model_type(model, state_dict)
|
set_model_type(model, state_dict)
|
||||||
set_model_fields(model)
|
set_model_fields(model)
|
||||||
if 'ztsnr' in state_dict:
|
|
||||||
model.ztsnr = True
|
|
||||||
else:
|
|
||||||
model.ztsnr = False
|
|
||||||
|
|
||||||
if model.is_sdxl:
|
if model.is_sdxl:
|
||||||
sd_models_xl.extend_sdxl(model)
|
sd_models_xl.extend_sdxl(model)
|
||||||
@@ -665,7 +661,7 @@ def apply_alpha_schedule_override(sd_model, p=None):
|
|||||||
p.extra_generation_params['Downcast alphas_cumprod'] = opts.use_downcasted_alpha_bar
|
p.extra_generation_params['Downcast alphas_cumprod'] = opts.use_downcasted_alpha_bar
|
||||||
sd_model.alphas_cumprod = sd_model.alphas_cumprod.half().to(shared.device)
|
sd_model.alphas_cumprod = sd_model.alphas_cumprod.half().to(shared.device)
|
||||||
|
|
||||||
if opts.sd_noise_schedule == "Zero Terminal SNR" or (hasattr(sd_model, 'ztsnr') and sd_model.ztsnr):
|
if opts.sd_noise_schedule == "Zero Terminal SNR":
|
||||||
if p is not None:
|
if p is not None:
|
||||||
p.extra_generation_params['Noise Schedule'] = opts.sd_noise_schedule
|
p.extra_generation_params['Noise Schedule'] = opts.sd_noise_schedule
|
||||||
sd_model.alphas_cumprod = rescale_zero_terminal_snr_abar(sd_model.alphas_cumprod).to(shared.device)
|
sd_model.alphas_cumprod = rescale_zero_terminal_snr_abar(sd_model.alphas_cumprod).to(shared.device)
|
||||||
@@ -787,7 +783,7 @@ def get_obj_from_str(string, reload=False):
|
|||||||
return getattr(importlib.import_module(module, package=None), cls)
|
return getattr(importlib.import_module(module, package=None), cls)
|
||||||
|
|
||||||
|
|
||||||
def load_model(checkpoint_info=None, already_loaded_state_dict=None, checkpoint_config=None):
|
def load_model(checkpoint_info=None, already_loaded_state_dict=None):
|
||||||
from modules import sd_hijack
|
from modules import sd_hijack
|
||||||
checkpoint_info = checkpoint_info or select_checkpoint()
|
checkpoint_info = checkpoint_info or select_checkpoint()
|
||||||
|
|
||||||
@@ -805,8 +801,7 @@ def load_model(checkpoint_info=None, already_loaded_state_dict=None, checkpoint_
|
|||||||
else:
|
else:
|
||||||
state_dict = get_checkpoint_state_dict(checkpoint_info, timer)
|
state_dict = get_checkpoint_state_dict(checkpoint_info, timer)
|
||||||
|
|
||||||
if not checkpoint_config:
|
checkpoint_config = sd_models_config.find_checkpoint_config(state_dict, checkpoint_info)
|
||||||
checkpoint_config = sd_models_config.find_checkpoint_config(state_dict, checkpoint_info)
|
|
||||||
clip_is_included_into_sd = any(x for x in [sd1_clip_weight, sd2_clip_weight, sdxl_clip_weight, sdxl_refiner_clip_weight] if x in state_dict)
|
clip_is_included_into_sd = any(x for x in [sd1_clip_weight, sd2_clip_weight, sdxl_clip_weight, sdxl_refiner_clip_weight] if x in state_dict)
|
||||||
|
|
||||||
timer.record("find config")
|
timer.record("find config")
|
||||||
@@ -979,7 +974,7 @@ def reload_model_weights(sd_model=None, info=None, forced_reload=False):
|
|||||||
if sd_model is not None:
|
if sd_model is not None:
|
||||||
send_model_to_trash(sd_model)
|
send_model_to_trash(sd_model)
|
||||||
|
|
||||||
load_model(checkpoint_info, already_loaded_state_dict=state_dict, checkpoint_config=checkpoint_config)
|
load_model(checkpoint_info, already_loaded_state_dict=state_dict)
|
||||||
return model_data.sd_model
|
return model_data.sd_model
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ config_sd2 = os.path.join(sd_repo_configs_path, "v2-inference.yaml")
|
|||||||
config_sd2v = os.path.join(sd_repo_configs_path, "v2-inference-v.yaml")
|
config_sd2v = os.path.join(sd_repo_configs_path, "v2-inference-v.yaml")
|
||||||
config_sd2_inpainting = os.path.join(sd_repo_configs_path, "v2-inpainting-inference.yaml")
|
config_sd2_inpainting = os.path.join(sd_repo_configs_path, "v2-inpainting-inference.yaml")
|
||||||
config_sdxl = os.path.join(sd_xl_repo_configs_path, "sd_xl_base.yaml")
|
config_sdxl = os.path.join(sd_xl_repo_configs_path, "sd_xl_base.yaml")
|
||||||
config_sdxlv = os.path.join(sd_configs_path, "sd_xl_v.yaml")
|
|
||||||
config_sdxl_refiner = os.path.join(sd_xl_repo_configs_path, "sd_xl_refiner.yaml")
|
config_sdxl_refiner = os.path.join(sd_xl_repo_configs_path, "sd_xl_refiner.yaml")
|
||||||
config_sdxl_inpainting = os.path.join(sd_configs_path, "sd_xl_inpaint.yaml")
|
config_sdxl_inpainting = os.path.join(sd_configs_path, "sd_xl_inpaint.yaml")
|
||||||
config_depth_model = os.path.join(sd_repo_configs_path, "v2-midas-inference.yaml")
|
config_depth_model = os.path.join(sd_repo_configs_path, "v2-midas-inference.yaml")
|
||||||
@@ -82,9 +81,6 @@ def guess_model_config_from_state_dict(sd, filename):
|
|||||||
if diffusion_model_input.shape[1] == 9:
|
if diffusion_model_input.shape[1] == 9:
|
||||||
return config_sdxl_inpainting
|
return config_sdxl_inpainting
|
||||||
else:
|
else:
|
||||||
if ('v_pred' in sd):
|
|
||||||
del sd['v_pred']
|
|
||||||
return config_sdxlv
|
|
||||||
return config_sdxl
|
return config_sdxl
|
||||||
|
|
||||||
if sd.get('conditioner.embedders.0.model.ln_final.weight', None) is not None:
|
if sd.get('conditioner.embedders.0.model.ln_final.weight', None) is not None:
|
||||||
|
|||||||
@@ -16,12 +16,10 @@ def dat_models_names():
|
|||||||
return [x.name for x in modules.dat_model.get_dat_models(None)]
|
return [x.name for x in modules.dat_model.get_dat_models(None)]
|
||||||
|
|
||||||
|
|
||||||
def postprocessing_scripts(filter_out_extra_only=False, filter_out_main_ui_only=False):
|
def postprocessing_scripts():
|
||||||
import modules.scripts
|
import modules.scripts
|
||||||
return list(filter(
|
|
||||||
lambda s: (not filter_out_extra_only or not s.extra_only) and (not filter_out_main_ui_only or not s.main_ui_only),
|
return modules.scripts.scripts_postproc.scripts
|
||||||
modules.scripts.scripts_postproc.scripts,
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
def sd_vae_items():
|
def sd_vae_items():
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ categories.register_category("training", "Training")
|
|||||||
|
|
||||||
options_templates.update(options_section(('saving-images', "Saving images/grids", "saving"), {
|
options_templates.update(options_section(('saving-images', "Saving images/grids", "saving"), {
|
||||||
"samples_save": OptionInfo(True, "Always save all generated images"),
|
"samples_save": OptionInfo(True, "Always save all generated images"),
|
||||||
"samples_format": OptionInfo('png', 'File format for images', ui_components.DropdownEditable, {"choices": ("png", "jpg", "jpeg", "webp", "avif")}).info("manual input of <a href='https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html' target='_blank'>other formats</a> is possible, but compatibility is not guaranteed"),
|
"samples_format": OptionInfo('png', 'File format for images'),
|
||||||
"samples_filename_pattern": OptionInfo("", "Images filename pattern", component_args=hide_dirs).link("wiki", "https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Custom-Images-Filename-Name-and-Subdirectory"),
|
"samples_filename_pattern": OptionInfo("", "Images filename pattern", component_args=hide_dirs).link("wiki", "https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Custom-Images-Filename-Name-and-Subdirectory"),
|
||||||
"save_images_add_number": OptionInfo(True, "Add number to filename when saving", component_args=hide_dirs),
|
"save_images_add_number": OptionInfo(True, "Add number to filename when saving", component_args=hide_dirs),
|
||||||
"save_images_replace_action": OptionInfo("Replace", "Saving the image to an existing file", gr.Radio, {"choices": ["Replace", "Add number suffix"], **hide_dirs}),
|
"save_images_replace_action": OptionInfo("Replace", "Saving the image to an existing file", gr.Radio, {"choices": ["Replace", "Add number suffix"], **hide_dirs}),
|
||||||
"grid_save": OptionInfo(True, "Always save all generated image grids"),
|
"grid_save": OptionInfo(True, "Always save all generated image grids"),
|
||||||
"grid_format": OptionInfo('png', 'File format for grids', ui_components.DropdownEditable, {"choices": ("png", "jpg", "jpeg", "webp", "avif")}).info("manual input of <a href='https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html' target='_blank'>other formats</a> is possible, but compatibility is not guaranteed"),
|
"grid_format": OptionInfo('png', 'File format for grids'),
|
||||||
"grid_extended_filename": OptionInfo(False, "Add extended info (seed, prompt) to filename when saving grid"),
|
"grid_extended_filename": OptionInfo(False, "Add extended info (seed, prompt) to filename when saving grid"),
|
||||||
"grid_only_if_multiple": OptionInfo(True, "Do not save grids consisting of one picture"),
|
"grid_only_if_multiple": OptionInfo(True, "Do not save grids consisting of one picture"),
|
||||||
"grid_prevent_empty_spots": OptionInfo(False, "Prevent empty spots in grid (when set to autodetect)"),
|
"grid_prevent_empty_spots": OptionInfo(False, "Prevent empty spots in grid (when set to autodetect)"),
|
||||||
@@ -128,7 +128,6 @@ options_templates.update(options_section(('system', "System", "system"), {
|
|||||||
"disable_mmap_load_safetensors": OptionInfo(False, "Disable memmapping for loading .safetensors files.").info("fixes very slow loading speed in some cases"),
|
"disable_mmap_load_safetensors": OptionInfo(False, "Disable memmapping for loading .safetensors files.").info("fixes very slow loading speed in some cases"),
|
||||||
"hide_ldm_prints": OptionInfo(True, "Prevent Stability-AI's ldm/sgm modules from printing noise to console."),
|
"hide_ldm_prints": OptionInfo(True, "Prevent Stability-AI's ldm/sgm modules from printing noise to console."),
|
||||||
"dump_stacks_on_signal": OptionInfo(False, "Print stack traces before exiting the program with ctrl+c."),
|
"dump_stacks_on_signal": OptionInfo(False, "Print stack traces before exiting the program with ctrl+c."),
|
||||||
"concurrent_git_fetch_limit": OptionInfo(16, "Number of simultaneous extension update checks ", gr.Slider, {"step": 1, "minimum": 1, "maximum": 100}).info("reduce extension update check time"),
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
options_templates.update(options_section(('profiler', "Profiler", "system"), {
|
options_templates.update(options_section(('profiler', "Profiler", "system"), {
|
||||||
@@ -232,7 +231,7 @@ options_templates.update(options_section(('img2img', "img2img", "sd"), {
|
|||||||
|
|
||||||
options_templates.update(options_section(('optimizations', "Optimizations", "sd"), {
|
options_templates.update(options_section(('optimizations', "Optimizations", "sd"), {
|
||||||
"cross_attention_optimization": OptionInfo("Automatic", "Cross attention optimization", gr.Dropdown, lambda: {"choices": shared_items.cross_attention_optimizations()}),
|
"cross_attention_optimization": OptionInfo("Automatic", "Cross attention optimization", gr.Dropdown, lambda: {"choices": shared_items.cross_attention_optimizations()}),
|
||||||
"s_min_uncond": OptionInfo(0.0, "Negative Guidance minimum sigma", gr.Slider, {"minimum": 0.0, "maximum": 15.0, "step": 0.01}, infotext='NGMS').link("PR", "https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/9177").info("skip negative prompt for some steps when the image is almost ready; 0=disable, higher=faster"),
|
"s_min_uncond": OptionInfo(0.0, "Negative Guidance minimum sigma", gr.Slider, {"minimum": 0.0, "maximum": 15.0, "step": 0.01}, infotext='NGMS').link("PR", "https://github.com/AUTOMATIC1111/stablediffusion-webui/pull/9177").info("skip negative prompt for some steps when the image is almost ready; 0=disable, higher=faster"),
|
||||||
"s_min_uncond_all": OptionInfo(False, "Negative Guidance minimum sigma all steps", infotext='NGMS all steps').info("By default, NGMS above skips every other step; this makes it skip all steps"),
|
"s_min_uncond_all": OptionInfo(False, "Negative Guidance minimum sigma all steps", infotext='NGMS all steps').info("By default, NGMS above skips every other step; this makes it skip all steps"),
|
||||||
"token_merging_ratio": OptionInfo(0.0, "Token merging ratio", gr.Slider, {"minimum": 0.0, "maximum": 0.9, "step": 0.1}, infotext='Token merging ratio').link("PR", "https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/9256").info("0=disable, higher=faster"),
|
"token_merging_ratio": OptionInfo(0.0, "Token merging ratio", gr.Slider, {"minimum": 0.0, "maximum": 0.9, "step": 0.1}, infotext='Token merging ratio').link("PR", "https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/9256").info("0=disable, higher=faster"),
|
||||||
"token_merging_ratio_img2img": OptionInfo(0.0, "Token merging ratio for img2img", gr.Slider, {"minimum": 0.0, "maximum": 0.9, "step": 0.1}).info("only applies if non-zero and overrides above"),
|
"token_merging_ratio_img2img": OptionInfo(0.0, "Token merging ratio for img2img", gr.Slider, {"minimum": 0.0, "maximum": 0.9, "step": 0.1}).info("only applies if non-zero and overrides above"),
|
||||||
@@ -292,7 +291,6 @@ options_templates.update(options_section(('extra_networks', "Extra Networks", "s
|
|||||||
"textual_inversion_print_at_load": OptionInfo(False, "Print a list of Textual Inversion embeddings when loading model"),
|
"textual_inversion_print_at_load": OptionInfo(False, "Print a list of Textual Inversion embeddings when loading model"),
|
||||||
"textual_inversion_add_hashes_to_infotext": OptionInfo(True, "Add Textual Inversion hashes to infotext"),
|
"textual_inversion_add_hashes_to_infotext": OptionInfo(True, "Add Textual Inversion hashes to infotext"),
|
||||||
"sd_hypernetwork": OptionInfo("None", "Add hypernetwork to prompt", gr.Dropdown, lambda: {"choices": ["None", *shared.hypernetworks]}, refresh=shared_items.reload_hypernetworks),
|
"sd_hypernetwork": OptionInfo("None", "Add hypernetwork to prompt", gr.Dropdown, lambda: {"choices": ["None", *shared.hypernetworks]}, refresh=shared_items.reload_hypernetworks),
|
||||||
"textual_inversion_image_embedding_data_cache": OptionInfo(False, 'Cache the data of image embeddings').info('potentially increase TI load time at the cost some disk space'),
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
options_templates.update(options_section(('ui_prompt_editing', "Prompt editing", "ui"), {
|
options_templates.update(options_section(('ui_prompt_editing', "Prompt editing", "ui"), {
|
||||||
@@ -406,15 +404,15 @@ options_templates.update(options_section(('sampler-params', "Sampler parameters"
|
|||||||
'uni_pc_order': OptionInfo(3, "UniPC order", gr.Slider, {"minimum": 1, "maximum": 50, "step": 1}, infotext='UniPC order').info("must be < sampling steps"),
|
'uni_pc_order': OptionInfo(3, "UniPC order", gr.Slider, {"minimum": 1, "maximum": 50, "step": 1}, infotext='UniPC order').info("must be < sampling steps"),
|
||||||
'uni_pc_lower_order_final': OptionInfo(True, "UniPC lower order final", infotext='UniPC lower order final'),
|
'uni_pc_lower_order_final': OptionInfo(True, "UniPC lower order final", infotext='UniPC lower order final'),
|
||||||
'sd_noise_schedule': OptionInfo("Default", "Noise schedule for sampling", gr.Radio, {"choices": ["Default", "Zero Terminal SNR"]}, infotext="Noise Schedule").info("for use with zero terminal SNR trained models"),
|
'sd_noise_schedule': OptionInfo("Default", "Noise schedule for sampling", gr.Radio, {"choices": ["Default", "Zero Terminal SNR"]}, infotext="Noise Schedule").info("for use with zero terminal SNR trained models"),
|
||||||
'skip_early_cond': OptionInfo(0.0, "Ignore negative prompt during early sampling", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}, infotext="Skip Early CFG").info("disables CFG on a proportion of steps at the beginning of generation; 0=skip none; 1=skip all; can both improve sample diversity/quality and speed up sampling; XYZ plot: Skip Early CFG"),
|
'skip_early_cond': OptionInfo(0.0, "Ignore negative prompt during early sampling", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}, infotext="Skip Early CFG").info("disables CFG on a proportion of steps at the beginning of generation; 0=skip none; 1=skip all; can both improve sample diversity/quality and speed up sampling"),
|
||||||
'beta_dist_alpha': OptionInfo(0.6, "Beta scheduler - alpha", gr.Slider, {"minimum": 0.01, "maximum": 1.0, "step": 0.01}, infotext='Beta scheduler alpha').info('Default = 0.6; the alpha parameter of the beta distribution used in Beta sampling'),
|
'beta_dist_alpha': OptionInfo(0.6, "Beta scheduler - alpha", gr.Slider, {"minimum": 0.01, "maximum": 1.0, "step": 0.01}, infotext='Beta scheduler alpha').info('Default = 0.6; the alpha parameter of the beta distribution used in Beta sampling'),
|
||||||
'beta_dist_beta': OptionInfo(0.6, "Beta scheduler - beta", gr.Slider, {"minimum": 0.01, "maximum": 1.0, "step": 0.01}, infotext='Beta scheduler beta').info('Default = 0.6; the beta parameter of the beta distribution used in Beta sampling'),
|
'beta_dist_beta': OptionInfo(0.6, "Beta scheduler - beta", gr.Slider, {"minimum": 0.01, "maximum": 1.0, "step": 0.01}, infotext='Beta scheduler beta').info('Default = 0.6; the beta parameter of the beta distribution used in Beta sampling'),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
options_templates.update(options_section(('postprocessing', "Postprocessing", "postprocessing"), {
|
options_templates.update(options_section(('postprocessing', "Postprocessing", "postprocessing"), {
|
||||||
'postprocessing_enable_in_main_ui': OptionInfo([], "Enable postprocessing operations in txt2img and img2img tabs", ui_components.DropdownMulti, lambda: {"choices": [x.name for x in shared_items.postprocessing_scripts(filter_out_extra_only=True)]}),
|
'postprocessing_enable_in_main_ui': OptionInfo([], "Enable postprocessing operations in txt2img and img2img tabs", ui_components.DropdownMulti, lambda: {"choices": [x.name for x in shared_items.postprocessing_scripts()]}),
|
||||||
'postprocessing_disable_in_extras': OptionInfo([], "Disable postprocessing operations in extras tab", ui_components.DropdownMulti, lambda: {"choices": [x.name for x in shared_items.postprocessing_scripts(filter_out_main_ui_only=True)]}),
|
'postprocessing_disable_in_extras': OptionInfo([], "Disable postprocessing operations in extras tab", ui_components.DropdownMulti, lambda: {"choices": [x.name for x in shared_items.postprocessing_scripts()]}),
|
||||||
'postprocessing_operation_order': OptionInfo([], "Postprocessing operation order", ui_components.DropdownMulti, lambda: {"choices": [x.name for x in shared_items.postprocessing_scripts(filter_out_main_ui_only=True)]}),
|
'postprocessing_operation_order': OptionInfo([], "Postprocessing operation order", ui_components.DropdownMulti, lambda: {"choices": [x.name for x in shared_items.postprocessing_scripts()]}),
|
||||||
'upscaling_max_images_in_cache': OptionInfo(5, "Maximum number of images in upscaling cache", gr.Slider, {"minimum": 0, "maximum": 10, "step": 1}),
|
'upscaling_max_images_in_cache': OptionInfo(5, "Maximum number of images in upscaling cache", gr.Slider, {"minimum": 0, "maximum": 10, "step": 1}),
|
||||||
'postprocessing_existing_caption_action': OptionInfo("Ignore", "Action for existing captions", gr.Radio, {"choices": ["Ignore", "Keep", "Prepend", "Append"]}).info("when generating captions using postprocessing; Ignore = use generated; Keep = use original; Prepend/Append = combine both"),
|
'postprocessing_existing_caption_action': OptionInfo("Ignore", "Action for existing captions", gr.Radio, {"choices": ["Ignore", "Keep", "Prepend", "Append"]}).info("when generating captions using postprocessing; Ignore = use generated; Keep = use original; Prepend/Append = combine both"),
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import safetensors.torch
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from PIL import Image, PngImagePlugin
|
from PIL import Image, PngImagePlugin
|
||||||
|
|
||||||
from modules import shared, devices, sd_hijack, sd_models, images, sd_samplers, sd_hijack_checkpoint, errors, hashes, cache
|
from modules import shared, devices, sd_hijack, sd_models, images, sd_samplers, sd_hijack_checkpoint, errors, hashes
|
||||||
import modules.textual_inversion.dataset
|
import modules.textual_inversion.dataset
|
||||||
from modules.textual_inversion.learn_schedule import LearnRateScheduler
|
from modules.textual_inversion.learn_schedule import LearnRateScheduler
|
||||||
|
|
||||||
@@ -116,7 +116,6 @@ class EmbeddingDatabase:
|
|||||||
self.expected_shape = -1
|
self.expected_shape = -1
|
||||||
self.embedding_dirs = {}
|
self.embedding_dirs = {}
|
||||||
self.previously_displayed_embeddings = ()
|
self.previously_displayed_embeddings = ()
|
||||||
self.image_embedding_cache = cache.cache('image-embedding')
|
|
||||||
|
|
||||||
def add_embedding_dir(self, path):
|
def add_embedding_dir(self, path):
|
||||||
self.embedding_dirs[path] = DirWithTextualInversionEmbeddings(path)
|
self.embedding_dirs[path] = DirWithTextualInversionEmbeddings(path)
|
||||||
@@ -155,31 +154,6 @@ class EmbeddingDatabase:
|
|||||||
vec = shared.sd_model.cond_stage_model.encode_embedding_init_text(",", 1)
|
vec = shared.sd_model.cond_stage_model.encode_embedding_init_text(",", 1)
|
||||||
return vec.shape[1]
|
return vec.shape[1]
|
||||||
|
|
||||||
def read_embedding_from_image(self, path, name):
|
|
||||||
try:
|
|
||||||
ondisk_mtime = os.path.getmtime(path)
|
|
||||||
|
|
||||||
if (cache_embedding := self.image_embedding_cache.get(path)) and ondisk_mtime == cache_embedding.get('mtime', 0):
|
|
||||||
# cache will only be used if the file has not been modified time matches
|
|
||||||
return cache_embedding.get('data', None), cache_embedding.get('name', None)
|
|
||||||
|
|
||||||
embed_image = Image.open(path)
|
|
||||||
if hasattr(embed_image, 'text') and 'sd-ti-embedding' in embed_image.text:
|
|
||||||
data = embedding_from_b64(embed_image.text['sd-ti-embedding'])
|
|
||||||
name = data.get('name', name)
|
|
||||||
elif data := extract_image_data_embed(embed_image):
|
|
||||||
name = data.get('name', name)
|
|
||||||
|
|
||||||
if data is None or shared.opts.textual_inversion_image_embedding_data_cache:
|
|
||||||
# data of image embeddings only will be cached if the option textual_inversion_image_embedding_data_cache is enabled
|
|
||||||
# results of images that are not embeddings will allways be cached to reduce unnecessary future disk reads
|
|
||||||
self.image_embedding_cache[path] = {'data': data, 'name': None if data is None else name, 'mtime': ondisk_mtime}
|
|
||||||
|
|
||||||
return data, name
|
|
||||||
except Exception:
|
|
||||||
errors.report(f"Error loading embedding {path}", exc_info=True)
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
def load_from_file(self, path, filename):
|
def load_from_file(self, path, filename):
|
||||||
name, ext = os.path.splitext(filename)
|
name, ext = os.path.splitext(filename)
|
||||||
ext = ext.upper()
|
ext = ext.upper()
|
||||||
@@ -189,10 +163,17 @@ class EmbeddingDatabase:
|
|||||||
if second_ext.upper() == '.PREVIEW':
|
if second_ext.upper() == '.PREVIEW':
|
||||||
return
|
return
|
||||||
|
|
||||||
data, name = self.read_embedding_from_image(path, name)
|
embed_image = Image.open(path)
|
||||||
if data is None:
|
if hasattr(embed_image, 'text') and 'sd-ti-embedding' in embed_image.text:
|
||||||
return
|
data = embedding_from_b64(embed_image.text['sd-ti-embedding'])
|
||||||
|
name = data.get('name', name)
|
||||||
|
else:
|
||||||
|
data = extract_image_data_embed(embed_image)
|
||||||
|
if data:
|
||||||
|
name = data.get('name', name)
|
||||||
|
else:
|
||||||
|
# if data is None, means this is not an embedding, just a preview image
|
||||||
|
return
|
||||||
elif ext in ['.BIN', '.PT']:
|
elif ext in ['.BIN', '.PT']:
|
||||||
data = torch.load(path, map_location="cpu")
|
data = torch.load(path, map_location="cpu")
|
||||||
elif ext in ['.SAFETENSORS']:
|
elif ext in ['.SAFETENSORS']:
|
||||||
@@ -210,6 +191,7 @@ class EmbeddingDatabase:
|
|||||||
else:
|
else:
|
||||||
print(f"Unable to load Textual inversion embedding due to data issue: '{name}'.")
|
print(f"Unable to load Textual inversion embedding due to data issue: '{name}'.")
|
||||||
|
|
||||||
|
|
||||||
def load_from_dir(self, embdir):
|
def load_from_dir(self, embdir):
|
||||||
if not os.path.isdir(embdir.path):
|
if not os.path.isdir(embdir.path):
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -44,9 +44,6 @@ mimetypes.add_type('application/javascript', '.mjs')
|
|||||||
mimetypes.add_type('image/webp', '.webp')
|
mimetypes.add_type('image/webp', '.webp')
|
||||||
mimetypes.add_type('image/avif', '.avif')
|
mimetypes.add_type('image/avif', '.avif')
|
||||||
|
|
||||||
# override potentially incorrect mimetypes
|
|
||||||
mimetypes.add_type('text/css', '.css')
|
|
||||||
|
|
||||||
if not cmd_opts.share and not cmd_opts.listen:
|
if not cmd_opts.share and not cmd_opts.listen:
|
||||||
# fix gradio phoning home
|
# fix gradio phoning home
|
||||||
gradio.utils.version_check = lambda: None
|
gradio.utils.version_check = lambda: None
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ class InputAccordion(gr.Checkbox):
|
|||||||
Actually just a hidden checkbox, but creates an accordion that follows and is followed by the state of the checkbox.
|
Actually just a hidden checkbox, but creates an accordion that follows and is followed by the state of the checkbox.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
accordion_id_set = set()
|
|
||||||
global_index = 0
|
global_index = 0
|
||||||
|
|
||||||
def __init__(self, value, **kwargs):
|
def __init__(self, value, **kwargs):
|
||||||
@@ -100,18 +99,6 @@ class InputAccordion(gr.Checkbox):
|
|||||||
self.accordion_id = f"input-accordion-{InputAccordion.global_index}"
|
self.accordion_id = f"input-accordion-{InputAccordion.global_index}"
|
||||||
InputAccordion.global_index += 1
|
InputAccordion.global_index += 1
|
||||||
|
|
||||||
if not InputAccordion.accordion_id_set:
|
|
||||||
from modules import script_callbacks
|
|
||||||
script_callbacks.on_script_unloaded(InputAccordion.reset)
|
|
||||||
|
|
||||||
if self.accordion_id in InputAccordion.accordion_id_set:
|
|
||||||
count = 1
|
|
||||||
while (unique_id := f'{self.accordion_id}-{count}') in InputAccordion.accordion_id_set:
|
|
||||||
count += 1
|
|
||||||
self.accordion_id = unique_id
|
|
||||||
|
|
||||||
InputAccordion.accordion_id_set.add(self.accordion_id)
|
|
||||||
|
|
||||||
kwargs_checkbox = {
|
kwargs_checkbox = {
|
||||||
**kwargs,
|
**kwargs,
|
||||||
"elem_id": f"{self.accordion_id}-checkbox",
|
"elem_id": f"{self.accordion_id}-checkbox",
|
||||||
@@ -156,7 +143,3 @@ class InputAccordion(gr.Checkbox):
|
|||||||
def get_block_name(self):
|
def get_block_name(self):
|
||||||
return "checkbox"
|
return "checkbox"
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def reset(cls):
|
|
||||||
cls.global_index = 0
|
|
||||||
cls.accordion_id_set.clear()
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
@@ -107,24 +106,18 @@ def check_updates(id_task, disable_list):
|
|||||||
exts = [ext for ext in extensions.extensions if ext.remote is not None and ext.name not in disabled]
|
exts = [ext for ext in extensions.extensions if ext.remote is not None and ext.name not in disabled]
|
||||||
shared.state.job_count = len(exts)
|
shared.state.job_count = len(exts)
|
||||||
|
|
||||||
lock = threading.Lock()
|
for ext in exts:
|
||||||
|
shared.state.textinfo = ext.name
|
||||||
|
|
||||||
def _check_update(ext):
|
|
||||||
try:
|
try:
|
||||||
ext.check_updates()
|
ext.check_updates()
|
||||||
except FileNotFoundError as e:
|
except FileNotFoundError as e:
|
||||||
if 'FETCH_HEAD' not in str(e):
|
if 'FETCH_HEAD' not in str(e):
|
||||||
raise
|
raise
|
||||||
except Exception:
|
except Exception:
|
||||||
with lock:
|
errors.report(f"Error checking updates for {ext.name}", exc_info=True)
|
||||||
errors.report(f"Error checking updates for {ext.name}", exc_info=True)
|
|
||||||
with lock:
|
|
||||||
shared.state.textinfo = ext.name
|
|
||||||
shared.state.nextjob()
|
|
||||||
|
|
||||||
with ThreadPoolExecutor(max_workers=max(1, int(shared.opts.concurrent_git_fetch_limit))) as executor:
|
shared.state.nextjob()
|
||||||
for ext in exts:
|
|
||||||
executor.submit(_check_update, ext)
|
|
||||||
|
|
||||||
return extension_table(), ""
|
return extension_table(), ""
|
||||||
|
|
||||||
|
|||||||
@@ -177,8 +177,10 @@ def add_pages_to_demo(app):
|
|||||||
app.add_api_route("/sd_extra_networks/get-single-card", get_single_card, methods=["GET"])
|
app.add_api_route("/sd_extra_networks/get-single-card", get_single_card, methods=["GET"])
|
||||||
|
|
||||||
|
|
||||||
def quote_js(s: str):
|
def quote_js(s):
|
||||||
return json.dumps(s, ensure_ascii=False)
|
s = s.replace('\\', '\\\\')
|
||||||
|
s = s.replace('"', '\\"')
|
||||||
|
return f'"{s}"'
|
||||||
|
|
||||||
|
|
||||||
class ExtraNetworksPage:
|
class ExtraNetworksPage:
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ class UiLoadsave:
|
|||||||
if new_value == old_value:
|
if new_value == old_value:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if old_value is None and (new_value == '' or new_value == []):
|
if old_value is None and new_value == '' or new_value == []:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
yield path, old_value, new_value
|
yield path, old_value, new_value
|
||||||
|
|||||||
+1
-2
@@ -93,14 +93,13 @@ class UpscalerData:
|
|||||||
scaler: Upscaler = None
|
scaler: Upscaler = None
|
||||||
model: None
|
model: None
|
||||||
|
|
||||||
def __init__(self, name: str, path: str, upscaler: Upscaler = None, scale: int = 4, model=None, sha256: str = None):
|
def __init__(self, name: str, path: str, upscaler: Upscaler = None, scale: int = 4, model=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.data_path = path
|
self.data_path = path
|
||||||
self.local_data_path = path
|
self.local_data_path = path
|
||||||
self.scaler = upscaler
|
self.scaler = upscaler
|
||||||
self.scale = scale
|
self.scale = scale
|
||||||
self.model = model
|
self.model = model
|
||||||
self.sha256 = sha256
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<UpscalerData name={self.name} path={self.data_path} scale={self.scale}>"
|
return f"<UpscalerData name={self.name} path={self.data_path} scale={self.scale}>"
|
||||||
|
|||||||
@@ -211,80 +211,3 @@ Requested path was: {path}
|
|||||||
subprocess.Popen(["explorer.exe", subprocess.check_output(["wslpath", "-w", path])])
|
subprocess.Popen(["explorer.exe", subprocess.check_output(["wslpath", "-w", path])])
|
||||||
else:
|
else:
|
||||||
subprocess.Popen(["xdg-open", path])
|
subprocess.Popen(["xdg-open", path])
|
||||||
|
|
||||||
|
|
||||||
def load_file_from_url(
|
|
||||||
url: str,
|
|
||||||
*,
|
|
||||||
model_dir: str,
|
|
||||||
progress: bool = True,
|
|
||||||
file_name: str | None = None,
|
|
||||||
hash_prefix: str | None = None,
|
|
||||||
re_download: bool = False,
|
|
||||||
) -> str:
|
|
||||||
"""Download a file from `url` into `model_dir`, using the file present if possible.
|
|
||||||
Returns the path to the downloaded file.
|
|
||||||
|
|
||||||
file_name: if specified, it will be used as the filename, otherwise the filename will be extracted from the url.
|
|
||||||
file is downloaded to {file_name}.tmp then moved to the final location after download is complete.
|
|
||||||
hash_prefix: sha256 hex string, if provided, the hash of the downloaded file will be checked against this prefix.
|
|
||||||
if the hash does not match, the temporary file is deleted and a ValueError is raised.
|
|
||||||
re_download: forcibly re-download the file even if it already exists.
|
|
||||||
"""
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
import requests
|
|
||||||
try:
|
|
||||||
from tqdm import tqdm
|
|
||||||
except ImportError:
|
|
||||||
class tqdm:
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def update(self, n=1, *args, **kwargs):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __enter__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
||||||
pass
|
|
||||||
|
|
||||||
if not file_name:
|
|
||||||
parts = urlparse(url)
|
|
||||||
file_name = os.path.basename(parts.path)
|
|
||||||
|
|
||||||
cached_file = os.path.abspath(os.path.join(model_dir, file_name))
|
|
||||||
|
|
||||||
if re_download or not os.path.exists(cached_file):
|
|
||||||
os.makedirs(model_dir, exist_ok=True)
|
|
||||||
temp_file = os.path.join(model_dir, f"{file_name}.tmp")
|
|
||||||
print(f'\nDownloading: "{url}" to {cached_file}')
|
|
||||||
response = requests.get(url, stream=True)
|
|
||||||
response.raise_for_status()
|
|
||||||
total_size = int(response.headers.get('content-length', 0))
|
|
||||||
with tqdm(total=total_size, unit='B', unit_scale=True, desc=file_name, disable=not progress) as progress_bar:
|
|
||||||
with open(temp_file, 'wb') as file:
|
|
||||||
for chunk in response.iter_content(chunk_size=1024):
|
|
||||||
if chunk:
|
|
||||||
file.write(chunk)
|
|
||||||
progress_bar.update(len(chunk))
|
|
||||||
|
|
||||||
if hash_prefix and not compare_sha256(temp_file, hash_prefix):
|
|
||||||
print(f"Hash mismatch for {temp_file}. Deleting the temporary file.")
|
|
||||||
os.remove(temp_file)
|
|
||||||
raise ValueError(f"File hash does not match the expected hash prefix {hash_prefix}!")
|
|
||||||
|
|
||||||
os.rename(temp_file, cached_file)
|
|
||||||
return cached_file
|
|
||||||
|
|
||||||
|
|
||||||
def compare_sha256(file_path: str, hash_prefix: str) -> bool:
|
|
||||||
"""Check if the SHA256 hash of the file matches the given prefix."""
|
|
||||||
import hashlib
|
|
||||||
hash_sha256 = hashlib.sha256()
|
|
||||||
blksize = 1024 * 1024
|
|
||||||
|
|
||||||
with open(file_path, "rb") as f:
|
|
||||||
for chunk in iter(lambda: f.read(blksize), b""):
|
|
||||||
hash_sha256.update(chunk)
|
|
||||||
return hash_sha256.hexdigest().startswith(hash_prefix.strip().lower())
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ protobuf==3.20.0
|
|||||||
psutil==5.9.5
|
psutil==5.9.5
|
||||||
pytorch_lightning==1.9.4
|
pytorch_lightning==1.9.4
|
||||||
resize-right==0.0.2
|
resize-right==0.0.2
|
||||||
safetensors==0.4.5
|
safetensors==0.4.2
|
||||||
scikit-image==0.21.0
|
scikit-image==0.21.0
|
||||||
spandrel==0.3.4
|
spandrel==0.3.4
|
||||||
spandrel-extra-arches==0.1.1
|
spandrel-extra-arches==0.1.1
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ class ScriptPostprocessingCodeFormer(scripts_postprocessing.ScriptPostprocessing
|
|||||||
def ui(self):
|
def ui(self):
|
||||||
with ui_components.InputAccordion(False, label="CodeFormer") as enable:
|
with ui_components.InputAccordion(False, label="CodeFormer") as enable:
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
codeformer_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Visibility", value=1.0, elem_id=self.elem_id_suffix("extras_codeformer_visibility"))
|
codeformer_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Visibility", value=1.0, elem_id="extras_codeformer_visibility")
|
||||||
codeformer_weight = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Weight (0 = maximum effect, 1 = minimum effect)", value=0, elem_id=self.elem_id_suffix("extras_codeformer_weight"))
|
codeformer_weight = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Weight (0 = maximum effect, 1 = minimum effect)", value=0, elem_id="extras_codeformer_weight")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"enable": enable,
|
"enable": enable,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class ScriptPostprocessingGfpGan(scripts_postprocessing.ScriptPostprocessing):
|
|||||||
|
|
||||||
def ui(self):
|
def ui(self):
|
||||||
with ui_components.InputAccordion(False, label="GFPGAN") as enable:
|
with ui_components.InputAccordion(False, label="GFPGAN") as enable:
|
||||||
gfpgan_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Visibility", value=1.0, elem_id=self.elem_id_suffix("extras_gfpgan_visibility"))
|
gfpgan_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Visibility", value=1.0, elem_id="extras_gfpgan_visibility")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"enable": enable,
|
"enable": enable,
|
||||||
|
|||||||
@@ -30,31 +30,31 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
|
|||||||
def ui(self):
|
def ui(self):
|
||||||
selected_tab = gr.Number(value=0, visible=False)
|
selected_tab = gr.Number(value=0, visible=False)
|
||||||
|
|
||||||
with InputAccordion(True, label="Upscale", elem_id=self.elem_id_suffix("extras_upscale")) as upscale_enabled:
|
with InputAccordion(True, label="Upscale", elem_id="extras_upscale") as upscale_enabled:
|
||||||
with FormRow():
|
with FormRow():
|
||||||
extras_upscaler_1 = gr.Dropdown(label='Upscaler 1', elem_id=self.elem_id_suffix("extras_upscaler_1"), choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
|
extras_upscaler_1 = gr.Dropdown(label='Upscaler 1', elem_id="extras_upscaler_1", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
|
||||||
|
|
||||||
with FormRow():
|
with FormRow():
|
||||||
extras_upscaler_2 = gr.Dropdown(label='Upscaler 2', elem_id=self.elem_id_suffix("extras_upscaler_2"), choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
|
extras_upscaler_2 = gr.Dropdown(label='Upscaler 2', elem_id="extras_upscaler_2", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
|
||||||
extras_upscaler_2_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Upscaler 2 visibility", value=0.0, elem_id=self.elem_id_suffix("extras_upscaler_2_visibility"))
|
extras_upscaler_2_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Upscaler 2 visibility", value=0.0, elem_id="extras_upscaler_2_visibility")
|
||||||
|
|
||||||
with FormRow():
|
with FormRow():
|
||||||
with gr.Tabs(elem_id=self.elem_id_suffix("extras_resize_mode")):
|
with gr.Tabs(elem_id="extras_resize_mode"):
|
||||||
with gr.TabItem('Scale by', elem_id=self.elem_id_suffix("extras_scale_by_tab")) as tab_scale_by:
|
with gr.TabItem('Scale by', elem_id="extras_scale_by_tab") as tab_scale_by:
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
with gr.Column(scale=4):
|
with gr.Column(scale=4):
|
||||||
upscaling_resize = gr.Slider(minimum=1.0, maximum=8.0, step=0.05, label="Resize", value=4, elem_id=self.elem_id_suffix("extras_upscaling_resize"))
|
upscaling_resize = gr.Slider(minimum=1.0, maximum=8.0, step=0.05, label="Resize", value=4, elem_id="extras_upscaling_resize")
|
||||||
with gr.Column(scale=1, min_width=160):
|
with gr.Column(scale=1, min_width=160):
|
||||||
max_side_length = gr.Number(label="Max side length", value=0, elem_id=self.elem_id_suffix("extras_upscale_max_side_length"), tooltip="If any of two sides of the image ends up larger than specified, will downscale it to fit. 0 = no limit.", min_width=160, step=8, minimum=0)
|
max_side_length = gr.Number(label="Max side length", value=0, elem_id="extras_upscale_max_side_length", tooltip="If any of two sides of the image ends up larger than specified, will downscale it to fit. 0 = no limit.", min_width=160, step=8, minimum=0)
|
||||||
|
|
||||||
with gr.TabItem('Scale to', elem_id=self.elem_id_suffix("extras_scale_to_tab")) as tab_scale_to:
|
with gr.TabItem('Scale to', elem_id="extras_scale_to_tab") as tab_scale_to:
|
||||||
with FormRow():
|
with FormRow():
|
||||||
with gr.Column(elem_id=self.elem_id_suffix("upscaling_column_size"), scale=4):
|
with gr.Column(elem_id="upscaling_column_size", scale=4):
|
||||||
upscaling_resize_w = gr.Slider(minimum=64, maximum=8192, step=8, label="Width", value=512, elem_id=self.elem_id_suffix("extras_upscaling_resize_w"))
|
upscaling_resize_w = gr.Slider(minimum=64, maximum=8192, step=8, label="Width", value=512, elem_id="extras_upscaling_resize_w")
|
||||||
upscaling_resize_h = gr.Slider(minimum=64, maximum=8192, step=8, label="Height", value=512, elem_id=self.elem_id_suffix("extras_upscaling_resize_h"))
|
upscaling_resize_h = gr.Slider(minimum=64, maximum=8192, step=8, label="Height", value=512, elem_id="extras_upscaling_resize_h")
|
||||||
with gr.Column(elem_id=self.elem_id_suffix("upscaling_dimensions_row"), scale=1, elem_classes="dimensions-tools"):
|
with gr.Column(elem_id="upscaling_dimensions_row", scale=1, elem_classes="dimensions-tools"):
|
||||||
upscaling_res_switch_btn = ToolButton(value=switch_values_symbol, elem_id=self.elem_id_suffix("upscaling_res_switch_btn"), tooltip="Switch width/height")
|
upscaling_res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="upscaling_res_switch_btn", tooltip="Switch width/height")
|
||||||
upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id=self.elem_id_suffix("extras_upscaling_crop"))
|
upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop")
|
||||||
|
|
||||||
def on_selected_upscale_method(upscale_method):
|
def on_selected_upscale_method(upscale_method):
|
||||||
if not shared.opts.set_scale_by_when_changing_upscaler:
|
if not shared.opts.set_scale_by_when_changing_upscaler:
|
||||||
@@ -169,7 +169,6 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
|
|||||||
class ScriptPostprocessingUpscaleSimple(ScriptPostprocessingUpscale):
|
class ScriptPostprocessingUpscaleSimple(ScriptPostprocessingUpscale):
|
||||||
name = "Simple Upscale"
|
name = "Simple Upscale"
|
||||||
order = 900
|
order = 900
|
||||||
main_ui_only = True
|
|
||||||
|
|
||||||
def ui(self):
|
def ui(self):
|
||||||
with FormRow():
|
with FormRow():
|
||||||
|
|||||||
@@ -11,25 +11,30 @@ from modules.shared import state
|
|||||||
|
|
||||||
|
|
||||||
def process_model_tag(tag):
|
def process_model_tag(tag):
|
||||||
|
"""\"mode-name\""""
|
||||||
info = sd_models.get_closet_checkpoint_match(tag)
|
info = sd_models.get_closet_checkpoint_match(tag)
|
||||||
assert info is not None, f'Unknown checkpoint: {tag}'
|
assert info is not None, f'Unknown checkpoint: {tag}'
|
||||||
return info.name
|
return info.name
|
||||||
|
|
||||||
|
|
||||||
def process_string_tag(tag):
|
def process_string_tag(tag):
|
||||||
|
"""\"str\""""
|
||||||
return tag
|
return tag
|
||||||
|
|
||||||
|
|
||||||
def process_int_tag(tag):
|
def process_int_tag(tag):
|
||||||
|
"""int-number"""
|
||||||
return int(tag)
|
return int(tag)
|
||||||
|
|
||||||
|
|
||||||
def process_float_tag(tag):
|
def process_float_tag(tag):
|
||||||
|
"""float-number"""
|
||||||
return float(tag)
|
return float(tag)
|
||||||
|
|
||||||
|
|
||||||
def process_boolean_tag(tag):
|
def process_boolean_tag(tag):
|
||||||
return True if (tag == "true") else False
|
"""true|false"""
|
||||||
|
return True if (tag.lower() == "true") else False
|
||||||
|
|
||||||
|
|
||||||
prompt_tags = {
|
prompt_tags = {
|
||||||
@@ -60,6 +65,27 @@ prompt_tags = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def doc_md():
|
||||||
|
md = '<details><summary>Usage Syntax</summary><p>\n\n'
|
||||||
|
for key, func in prompt_tags.items():
|
||||||
|
md += f'`--{key}` `{func.__doc__}`\n'
|
||||||
|
|
||||||
|
md += '''
|
||||||
|
<details><summary>Example</summary><p>
|
||||||
|
|
||||||
|
```shell
|
||||||
|
--prompt "photo of sunset"
|
||||||
|
--prompt "photo of sunset" --negative_prompt "orange, pink, red, sea, water, lake" --width 1024 --height 768 --sampler_name "DPM++ 2M Karras" --steps 10 --batch_size 2 --cfg_scale 3 --seed 9
|
||||||
|
--prompt "photo of winter mountains" --steps 7 --sampler_name "DDIM"
|
||||||
|
--prompt "photo of winter mountains" --width 1024
|
||||||
|
```
|
||||||
|
</p></details>
|
||||||
|
'''
|
||||||
|
|
||||||
|
md += '</p></details>'
|
||||||
|
return md
|
||||||
|
|
||||||
|
|
||||||
def cmdargs(line):
|
def cmdargs(line):
|
||||||
args = shlex.split(line)
|
args = shlex.split(line)
|
||||||
pos = 0
|
pos = 0
|
||||||
@@ -84,7 +110,6 @@ def cmdargs(line):
|
|||||||
res[tag] = prompt
|
res[tag] = prompt
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
func = prompt_tags.get(tag, None)
|
func = prompt_tags.get(tag, None)
|
||||||
assert func, f'unknown commandline option: {arg}'
|
assert func, f'unknown commandline option: {arg}'
|
||||||
|
|
||||||
@@ -125,6 +150,9 @@ class Script(scripts.Script):
|
|||||||
# We don't shrink back to 1, because that causes the control to ignore [enter], and it may
|
# We don't shrink back to 1, because that causes the control to ignore [enter], and it may
|
||||||
# be unclear to the user that shift-enter is needed.
|
# be unclear to the user that shift-enter is needed.
|
||||||
prompt_txt.change(lambda tb: gr.update(lines=7) if ("\n" in tb) else gr.update(lines=2), inputs=[prompt_txt], outputs=[prompt_txt], show_progress=False)
|
prompt_txt.change(lambda tb: gr.update(lines=7) if ("\n" in tb) else gr.update(lines=2), inputs=[prompt_txt], outputs=[prompt_txt], show_progress=False)
|
||||||
|
|
||||||
|
gr.Markdown(doc_md())
|
||||||
|
|
||||||
return [checkbox_iterate, checkbox_iterate_batch, prompt_position, prompt_txt]
|
return [checkbox_iterate, checkbox_iterate_batch, prompt_position, prompt_txt]
|
||||||
|
|
||||||
def run(self, p, checkbox_iterate, checkbox_iterate_batch, prompt_position, prompt_txt: str):
|
def run(self, p, checkbox_iterate, checkbox_iterate_batch, prompt_position, prompt_txt: str):
|
||||||
|
|||||||
+34
-40
@@ -20,7 +20,7 @@ import modules.sd_models
|
|||||||
import modules.sd_vae
|
import modules.sd_vae
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from modules.ui_components import ToolButton, InputAccordion
|
from modules.ui_components import ToolButton
|
||||||
|
|
||||||
fill_values_symbol = "\U0001f4d2" # 📒
|
fill_values_symbol = "\U0001f4d2" # 📒
|
||||||
|
|
||||||
@@ -259,7 +259,6 @@ axis_options = [
|
|||||||
AxisOption("Schedule min sigma", float, apply_override("sigma_min")),
|
AxisOption("Schedule min sigma", float, apply_override("sigma_min")),
|
||||||
AxisOption("Schedule max sigma", float, apply_override("sigma_max")),
|
AxisOption("Schedule max sigma", float, apply_override("sigma_max")),
|
||||||
AxisOption("Schedule rho", float, apply_override("rho")),
|
AxisOption("Schedule rho", float, apply_override("rho")),
|
||||||
AxisOption("Skip Early CFG", float, apply_override('skip_early_cond')),
|
|
||||||
AxisOption("Beta schedule alpha", float, apply_override("beta_dist_alpha")),
|
AxisOption("Beta schedule alpha", float, apply_override("beta_dist_alpha")),
|
||||||
AxisOption("Beta schedule beta", float, apply_override("beta_dist_beta")),
|
AxisOption("Beta schedule beta", float, apply_override("beta_dist_beta")),
|
||||||
AxisOption("Eta", float, apply_field("eta")),
|
AxisOption("Eta", float, apply_field("eta")),
|
||||||
@@ -285,7 +284,7 @@ axis_options = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend, include_lone_images, include_sub_grids, first_axes_processed, second_axes_processed, margin_size, draw_grid):
|
def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend, include_lone_images, include_sub_grids, first_axes_processed, second_axes_processed, margin_size):
|
||||||
hor_texts = [[images.GridAnnotation(x)] for x in x_labels]
|
hor_texts = [[images.GridAnnotation(x)] for x in x_labels]
|
||||||
ver_texts = [[images.GridAnnotation(y)] for y in y_labels]
|
ver_texts = [[images.GridAnnotation(y)] for y in y_labels]
|
||||||
title_texts = [[images.GridAnnotation(z)] for z in z_labels]
|
title_texts = [[images.GridAnnotation(z)] for z in z_labels]
|
||||||
@@ -370,30 +369,29 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend
|
|||||||
print("Unexpected error: draw_xyz_grid failed to return even a single processed image")
|
print("Unexpected error: draw_xyz_grid failed to return even a single processed image")
|
||||||
return Processed(p, [])
|
return Processed(p, [])
|
||||||
|
|
||||||
if draw_grid:
|
z_count = len(zs)
|
||||||
z_count = len(zs)
|
|
||||||
|
|
||||||
for i in range(z_count):
|
for i in range(z_count):
|
||||||
start_index = (i * len(xs) * len(ys)) + i
|
start_index = (i * len(xs) * len(ys)) + i
|
||||||
end_index = start_index + len(xs) * len(ys)
|
end_index = start_index + len(xs) * len(ys)
|
||||||
grid = images.image_grid(processed_result.images[start_index:end_index], rows=len(ys))
|
grid = images.image_grid(processed_result.images[start_index:end_index], rows=len(ys))
|
||||||
if draw_legend:
|
|
||||||
grid_max_w, grid_max_h = map(max, zip(*(img.size for img in processed_result.images[start_index:end_index])))
|
|
||||||
grid = images.draw_grid_annotations(grid, grid_max_w, grid_max_h, hor_texts, ver_texts, margin_size)
|
|
||||||
processed_result.images.insert(i, grid)
|
|
||||||
processed_result.all_prompts.insert(i, processed_result.all_prompts[start_index])
|
|
||||||
processed_result.all_seeds.insert(i, processed_result.all_seeds[start_index])
|
|
||||||
processed_result.infotexts.insert(i, processed_result.infotexts[start_index])
|
|
||||||
|
|
||||||
z_grid = images.image_grid(processed_result.images[:z_count], rows=1)
|
|
||||||
z_sub_grid_max_w, z_sub_grid_max_h = map(max, zip(*(img.size for img in processed_result.images[:z_count])))
|
|
||||||
if draw_legend:
|
if draw_legend:
|
||||||
z_grid = images.draw_grid_annotations(z_grid, z_sub_grid_max_w, z_sub_grid_max_h, title_texts, [[images.GridAnnotation()]])
|
grid_max_w, grid_max_h = map(max, zip(*(img.size for img in processed_result.images[start_index:end_index])))
|
||||||
processed_result.images.insert(0, z_grid)
|
grid = images.draw_grid_annotations(grid, grid_max_w, grid_max_h, hor_texts, ver_texts, margin_size)
|
||||||
# TODO: Deeper aspects of the program rely on grid info being misaligned between metadata arrays, which is not ideal.
|
processed_result.images.insert(i, grid)
|
||||||
# processed_result.all_prompts.insert(0, processed_result.all_prompts[0])
|
processed_result.all_prompts.insert(i, processed_result.all_prompts[start_index])
|
||||||
# processed_result.all_seeds.insert(0, processed_result.all_seeds[0])
|
processed_result.all_seeds.insert(i, processed_result.all_seeds[start_index])
|
||||||
processed_result.infotexts.insert(0, processed_result.infotexts[0])
|
processed_result.infotexts.insert(i, processed_result.infotexts[start_index])
|
||||||
|
|
||||||
|
z_grid = images.image_grid(processed_result.images[:z_count], rows=1)
|
||||||
|
z_sub_grid_max_w, z_sub_grid_max_h = map(max, zip(*(img.size for img in processed_result.images[:z_count])))
|
||||||
|
if draw_legend:
|
||||||
|
z_grid = images.draw_grid_annotations(z_grid, z_sub_grid_max_w, z_sub_grid_max_h, title_texts, [[images.GridAnnotation()]])
|
||||||
|
processed_result.images.insert(0, z_grid)
|
||||||
|
# TODO: Deeper aspects of the program rely on grid info being misaligned between metadata arrays, which is not ideal.
|
||||||
|
# processed_result.all_prompts.insert(0, processed_result.all_prompts[0])
|
||||||
|
# processed_result.all_seeds.insert(0, processed_result.all_seeds[0])
|
||||||
|
processed_result.infotexts.insert(0, processed_result.infotexts[0])
|
||||||
|
|
||||||
return processed_result
|
return processed_result
|
||||||
|
|
||||||
@@ -443,6 +441,7 @@ class Script(scripts.Script):
|
|||||||
|
|
||||||
with gr.Row(variant="compact", elem_id="axis_options"):
|
with gr.Row(variant="compact", elem_id="axis_options"):
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
|
draw_legend = gr.Checkbox(label='Draw legend', value=True, elem_id=self.elem_id("draw_legend"))
|
||||||
no_fixed_seeds = gr.Checkbox(label='Keep -1 for seeds', value=False, elem_id=self.elem_id("no_fixed_seeds"))
|
no_fixed_seeds = gr.Checkbox(label='Keep -1 for seeds', value=False, elem_id=self.elem_id("no_fixed_seeds"))
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
vary_seeds_x = gr.Checkbox(label='Vary seeds for X', value=False, min_width=80, elem_id=self.elem_id("vary_seeds_x"), tooltip="Use different seeds for images along X axis.")
|
vary_seeds_x = gr.Checkbox(label='Vary seeds for X', value=False, min_width=80, elem_id=self.elem_id("vary_seeds_x"), tooltip="Use different seeds for images along X axis.")
|
||||||
@@ -450,12 +449,9 @@ class Script(scripts.Script):
|
|||||||
vary_seeds_z = gr.Checkbox(label='Vary seeds for Z', value=False, min_width=80, elem_id=self.elem_id("vary_seeds_z"), tooltip="Use different seeds for images along Z axis.")
|
vary_seeds_z = gr.Checkbox(label='Vary seeds for Z', value=False, min_width=80, elem_id=self.elem_id("vary_seeds_z"), tooltip="Use different seeds for images along Z axis.")
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
include_lone_images = gr.Checkbox(label='Include Sub Images', value=False, elem_id=self.elem_id("include_lone_images"))
|
include_lone_images = gr.Checkbox(label='Include Sub Images', value=False, elem_id=self.elem_id("include_lone_images"))
|
||||||
csv_mode = gr.Checkbox(label='Use text inputs instead of dropdowns', value=False, elem_id=self.elem_id("csv_mode"))
|
|
||||||
|
|
||||||
with InputAccordion(True, label='Draw grid', elem_id=self.elem_id('draw_grid')) as draw_grid:
|
|
||||||
with gr.Row():
|
|
||||||
include_sub_grids = gr.Checkbox(label='Include Sub Grids', value=False, elem_id=self.elem_id("include_sub_grids"))
|
include_sub_grids = gr.Checkbox(label='Include Sub Grids', value=False, elem_id=self.elem_id("include_sub_grids"))
|
||||||
draw_legend = gr.Checkbox(label='Draw legend', value=True, elem_id=self.elem_id("draw_legend"))
|
csv_mode = gr.Checkbox(label='Use text inputs instead of dropdowns', value=False, elem_id=self.elem_id("csv_mode"))
|
||||||
|
with gr.Column():
|
||||||
margin_size = gr.Slider(label="Grid margins (px)", minimum=0, maximum=500, value=0, step=2, elem_id=self.elem_id("margin_size"))
|
margin_size = gr.Slider(label="Grid margins (px)", minimum=0, maximum=500, value=0, step=2, elem_id=self.elem_id("margin_size"))
|
||||||
|
|
||||||
with gr.Row(variant="compact", elem_id="swap_axes"):
|
with gr.Row(variant="compact", elem_id="swap_axes"):
|
||||||
@@ -537,9 +533,9 @@ class Script(scripts.Script):
|
|||||||
(z_values_dropdown, lambda params: get_dropdown_update_from_params("Z", params)),
|
(z_values_dropdown, lambda params: get_dropdown_update_from_params("Z", params)),
|
||||||
)
|
)
|
||||||
|
|
||||||
return [x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, draw_legend, include_lone_images, include_sub_grids, no_fixed_seeds, vary_seeds_x, vary_seeds_y, vary_seeds_z, margin_size, csv_mode, draw_grid]
|
return [x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, draw_legend, include_lone_images, include_sub_grids, no_fixed_seeds, vary_seeds_x, vary_seeds_y, vary_seeds_z, margin_size, csv_mode]
|
||||||
|
|
||||||
def run(self, p, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, draw_legend, include_lone_images, include_sub_grids, no_fixed_seeds, vary_seeds_x, vary_seeds_y, vary_seeds_z, margin_size, csv_mode, draw_grid):
|
def run(self, p, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, draw_legend, include_lone_images, include_sub_grids, no_fixed_seeds, vary_seeds_x, vary_seeds_y, vary_seeds_z, margin_size, csv_mode):
|
||||||
x_type, y_type, z_type = x_type or 0, y_type or 0, z_type or 0 # if axle type is None set to 0
|
x_type, y_type, z_type = x_type or 0, y_type or 0, z_type or 0 # if axle type is None set to 0
|
||||||
|
|
||||||
if not no_fixed_seeds:
|
if not no_fixed_seeds:
|
||||||
@@ -784,8 +780,7 @@ class Script(scripts.Script):
|
|||||||
include_sub_grids=include_sub_grids,
|
include_sub_grids=include_sub_grids,
|
||||||
first_axes_processed=first_axes_processed,
|
first_axes_processed=first_axes_processed,
|
||||||
second_axes_processed=second_axes_processed,
|
second_axes_processed=second_axes_processed,
|
||||||
margin_size=margin_size,
|
margin_size=margin_size
|
||||||
draw_grid=draw_grid,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if not processed.images:
|
if not processed.images:
|
||||||
@@ -794,15 +789,14 @@ class Script(scripts.Script):
|
|||||||
|
|
||||||
z_count = len(zs)
|
z_count = len(zs)
|
||||||
|
|
||||||
if draw_grid:
|
# Set the grid infotexts to the real ones with extra_generation_params (1 main grid + z_count sub-grids)
|
||||||
# Set the grid infotexts to the real ones with extra_generation_params (1 main grid + z_count sub-grids)
|
processed.infotexts[:1 + z_count] = grid_infotext[:1 + z_count]
|
||||||
processed.infotexts[:1 + z_count] = grid_infotext[:1 + z_count]
|
|
||||||
|
|
||||||
if not include_lone_images:
|
if not include_lone_images:
|
||||||
# Don't need sub-images anymore, drop from list:
|
# Don't need sub-images anymore, drop from list:
|
||||||
processed.images = processed.images[:z_count + 1] if draw_grid else []
|
processed.images = processed.images[:z_count + 1]
|
||||||
|
|
||||||
if draw_grid and opts.grid_save:
|
if opts.grid_save:
|
||||||
# Auto-save main and sub-grids:
|
# Auto-save main and sub-grids:
|
||||||
grid_count = z_count + 1 if z_count > 1 else 1
|
grid_count = z_count + 1 if z_count > 1 else 1
|
||||||
for g in range(grid_count):
|
for g in range(grid_count):
|
||||||
@@ -812,7 +806,7 @@ class Script(scripts.Script):
|
|||||||
if not include_sub_grids: # if not include_sub_grids then skip saving after the first grid
|
if not include_sub_grids: # if not include_sub_grids then skip saving after the first grid
|
||||||
break
|
break
|
||||||
|
|
||||||
if draw_grid and not include_sub_grids:
|
if not include_sub_grids:
|
||||||
# Done with sub-grids, drop all related information:
|
# Done with sub-grids, drop all related information:
|
||||||
for _ in range(z_count):
|
for _ in range(z_count):
|
||||||
del processed.images[1]
|
del processed.images[1]
|
||||||
|
|||||||
@@ -4,16 +4,7 @@ if exist webui.settings.bat (
|
|||||||
call webui.settings.bat
|
call webui.settings.bat
|
||||||
)
|
)
|
||||||
|
|
||||||
if not defined PYTHON (
|
if not defined PYTHON (set PYTHON=python)
|
||||||
for /f "delims=" %%A in ('where python ^| findstr /n . ^| findstr ^^1:') do (
|
|
||||||
if /i "%%~xA" == ".exe" (
|
|
||||||
set PYTHON=python
|
|
||||||
) else (
|
|
||||||
set PYTHON=call python
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if defined GIT (set "GIT_PYTHON_GIT_EXECUTABLE=%GIT%")
|
if defined GIT (set "GIT_PYTHON_GIT_EXECUTABLE=%GIT%")
|
||||||
if not defined VENV_DIR (set "VENV_DIR=%~dp0%venv")
|
if not defined VENV_DIR (set "VENV_DIR=%~dp0%venv")
|
||||||
|
|
||||||
|
|||||||
@@ -45,44 +45,6 @@ def api_only():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def warning_if_invalid_install_dir():
|
|
||||||
"""
|
|
||||||
Shows a warning if the webui is installed under a path that contains a leading dot in any of its parent directories.
|
|
||||||
|
|
||||||
Gradio '/file=' route will block access to files that have a leading dot in the path segments.
|
|
||||||
We use this route to serve files such as JavaScript and CSS to the webpage,
|
|
||||||
if those files are blocked, the webpage will not function properly.
|
|
||||||
See https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/13292
|
|
||||||
|
|
||||||
This is a security feature was added to Gradio 3.32.0 and is removed in later versions,
|
|
||||||
this function replicates Gradio file access blocking logic.
|
|
||||||
|
|
||||||
This check should be removed when it's no longer applicable.
|
|
||||||
"""
|
|
||||||
from packaging.version import parse
|
|
||||||
from pathlib import Path
|
|
||||||
import gradio
|
|
||||||
|
|
||||||
if parse('3.32.0') <= parse(gradio.__version__) < parse('4'):
|
|
||||||
|
|
||||||
def abspath(path):
|
|
||||||
"""modified from Gradio 3.41.2 gradio.utils.abspath()"""
|
|
||||||
if path.is_absolute():
|
|
||||||
return path
|
|
||||||
is_symlink = path.is_symlink() or any(parent.is_symlink() for parent in path.parents)
|
|
||||||
return Path.cwd() / path if (is_symlink or path == path.resolve()) else path.resolve()
|
|
||||||
|
|
||||||
webui_root = Path(__file__).parent
|
|
||||||
if any(part.startswith(".") for part in abspath(webui_root).parts):
|
|
||||||
print(f'''{"!"*25} Warning {"!"*25}
|
|
||||||
WebUI is installed in a directory that has a leading dot (.) in one of its parent directories.
|
|
||||||
This will prevent WebUI from functioning properly.
|
|
||||||
Please move the installation to a different directory.
|
|
||||||
Current path: "{webui_root}"
|
|
||||||
For more information see: https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/13292
|
|
||||||
{"!"*25} Warning {"!"*25}''')
|
|
||||||
|
|
||||||
|
|
||||||
def webui():
|
def webui():
|
||||||
from modules.shared_cmd_options import cmd_opts
|
from modules.shared_cmd_options import cmd_opts
|
||||||
|
|
||||||
@@ -91,8 +53,6 @@ def webui():
|
|||||||
|
|
||||||
from modules import shared, ui_tempdir, script_callbacks, ui, progress, ui_extra_networks
|
from modules import shared, ui_tempdir, script_callbacks, ui, progress, ui_extra_networks
|
||||||
|
|
||||||
warning_if_invalid_install_dir()
|
|
||||||
|
|
||||||
while 1:
|
while 1:
|
||||||
if shared.opts.clean_temp_dir_at_start:
|
if shared.opts.clean_temp_dir_at_start:
|
||||||
ui_tempdir.cleanup_tmpdr()
|
ui_tempdir.cleanup_tmpdr()
|
||||||
|
|||||||
Reference in New Issue
Block a user