@@ -112,6 +112,8 @@
|
||||
"idbPut": "readonly",
|
||||
"idbDel": "readonly",
|
||||
"idbAdd": "readonly",
|
||||
// changelog.js
|
||||
"initChangelog": "readonly",
|
||||
// notification.js
|
||||
"sendNotification": "readonly"
|
||||
},
|
||||
|
||||
@@ -44,6 +44,11 @@ tunableop_results*.csv
|
||||
!webui.sh
|
||||
!package.json
|
||||
|
||||
# pyinstaller
|
||||
*.spec
|
||||
build/
|
||||
dist/
|
||||
|
||||
# dynamically generated
|
||||
/repositories/ip-instruct/
|
||||
|
||||
@@ -69,3 +74,4 @@ tunableop_results*.csv
|
||||
!/models/VAE-approx/model.pt
|
||||
!/models/Reference
|
||||
!/models/Reference/**/*
|
||||
|
||||
|
||||
@@ -1,5 +1,43 @@
|
||||
# Change Log for SD.Next
|
||||
|
||||
## Update for 2024-11-01
|
||||
|
||||
Smaller release just 3 days after the last one, but with some important fixes and improvements.
|
||||
This release can be considered an LTS release before we kick off the next round of major updates.
|
||||
|
||||
- XYZ grid:
|
||||
- optional per-image time benchmark info
|
||||
- UI:
|
||||
- add additional [hotkeys](https://github.com/vladmandic/automatic/wiki/Hotkeys)
|
||||
- Docs:
|
||||
- add built-in [changelog](https://github.com/vladmandic/automatic/blob/master/CHANGELOG.md) search
|
||||
since changelog is the best up-to-date source of info
|
||||
go to system -> changelog and search/highligh/navigate directly in UI!
|
||||
- SD3: ControlNets:
|
||||
- *InstantX Canny, Pose, Depth, Tile*
|
||||
- *Alimama Inpainting, SoftEdge*
|
||||
- *note*: that just like with FLUX.1 or any large model, ControlNet are also large and can push your system over the limit
|
||||
e.g. SD3 controlnets vary from 1GB to over 4GB in size
|
||||
- SD3: all-in-one safetensors
|
||||
- *examples*: [large](https://civitai.com/models/882666/sd35-large-google-flan?modelVersionId=1003031), [medium](https://civitai.com/models/900327)
|
||||
- *note*: enable *bnb* on-the-fly quantization for even bigger gains
|
||||
- CLI:
|
||||
- refactor command line params
|
||||
run `webui.sh`/`webui.bat` with `--help` to see all options
|
||||
- Other:
|
||||
- Repo: move screenshots to GH pages
|
||||
- Update requirements
|
||||
- Fixes:
|
||||
- detailer min/max size as fractions of image size
|
||||
- ipadapter load on-demand
|
||||
- ipadapter face use correct yolo model
|
||||
- list diffusers remove duplicates
|
||||
- fix legacy extensions access to shared objects
|
||||
- fix diffusers load from folder
|
||||
- fix lora enum logging on windows
|
||||
- fix xyz grid with batch count
|
||||
- move dowwloads of some auxillary models to hfcache instead of models folder
|
||||
|
||||
## Update for 2024-10-29
|
||||
|
||||
### Highlights for 2024-10-29
|
||||
|
||||
@@ -24,5 +24,5 @@ abstract: >-
|
||||
generation
|
||||
keywords:
|
||||
- stablediffusion diffusers sdnext
|
||||
license: AGPL-3.0
|
||||
license: Apache-2.0
|
||||
date-released: 2022-12-24
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (c) 2023 AUTOMATIC1111
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
@@ -635,8 +633,8 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -50,12 +50,13 @@ All individual features are not listed here, instead check [ChangeLog](CHANGELOG
|
||||
<br>
|
||||
|
||||
*Main interface using **StandardUI***:
|
||||

|
||||

|
||||
|
||||
*Main interface using **ModernUI***:
|
||||

|
||||

|
||||

|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
For screenshots and informations on other available themes, see [Themes Wiki](https://github.com/vladmandic/automatic/wiki/Themes)
|
||||
|
||||
@@ -63,12 +64,13 @@ For screenshots and informations on other available themes, see [Themes Wiki](ht
|
||||
|
||||
## Model support
|
||||
|
||||
Additional models will be added as they become available and there is public interest in them
|
||||
Additional models will be added as they become available and there is public interest in them
|
||||
See [models overview](https://github.com/vladmandic/automatic/wiki/Models) for details on each model, including their architecture, complexity and other info
|
||||
|
||||
- [RunwayML Stable Diffusion](https://github.com/Stability-AI/stablediffusion/) 1.x and 2.x *(all variants)*
|
||||
- [StabilityAI Stable Diffusion XL](https://github.com/Stability-AI/generative-models)
|
||||
- [StabilityAI Stable Diffusion 3 Medium](https://stability.ai/news/stable-diffusion-3-medium)
|
||||
- [Stable Diffusion 3.5 Large](https://huggingface.co/stabilityai/stable-diffusion-3.5-large)
|
||||
- [StabilityAI Stable Diffusion](https://stability.ai/news/stable-diffusion-3-medium)
|
||||
- [Stable Diffusion 3.x](https://huggingface.co/stabilityai/stable-diffusion-3.5-large) 3.0 Medium, 3.5 Medium, 3.5 Large, 3.5 Large Turbo
|
||||
- [StabilityAI Stable Video Diffusion](https://huggingface.co/stabilityai/stable-video-diffusion-img2vid) Base, XT 1.0, XT 1.1
|
||||
- [StabilityAI Stable Cascade](https://github.com/Stability-AI/StableCascade) *Full* and *Lite*
|
||||
- [Black Forest Labs FLUX.1](https://blackforestlabs.ai/announcing-black-forest-labs/) Dev, Schnell
|
||||
@@ -136,13 +138,13 @@ Also supported are modifiers such as:
|
||||
## Examples
|
||||
|
||||
*IP Adapters*:
|
||||

|
||||

|
||||
|
||||
*Color grading*:
|
||||

|
||||

|
||||
|
||||
*InstantID*:
|
||||

|
||||

|
||||
|
||||
> [!IMPORTANT]
|
||||
> - Loading any model other than standard SD 1.x / SD 2.x requires use of backend **Diffusers**
|
||||
@@ -173,92 +175,34 @@ Also supported are modifiers such as:
|
||||
|
||||
Once SD.Next is installed, simply run `webui.ps1` or `webui.bat` (*Windows*) or `webui.sh` (*Linux or MacOS*)
|
||||
|
||||
List of available parameters, run `webui --help` for the full & up-to-date list:
|
||||
For list of available command line options, run `webui --help` for the full & up-to-date list
|
||||
|
||||
Server options:
|
||||
--config CONFIG Use specific server configuration file, default: config.json
|
||||
--ui-config UI_CONFIG Use specific UI configuration file, default: ui-config.json
|
||||
--medvram Split model stages and keep only active part in VRAM, default: False
|
||||
--lowvram Split model components and keep only active part in VRAM, default: False
|
||||
--ckpt CKPT Path to model checkpoint to load immediately, default: None
|
||||
--vae VAE Path to VAE checkpoint to load immediately, default: None
|
||||
--data-dir DATA_DIR Base path where all user data is stored, default:
|
||||
--models-dir MODELS_DIR Base path where all models are stored, default: models
|
||||
--allow-code Allow custom script execution, default: False
|
||||
--share Enable UI accessible through Gradio site, default: False
|
||||
--insecure Enable extensions tab regardless of other options, default: False
|
||||
--use-cpu USE_CPU [USE_CPU ...] Force use CPU for specified modules, default: []
|
||||
--listen Launch web server using public IP address, default: False
|
||||
--port PORT Launch web server with given server port, default: 7860
|
||||
--freeze Disable editing settings
|
||||
--auth AUTH Set access authentication like "user:pwd,user:pwd""
|
||||
--auth-file AUTH_FILE Set access authentication using file, default: None
|
||||
--autolaunch Open the UI URL in the system's default browser upon launch
|
||||
--docs Mount API docs, default: False
|
||||
--api-only Run in API only mode without starting UI
|
||||
--api-log Enable logging of all API requests, default: False
|
||||
--device-id DEVICE_ID Select the default CUDA device to use, default: None
|
||||
--cors-origins CORS_ORIGINS Allowed CORS origins as comma-separated list, default: None
|
||||
--cors-regex CORS_REGEX Allowed CORS origins as regular expression, default: None
|
||||
--tls-keyfile TLS_KEYFILE Enable TLS and specify key file, default: None
|
||||
--tls-certfile TLS_CERTFILE Enable TLS and specify cert file, default: None
|
||||
--tls-selfsign Enable TLS with self-signed certificates, default: False
|
||||
--server-name SERVER_NAME Sets hostname of server, default: None
|
||||
--no-hashing Disable hashing of checkpoints, default: False
|
||||
--no-metadata Disable reading of metadata from models, default: False
|
||||
--disable-queue Disable queues, default: False
|
||||
--subpath SUBPATH Customize the URL subpath for usage with reverse proxy
|
||||
--backend {original,diffusers} force model pipeline type
|
||||
--allowed-paths ALLOWED_PATHS [ALLOWED_PATHS ...] add additional paths to paths allowed for web access
|
||||
|
||||
Setup options:
|
||||
--reset Reset main repository to latest version, default: False
|
||||
--upgrade Upgrade main repository to latest version, default: False
|
||||
--requirements Force re-check of requirements, default: False
|
||||
--quick Bypass version checks, default: False
|
||||
--use-directml Use DirectML if no compatible GPU is detected, default: False
|
||||
--use-openvino Use Intel OpenVINO backend, default: False
|
||||
--use-ipex Force use Intel OneAPI XPU backend, default: False
|
||||
--use-cuda Force use nVidia CUDA backend, default: False
|
||||
--use-rocm Force use AMD ROCm backend, default: False
|
||||
--use-zluda Force use ZLUDA, AMD GPUs only, default: False
|
||||
--use-xformers Force use xFormers cross-optimization, default: False
|
||||
--skip-requirements Skips checking and installing requirements, default: False
|
||||
--skip-extensions Skips running individual extension installers, default: False
|
||||
--skip-git Skips running all GIT operations, default: False
|
||||
--skip-torch Skips running Torch checks, default: False
|
||||
--skip-all Skips running all checks, default: False
|
||||
--skip-env Skips setting of env variables during startup, default: False
|
||||
--experimental Allow unsupported versions of libraries, default: False
|
||||
--reinstall Force reinstallation of all requirements, default: False
|
||||
--test Run test only and exit
|
||||
--version Print version information
|
||||
--ignore Ignore any errors and attempt to continue
|
||||
--safe Run in safe mode with no user extensions
|
||||
--uv Use uv as installer, default: False
|
||||
|
||||
Logging options:
|
||||
--log LOG Set log file, default: None
|
||||
--debug Run installer with debug logging, default: False
|
||||
--profile Run profiler, default: False
|
||||
> [!TIP]
|
||||
> All command line options can also be set via env variable
|
||||
> For example `--debug` is same as `set SD_DEBUG=true`
|
||||
|
||||
## Notes
|
||||
|
||||
> [!TIP]
|
||||
> If you don't want to use built-in `venv` support and prefer to run SD.Next in your own environment such as *Docker* container, *Conda* environment or any other virtual environment, you can skip `venv` create/activate and launch SD.Next directly using `python launch.py` (command line flags noted above still apply).
|
||||
|
||||
### Quantization
|
||||
|
||||
**SD.Next** comes with broad quantization support, including support for BitsAndBytes, Optimum.Quanto, TorchAO, NNCF and GGUF
|
||||
See [Quantization Wiki](https://github.com/vladmandic/automatic/wiki/Quantization)
|
||||
|
||||
### Control
|
||||
|
||||
**SD.Next** comes with built-in control for all types of text2image, image2image, video2video and batch processing
|
||||
|
||||
*Control interface*:
|
||||

|
||||

|
||||
|
||||
*Control processors*:
|
||||

|
||||

|
||||
|
||||
*Masking*:
|
||||

|
||||

|
||||
|
||||
### Extensions
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Main ToDo list can be found at [GitHub projects](https://github.com/users/vladma
|
||||
|
||||
- async lowvram: <https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/14855>
|
||||
- fp8: <https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/14031>
|
||||
- ipadapter-negative: https://github.com/huggingface/diffusers/discussions/7167
|
||||
- ipadapter-negative: <https://github.com/huggingface/diffusers/discussions/7167>
|
||||
- include reference styles
|
||||
|
||||
### Missing
|
||||
|
||||
@@ -128,7 +128,7 @@ def load_diffusers(name, network_on_disk, lora_scale=shared.opts.extra_networks_
|
||||
|
||||
def load_network(name, network_on_disk) -> network.Network:
|
||||
if not shared.sd_loaded:
|
||||
return
|
||||
return None
|
||||
t0 = time.time()
|
||||
cached = lora_cache.get(name, None)
|
||||
if debug:
|
||||
@@ -533,18 +533,14 @@ def network_MultiheadAttention_load_state_dict(self, *args, **kwargs):
|
||||
|
||||
|
||||
def list_available_networks():
|
||||
t0 = time.time()
|
||||
available_networks.clear()
|
||||
available_network_aliases.clear()
|
||||
forbidden_network_aliases.clear()
|
||||
available_network_hash_lookup.clear()
|
||||
forbidden_network_aliases.update({"none": 1, "Addams": 1})
|
||||
directories = []
|
||||
if os.path.exists(shared.cmd_opts.lora_dir):
|
||||
directories.append(shared.cmd_opts.lora_dir)
|
||||
else:
|
||||
if not os.path.exists(shared.cmd_opts.lora_dir):
|
||||
shared.log.warning(f'LoRA directory not found: path="{shared.cmd_opts.lora_dir}"')
|
||||
if os.path.exists(shared.cmd_opts.lyco_dir) and shared.cmd_opts.lyco_dir != shared.cmd_opts.lora_dir:
|
||||
directories.append(shared.cmd_opts.lyco_dir)
|
||||
|
||||
def add_network(filename):
|
||||
if not os.path.isfile(filename):
|
||||
@@ -565,11 +561,12 @@ def list_available_networks():
|
||||
except OSError as e: # should catch FileNotFoundError and PermissionError etc.
|
||||
shared.log.error(f'LoRA: filename="{filename}" {e}')
|
||||
|
||||
candidates = list(files_cache.list_files(*directories, ext_filter=[".pt", ".ckpt", ".safetensors"]))
|
||||
candidates = list(files_cache.list_files(shared.cmd_opts.lora_dir, ext_filter=[".pt", ".ckpt", ".safetensors"]))
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=shared.max_workers) as executor:
|
||||
for fn in candidates:
|
||||
executor.submit(add_network, fn)
|
||||
shared.log.info(f'Available LoRAs: items={len(available_networks)} folders={len(forbidden_network_aliases)}')
|
||||
t1 = time.time()
|
||||
shared.log.info(f'Available LoRAs: path="{shared.cmd_opts.lora_dir}" items={len(available_networks)} folders={len(forbidden_network_aliases)} time={t1 - t0:.2f}')
|
||||
|
||||
|
||||
def infotext_pasted(infotext, params): # pylint: disable=W0613
|
||||
|
||||
|
Before Width: | Height: | Size: 438 KiB After Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 162 KiB |
|
Before Width: | Height: | Size: 155 KiB |
|
Before Width: | Height: | Size: 193 KiB |
|
Before Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 102 KiB |
@@ -552,7 +552,7 @@ def install_rocm_zluda():
|
||||
from modules import zluda_installer
|
||||
zluda_installer.set_default_agent(device)
|
||||
try:
|
||||
if args.reinstall_zluda:
|
||||
if args.reinstall:
|
||||
zluda_installer.uninstall()
|
||||
zluda_path = zluda_installer.get_path()
|
||||
zluda_installer.install(zluda_path)
|
||||
@@ -1234,39 +1234,44 @@ def check_timestamp():
|
||||
|
||||
|
||||
def add_args(parser):
|
||||
group = parser.add_argument_group('Setup options')
|
||||
group.add_argument('--reset', default = os.environ.get("SD_RESET",False), action='store_true', help = "Reset main repository to latest version, default: %(default)s")
|
||||
group.add_argument('--upgrade', '--update', default = os.environ.get("SD_UPGRADE",False), action='store_true', help = "Upgrade main repository to latest version, default: %(default)s")
|
||||
group.add_argument('--requirements', default = os.environ.get("SD_REQUIREMENTS",False), action='store_true', help = "Force re-check of requirements, default: %(default)s")
|
||||
group.add_argument('--quick', default = os.environ.get("SD_QUICK",False), action='store_true', help = "Bypass version checks, default: %(default)s")
|
||||
group.add_argument('--use-directml', default = os.environ.get("SD_USEDIRECTML",False), action='store_true', help = "Use DirectML if no compatible GPU is detected, default: %(default)s")
|
||||
group.add_argument("--use-openvino", default = os.environ.get("SD_USEOPENVINO",False), action='store_true', help="Use Intel OpenVINO backend, default: %(default)s")
|
||||
group.add_argument("--use-ipex", default = os.environ.get("SD_USEIPEX",False), action='store_true', help="Force use Intel OneAPI XPU backend, default: %(default)s")
|
||||
group.add_argument("--use-cuda", default = os.environ.get("SD_USECUDA",False), action='store_true', help="Force use nVidia CUDA backend, default: %(default)s")
|
||||
group.add_argument("--use-rocm", default = os.environ.get("SD_USEROCM",False), action='store_true', help="Force use AMD ROCm backend, default: %(default)s")
|
||||
group.add_argument('--use-zluda', default=os.environ.get("SD_USEZLUDA", False), action='store_true', help = "Force use ZLUDA, AMD GPUs only, default: %(default)s")
|
||||
group.add_argument("--use-xformers", default = os.environ.get("SD_USEXFORMERS",False), action='store_true', help="Force use xFormers cross-optimization, default: %(default)s")
|
||||
group.add_argument('--skip-requirements', default = os.environ.get("SD_SKIPREQUIREMENTS",False), action='store_true', help = "Skips checking and installing requirements, default: %(default)s")
|
||||
group.add_argument('--skip-extensions', default = os.environ.get("SD_SKIPEXTENSION",False), action='store_true', help = "Skips running individual extension installers, default: %(default)s")
|
||||
group.add_argument('--skip-git', default = os.environ.get("SD_SKIPGIT",False), action='store_true', help = "Skips running all GIT operations, default: %(default)s")
|
||||
group.add_argument('--skip-torch', default = os.environ.get("SD_SKIPTORCH",False), action='store_true', help = "Skips running Torch checks, default: %(default)s")
|
||||
group.add_argument('--skip-all', default = os.environ.get("SD_SKIPALL",False), action='store_true', help = "Skips running all checks, default: %(default)s")
|
||||
group.add_argument('--skip-env', default = os.environ.get("SD_SKIPENV",False), action='store_true', help = "Skips setting of env variables during startup, default: %(default)s")
|
||||
group.add_argument('--experimental', default = os.environ.get("SD_EXPERIMENTAL",False), action='store_true', help = "Allow unsupported versions of libraries, default: %(default)s")
|
||||
group.add_argument('--reinstall', default = os.environ.get("SD_REINSTALL",False), action='store_true', help = "Force reinstallation of all requirements, default: %(default)s")
|
||||
group.add_argument('--reinstall-zluda', default = os.environ.get("SD_REINSTALL_ZLUDA",False), action='store_true', help = "Force reinstallation of ZLUDA, default: %(default)s")
|
||||
group.add_argument('--test', default = os.environ.get("SD_TEST",False), action='store_true', help = "Run test only and exit")
|
||||
group.add_argument('--version', default = False, action='store_true', help = "Print version information")
|
||||
group.add_argument('--ignore', default = os.environ.get("SD_IGNORE",False), action='store_true', help = "Ignore any errors and attempt to continue")
|
||||
group.add_argument('--safe', default = os.environ.get("SD_SAFE",False), action='store_true', help = "Run in safe mode with no user extensions")
|
||||
group.add_argument('--uv', default = os.environ.get("SD_UV",False), action='store_true', help = "Use uv instead of pip to install the packages")
|
||||
group_setup = parser.add_argument_group('Setup')
|
||||
group_setup.add_argument('--reset', default = os.environ.get("SD_RESET",False), action='store_true', help = "Reset main repository to latest version, default: %(default)s")
|
||||
group_setup.add_argument('--upgrade', '--update', default = os.environ.get("SD_UPGRADE",False), action='store_true', help = "Upgrade main repository to latest version, default: %(default)s")
|
||||
group_setup.add_argument('--requirements', default = os.environ.get("SD_REQUIREMENTS",False), action='store_true', help = "Force re-check of requirements, default: %(default)s")
|
||||
group_setup.add_argument('--reinstall', default = os.environ.get("SD_REINSTALL",False), action='store_true', help = "Force reinstallation of all requirements, default: %(default)s")
|
||||
group_setup.add_argument('--uv', default = os.environ.get("SD_UV",False), action='store_true', help = "Use uv instead of pip to install the packages")
|
||||
|
||||
group = parser.add_argument_group('Logging options')
|
||||
group.add_argument("--log", type=str, default=os.environ.get("SD_LOG", None), help="Set log file, default: %(default)s")
|
||||
group.add_argument('--debug', default = os.environ.get("SD_DEBUG",False), action='store_true', help = "Run installer with debug logging, default: %(default)s")
|
||||
group.add_argument("--profile", default=os.environ.get("SD_PROFILE", False), action='store_true', help="Run profiler, default: %(default)s")
|
||||
group.add_argument('--docs', default=os.environ.get("SD_DOCS", False), action='store_true', help = "Mount API docs, default: %(default)s")
|
||||
group.add_argument("--api-log", default=os.environ.get("SD_APILOG", False), action='store_true', help="Enable logging of all API requests, default: %(default)s")
|
||||
group_startup = parser.add_argument_group('Startup')
|
||||
group_startup.add_argument('--quick', default = os.environ.get("SD_QUICK",False), action='store_true', help = "Bypass version checks, default: %(default)s")
|
||||
group_startup.add_argument('--skip-requirements', default = os.environ.get("SD_SKIPREQUIREMENTS",False), action='store_true', help = "Skips checking and installing requirements, default: %(default)s")
|
||||
group_startup.add_argument('--skip-extensions', default = os.environ.get("SD_SKIPEXTENSION",False), action='store_true', help = "Skips running individual extension installers, default: %(default)s")
|
||||
group_startup.add_argument('--skip-git', default = os.environ.get("SD_SKIPGIT",False), action='store_true', help = "Skips running all GIT operations, default: %(default)s")
|
||||
group_startup.add_argument('--skip-torch', default = os.environ.get("SD_SKIPTORCH",False), action='store_true', help = "Skips running Torch checks, default: %(default)s")
|
||||
group_startup.add_argument('--skip-all', default = os.environ.get("SD_SKIPALL",False), action='store_true', help = "Skips running all checks, default: %(default)s")
|
||||
group_startup.add_argument('--skip-env', default = os.environ.get("SD_SKIPENV",False), action='store_true', help = "Skips setting of env variables during startup, default: %(default)s")
|
||||
|
||||
group_compute = parser.add_argument_group('Compute Engine')
|
||||
group_compute.add_argument('--use-directml', default = os.environ.get("SD_USEDIRECTML",False), action='store_true', help = "Use DirectML if no compatible GPU is detected, default: %(default)s")
|
||||
group_compute.add_argument("--use-openvino", default = os.environ.get("SD_USEOPENVINO",False), action='store_true', help="Use Intel OpenVINO backend, default: %(default)s")
|
||||
group_compute.add_argument("--use-ipex", default = os.environ.get("SD_USEIPEX",False), action='store_true', help="Force use Intel OneAPI XPU backend, default: %(default)s")
|
||||
group_compute.add_argument("--use-cuda", default = os.environ.get("SD_USECUDA",False), action='store_true', help="Force use nVidia CUDA backend, default: %(default)s")
|
||||
group_compute.add_argument("--use-rocm", default = os.environ.get("SD_USEROCM",False), action='store_true', help="Force use AMD ROCm backend, default: %(default)s")
|
||||
group_compute.add_argument('--use-zluda', default=os.environ.get("SD_USEZLUDA", False), action='store_true', help = "Force use ZLUDA, AMD GPUs only, default: %(default)s")
|
||||
group_compute.add_argument("--use-xformers", default = os.environ.get("SD_USEXFORMERS",False), action='store_true', help="Force use xFormers cross-optimization, default: %(default)s")
|
||||
|
||||
group_diag = parser.add_argument_group('Diagnostics')
|
||||
group_diag.add_argument('--safe', default = os.environ.get("SD_SAFE",False), action='store_true', help = "Run in safe mode with no user extensions")
|
||||
group_diag.add_argument('--experimental', default = os.environ.get("SD_EXPERIMENTAL",False), action='store_true', help = "Allow unsupported versions of libraries, default: %(default)s")
|
||||
group_diag.add_argument('--test', default = os.environ.get("SD_TEST",False), action='store_true', help = "Run test only and exit")
|
||||
group_diag.add_argument('--version', default = False, action='store_true', help = "Print version information")
|
||||
group_diag.add_argument('--ignore', default = os.environ.get("SD_IGNORE",False), action='store_true', help = "Ignore any errors and attempt to continue")
|
||||
|
||||
group_log = parser.add_argument_group('Logging')
|
||||
group_log.add_argument("--log", type=str, default=os.environ.get("SD_LOG", None), help="Set log file, default: %(default)s")
|
||||
group_log.add_argument('--debug', default = os.environ.get("SD_DEBUG",False), action='store_true', help = "Run installer with debug logging, default: %(default)s")
|
||||
group_log.add_argument("--profile", default=os.environ.get("SD_PROFILE", False), action='store_true', help="Run profiler, default: %(default)s")
|
||||
group_log.add_argument('--docs', default=os.environ.get("SD_DOCS", False), action='store_true', help = "Mount API docs, default: %(default)s")
|
||||
group_log.add_argument("--api-log", default=os.environ.get("SD_APILOG", False), action='store_true', help="Enable logging of all API requests, default: %(default)s")
|
||||
|
||||
|
||||
def parse_args(parser):
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
let changelogElements = [];
|
||||
|
||||
const getAllChildren = (el) => {
|
||||
const elements = [];
|
||||
for (let i = 0; i < el.children.length; i++) {
|
||||
elements.push(el.children[i]);
|
||||
if (el.children[i].children.length) elements.push(...getAllChildren(el.children[i]));
|
||||
}
|
||||
return elements;
|
||||
};
|
||||
|
||||
function getText(el) {
|
||||
let text = '';
|
||||
el.childNodes.forEach((node) => {
|
||||
if (node.nodeType === Node.TEXT_NODE) text += node.nodeValue;
|
||||
});
|
||||
return text.trim();
|
||||
}
|
||||
|
||||
let currentElement = -1;
|
||||
|
||||
function changelogNavigate(found) {
|
||||
const result = gradioApp().getElementById('changelog_result');
|
||||
result.innerHTML = '';
|
||||
const text = document.createElement('p');
|
||||
|
||||
const onPrev = () => {
|
||||
if (currentElement > 0) {
|
||||
currentElement--;
|
||||
found[currentElement].scrollIntoView();
|
||||
text.innerHTML = `   search item ${currentElement + 1} of ${found.length}`;
|
||||
}
|
||||
};
|
||||
const onNext = () => {
|
||||
if (currentElement < found.length - 1) {
|
||||
currentElement++;
|
||||
found[currentElement].scrollIntoView();
|
||||
text.innerHTML = `   search item ${currentElement + 1} of ${found.length}`;
|
||||
}
|
||||
};
|
||||
|
||||
const prev = document.createElement('p');
|
||||
prev.innerHTML = ' ⇦ ';
|
||||
prev.className = 'changelog_arrow';
|
||||
prev.onclick = onPrev;
|
||||
prev.title = 'Search previous';
|
||||
result.appendChild(prev);
|
||||
|
||||
const next = document.createElement('p');
|
||||
next.innerHTML = ' ⇨ ';
|
||||
next.className = 'changelog_arrow';
|
||||
next.title = 'Search next';
|
||||
next.onclick = onNext;
|
||||
result.appendChild(next);
|
||||
|
||||
text.innerHTML = `   found ${found.length} items`;
|
||||
result.appendChild(text);
|
||||
}
|
||||
|
||||
async function initChangelog() {
|
||||
const search = gradioApp().querySelector('#changelog_search > label> textarea');
|
||||
const md = gradioApp().getElementById('changelog_markdown');
|
||||
const searchChangelog = async (e) => {
|
||||
if (changelogElements.length < 100) changelogElements = getAllChildren(md);
|
||||
const found = [];
|
||||
for (const el of changelogElements) {
|
||||
if (search.value.length > 1 && getText(el).toLowerCase().includes(search.value.toLowerCase())) {
|
||||
el.classList.add('changelog_highlight');
|
||||
found.push(el);
|
||||
} else {
|
||||
el.classList.remove('changelog_highlight');
|
||||
}
|
||||
}
|
||||
changelogNavigate(found);
|
||||
};
|
||||
search.addEventListener('keyup', searchChangelog);
|
||||
}
|
||||
@@ -133,19 +133,23 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
|
||||
/**
|
||||
* Add a ctrl+enter as a shortcut to start a generation
|
||||
* Add a listener to the document for keydown events
|
||||
*/
|
||||
document.addEventListener('keydown', (e) => {
|
||||
let handled = false;
|
||||
if (e.key !== undefined) {
|
||||
if ((e.key === 'Enter' && (e.metaKey || e.ctrlKey || e.altKey))) handled = true;
|
||||
} else if (e.keyCode !== undefined) {
|
||||
if ((e.keyCode === 13 && (e.metaKey || e.ctrlKey || e.altKey))) handled = true;
|
||||
}
|
||||
if (handled) {
|
||||
const button = getUICurrentTabContent().querySelector('button[id$=_generate]');
|
||||
if (button) button.click();
|
||||
let elem;
|
||||
if (e.key === 'Escape') elem = getUICurrentTabContent().querySelector('button[id$=_interrupt]');
|
||||
if (e.key === 'Enter' && e.ctrlKey) elem = getUICurrentTabContent().querySelector('button[id$=_generate]');
|
||||
if (e.key === 'Backspace' && e.ctrlKey) elem = getUICurrentTabContent().querySelector('button[id$=_reprocess]');
|
||||
if (e.key === ' ' && e.ctrlKey) elem = getUICurrentTabContent().querySelector('button[id$=_extra_networks_btn]');
|
||||
if (e.key === 's' && e.ctrlKey) elem = getUICurrentTabContent().querySelector('button[id^=save_]');
|
||||
if (e.key === 'Insert' && e.ctrlKey) elem = getUICurrentTabContent().querySelector('button[id^=save_]');
|
||||
if (e.key === 'Delete' && e.ctrlKey) elem = getUICurrentTabContent().querySelector('button[id^=delete_]');
|
||||
// if (e.key === 'm' && e.ctrlKey) elem = gradioApp().getElementById('setting_sd_model_checkpoint');
|
||||
if (elem) {
|
||||
e.preventDefault();
|
||||
log('hotkey', { key: e.key, meta: e.metaKey, ctrl: e.ctrlKey, alt: e.altKey }, elem?.id, elem.nodeName);
|
||||
if (elem.nodeName === 'BUTTON') elem.click();
|
||||
else elem.focus();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -319,6 +319,13 @@ div:has(>#tab-gallery-folders) { flex-grow: 0 !important; background-color: var(
|
||||
.gallery-sort { background: var(--input-background-fill) !important; margin: 0 !important; padding: 6px !important; }
|
||||
.gallery-sort:hover { background: var(--button-primary-background-fill-hover) !important; }
|
||||
|
||||
/* changelog */
|
||||
#changelog_markdown { max-height: 55vh; margin-top: 1em; }
|
||||
#changelog_result { display: flex; margin-left: 1em; align-items: center; }
|
||||
.changelog_arrow { font-size: 2em; padding: 0.1em; cursor: pointer; height: 1em; background-color: var(--button-secondary-background-fill); }
|
||||
.changelog_arrow:hover { background-color: var(--button-primary-border-color-hover); }
|
||||
.changelog_highlight { background-color: var(--color-warning); }
|
||||
|
||||
/* loader */
|
||||
.splash { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: 1000; display: block; text-align: center; }
|
||||
.motd { margin-top: 2em; color: var(--body-text-color-subdued); font-family: monospace; font-variant: all-petite-caps; }
|
||||
|
||||
@@ -16,6 +16,7 @@ async function initStartup() {
|
||||
initImageViewer();
|
||||
initGallery();
|
||||
initiGenerationParams();
|
||||
initChangelog();
|
||||
setupControlUI();
|
||||
|
||||
// reconnect server session
|
||||
|
||||
@@ -164,7 +164,6 @@ def start_server(immediate=True, server=None):
|
||||
module_spec = importlib.util.spec_from_file_location('webui', 'webui.py')
|
||||
server = importlib.util.module_from_spec(module_spec)
|
||||
installer.log.debug(f'Starting module: {server}')
|
||||
get_custom_args()
|
||||
module_spec.loader.exec_module(server)
|
||||
uvicorn = None
|
||||
if args.test:
|
||||
@@ -209,6 +208,7 @@ def main():
|
||||
installer.log.info('Skipping GIT operations')
|
||||
installer.check_version()
|
||||
installer.log.info(f'Platform: {installer.print_dict(installer.get_platform())}')
|
||||
installer.log.info(f'Args: {sys.argv[1:]}')
|
||||
if not args.skip_env:
|
||||
installer.set_environment()
|
||||
if args.uv:
|
||||
@@ -246,6 +246,7 @@ def main():
|
||||
installer.log.warning(f'See log file for more details: {installer.log_file}')
|
||||
installer.extensions_preload(parser) # adds additional args from extensions
|
||||
args = installer.parse_args(parser)
|
||||
get_custom_args()
|
||||
|
||||
uv, instance = start_server(immediate=True, server=None)
|
||||
while True:
|
||||
|
||||
@@ -113,10 +113,9 @@ class APIProcess():
|
||||
images = []
|
||||
scores = []
|
||||
with self.queue_lock:
|
||||
yolo.load()
|
||||
faces = yolo.predict(image)
|
||||
faces = yolo.predict('face-yolo8n', image)
|
||||
for face in faces:
|
||||
images.append(encode_pil_to_base64(face.face))
|
||||
images.append(encode_pil_to_base64(face.item))
|
||||
scores.append(face.score)
|
||||
shared.state.end(api=False)
|
||||
return ResFace(images=images, scores=scores)
|
||||
|
||||
@@ -2,104 +2,134 @@ import os
|
||||
import argparse
|
||||
from modules.paths import data_path
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description="SD.Next", conflict_handler='resolve', epilog='For other options see UI Settings page', prog='', add_help=True, formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=55, indent_increment=2, width=200))
|
||||
parser._optionals = parser.add_argument_group('Other options') # pylint: disable=protected-access
|
||||
group = parser.add_argument_group('Server options')
|
||||
|
||||
# main server args
|
||||
group.add_argument("--config", type=str, default=os.environ.get("SD_CONFIG", os.path.join(data_path, 'config.json')), help="Use specific server configuration file, default: %(default)s")
|
||||
group.add_argument("--ui-config", type=str, default=os.environ.get("SD_UICONFIG", os.path.join(data_path, 'ui-config.json')), help="Use specific UI configuration file, default: %(default)s")
|
||||
group.add_argument("--medvram", default=os.environ.get("SD_MEDVRAM", False), action='store_true', help="Split model stages and keep only active part in VRAM, default: %(default)s")
|
||||
group.add_argument("--lowvram", default=os.environ.get("SD_LOWVRAM", False), action='store_true', help="Split model components and keep only active part in VRAM, default: %(default)s")
|
||||
group.add_argument("--ckpt", type=str, default=os.environ.get("SD_MODEL", None), help="Path to model checkpoint to load immediately, default: %(default)s")
|
||||
group.add_argument('--vae', type=str, default=os.environ.get("SD_VAE", None), help='Path to VAE checkpoint to load immediately, default: %(default)s')
|
||||
group.add_argument("--data-dir", type=str, default=os.environ.get("SD_DATADIR", ''), help="Base path where all user data is stored, default: %(default)s")
|
||||
group.add_argument("--models-dir", type=str, default=os.environ.get("SD_MODELSDIR", 'models'), help="Base path where all models are stored, default: %(default)s",)
|
||||
group.add_argument("--allow-code", default=os.environ.get("SD_ALLOWCODE", False), action='store_true', help="Allow custom script execution, default: %(default)s")
|
||||
group.add_argument("--share", default=os.environ.get("SD_SHARE", False), action='store_true', help="Enable UI accessible through Gradio site, default: %(default)s")
|
||||
group.add_argument("--insecure", default=os.environ.get("SD_INSECURE", False), action='store_true', help="Enable extensions tab regardless of other options, default: %(default)s")
|
||||
group.add_argument("--use-cpu", nargs='+', default=[], type=str.lower, help="Force use CPU for specified modules, default: %(default)s")
|
||||
group.add_argument("--listen", default=os.environ.get("SD_LISTEN", False), action='store_true', help="Launch web server using public IP address, default: %(default)s")
|
||||
group.add_argument("--port", type=int, default=os.environ.get("SD_PORT", 7860), help="Launch web server with given server port, default: %(default)s")
|
||||
group.add_argument("--freeze", default=os.environ.get("SD_FREEZE", False), action='store_true', help="Disable editing settings")
|
||||
group.add_argument("--auth", type=str, default=os.environ.get("SD_AUTH", None), help='Set access authentication like "user:pwd,user:pwd""')
|
||||
group.add_argument("--auth-file", type=str, default=os.environ.get("SD_AUTHFILE", None), help='Set access authentication using file, default: %(default)s')
|
||||
group.add_argument("--autolaunch", default=os.environ.get("SD_AUTOLAUNCH", False), action='store_true', help="Open the UI URL in the system's default browser upon launch")
|
||||
group.add_argument('--docs', default=os.environ.get("SD_DOCS", False), action='store_true', help = "Mount API docs, default: %(default)s")
|
||||
group.add_argument('--api-only', default=os.environ.get("SD_APIONLY", False), action='store_true', help = "Run in API only mode without starting UI")
|
||||
group.add_argument("--device-id", type=str, default=os.environ.get("SD_DEVICEID", None), help="Select the default CUDA device to use, default: %(default)s")
|
||||
group.add_argument("--cors-origins", type=str, default=os.environ.get("SD_CORSORIGINS", None), help="Allowed CORS origins as comma-separated list, default: %(default)s")
|
||||
group.add_argument("--cors-regex", type=str, default=os.environ.get("SD_CORSREGEX", None), help="Allowed CORS origins as regular expression, default: %(default)s")
|
||||
group.add_argument("--tls-keyfile", type=str, default=os.environ.get("SD_TLSKEYFILE", None), help="Enable TLS and specify key file, default: %(default)s")
|
||||
group.add_argument("--tls-certfile", type=str, default=os.environ.get("SD_TLSCERTFILE", None), help="Enable TLS and specify cert file, default: %(default)s")
|
||||
group.add_argument("--tls-selfsign", action="store_true", default=os.environ.get("SD_TLSSELFSIGN", False), help="Enable TLS with self-signed certificates, default: %(default)s")
|
||||
group.add_argument("--server-name", type=str, default=os.environ.get("SD_SERVERNAME", None), help="Sets hostname of server, default: %(default)s")
|
||||
group.add_argument("--no-hashing", default=os.environ.get("SD_NOHASHING", False), action='store_true', help="Disable hashing of checkpoints, default: %(default)s")
|
||||
group.add_argument("--no-metadata", default=os.environ.get("SD_NOMETADATA", False), action='store_true', help="Disable reading of metadata from models, default: %(default)s")
|
||||
group.add_argument("--profile", default=os.environ.get("SD_PROFILE", False), action='store_true', help="Run profiler, default: %(default)s")
|
||||
group.add_argument("--disable-queue", default=os.environ.get("SD_DISABLEQUEUE", False), action='store_true', help="Disable queues, default: %(default)s")
|
||||
group.add_argument('--debug', default=os.environ.get("SD_DEBUG", False), action='store_true', help = "Run installer with debug logging, default: %(default)s")
|
||||
group.add_argument('--use-directml', default=os.environ.get("SD_USEDIRECTML", False), action='store_true', help = "Use DirectML if no compatible GPU is detected, default: %(default)s")
|
||||
group.add_argument('--use-zluda', default=os.environ.get("SD_USEZLUDA", False), action='store_true', help = "Force use ZLUDA, AMD GPUs only, default: %(default)s")
|
||||
group.add_argument("--use-openvino", default=os.environ.get("SD_USEOPENVINO", False), action='store_true', help="Use Intel OpenVINO backend, default: %(default)s")
|
||||
group.add_argument("--use-ipex", default=os.environ.get("SD_USEIPX", False), action='store_true', help="Force use Intel OneAPI XPU backend, default: %(default)s")
|
||||
group.add_argument("--use-cuda", default=os.environ.get("SD_USECUDA", False), action='store_true', help="Force use nVidia CUDA backend, default: %(default)s")
|
||||
group.add_argument("--use-rocm", default=os.environ.get("SD_USEROCM", False), action='store_true', help="Force use AMD ROCm backend, default: %(default)s")
|
||||
group.add_argument('--subpath', type=str, default=os.environ.get("SD_SUBPATH", None), help='Customize the URL subpath for usage with reverse proxy')
|
||||
group.add_argument('--backend', type=str, default=os.environ.get("SD_BACKEND", None), choices=['original', 'diffusers'], required=False, help='force model pipeline type')
|
||||
group.add_argument('--theme', type=str, default=os.environ.get("SD_THEME", None), help='Override UI theme')
|
||||
|
||||
|
||||
# removed args are added here as hidden in fixed format for compatbility reasons
|
||||
group.add_argument("-f", action='store_true', help=argparse.SUPPRESS) # allows running as root; implemented outside of webui
|
||||
group.add_argument("--ui-settings-file", type=str, help=argparse.SUPPRESS, default=os.path.join(data_path, 'config.json'))
|
||||
group.add_argument("--ui-config-file", type=str, help=argparse.SUPPRESS, default=os.path.join(data_path, 'ui-config.json'))
|
||||
group.add_argument("--hide-ui-dir-config", action='store_true', help=argparse.SUPPRESS, default=False)
|
||||
group.add_argument("--theme", type=str, help=argparse.SUPPRESS, default=None)
|
||||
group.add_argument("--disable-console-progressbars", action='store_true', help=argparse.SUPPRESS, default=True)
|
||||
group.add_argument("--disable-safe-unpickle", action='store_true', help=argparse.SUPPRESS, default=True)
|
||||
group.add_argument("--lowram", action='store_true', help=argparse.SUPPRESS)
|
||||
group.add_argument("--disable-extension-access", default=False, action='store_true', help=argparse.SUPPRESS)
|
||||
group.add_argument("--allowed-paths", nargs='+', default=[], type=str, required=False, help="add additional paths to paths allowed for web access")
|
||||
group.add_argument("--api", help=argparse.SUPPRESS, default=True)
|
||||
group.add_argument("--api-auth", type=str, help=argparse.SUPPRESS, default=None)
|
||||
def main_args():
|
||||
# main server args
|
||||
group_config = parser.add_argument_group('Configuration')
|
||||
group_config.add_argument('--backend', type=str, default=os.environ.get("SD_BACKEND", None), choices=['original', 'diffusers'], required=False, help='force model pipeline type')
|
||||
group_config.add_argument("--config", type=str, default=os.environ.get("SD_CONFIG", os.path.join(data_path, 'config.json')), help="Use specific server configuration file, default: %(default)s")
|
||||
group_config.add_argument("--ui-config", type=str, default=os.environ.get("SD_UICONFIG", os.path.join(data_path, 'ui-config.json')), help="Use specific UI configuration file, default: %(default)s")
|
||||
group_config.add_argument("--medvram", default=os.environ.get("SD_MEDVRAM", False), action='store_true', help="Split model stages and keep only active part in VRAM, default: %(default)s")
|
||||
group_config.add_argument("--lowvram", default=os.environ.get("SD_LOWVRAM", False), action='store_true', help="Split model components and keep only active part in VRAM, default: %(default)s")
|
||||
group_config.add_argument("--freeze", default=os.environ.get("SD_FREEZE", False), action='store_true', help="Disable editing settings")
|
||||
|
||||
group_paths = parser.add_argument_group('Paths')
|
||||
group_paths.add_argument("--ckpt", type=str, default=os.environ.get("SD_MODEL", None), help="Path to model checkpoint to load immediately, default: %(default)s")
|
||||
group_paths.add_argument("--data-dir", type=str, default=os.environ.get("SD_DATADIR", ''), help="Base path where all user data is stored, default: %(default)s")
|
||||
group_paths.add_argument("--models-dir", type=str, default=os.environ.get("SD_MODELSDIR", 'models'), help="Base path where all models are stored, default: %(default)s",)
|
||||
|
||||
group_diag = parser.add_argument_group('Diagnostics')
|
||||
group_diag.add_argument("--no-hashing", default=os.environ.get("SD_NOHASHING", False), action='store_true', help="Disable hashing of checkpoints, default: %(default)s")
|
||||
group_diag.add_argument("--no-metadata", default=os.environ.get("SD_NOMETADATA", False), action='store_true', help="Disable reading of metadata from models, default: %(default)s")
|
||||
group_diag.add_argument("--profile", default=os.environ.get("SD_PROFILE", False), action='store_true', help="Run profiler, default: %(default)s")
|
||||
group_diag.add_argument("--disable-queue", default=os.environ.get("SD_DISABLEQUEUE", False), action='store_true', help="Disable queues, default: %(default)s")
|
||||
group_diag.add_argument('--debug', default=os.environ.get("SD_DEBUG", False), action='store_true', help = "Run installer with debug logging, default: %(default)s")
|
||||
|
||||
group_compute = parser.add_argument_group('Compute Engine')
|
||||
group_compute.add_argument('--use-directml', default=os.environ.get("SD_USEDIRECTML", False), action='store_true', help = "Use DirectML if no compatible GPU is detected, default: %(default)s")
|
||||
group_compute.add_argument('--use-zluda', default=os.environ.get("SD_USEZLUDA", False), action='store_true', help = "Force use ZLUDA, AMD GPUs only, default: %(default)s")
|
||||
group_compute.add_argument("--use-openvino", default=os.environ.get("SD_USEOPENVINO", False), action='store_true', help="Use Intel OpenVINO backend, default: %(default)s")
|
||||
group_compute.add_argument("--use-ipex", default=os.environ.get("SD_USEIPX", False), action='store_true', help="Force use Intel OneAPI XPU backend, default: %(default)s")
|
||||
group_compute.add_argument("--use-cuda", default=os.environ.get("SD_USECUDA", False), action='store_true', help="Force use nVidia CUDA backend, default: %(default)s")
|
||||
group_compute.add_argument("--use-rocm", default=os.environ.get("SD_USEROCM", False), action='store_true', help="Force use AMD ROCm backend, default: %(default)s")
|
||||
group_diag.add_argument("--device-id", type=str, default=os.environ.get("SD_DEVICEID", None), help="Select the default CUDA device to use, default: %(default)s")
|
||||
|
||||
group_http = parser.add_argument_group('HTTP')
|
||||
group_http.add_argument('--theme', type=str, default=os.environ.get("SD_THEME", None), help='Override UI theme')
|
||||
group_http.add_argument("--server-name", type=str, default=os.environ.get("SD_SERVERNAME", None), help="Sets hostname of server, default: %(default)s")
|
||||
group_http.add_argument("--tls-keyfile", type=str, default=os.environ.get("SD_TLSKEYFILE", None), help="Enable TLS and specify key file, default: %(default)s")
|
||||
group_http.add_argument("--tls-certfile", type=str, default=os.environ.get("SD_TLSCERTFILE", None), help="Enable TLS and specify cert file, default: %(default)s")
|
||||
group_http.add_argument("--tls-selfsign", action="store_true", default=os.environ.get("SD_TLSSELFSIGN", False), help="Enable TLS with self-signed certificates, default: %(default)s")
|
||||
group_http.add_argument("--cors-origins", type=str, default=os.environ.get("SD_CORSORIGINS", None), help="Allowed CORS origins as comma-separated list, default: %(default)s")
|
||||
group_http.add_argument("--cors-regex", type=str, default=os.environ.get("SD_CORSREGEX", None), help="Allowed CORS origins as regular expression, default: %(default)s")
|
||||
group_http.add_argument('--subpath', type=str, default=os.environ.get("SD_SUBPATH", None), help='Customize the URL subpath for usage with reverse proxy')
|
||||
group_http.add_argument("--autolaunch", default=os.environ.get("SD_AUTOLAUNCH", False), action='store_true', help="Open the UI URL in the system's default browser upon launch")
|
||||
group_http.add_argument('--docs', default=os.environ.get("SD_DOCS", False), action='store_true', help = "Mount API docs, default: %(default)s")
|
||||
group_http.add_argument("--auth", type=str, default=os.environ.get("SD_AUTH", None), help='Set access authentication like "user:pwd,user:pwd""')
|
||||
group_http.add_argument("--auth-file", type=str, default=os.environ.get("SD_AUTHFILE", None), help='Set access authentication using file, default: %(default)s')
|
||||
group_http.add_argument('--api-only', default=os.environ.get("SD_APIONLY", False), action='store_true', help = "Run in API only mode without starting UI")
|
||||
group_http.add_argument("--allowed-paths", nargs='+', default=[], type=str, required=False, help="add additional paths to paths allowed for web access")
|
||||
group_http.add_argument("--share", default=os.environ.get("SD_SHARE", False), action='store_true', help="Enable UI accessible through Gradio site, default: %(default)s")
|
||||
group_http.add_argument("--insecure", default=os.environ.get("SD_INSECURE", False), action='store_true', help="Enable extensions tab regardless of other options, default: %(default)s")
|
||||
group_http.add_argument("--listen", default=os.environ.get("SD_LISTEN", False), action='store_true', help="Launch web server using public IP address, default: %(default)s")
|
||||
group_http.add_argument("--port", type=int, default=os.environ.get("SD_PORT", 7860), help="Launch web server with given server port, default: %(default)s")
|
||||
|
||||
|
||||
def compatibility_args(opts, args):
|
||||
def compatibility_args():
|
||||
group_compat = parser.add_argument_group('Compatibility options')
|
||||
# removed args are added here as hidden in fixed format for compatbility reasons
|
||||
group_compat.add_argument("--allow-code", default=os.environ.get("SD_ALLOWCODE", False), action='store_true', help=argparse.SUPPRESS)
|
||||
group_compat.add_argument("--use-cpu", nargs='+', default=[], type=str.lower, help=argparse.SUPPRESS)
|
||||
group_compat.add_argument("-f", action='store_true', help=argparse.SUPPRESS) # allows running as root; implemented outside of webui
|
||||
group_compat.add_argument('--vae', type=str, default=os.environ.get("SD_VAE", None), help=argparse.SUPPRESS)
|
||||
group_compat.add_argument("--ui-settings-file", type=str, help=argparse.SUPPRESS, default=os.path.join(data_path, 'config.json'))
|
||||
group_compat.add_argument("--ui-config-file", type=str, help=argparse.SUPPRESS, default=os.path.join(data_path, 'ui-config.json'))
|
||||
group_compat.add_argument("--hide-ui-dir-config", action='store_true', help=argparse.SUPPRESS, default=False)
|
||||
group_compat.add_argument("--theme", type=str, help=argparse.SUPPRESS, default=None)
|
||||
group_compat.add_argument("--disable-console-progressbars", action='store_true', help=argparse.SUPPRESS, default=True)
|
||||
group_compat.add_argument("--disable-safe-unpickle", action='store_true', help=argparse.SUPPRESS, default=True)
|
||||
group_compat.add_argument("--lowram", action='store_true', help=argparse.SUPPRESS)
|
||||
group_compat.add_argument("--disable-extension-access", default=False, action='store_true', help=argparse.SUPPRESS)
|
||||
group_compat.add_argument("--api", help=argparse.SUPPRESS, default=True)
|
||||
group_compat.add_argument("--api-auth", type=str, help=argparse.SUPPRESS, default=None)
|
||||
|
||||
|
||||
def settings_args(opts, args):
|
||||
group_compat = parser.add_argument_group('Compatibility options')
|
||||
# removed args are added here as hidden in fixed format for compatbility reasons
|
||||
group_compat.add_argument("--allow-code", default=os.environ.get("SD_ALLOWCODE", False), action='store_true', help=argparse.SUPPRESS)
|
||||
group_compat.add_argument("--use-cpu", nargs='+', default=[], type=str.lower, help=argparse.SUPPRESS)
|
||||
group_compat.add_argument("-f", action='store_true', help=argparse.SUPPRESS) # allows running as root; implemented outside of webui
|
||||
group_compat.add_argument('--vae', type=str, default=os.environ.get("SD_VAE", None), help=argparse.SUPPRESS)
|
||||
group_compat.add_argument("--ui-settings-file", type=str, help=argparse.SUPPRESS, default=os.path.join(data_path, 'config.json'))
|
||||
group_compat.add_argument("--ui-config-file", type=str, help=argparse.SUPPRESS, default=os.path.join(data_path, 'ui-config.json'))
|
||||
group_compat.add_argument("--hide-ui-dir-config", action='store_true', help=argparse.SUPPRESS, default=False)
|
||||
group_compat.add_argument("--theme", type=str, help=argparse.SUPPRESS, default=None)
|
||||
group_compat.add_argument("--disable-console-progressbars", action='store_true', help=argparse.SUPPRESS, default=True)
|
||||
group_compat.add_argument("--disable-safe-unpickle", action='store_true', help=argparse.SUPPRESS, default=True)
|
||||
group_compat.add_argument("--lowram", action='store_true', help=argparse.SUPPRESS)
|
||||
group_compat.add_argument("--disable-extension-access", default=False, action='store_true', help=argparse.SUPPRESS)
|
||||
group_compat.add_argument("--allowed-paths", nargs='+', default=[], type=str, required=False, help="add additional paths to paths allowed for web access")
|
||||
group_compat.add_argument("--api", help=argparse.SUPPRESS, default=True)
|
||||
group_compat.add_argument("--api-auth", type=str, help=argparse.SUPPRESS, default=None)
|
||||
# removed args that have been moved to opts are added here as hidden with default values as defined in opts
|
||||
group.add_argument("--ckpt-dir", type=str, help=argparse.SUPPRESS, default=opts.ckpt_dir)
|
||||
group.add_argument("--vae-dir", type=str, help=argparse.SUPPRESS, default=opts.vae_dir)
|
||||
group.add_argument("--embeddings-dir", type=str, help=argparse.SUPPRESS, default=opts.embeddings_dir)
|
||||
group.add_argument("--embeddings-templates-dir", type=str, help=argparse.SUPPRESS, default=opts.embeddings_templates_dir)
|
||||
group.add_argument("--hypernetwork-dir", type=str, help=argparse.SUPPRESS, default=opts.hypernetwork_dir)
|
||||
group.add_argument("--codeformer-models-path", type=str, help=argparse.SUPPRESS, default=opts.codeformer_models_path)
|
||||
group.add_argument("--gfpgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.gfpgan_models_path)
|
||||
group.add_argument("--esrgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.esrgan_models_path)
|
||||
group.add_argument("--bsrgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.bsrgan_models_path)
|
||||
group.add_argument("--realesrgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.realesrgan_models_path)
|
||||
group.add_argument("--scunet-models-path", help=argparse.SUPPRESS, default=opts.scunet_models_path)
|
||||
group.add_argument("--swinir-models-path", help=argparse.SUPPRESS, default=opts.swinir_models_path)
|
||||
group.add_argument("--ldsr-models-path", help=argparse.SUPPRESS, default=opts.ldsr_models_path)
|
||||
group.add_argument("--clip-models-path", type=str, help=argparse.SUPPRESS, default=opts.clip_models_path)
|
||||
group.add_argument("--opt-channelslast", help=argparse.SUPPRESS, action='store_true', default=opts.opt_channelslast)
|
||||
group.add_argument("--xformers", default=(opts.cross_attention_optimization == "xFormers"), action='store_true', help=argparse.SUPPRESS)
|
||||
group.add_argument("--disable-nan-check", help=argparse.SUPPRESS, action='store_true', default=opts.disable_nan_check)
|
||||
group.add_argument("--rollback-vae", help=argparse.SUPPRESS, default=opts.rollback_vae)
|
||||
group.add_argument("--no-half", help=argparse.SUPPRESS, action='store_true', default=opts.no_half)
|
||||
group.add_argument("--no-half-vae", help=argparse.SUPPRESS, action='store_true', default=opts.no_half_vae)
|
||||
group.add_argument("--precision", help=argparse.SUPPRESS, default=opts.precision)
|
||||
group.add_argument("--sub-quad-q-chunk-size", help=argparse.SUPPRESS, default=opts.sub_quad_q_chunk_size)
|
||||
group.add_argument("--sub-quad-kv-chunk-size", help=argparse.SUPPRESS, default=opts.sub_quad_kv_chunk_size)
|
||||
group.add_argument("--sub-quad-chunk-threshold", help=argparse.SUPPRESS, default=opts.sub_quad_chunk_threshold)
|
||||
group.add_argument("--lora-dir", help=argparse.SUPPRESS, default=opts.lora_dir)
|
||||
group.add_argument("--lyco-dir", help=argparse.SUPPRESS, default=opts.lyco_dir)
|
||||
group.add_argument("--embeddings-dir", help=argparse.SUPPRESS, default=opts.embeddings_dir)
|
||||
group.add_argument("--hypernetwork-dir", help=argparse.SUPPRESS, default=opts.hypernetwork_dir)
|
||||
group.add_argument("--lyco-patch-lora", help=argparse.SUPPRESS, action='store_true', default=False)
|
||||
group.add_argument("--lyco-debug", help=argparse.SUPPRESS, action='store_true', default=False)
|
||||
group.add_argument("--enable-console-prompts", help=argparse.SUPPRESS, action='store_true', default=False)
|
||||
group.add_argument("--safe", help=argparse.SUPPRESS, action='store_true', default=False)
|
||||
group.add_argument("--use-xformers", help=argparse.SUPPRESS, action='store_true', default=False)
|
||||
group_compat.add_argument("--ckpt-dir", type=str, help=argparse.SUPPRESS, default=opts.ckpt_dir)
|
||||
group_compat.add_argument("--vae-dir", type=str, help=argparse.SUPPRESS, default=opts.vae_dir)
|
||||
group_compat.add_argument("--embeddings-dir", type=str, help=argparse.SUPPRESS, default=opts.embeddings_dir)
|
||||
group_compat.add_argument("--embeddings-templates-dir", type=str, help=argparse.SUPPRESS, default=opts.embeddings_templates_dir)
|
||||
group_compat.add_argument("--hypernetwork-dir", type=str, help=argparse.SUPPRESS, default=opts.hypernetwork_dir)
|
||||
group_compat.add_argument("--codeformer-models-path", type=str, help=argparse.SUPPRESS, default=opts.codeformer_models_path)
|
||||
group_compat.add_argument("--gfpgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.gfpgan_models_path)
|
||||
group_compat.add_argument("--esrgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.esrgan_models_path)
|
||||
group_compat.add_argument("--bsrgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.bsrgan_models_path)
|
||||
group_compat.add_argument("--realesrgan-models-path", type=str, help=argparse.SUPPRESS, default=opts.realesrgan_models_path)
|
||||
group_compat.add_argument("--scunet-models-path", help=argparse.SUPPRESS, default=opts.scunet_models_path)
|
||||
group_compat.add_argument("--swinir-models-path", help=argparse.SUPPRESS, default=opts.swinir_models_path)
|
||||
group_compat.add_argument("--ldsr-models-path", help=argparse.SUPPRESS, default=opts.ldsr_models_path)
|
||||
group_compat.add_argument("--clip-models-path", type=str, help=argparse.SUPPRESS, default=opts.clip_models_path)
|
||||
group_compat.add_argument("--opt-channelslast", help=argparse.SUPPRESS, action='store_true', default=opts.opt_channelslast)
|
||||
group_compat.add_argument("--xformers", default=(opts.cross_attention_optimization == "xFormers"), action='store_true', help=argparse.SUPPRESS)
|
||||
group_compat.add_argument("--disable-nan-check", help=argparse.SUPPRESS, action='store_true', default=opts.disable_nan_check)
|
||||
group_compat.add_argument("--rollback-vae", help=argparse.SUPPRESS, default=opts.rollback_vae)
|
||||
group_compat.add_argument("--no-half", help=argparse.SUPPRESS, action='store_true', default=opts.no_half)
|
||||
group_compat.add_argument("--no-half-vae", help=argparse.SUPPRESS, action='store_true', default=opts.no_half_vae)
|
||||
group_compat.add_argument("--precision", help=argparse.SUPPRESS, default=opts.precision)
|
||||
group_compat.add_argument("--sub-quad-q-chunk-size", help=argparse.SUPPRESS, default=opts.sub_quad_q_chunk_size)
|
||||
group_compat.add_argument("--sub-quad-kv-chunk-size", help=argparse.SUPPRESS, default=opts.sub_quad_kv_chunk_size)
|
||||
group_compat.add_argument("--sub-quad-chunk-threshold", help=argparse.SUPPRESS, default=opts.sub_quad_chunk_threshold)
|
||||
group_compat.add_argument("--lora-dir", help=argparse.SUPPRESS, default=opts.lora_dir)
|
||||
group_compat.add_argument("--lyco-dir", help=argparse.SUPPRESS, default=opts.lyco_dir)
|
||||
group_compat.add_argument("--embeddings-dir", help=argparse.SUPPRESS, default=opts.embeddings_dir)
|
||||
group_compat.add_argument("--hypernetwork-dir", help=argparse.SUPPRESS, default=opts.hypernetwork_dir)
|
||||
group_compat.add_argument("--lyco-patch-lora", help=argparse.SUPPRESS, action='store_true', default=False)
|
||||
group_compat.add_argument("--lyco-debug", help=argparse.SUPPRESS, action='store_true', default=False)
|
||||
group_compat.add_argument("--enable-console-prompts", help=argparse.SUPPRESS, action='store_true', default=False)
|
||||
group_compat.add_argument("--safe", help=argparse.SUPPRESS, action='store_true', default=False)
|
||||
group_compat.add_argument("--use-xformers", help=argparse.SUPPRESS, action='store_true', default=False)
|
||||
|
||||
# removed opts are added here with fixed values for compatibility reasons
|
||||
opts.use_old_emphasis_implementation = False
|
||||
@@ -126,3 +156,7 @@ def compatibility_args(opts, args):
|
||||
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
main_args()
|
||||
compatibility_args()
|
||||
|
||||
@@ -564,8 +564,8 @@ def control_run(state: str = '',
|
||||
return [], '', '', 'Reference mode without image'
|
||||
elif unit_type == 'controlnet' and has_models:
|
||||
if input_type == 0: # Control only
|
||||
if shared.sd_model_type == 'f1' and 'control_image' not in p.task_args:
|
||||
p.task_args['control_image'] = p.init_images # flux controlnet mandates this
|
||||
if shared.sd_model_type in ['f1', 'sd3'] and 'control_image' not in p.task_args:
|
||||
p.task_args['control_image'] = p.init_images # some controlnets mandate this
|
||||
p.task_args['strength'] = p.denoising_strength
|
||||
elif input_type == 1: # Init image same as control
|
||||
p.task_args['control_image'] = p.init_images # switch image and control_image
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
import time
|
||||
from typing import Union
|
||||
from diffusers import StableDiffusionPipeline, StableDiffusionXLPipeline, FluxPipeline, ControlNetModel
|
||||
from diffusers import StableDiffusionPipeline, StableDiffusionXLPipeline, FluxPipeline, StableDiffusion3Pipeline, ControlNetModel
|
||||
from modules.control.units import detect
|
||||
from modules.shared import log, opts, listdir
|
||||
from modules import errors, sd_models, devices, model_quant
|
||||
@@ -50,7 +50,6 @@ predefined_sdxl = {
|
||||
'Depth Zoe XL': 'diffusers/controlnet-zoe-depth-sdxl-1.0',
|
||||
'Depth Mid XL': 'diffusers/controlnet-depth-sdxl-1.0-mid',
|
||||
'OpenPose XL': 'thibaud/controlnet-openpose-sdxl-1.0/bin',
|
||||
# 'OpenPose XL': 'thibaud/controlnet-openpose-sdxl-1.0/OpenPoseXL2.safetensors',
|
||||
'Xinsir Union XL': 'xinsir/controlnet-union-sdxl-1.0',
|
||||
'Xinsir OpenPose XL': 'xinsir/controlnet-openpose-sdxl-1.0',
|
||||
'Xinsir Canny XL': 'xinsir/controlnet-canny-sdxl-1.0',
|
||||
@@ -79,11 +78,20 @@ predefined_f1 = {
|
||||
"XLabs-AI Depth": 'XLabs-AI/flux-controlnet-depth-diffusers',
|
||||
"XLabs-AI HED": 'XLabs-AI/flux-controlnet-hed-diffusers'
|
||||
}
|
||||
predefined_sd3 = {
|
||||
"InstantX Canny": 'InstantX/SD3-Controlnet-Canny',
|
||||
"InstantX Pose": 'InstantX/SD3-Controlnet-Pose',
|
||||
"InstantX Depth": 'InstantX/SD3-Controlnet-Depth',
|
||||
"InstantX Tile": 'InstantX/SD3-Controlnet-Tile',
|
||||
"Alimama Inpainting": 'alimama-creative/SD3-Controlnet-Inpainting',
|
||||
"Alimama SoftEdge": 'alimama-creative/SD3-Controlnet-Softedge',
|
||||
}
|
||||
models = {}
|
||||
all_models = {}
|
||||
all_models.update(predefined_sd15)
|
||||
all_models.update(predefined_sdxl)
|
||||
all_models.update(predefined_f1)
|
||||
all_models.update(predefined_sd3)
|
||||
cache_dir = 'models/control/controlnet'
|
||||
|
||||
|
||||
@@ -118,9 +126,11 @@ def list_models(refresh=False):
|
||||
models = ['None'] + list(predefined_sd15) + sorted(find_models())
|
||||
elif modules.shared.sd_model_type == 'f1':
|
||||
models = ['None'] + list(predefined_f1) + sorted(find_models())
|
||||
elif modules.shared.sd_model_type == 'sd3':
|
||||
models = ['None'] + list(predefined_sd3) + sorted(find_models())
|
||||
else:
|
||||
log.warning(f'Control {what} model list failed: unknown model type')
|
||||
models = ['None'] + sorted(predefined_sd15) + sorted(predefined_sdxl) + sorted(find_models())
|
||||
models = ['None'] + sorted(predefined_sd15) + sorted(predefined_sdxl) + sorted(predefined_f1) + sorted(predefined_sd3) + sorted(find_models())
|
||||
debug(f'Control list {what}: path={cache_dir} models={models}')
|
||||
return models
|
||||
|
||||
@@ -151,6 +161,8 @@ class ControlNet():
|
||||
from diffusers import ControlNetModel as model_class # pylint: disable=reimported # sdxl shares same model class
|
||||
elif modules.shared.sd_model_type == 'f1':
|
||||
from diffusers import FluxControlNetModel as model_class
|
||||
elif modules.shared.sd_model_type == 'sd3':
|
||||
from diffusers import SD3ControlNetModel as model_class
|
||||
else:
|
||||
log.error(f'Control {what}: type={modules.shared.sd_model_type} unsupported model')
|
||||
return None
|
||||
@@ -247,7 +259,11 @@ class ControlNet():
|
||||
|
||||
|
||||
class ControlNetPipeline():
|
||||
def __init__(self, controlnet: Union[ControlNetModel, list[ControlNetModel]], pipeline: Union[StableDiffusionXLPipeline, StableDiffusionPipeline, FluxPipeline], dtype = None):
|
||||
def __init__(self,
|
||||
controlnet: Union[ControlNetModel, list[ControlNetModel]],
|
||||
pipeline: Union[StableDiffusionXLPipeline, StableDiffusionPipeline, FluxPipeline, StableDiffusion3Pipeline],
|
||||
dtype = None,
|
||||
):
|
||||
t0 = time.time()
|
||||
self.orig_pipeline = pipeline
|
||||
self.pipeline = None
|
||||
@@ -293,6 +309,20 @@ class ControlNetPipeline():
|
||||
scheduler=pipeline.scheduler,
|
||||
controlnet=controlnet, # can be a list
|
||||
)
|
||||
elif detect.is_sd3(pipeline):
|
||||
from diffusers import StableDiffusion3ControlNetPipeline
|
||||
self.pipeline = StableDiffusion3ControlNetPipeline(
|
||||
vae=pipeline.vae,
|
||||
text_encoder=pipeline.text_encoder,
|
||||
text_encoder_2=pipeline.text_encoder_2,
|
||||
text_encoder_3=pipeline.text_encoder_3,
|
||||
tokenizer=pipeline.tokenizer,
|
||||
tokenizer_2=pipeline.tokenizer_2,
|
||||
tokenizer_3=pipeline.tokenizer_3,
|
||||
transformer=pipeline.transformer,
|
||||
scheduler=pipeline.scheduler,
|
||||
controlnet=controlnet, # can be a list
|
||||
)
|
||||
else:
|
||||
log.error(f'Control {what} pipeline: class={pipeline.__class__.__name__} unsupported model type')
|
||||
return
|
||||
|
||||
@@ -20,5 +20,12 @@ def is_f1(model):
|
||||
if model is None:
|
||||
return False
|
||||
if hasattr(model, '__name__'):
|
||||
return model.__name__ == p.FluxPipeline.__name__
|
||||
return isinstance(model, p.FluxPipeline)
|
||||
return model.__name__ == p.FluxPipeline.__name__ or model.__name__ == p.FluxImg2ImgPipeline.__name__ or model.__name__ == p.FluxInpaintPipeline.__name__
|
||||
return isinstance(model, p.FluxPipeline) or isinstance(model, p.FluxImg2ImgPipeline) or isinstance(model, p.FluxInpaintPipeline)
|
||||
|
||||
def is_sd3(model):
|
||||
if model is None:
|
||||
return False
|
||||
if hasattr(model, '__name__'):
|
||||
return model.__name__ == p.StableDiffusion3Pipeline.__name__ or model.__name__ == p.StableDiffusion3Img2ImgPipeline.__name__ or model.__name__ == p.StableDiffusion3InpaintPipeline.__name__
|
||||
return isinstance(model, p.StableDiffusion3Pipeline) or isinstance(model, p.StableDiffusion3Img2ImgPipeline) or isinstance(model, p.StableDiffusion3InpaintPipeline)
|
||||
|
||||
@@ -79,7 +79,7 @@ def face_id(
|
||||
ip_ckpt = FACEID_MODELS[model]
|
||||
folder, filename = os.path.split(ip_ckpt)
|
||||
basename, _ext = os.path.splitext(filename)
|
||||
model_path = hf.hf_hub_download(repo_id=folder, filename=filename, cache_dir=shared.opts.diffusers_dir)
|
||||
model_path = hf.hf_hub_download(repo_id=folder, filename=filename, cache_dir=shared.opts.hfcache_dir)
|
||||
if model_path is None:
|
||||
shared.log.error(f'FaceID download failed: model={model} file="{ip_ckpt}"')
|
||||
return None
|
||||
|
||||
@@ -32,7 +32,7 @@ def get_app(mp_name):
|
||||
repo_id='vladmandic/insightface-faceanalysis',
|
||||
filename=f'{mp_name}.zip',
|
||||
local_dir_use_symlinks=False,
|
||||
cache_dir=opts.diffusers_dir,
|
||||
cache_dir=opts.hfcache_dir,
|
||||
local_dir=local_dir
|
||||
)
|
||||
if not os.path.exists(extract_dir):
|
||||
|
||||
@@ -189,7 +189,7 @@ def create_override_settings_dict(text_pairs):
|
||||
def connect_paste(button, local_paste_fields, input_comp, override_settings_component, tabname):
|
||||
|
||||
def paste_func(prompt):
|
||||
if prompt is None or len(prompt.strip()) == 0 and not shared.cmd_opts.hide_ui_dir_config:
|
||||
if prompt is None or len(prompt.strip()) == 0:
|
||||
filename = os.path.join(data_path, "params.txt")
|
||||
if os.path.exists(filename):
|
||||
with open(filename, "r", encoding="utf8") as file:
|
||||
|
||||
@@ -10,7 +10,7 @@ import threading
|
||||
import numpy as np
|
||||
import piexif
|
||||
import piexif.helper
|
||||
from PIL import Image, PngImagePlugin, ExifTags
|
||||
from PIL import Image, PngImagePlugin, ExifTags, ImageDraw
|
||||
from modules import sd_samplers, shared, script_callbacks, errors, paths
|
||||
from modules.images_grid import image_grid, get_grid_size, split_grid, combine_grid, check_grid_size, get_font, draw_grid_annotations, draw_prompt_matrix, GridAnnotation, Grid # pylint: disable=unused-import
|
||||
from modules.images_resize import resize_image # pylint: disable=unused-import
|
||||
@@ -361,6 +361,14 @@ def flatten(img, bgcolor):
|
||||
return img.convert('RGB')
|
||||
|
||||
|
||||
def draw_overlay(im, text):
|
||||
d = ImageDraw.Draw(im)
|
||||
fontsize = (im.width + im.height) // 50
|
||||
font = get_font(fontsize)
|
||||
d.text((fontsize//2, fontsize//2), text, font=font, fill=shared.opts.font_color)
|
||||
return im
|
||||
|
||||
|
||||
def set_watermark(image, watermark):
|
||||
if shared.opts.image_watermark_position != 'none': # visible watermark
|
||||
wm_image = None
|
||||
|
||||
@@ -113,7 +113,7 @@ def get_font(fontsize):
|
||||
return ImageFont.truetype("javascript/notosans-nerdfont-regular.ttf", fontsize)
|
||||
|
||||
|
||||
def draw_grid_annotations(im, width, height, hor_texts, ver_texts, margin=0, title=None):
|
||||
def draw_grid_annotations(im, width, height, x_texts, y_texts, margin=0, title=None):
|
||||
def wrap(drawing, text, font, line_length):
|
||||
lines = ['']
|
||||
for word in text.split():
|
||||
@@ -140,15 +140,15 @@ def draw_grid_annotations(im, width, height, hor_texts, ver_texts, margin=0, tit
|
||||
line_spacing = fontsize // 2
|
||||
font = get_font(fontsize)
|
||||
color_inactive = (127, 127, 127)
|
||||
pad_left = 0 if sum([sum([len(line.text) for line in lines]) for lines in ver_texts]) == 0 else width * 3 // 4
|
||||
cols = len(hor_texts)
|
||||
rows = len(ver_texts)
|
||||
pad_left = 0 if sum([sum([len(line.text) for line in lines]) for lines in y_texts]) == 0 else width * 3 // 4
|
||||
cols = len(x_texts)
|
||||
rows = len(y_texts)
|
||||
# assert cols == len(hor_texts), f'bad number of horizontal texts: {len(hor_texts)}; must be {cols}'
|
||||
# assert rows == len(hor_texts), f'bad number of vertical texts: {len(ver_texts)}; must be {rows}'
|
||||
calc_img = Image.new("RGB", (1, 1), shared.opts.grid_background)
|
||||
calc_d = ImageDraw.Draw(calc_img)
|
||||
title_texts = [title] if title else [[GridAnnotation()]]
|
||||
for texts, allowed_width in zip(hor_texts + ver_texts + title_texts, [width] * len(hor_texts) + [pad_left] * len(ver_texts) + [(width+margin)*cols]):
|
||||
for texts, allowed_width in zip(x_texts + y_texts + title_texts, [width] * len(x_texts) + [pad_left] * len(y_texts) + [(width+margin)*cols]):
|
||||
items = [] + texts
|
||||
texts.clear()
|
||||
for line in items:
|
||||
@@ -158,8 +158,8 @@ def draw_grid_annotations(im, width, height, hor_texts, ver_texts, margin=0, tit
|
||||
bbox = calc_d.multiline_textbbox((0, 0), line.text, font=font)
|
||||
line.size = (bbox[2] - bbox[0], bbox[3] - bbox[1])
|
||||
line.allowed_width = allowed_width
|
||||
hor_text_heights = [sum([line.size[1] + line_spacing for line in lines]) - line_spacing for lines in hor_texts]
|
||||
ver_text_heights = [sum([line.size[1] + line_spacing for line in lines]) - line_spacing * len(lines) for lines in ver_texts]
|
||||
hor_text_heights = [sum([line.size[1] + line_spacing for line in lines]) - line_spacing for lines in x_texts]
|
||||
ver_text_heights = [sum([line.size[1] + line_spacing for line in lines]) - line_spacing * len(lines) for lines in y_texts]
|
||||
pad_top = 0 if sum(hor_text_heights) == 0 else max(hor_text_heights) + line_spacing * 2
|
||||
title_pad = 0
|
||||
if title:
|
||||
@@ -178,11 +178,11 @@ def draw_grid_annotations(im, width, height, hor_texts, ver_texts, margin=0, tit
|
||||
for col in range(cols):
|
||||
x = pad_left + (width + margin) * col + width / 2
|
||||
y = (pad_top / 2 - hor_text_heights[col] / 2) + title_pad
|
||||
draw_texts(d, x, y, hor_texts[col], font, fontsize)
|
||||
draw_texts(d, x, y, x_texts[col], font, fontsize)
|
||||
for row in range(rows):
|
||||
x = pad_left / 2
|
||||
y = (pad_top + (height + margin) * row + height / 2 - ver_text_heights[row] / 2) + title_pad
|
||||
draw_texts(d, x, y, ver_texts[row], font, fontsize)
|
||||
draw_texts(d, x, y, y_texts[row], font, fontsize)
|
||||
return result
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ ADAPTERS_SDXL = {
|
||||
'Ostris Composition ViT-H SDXL': { 'name': 'ip_plus_composition_sdxl.safetensors', 'repo': 'ostris/ip-composition-adapter', 'subfolder': '' },
|
||||
}
|
||||
ADAPTERS = { **ADAPTERS_SD15, **ADAPTERS_SDXL }
|
||||
ADAPTERS_ALL = { **ADAPTERS_SD15, **ADAPTERS_SDXL }
|
||||
|
||||
|
||||
def get_adapters():
|
||||
@@ -101,13 +102,12 @@ def crop_images(images, crops):
|
||||
try:
|
||||
for i in range(len(images)):
|
||||
if crops[i]:
|
||||
from shared import yolo # pylint: disable=no-name-in-module
|
||||
yolo.load()
|
||||
from modules.shared import yolo # pylint: disable=no-name-in-module
|
||||
cropped = []
|
||||
for image in images[i]:
|
||||
faces = yolo.predict(image)
|
||||
faces = yolo.predict('face-yolo8n', image)
|
||||
if len(faces) > 0:
|
||||
cropped.append(faces[0].face)
|
||||
cropped.append(faces[0].item)
|
||||
if len(cropped) == len(images[i]):
|
||||
images[i] = cropped
|
||||
else:
|
||||
@@ -135,7 +135,7 @@ def apply(pipe, p: processing.StableDiffusionProcessing, adapter_names=[], adapt
|
||||
if hasattr(p, 'ip_adapter_names'):
|
||||
if isinstance(p.ip_adapter_names, str):
|
||||
p.ip_adapter_names = [p.ip_adapter_names]
|
||||
adapters = [ADAPTERS.get(adapter_name, None) for adapter_name in p.ip_adapter_names if adapter_name is not None and adapter_name.lower() != 'none']
|
||||
adapters = [ADAPTERS_ALL.get(adapter_name, None) for adapter_name in p.ip_adapter_names if adapter_name is not None and adapter_name.lower() != 'none']
|
||||
adapter_names = p.ip_adapter_names
|
||||
else:
|
||||
if isinstance(adapter_names, str):
|
||||
|
||||
@@ -7,10 +7,10 @@ bnb = None
|
||||
quanto = None
|
||||
|
||||
|
||||
def create_bnb_config(kwargs):
|
||||
def create_bnb_config(kwargs = None):
|
||||
from modules import shared, devices
|
||||
if len(shared.opts.bnb_quantization) > 0:
|
||||
if 'Model' in shared.opts.bnb_quantization and 'transformer' not in kwargs:
|
||||
if 'Model' in shared.opts.bnb_quantization and 'transformer' not in (kwargs or {}):
|
||||
load_bnb()
|
||||
bnb_config = diffusers.BitsAndBytesConfig(
|
||||
load_in_8bit=shared.opts.bnb_quantization_type in ['fp8'],
|
||||
@@ -19,8 +19,12 @@ def create_bnb_config(kwargs):
|
||||
bnb_4bit_quant_type=shared.opts.bnb_quantization_type,
|
||||
bnb_4bit_compute_dtype=devices.dtype
|
||||
)
|
||||
kwargs['quantization_config'] = bnb_config
|
||||
shared.log.debug(f'Quantization: module=all type=bnb dtype={shared.opts.bnb_quantization_type} storage={shared.opts.bnb_quantization_storage}')
|
||||
if kwargs is None:
|
||||
return bnb_config
|
||||
else:
|
||||
kwargs['quantization_config'] = bnb_config
|
||||
return kwargs
|
||||
return kwargs
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
import diffusers
|
||||
import transformers
|
||||
from modules import shared, devices, sd_models, sd_unet, model_te, model_quant
|
||||
from modules import shared, devices, sd_models, sd_unet, model_te, model_quant, model_tools
|
||||
|
||||
|
||||
def load_overrides(kwargs, cache_dir):
|
||||
@@ -69,7 +69,7 @@ def load_quants(kwargs, repo_id, cache_dir):
|
||||
|
||||
|
||||
def load_missing(kwargs, fn, cache_dir):
|
||||
keys = sd_models.get_safetensor_keys(fn)
|
||||
keys = model_tools.get_safetensor_keys(fn)
|
||||
size = os.stat(fn).st_size // 1024 // 1024
|
||||
if size > 15000:
|
||||
repo_id = 'stabilityai/stable-diffusion-3.5-large'
|
||||
@@ -129,7 +129,11 @@ def load_sd3(checkpoint_info, cache_dir=None, config=None):
|
||||
if fn is not None and os.path.exists(fn) and os.path.isfile(fn):
|
||||
if fn.endswith('.safetensors'):
|
||||
loader = diffusers.StableDiffusion3Pipeline.from_single_file
|
||||
kwargs = load_missing(kwargs, fn, cache_dir)
|
||||
# required_modules = model_tools.get_modules(diffusers.StableDiffusion3Pipeline)
|
||||
# have_modules = model_tools.get_safetensor_keys(fn)
|
||||
# loaded_modules = model_tools.load_modules('stabilityai/stable-diffusion-3.5-medium', required_modules)
|
||||
# kwargs = {**kwargs, **loaded_modules}
|
||||
# kwargs = load_missing(kwargs, fn, cache_dir)
|
||||
repo_id = fn
|
||||
elif fn.endswith('.gguf'):
|
||||
kwargs = load_gguf(kwargs, fn)
|
||||
@@ -138,7 +142,7 @@ def load_sd3(checkpoint_info, cache_dir=None, config=None):
|
||||
else:
|
||||
kwargs['variant'] = 'fp16'
|
||||
|
||||
shared.log.debug(f'Load model: type=SD3 kwargs={list(kwargs)}')
|
||||
shared.log.debug(f'Load model: type=SD3 kwargs={list(kwargs)} repo="{repo_id}"')
|
||||
|
||||
kwargs = model_quant.create_bnb_config(kwargs)
|
||||
pipe = loader(
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import inspect
|
||||
import diffusers
|
||||
import transformers
|
||||
import safetensors.torch
|
||||
from modules import shared, devices, model_quant
|
||||
|
||||
|
||||
def get_safetensor_keys(filename):
|
||||
keys = []
|
||||
try:
|
||||
with safetensors.torch.safe_open(filename, framework="pt", device="cpu") as f:
|
||||
keys = f.keys()
|
||||
except Exception as e:
|
||||
shared.log.error(f'Load dict: path="{filename}" {e}')
|
||||
return keys
|
||||
|
||||
|
||||
def get_modules(model: callable):
|
||||
signature = inspect.signature(model.__init__, follow_wrapped=True)
|
||||
params = {param.name: param.annotation for param in signature.parameters.values() if param.annotation != inspect._empty and hasattr(param.annotation, 'from_pretrained')} # pylint: disable=protected-access
|
||||
for name, cls in params.items():
|
||||
shared.log.debug(f'Analyze: model={model} module={name} class={cls.__name__} loadable={getattr(cls, "from_pretrained", None)}')
|
||||
return params
|
||||
|
||||
|
||||
def load_modules(repo_id: str, params: dict):
|
||||
cache_dir = shared.opts.hfcache_dir
|
||||
modules = {}
|
||||
for name, cls in params.items():
|
||||
subfolder = None
|
||||
kwargs = {}
|
||||
if cls == diffusers.AutoencoderKL:
|
||||
subfolder = 'vae'
|
||||
if cls == transformers.CLIPTextModel: # clip-vit-l
|
||||
subfolder = 'text_encoder'
|
||||
if cls == transformers.CLIPTextModelWithProjection: # clip-vit-g
|
||||
subfolder = 'text_encoder_2'
|
||||
if cls == transformers.T5EncoderModel: # t5-xxl
|
||||
subfolder = 'text_encoder_3'
|
||||
kwargs['quantization_config'] = model_quant.create_bnb_config()
|
||||
kwargs['variant'] = 'fp16'
|
||||
if cls == diffusers.SD3Transformer2DModel:
|
||||
subfolder = 'transformer'
|
||||
kwargs['quantization_config'] = model_quant.create_bnb_config()
|
||||
if subfolder is None:
|
||||
continue
|
||||
shared.log.debug(f'Load: module={name} class={cls.__name__} repo={repo_id} location={subfolder}')
|
||||
modules[name] = cls.from_pretrained(repo_id, subfolder=subfolder, cache_dir=cache_dir, torch_dtype=devices.dtype, **kwargs)
|
||||
return modules
|
||||
@@ -273,6 +273,7 @@ def load_diffusers_models(clear=True):
|
||||
place = os.path.join(models_path, 'Diffusers')
|
||||
if clear:
|
||||
diffuser_repos.clear()
|
||||
already_found = []
|
||||
try:
|
||||
for folder in os.listdir(place):
|
||||
try:
|
||||
@@ -303,7 +304,11 @@ def load_diffusers_models(clear=True):
|
||||
if (not os.path.exists(index)) and (not os.path.exists(info)) and (not os.path.exists(config)):
|
||||
debug(f'Diffusers skip model no info: {name}')
|
||||
continue
|
||||
if name in already_found:
|
||||
debug(f'Diffusers skip model already found: {name}')
|
||||
continue
|
||||
repo = { 'name': name, 'filename': name, 'friendly': friendly, 'folder': folder, 'path': commit, 'hash': snapshot, 'mtime': mtime, 'model_info': info, 'model_index': index, 'model_config': config }
|
||||
already_found.append(name)
|
||||
diffuser_repos.append(repo)
|
||||
if os.path.exists(os.path.join(folder, 'hidden')):
|
||||
continue
|
||||
|
||||
@@ -78,6 +78,10 @@ class YoloRestorer(Detailer):
|
||||
) -> list[YoloResult]:
|
||||
|
||||
result = []
|
||||
if isinstance(model, str):
|
||||
model = self.models.get(model, None)
|
||||
if model is None:
|
||||
_, model = self.load(model)
|
||||
if model is None:
|
||||
return result
|
||||
args = {
|
||||
@@ -124,7 +128,9 @@ class YoloRestorer(Detailer):
|
||||
mask_image = None
|
||||
w, h = box[2] - box[0], box[3] - box[1]
|
||||
size = w * h / (image.width * image.height)
|
||||
if (min(w, h) > shared.opts.detailer_min_size if shared.opts.detailer_min_size > 0 else True) and (max(w, h) < shared.opts.detailer_max_size if shared.opts.detailer_max_size > 0 else True):
|
||||
min_size = (shared.opts.detailer_min_size if shared.opts.detailer_min_size > 0 else 0) * min(w, h)
|
||||
max_size = (shared.opts.detailer_max_size if shared.opts.detailer_max_size > 0 else 1) * max(w, h)
|
||||
if (min(w, h) > min_size) and (max(w, h) < max_size):
|
||||
if mask:
|
||||
mask_image = image.copy()
|
||||
mask_image = Image.new('L', image.size, 0)
|
||||
@@ -138,6 +144,7 @@ class YoloRestorer(Detailer):
|
||||
|
||||
def load(self, model_name: str = None):
|
||||
from modules import modelloader
|
||||
model = None
|
||||
self.dependencies()
|
||||
if model_name is None:
|
||||
model_name = list(self.list)[0]
|
||||
@@ -158,7 +165,7 @@ class YoloRestorer(Detailer):
|
||||
return model_name, model
|
||||
except Exception as e:
|
||||
shared.log.error(f'Load: type=Detailer name="{model_name}" error="{e}"')
|
||||
return None
|
||||
return None, None
|
||||
|
||||
def restore(self, np_image, p: processing.StableDiffusionProcessing = None):
|
||||
if hasattr(p, 'recursion'):
|
||||
@@ -323,8 +330,10 @@ class YoloRestorer(Detailer):
|
||||
min_confidence = gr.Slider(label="Min confidence", elem_id=f"{tab}_detailer_conf", value=shared.opts.detailer_conf, minimum=0.0, maximum=1.0, step=0.05)
|
||||
iou = gr.Slider(label="Max overlap", elem_id=f"{tab}_detailer_iou", value=shared.opts.detailer_iou, minimum=0, maximum=1.0, step=0.05)
|
||||
with gr.Row():
|
||||
min_size = gr.Slider(label="Min size", elem_id=f"{tab}_detailer_min_size", value=shared.opts.detailer_min_size, minimum=0, maximum=1024, step=1)
|
||||
max_size = gr.Slider(label="Max size", elem_id=f"{tab}_detailer_max_size", value=shared.opts.detailer_max_size, minimum=0, maximum=1024, step=1)
|
||||
min_size = shared.opts.detailer_min_size if shared.opts.detailer_min_size < 1 else 0.0
|
||||
min_size = gr.Slider(label="Min size", elem_id=f"{tab}_detailer_min_size", value=min_size, minimum=0.1, maximum=1.0, step=0.05)
|
||||
max_size = shared.opts.detailer_min_size if shared.opts.detailer_min_size < 1 and shared.opts.detailer_min_size > 0 else 1.0
|
||||
max_size = gr.Slider(label="Max size", elem_id=f"{tab}_detailer_max_size", value=max_size, minimum=0.1, maximum=1.0, step=0.05)
|
||||
detailers.change(fn=ui_settings_change, inputs=[detailers, classes, strength, padding, blur, min_confidence, max_detected, min_size, max_size, iou], outputs=[])
|
||||
classes.change(fn=ui_settings_change, inputs=[detailers, classes, strength, padding, blur, min_confidence, max_detected, min_size, max_size, iou], outputs=[])
|
||||
strength.change(fn=ui_settings_change, inputs=[detailers, classes, strength, padding, blur, min_confidence, max_detected, min_size, max_size, iou], outputs=[])
|
||||
|
||||
@@ -37,7 +37,6 @@ def run_postprocessing(extras_mode, image, image_folder: List[tempfile.NamedTemp
|
||||
image_ext.append(ext)
|
||||
shared.log.debug(f'Process: mode=batch inputs={len(image_folder)} images={len(image_data)}')
|
||||
elif extras_mode == 2:
|
||||
assert not shared.cmd_opts.hide_ui_dir_config, '--hide-ui-dir-config option must be disabled'
|
||||
assert input_dir, 'input directory not selected'
|
||||
image_list = os.listdir(input_dir)
|
||||
for filename in image_list:
|
||||
|
||||
@@ -14,7 +14,7 @@ def load_module(path):
|
||||
module_spec = importlib.util.spec_from_file_location(os.path.basename(path), path)
|
||||
module = importlib.util.module_from_spec(module_spec)
|
||||
try:
|
||||
if '/sd-extension-' in path or '/Lora' in path: # safe extensions without stdout intercept
|
||||
if 'sd-extension-' in path or 'Lora' in path: # safe extensions without stdout intercept
|
||||
module_spec.loader.exec_module(module)
|
||||
else:
|
||||
if debug:
|
||||
|
||||
@@ -84,6 +84,8 @@ def detect_pipeline(f: str, op: str = 'model', warning=True, quiet=False):
|
||||
if 'omnigen' in f.lower():
|
||||
guess = 'OmniGen'
|
||||
pipeline = 'custom'
|
||||
if 'sd3' in f.lower():
|
||||
guess = 'Stable Diffusion 3'
|
||||
if 'flux' in f.lower():
|
||||
guess = 'FLUX'
|
||||
if size > 11000 and size < 20000:
|
||||
|
||||
@@ -19,7 +19,7 @@ from modules import paths, shared, shared_state, modelloader, devices, script_ca
|
||||
from modules.timer import Timer
|
||||
from modules.memstats import memory_stats
|
||||
from modules.modeldata import model_data
|
||||
from modules.sd_checkpoint import CheckpointInfo, select_checkpoint, list_models, checkpoints_list, checkpoint_titles, get_closet_checkpoint_match, update_model_hashes, setup_model, write_metadata, read_metadata_from_safetensors # pylint: disable=unused-import
|
||||
from modules.sd_checkpoint import CheckpointInfo, select_checkpoint, list_models, checkpoints_list, checkpoint_titles, get_closet_checkpoint_match, model_hash, update_model_hashes, setup_model, write_metadata, read_metadata_from_safetensors # pylint: disable=unused-import
|
||||
|
||||
|
||||
model_dir = "Stable-diffusion"
|
||||
@@ -75,16 +75,6 @@ def read_state_dict(checkpoint_file, map_location=None, what:str='model'): # pyl
|
||||
return sd
|
||||
|
||||
|
||||
def get_safetensor_keys(filename):
|
||||
keys = []
|
||||
try:
|
||||
with safetensors.torch.safe_open(filename, framework="pt", device="cpu") as f:
|
||||
keys = f.keys()
|
||||
except Exception as e:
|
||||
shared.log.error(f'Load dict: path="{filename}" {e}')
|
||||
return keys
|
||||
|
||||
|
||||
def get_state_dict_from_checkpoint(pl_sd):
|
||||
checkpoint_dict_replacements = {
|
||||
'cond_stage_model.transformer.embeddings.': 'cond_stage_model.transformer.text_model.embeddings.',
|
||||
@@ -1052,6 +1042,15 @@ def clean_diffuser_pipe(pipe):
|
||||
|
||||
|
||||
def set_diffuser_pipe(pipe, new_pipe_type):
|
||||
exclude = [
|
||||
'StableDiffusionReferencePipeline',
|
||||
'StableDiffusionAdapterPipeline',
|
||||
'AnimateDiffPipeline',
|
||||
'AnimateDiffSDXLPipeline',
|
||||
'OmniGenPipeline',
|
||||
'StableDiffusion3ControlNetPipeline',
|
||||
]
|
||||
|
||||
n = getattr(pipe.__class__, '__name__', '')
|
||||
if new_pipe_type == DiffusersTaskType.TEXT_2_IMAGE:
|
||||
clean_diffuser_pipe(pipe)
|
||||
@@ -1060,7 +1059,7 @@ def set_diffuser_pipe(pipe, new_pipe_type):
|
||||
return pipe
|
||||
|
||||
# skip specific pipelines
|
||||
if n in ['StableDiffusionReferencePipeline', 'StableDiffusionAdapterPipeline', 'AnimateDiffPipeline', 'AnimateDiffSDXLPipeline', 'OmniGenPipeline']:
|
||||
if n in exclude:
|
||||
return pipe
|
||||
if 'Onnx' in pipe.__class__.__name__:
|
||||
return pipe
|
||||
|
||||
@@ -821,8 +821,8 @@ options_templates.update(options_section(('postprocessing', "Postprocessing"), {
|
||||
"detailer_conf": OptionInfo(0.6, "Min confidence", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.05, "visible": False}),
|
||||
"detailer_max": OptionInfo(2, "Max detected", gr.Slider, {"minimum": 1, "maximum": 10, "step": 1, "visible": False}),
|
||||
"detailer_iou": OptionInfo(0.5, "Max overlap", gr.Slider, {"minimum": 0, "maximum": 1.0, "step": 0.05, "visible": False}),
|
||||
"detailer_min_size": OptionInfo(0, "Min object size", gr.Slider, {"minimum": 0, "maximum": 1024, "step": 1, "visible": False}),
|
||||
"detailer_max_size": OptionInfo(0, "Max object size", gr.Slider, {"minimum": 0, "maximum": 1024, "step": 1, "visible": False}),
|
||||
"detailer_min_size": OptionInfo(0.0, "Min object size", gr.Slider, {"minimum": 0.1, "maximum": 1, "step": 0.05, "visible": False}),
|
||||
"detailer_max_size": OptionInfo(1.0, "Max object size", gr.Slider, {"minimum": 0.1, "maximum": 1, "step": 0.05, "visible": False}),
|
||||
"detailer_padding": OptionInfo(20, "Item padding", gr.Slider, {"minimum": 0, "maximum": 100, "step": 1, "visible": False}),
|
||||
"detailer_blur": OptionInfo(10, "Item edge blur", gr.Slider, {"minimum": 0, "maximum": 100, "step": 1, "visible": False}),
|
||||
"detailer_strength": OptionInfo(0.5, "Detailer strength", gr.Slider, {"minimum": 0, "maximum": 1, "step": 0.01, "visible": False}),
|
||||
@@ -1101,7 +1101,7 @@ profiler = None
|
||||
opts = Options()
|
||||
config_filename = cmd_opts.config
|
||||
opts.load(config_filename)
|
||||
cmd_opts = cmd_args.compatibility_args(opts, cmd_opts)
|
||||
cmd_opts = cmd_args.settings_args(opts, cmd_opts)
|
||||
if cmd_opts.use_xformers:
|
||||
opts.data['cross_attention_optimization'] = 'xFormers'
|
||||
opts.data['uni_pc_lower_order_final'] = opts.schedulers_use_loworder # compatibility
|
||||
|
||||
@@ -355,13 +355,20 @@ def create_ui(startup_timer = None):
|
||||
ui_onnx.create_ui()
|
||||
|
||||
with gr.TabItem("Change log", id="change_log", elem_id="system_tab_changelog"):
|
||||
with open('CHANGELOG.md', 'r', encoding='utf-8') as f:
|
||||
md = f.read()
|
||||
gr.Markdown(md)
|
||||
def get_changelog():
|
||||
with open('CHANGELOG.md', 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
content = content.replace('# Change Log for SD.Next', ' ')
|
||||
return content
|
||||
|
||||
with gr.TabItem("Licenses", id="system_licenses", elem_id="system_tab_licenses"):
|
||||
gr.HTML(shared.html("licenses.html"), elem_id="licenses", elem_classes="licenses")
|
||||
create_dirty_indicator("tab_licenses", [], interactive=False)
|
||||
with gr.Column():
|
||||
get_changelog_btn = gr.Button(value='Get changelog', elem_id="get_changelog")
|
||||
with gr.Column():
|
||||
_changelog_search = gr.Textbox(label="Search", elem_id="changelog_search")
|
||||
_changelog_result = gr.HTML(elem_id="changelog_result")
|
||||
|
||||
changelog_markdown = gr.Markdown('', elem_id="changelog_markdown")
|
||||
get_changelog_btn.click(fn=get_changelog, outputs=[changelog_markdown], show_progress=True)
|
||||
|
||||
def unload_sd_weights():
|
||||
modules.sd_models.unload_model_weights(op='model')
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"url": "https://github.com/vladmandic/automatic/issues"
|
||||
},
|
||||
"homepage": "https://github.com/vladmandic/automatic",
|
||||
"license": "AGPLv3",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
|
||||
@@ -50,7 +50,7 @@ pandas
|
||||
protobuf==4.25.3
|
||||
pytorch_lightning==1.9.4
|
||||
tokenizers==0.20.1
|
||||
transformers==4.46.0
|
||||
transformers==4.46.1
|
||||
urllib3==1.26.19
|
||||
Pillow==10.4.0
|
||||
timm==0.9.16
|
||||
|
||||
@@ -32,10 +32,10 @@ class Script(scripts.Script):
|
||||
|
||||
def load(self):
|
||||
if self.tokenizer is None:
|
||||
self.tokenizer = AutoTokenizer.from_pretrained('gokaygokay/Flux-Prompt-Enhance', cache_dir=shared.opts.diffusers_dir)
|
||||
self.tokenizer = AutoTokenizer.from_pretrained('gokaygokay/Flux-Prompt-Enhance', cache_dir=shared.opts.hfcache_dir)
|
||||
if self.model is None:
|
||||
shared.log.info(f'Prompt enhance: model="{repo_id}"')
|
||||
self.model = AutoModelForSeq2SeqLM.from_pretrained('gokaygokay/Flux-Prompt-Enhance', cache_dir=shared.opts.diffusers_dir).to(device=devices.cpu, dtype=devices.dtype)
|
||||
self.model = AutoModelForSeq2SeqLM.from_pretrained('gokaygokay/Flux-Prompt-Enhance', cache_dir=shared.opts.hfcache_dir).to(device=devices.cpu, dtype=devices.dtype)
|
||||
|
||||
def enhance(self, prompt, auto_apply: bool = False, temperature: float = 0.7, repetition_penalty: float = 1.2, max_length: int = 128):
|
||||
self.load()
|
||||
|
||||
@@ -48,10 +48,11 @@ class Script(scripts.Script):
|
||||
csv_mode = gr.Checkbox(label='Text inputs', value=False, elem_id=self.elem_id("csv_mode"), container=False)
|
||||
draw_legend = gr.Checkbox(label='Legend', value=True, elem_id=self.elem_id("draw_legend"), container=False)
|
||||
no_fixed_seeds = gr.Checkbox(label='Random seeds', value=False, elem_id=self.elem_id("no_fixed_seeds"), container=False)
|
||||
include_time = gr.Checkbox(label='Add time info', value=False, elem_id=self.elem_id("include_time"), container=False)
|
||||
with gr.Column():
|
||||
no_grid = gr.Checkbox(label='Skip grid', value=False, elem_id=self.elem_id("no_xyz_grid"), container=False)
|
||||
include_lone_images = gr.Checkbox(label='Sub-images', value=False, elem_id=self.elem_id("include_lone_images"), container=False)
|
||||
include_sub_grids = gr.Checkbox(label='Sub-grids', value=False, elem_id=self.elem_id("include_sub_grids"), container=False)
|
||||
include_grid = gr.Checkbox(label='Include main grid', value=True, elem_id=self.elem_id("no_xyz_grid"), container=False)
|
||||
include_subgrids = gr.Checkbox(label='Include sub grids', value=False, elem_id=self.elem_id("include_sub_grids"), container=False)
|
||||
include_images = gr.Checkbox(label='Include images', value=False, elem_id=self.elem_id("include_lone_images"), container=False)
|
||||
with gr.Row():
|
||||
margin_size = gr.Slider(label="Grid margins", minimum=0, maximum=500, value=0, step=2, elem_id=self.elem_id("margin_size"))
|
||||
with gr.Row():
|
||||
@@ -130,10 +131,9 @@ class Script(scripts.Script):
|
||||
(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, csv_mode, draw_legend, no_fixed_seeds, no_grid, include_lone_images, include_sub_grids, margin_size]
|
||||
return [x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, include_time, margin_size]
|
||||
|
||||
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, csv_mode, draw_legend, no_fixed_seeds, no_grid, include_lone_images, include_sub_grids, margin_size): # pylint: disable=W0221
|
||||
shared.log.debug(f'xyzgrid: x_type={x_type}|x_values={x_values}|x_values_dropdown={x_values_dropdown}|y_type={y_type}|{y_values}={y_values}|{y_values_dropdown}={y_values_dropdown}|z_type={z_type}|z_values={z_values}|z_values_dropdown={z_values_dropdown}|draw_legend={draw_legend}|include_lone_images={include_lone_images}|include_sub_grids={include_sub_grids}|no_grid={no_grid}|margin_size={margin_size}')
|
||||
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, csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, include_time, margin_size): # pylint: disable=W0221
|
||||
if not no_fixed_seeds:
|
||||
processing.fix_seed(p)
|
||||
if not shared.opts.return_grid:
|
||||
@@ -307,38 +307,38 @@ class Script(scripts.Script):
|
||||
z_labels=[z_opt.format_value(p, z_opt, z) for z in zs],
|
||||
cell=cell,
|
||||
draw_legend=draw_legend,
|
||||
include_lone_images=include_lone_images,
|
||||
include_sub_grids=include_sub_grids,
|
||||
include_lone_images=include_images,
|
||||
include_sub_grids=include_subgrids,
|
||||
first_axes_processed=first_axes_processed,
|
||||
second_axes_processed=second_axes_processed,
|
||||
margin_size=margin_size,
|
||||
no_grid=no_grid,
|
||||
no_grid=not include_grid,
|
||||
include_time=include_time,
|
||||
)
|
||||
|
||||
if not processed.images:
|
||||
return processed # It broke, no further handling needed.
|
||||
return processed # something broke, no further handling needed.
|
||||
z_count = len(zs)
|
||||
processed.infotexts[:1+z_count] = grid_infotext[:1+z_count] # Set the grid infotexts to the real ones with extra_generation_params (1 main grid + z_count sub-grids)
|
||||
if not include_lone_images:
|
||||
# Don't need sub-images anymore, drop from list:
|
||||
if no_grid and include_sub_grids:
|
||||
processed.infotexts[:1+z_count] = grid_infotext[:1+z_count] # set the grid infotexts to the real ones with extra_generation_params (1 main grid + z_count sub-grids)
|
||||
if not include_images: # dont need sub-images anymore, drop from list:
|
||||
if not include_grid and include_subgrids:
|
||||
processed.images = processed.images[:z_count] # we don't have the main grid image, and need zero additional sub-images
|
||||
else:
|
||||
processed.images = processed.images[:z_count+1] # we either have the main grid image, or need one sub-images
|
||||
if shared.opts.grid_save: # Auto-save main and sub-grids:
|
||||
grid_count = z_count + ( 1 if not no_grid and z_count > 1 else 0 )
|
||||
if shared.opts.grid_save: # auto-save main and sub-grids:
|
||||
grid_count = z_count + ( 1 if include_grid and z_count > 1 else 0 )
|
||||
for g in range(grid_count):
|
||||
adj_g = g-1 if g > 0 else g
|
||||
info = processed.infotexts[g]
|
||||
prompt = processed.all_prompts[adj_g]
|
||||
seed = processed.all_seeds[adj_g]
|
||||
images.save_image(processed.images[g], p.outpath_grids, "grid", info=info, extension=shared.opts.grid_format, prompt=prompt, seed=seed, grid=True, p=processed)
|
||||
if not include_sub_grids: # Done with sub-grids, drop all related information:
|
||||
if not include_subgrids: # done with sub-grids, drop all related information:
|
||||
for _sg in range(z_count):
|
||||
del processed.images[1]
|
||||
del processed.all_prompts[1]
|
||||
del processed.all_seeds[1]
|
||||
del processed.infotexts[1]
|
||||
elif no_grid:
|
||||
elif include_grid:
|
||||
del processed.infotexts[0]
|
||||
return processed
|
||||
|
||||
@@ -84,13 +84,13 @@ class SharedSettingsStackHelper(object):
|
||||
|
||||
axis_options = [
|
||||
AxisOption("Nothing", str, do_nothing, fmt=format_nothing),
|
||||
AxisOption("[Model] Model", str, apply_checkpoint, cost=1.0, fmt=format_value, choices=lambda: sorted(sd_models.checkpoints_list)),
|
||||
AxisOption("[Model] Model", str, apply_checkpoint, cost=1.0, fmt=format_value_add_label, choices=lambda: sorted(sd_models.checkpoints_list)),
|
||||
AxisOption("[Model] UNET", str, apply_unet, cost=0.8, choices=lambda: ['None'] + list(sd_unet.unet_dict)),
|
||||
AxisOption("[Model] VAE", str, apply_vae, cost=0.6, choices=lambda: ['None'] + list(sd_vae.vae_dict)),
|
||||
AxisOption("[Model] Refiner", str, apply_refiner, cost=0.8, fmt=format_value, choices=lambda: ['None'] + sorted(sd_models.checkpoints_list)),
|
||||
AxisOption("[Model] Refiner", str, apply_refiner, cost=0.8, fmt=format_value_add_label, choices=lambda: ['None'] + sorted(sd_models.checkpoints_list)),
|
||||
AxisOption("[Model] Text encoder", str, apply_te, cost=0.7, choices=shared_items.sd_te_items),
|
||||
AxisOption("[Model] Dictionary", str, apply_dict, fmt=format_value, cost=0.9, choices=lambda: ['None'] + list(sd_models.checkpoints_list)),
|
||||
AxisOption("[Prompt] Search & replace", str, apply_prompt, fmt=format_value),
|
||||
AxisOption("[Model] Dictionary", str, apply_dict, fmt=format_value_add_label, cost=0.9, choices=lambda: ['None'] + list(sd_models.checkpoints_list)),
|
||||
AxisOption("[Prompt] Search & replace", str, apply_prompt, fmt=format_value_add_label),
|
||||
AxisOption("[Prompt] Prompt order", str_permutations, apply_order, fmt=format_value_join_list),
|
||||
AxisOption("[Network] LoRA", str, apply_lora, cost=0.5, choices=list_lora),
|
||||
AxisOption("[Network] LoRA strength", float, apply_setting('extra_networks_default_multiplier')),
|
||||
@@ -109,8 +109,8 @@ axis_options = [
|
||||
AxisOption("[Process] Model args", str, apply_task_args),
|
||||
AxisOption("[Process] Processing args", str, apply_processing),
|
||||
AxisOption("[Process] Server options", str, apply_options),
|
||||
AxisOptionTxt2Img("[Sampler] Name", str, apply_sampler, fmt=format_value, confirm=confirm_samplers, choices=lambda: [x.name for x in sd_samplers.samplers]),
|
||||
AxisOptionImg2Img("[Sampler] Name", str, apply_sampler, fmt=format_value, confirm=confirm_samplers, choices=lambda: [x.name for x in sd_samplers.samplers_for_img2img]),
|
||||
AxisOptionTxt2Img("[Sampler] Name", str, apply_sampler, fmt=format_value_add_label, confirm=confirm_samplers, choices=lambda: [x.name for x in sd_samplers.samplers]),
|
||||
AxisOptionImg2Img("[Sampler] Name", str, apply_sampler, fmt=format_value_add_label, confirm=confirm_samplers, choices=lambda: [x.name for x in sd_samplers.samplers_for_img2img]),
|
||||
AxisOption("[Sampler] Sigma method", str, apply_setting("schedulers_sigma"), choices=lambda: ['default', 'karras', 'beta', 'exponential']),
|
||||
AxisOption("[Sampler] Timestep spacing", str, apply_setting("schedulers_timestep_spacing"), choices=lambda: ['default', 'linspace', 'leading', 'trailing']),
|
||||
AxisOption("[Sampler] Timestep range", int, apply_setting("schedulers_timesteps_range")),
|
||||
@@ -122,7 +122,7 @@ axis_options = [
|
||||
AxisOption("[Sampler] eta delta", float, apply_setting("eta_noise_seed_delta")),
|
||||
AxisOption("[Sampler] eta multiplier", float, apply_setting("scheduler_eta")),
|
||||
AxisOption("[Refine] Upscaler", str, apply_field("hr_upscaler"), cost=0.3, choices=lambda: [*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]]),
|
||||
AxisOption("[Refine] Sampler", str, apply_hr_sampler_name, fmt=format_value, confirm=confirm_samplers, choices=lambda: [x.name for x in sd_samplers.samplers]),
|
||||
AxisOption("[Refine] Sampler", str, apply_hr_sampler_name, fmt=format_value_add_label, confirm=confirm_samplers, choices=lambda: [x.name for x in sd_samplers.samplers]),
|
||||
AxisOption("[Refine] Denoising strength", float, apply_field("denoising_strength")),
|
||||
AxisOption("[Refine] Hires steps", int, apply_field("hr_second_pass_steps")),
|
||||
AxisOption("[Refine] Guidance scale", float, apply_field("image_cfg_scale")),
|
||||
@@ -131,7 +131,7 @@ axis_options = [
|
||||
AxisOption("[Refine] Refiner steps", float, apply_field("refiner_steps")),
|
||||
AxisOption("[Postprocess] Upscaler", str, apply_upscaler, cost=0.4, choices=lambda: [x.name for x in shared.sd_upscalers][1:]),
|
||||
AxisOption("[Postprocess] Context", str, apply_context, choices=lambda: ["Add with forward", "Remove with forward", "Add with backward", "Remove with backward"]),
|
||||
AxisOption("[Postprocess] Detailer", str, apply_detailer, fmt=format_value),
|
||||
AxisOption("[Postprocess] Detailer", str, apply_detailer, fmt=format_value_add_label),
|
||||
AxisOption("[HDR] Mode", int, apply_field("hdr_mode")),
|
||||
AxisOption("[HDR] Brightness", float, apply_field("hdr_brightness")),
|
||||
AxisOption("[HDR] Color", float, apply_field("hdr_color")),
|
||||
|
||||
@@ -4,23 +4,28 @@ from PIL import Image
|
||||
from modules import shared, images, processing
|
||||
|
||||
|
||||
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, no_grid): # pylint: disable=unused-argument
|
||||
hor_texts = [[images.GridAnnotation(x)] for x in x_labels]
|
||||
ver_texts = [[images.GridAnnotation(y)] for y in y_labels]
|
||||
title_texts = [[images.GridAnnotation(z)] for z in z_labels]
|
||||
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, no_grid: False, include_time: False): # pylint: disable=unused-argument
|
||||
x_texts = [[images.GridAnnotation(x)] for x in x_labels]
|
||||
y_texts = [[images.GridAnnotation(y)] for y in y_labels]
|
||||
z_texts = [[images.GridAnnotation(z)] for z in z_labels]
|
||||
list_size = (len(xs) * len(ys) * len(zs))
|
||||
processed_result = None
|
||||
shared.state.job_count = list_size * p.n_iter
|
||||
t0 = time.time()
|
||||
i = 0
|
||||
|
||||
def process_cell(x, y, z, ix, iy, iz):
|
||||
nonlocal processed_result
|
||||
nonlocal processed_result, i
|
||||
i += 1
|
||||
shared.log.debug(f'XYZ grid process: x={ix+1}/{len(xs)} y={iy+1}/{len(ys)} z={iz+1}/{len(zs)} total={i/list_size:.2f}')
|
||||
|
||||
def index(ix, iy, iz):
|
||||
return ix + iy * len(xs) + iz * len(xs) * len(ys)
|
||||
|
||||
shared.state.job = 'grid'
|
||||
p0 = time.time()
|
||||
processed: processing.Processed = cell(x, y, z, ix, iy, iz)
|
||||
p1 = time.time()
|
||||
if processed_result is None:
|
||||
processed_result = copy(processed)
|
||||
if processed_result is None:
|
||||
@@ -30,13 +35,17 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend
|
||||
processed_result.all_prompts = [None] * list_size
|
||||
processed_result.all_seeds = [None] * list_size
|
||||
processed_result.infotexts = [None] * list_size
|
||||
processed_result.time = [0] * list_size
|
||||
processed_result.index_of_first_image = 1
|
||||
idx = index(ix, iy, iz)
|
||||
if processed is not None and processed.images:
|
||||
processed_result.images[idx] = processed.images[0]
|
||||
if include_time:
|
||||
processed_result.images[idx] = images.draw_overlay(processed_result.images[idx], f'time: {p1 - p0:.2f}')
|
||||
processed_result.all_prompts[idx] = processed.prompt
|
||||
processed_result.all_seeds[idx] = processed.seed
|
||||
processed_result.infotexts[idx] = processed.infotexts[0]
|
||||
processed_result.time[idx] = round(p1 - p0, 2)
|
||||
else:
|
||||
cell_mode = "P"
|
||||
cell_size = (processed_result.width, processed_result.height)
|
||||
@@ -44,6 +53,7 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend
|
||||
cell_mode = processed_result.images[0].mode
|
||||
cell_size = processed_result.images[0].size
|
||||
processed_result.images[idx] = Image.new(cell_mode, cell_size)
|
||||
return
|
||||
|
||||
if first_axes_processed == 'x':
|
||||
for ix, x in enumerate(xs):
|
||||
@@ -93,7 +103,7 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend
|
||||
if (not no_grid or include_sub_grids) and images.check_grid_size(to_process):
|
||||
grid = images.image_grid(to_process, rows=len(ys))
|
||||
if draw_legend:
|
||||
grid = images.draw_grid_annotations(grid, w, h, hor_texts, ver_texts, margin_size, title=title_texts[i])
|
||||
grid = images.draw_grid_annotations(grid, w, h, x_texts, y_texts, margin_size, title=z_texts[i])
|
||||
processed_result.images.insert(i, grid)
|
||||
processed_result.all_prompts.insert(i, processed_result.all_prompts[idx0])
|
||||
processed_result.all_seeds.insert(i, processed_result.all_seeds[idx0])
|
||||
|
||||
@@ -57,9 +57,10 @@ class Script(scripts.Script):
|
||||
draw_legend = gr.Checkbox(label='Draw legend', value=True, elem_id=self.elem_id("draw_legend"), container=False)
|
||||
csv_mode = gr.Checkbox(label='Use text inputs', value=False, elem_id=self.elem_id("csv_mode"), container=False)
|
||||
no_fixed_seeds = gr.Checkbox(label='Use random seeds', value=False, elem_id=self.elem_id("no_fixed_seeds"), container=False)
|
||||
include_time = gr.Checkbox(label='Add time info', value=False, elem_id=self.elem_id("include_time"), container=False)
|
||||
with gr.Column():
|
||||
include_grid = gr.Checkbox(label='Create main grid', value=True, elem_id=self.elem_id("no_xyz_grid"), container=False)
|
||||
include_subgrids = gr.Checkbox(label='Create partial grids', value=False, elem_id=self.elem_id("include_sub_grids"), container=False)
|
||||
include_grid = gr.Checkbox(label='Include main grid', value=True, elem_id=self.elem_id("no_xyz_grid"), container=False)
|
||||
include_subgrids = gr.Checkbox(label='Include sub grids', value=False, elem_id=self.elem_id("include_sub_grids"), container=False)
|
||||
include_images = gr.Checkbox(label='Include images', value=False, elem_id=self.elem_id("include_lone_images"), container=False)
|
||||
with gr.Row():
|
||||
margin_size = gr.Slider(label="Grid margins", minimum=0, maximum=500, value=0, step=2, elem_id=self.elem_id("margin_size"))
|
||||
@@ -139,9 +140,9 @@ class Script(scripts.Script):
|
||||
(z_values_dropdown, lambda params:get_dropdown_update_from_params("Z",params)),
|
||||
)
|
||||
|
||||
return [enabled, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, margin_size]
|
||||
return [enabled, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, include_time, margin_size]
|
||||
|
||||
def process(self, p, enabled, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, margin_size): # pylint: disable=W0221
|
||||
def process(self, p, enabled, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, include_time, margin_size): # pylint: disable=W0221
|
||||
global active, cache # pylint: disable=W0603
|
||||
cache = None
|
||||
if not enabled or active:
|
||||
@@ -327,8 +328,10 @@ class Script(scripts.Script):
|
||||
second_axes_processed=second_axes_processed,
|
||||
margin_size=margin_size,
|
||||
no_grid=not include_grid,
|
||||
include_time=include_time,
|
||||
)
|
||||
|
||||
"""
|
||||
if not processed.images:
|
||||
active = False
|
||||
return processed # It broke, no further handling needed.
|
||||
@@ -354,6 +357,43 @@ class Script(scripts.Script):
|
||||
active = False
|
||||
cache = processed
|
||||
return processed
|
||||
"""
|
||||
|
||||
def process_images(self, p, enabled, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, margin_size): # pylint: disable=W0221, W0613
|
||||
if not processed.images:
|
||||
return processed # It broke, no further handling needed.
|
||||
z_count = len(zs)
|
||||
processed.infotexts[:1+z_count] = grid_infotext[:1+z_count] # set the grid infotexts to the real ones with extra_generation_params (1 main grid + z_count sub-grids)
|
||||
if not include_images: # dont need sub-images anymore, drop from list:
|
||||
if not include_grid and include_subgrids:
|
||||
processed.images = processed.images[:z_count] # we don't have the main grid image, and need zero additional sub-images
|
||||
else:
|
||||
processed.images = processed.images[:z_count+1] # we either have the main grid image, or need one sub-images
|
||||
|
||||
if shared.opts.grid_save: # auto-save main and sub-grids:
|
||||
grid_count = z_count + ( 1 if include_grid and z_count > 1 else 0 )
|
||||
for g in range(grid_count):
|
||||
adj_g = g-1 if g > 0 else g
|
||||
info = processed.infotexts[g]
|
||||
prompt = processed.all_prompts[adj_g]
|
||||
seed = processed.all_seeds[adj_g]
|
||||
images.save_image(processed.images[g], p.outpath_grids, "grid", info=info, extension=shared.opts.grid_format, prompt=prompt, seed=seed, grid=True, p=processed)
|
||||
if not include_subgrids: # done with sub-grids, drop all related information:
|
||||
for _sg in range(z_count):
|
||||
del processed.images[1]
|
||||
del processed.all_prompts[1]
|
||||
del processed.all_seeds[1]
|
||||
del processed.infotexts[1]
|
||||
elif include_grid:
|
||||
del processed.infotexts[0]
|
||||
|
||||
p.do_not_save_grid = True
|
||||
p.do_not_save_samples = True
|
||||
active = False
|
||||
cache = processed
|
||||
return processed
|
||||
|
||||
|
||||
def process_images(self, p, *args): # pylint: disable=W0221, W0613
|
||||
if p.iteration > 0 and cache is not None and len(cache.images) > 0:
|
||||
cache.images = [] # avoid returning same images multiple items
|
||||
return cache
|
||||
|
||||