Compare commits

...
24 Commits
Author SHA1 Message Date
Manuel Schmid 2c78cec01d Merge pull request #3436 from lllyasviel/develop
fix: change wrong label for in describe apply styles checkbox
2024-08-03 15:18:24 +02:00
Manuel Schmid ef0acca9f9 fix: change wrong label for in describe apply styles checkbox 2024-08-03 15:16:18 +02:00
Manuel Schmid 60af8d2d84 Merge pull request #3434 from lllyasviel/develop
Release 2.5.3 - fix changelog
2024-08-03 15:11:35 +02:00
Manuel Schmid 39d07bf0f3 release: fix changelog 2024-08-03 15:10:27 +02:00
Manuel Schmid f0dcf5a911 Merge pull request #3433 from lllyasviel/develop
Release 2.5.3
2024-08-03 15:08:34 +02:00
Manuel Schmid c4d5b160be release: bump version to 2.5.3, update changelog 2024-08-03 15:07:14 +02:00
Manuel Schmid 2f08cb4360 feat: add checkbox and config to disable updating selected styles when describing an image (#3430)
* feat: add checkbox and config to disable updating selected styles when describing an image

* i18n: add translation for checkbox label

* feat: change describe content type from Radio to CheckboxGroup, add config

* fix: cast set to list when styles contains elements

* feat: sort styles after describe
2024-08-03 14:46:31 +02:00
Sergii DymchenkoandManuel Schmid da3d4d006f Use weights_only for loading (#3427)
Co-authored-by: Manuel Schmid <9307310+mashb1t@users.noreply.github.com>
2024-08-03 12:33:01 +02:00
Manuel Schmid c2dc17e883 Merge pull request #3384 from lllyasviel/develop
Release v2.5.2
2024-07-27 23:29:40 +02:00
Manuel Schmid 1a53e0676a release: bump version to 2.5.2, update changelog 2024-07-27 23:26:42 +02:00
Manuel Schmid a5040f6218 feat: count image count index from 1 (#3383)
* docs: update numbering of basic debug procedure in issue template
2024-07-27 23:07:44 +02:00
Manuel Schmid 3f25b885a7 feat: extend config settings for image input (#3382)
* docs: update numbering of basic debug procedure in issue template

* feat: add config default_image_prompt_checkbox

* feat: add config for default_image_prompt_advanced_checkbox

* feat: add config for default_inpaint_advanced_masking_checkbox

* feat: add config for default_invert_mask_checkbox

* feat: add config for default_developer_debug_mode_checkbox

* refactor: regroup checkbox configs

* feat: add config for default_uov_method

* feat: add configs for controlnet

default_controlnet_image_count, ip_images, ip_stop_ats, ip_weights and ip_types

* feat: add config for selected tab, rename desc to describe
2024-07-27 23:03:21 +02:00
Manuel Schmid e36fa0b5f7 docs: update numbering of basic debug procedure in issue template (#3376) 2024-07-27 13:14:44 +02:00
Manuel Schmid 1be3c504ed fix: add positive prompt if styles don't have a prompt placeholder (#3372)
fixes https://github.com/lllyasviel/Fooocus/issues/3367
2024-07-27 12:35:55 +02:00
Manuel Schmid c4ce2ce600 Merge pull request #3359 from lllyasviel/develop
Release v2.5.1
2024-07-25 16:00:08 +02:00
Manuel Schmid 03655fa5ea release: bump version to 2.5.1, update changelog 2024-07-25 15:22:02 +02:00
Manuel Schmid a9248c8e46 feat: sort enhance images (mashb1t#62)
* feat: add checkbox, config and handling for saving only the final enhanced image

* feat: sort output of enhance feature

(cherry picked from commit 9d45c0e6ca)
2024-07-25 15:21:56 +02:00
Manuel Schmid 37360e95fe feat: add checkbox, config and handling for saving only the final enhanced image (mashb1t#61)
(cherry picked from commit 829a6dc046)
2024-07-25 15:21:37 +02:00
Manuel Schmid 54985596e8 Merge remote-tracking branch 'upstream/main' into develop_upstream 2024-07-21 12:37:07 +02:00
Manuel Schmid 3a20e14ca0 docs: update attributes and add add inline prompt features section to readme (#3333)
* docs: update attributes and add add inline prompt features section to readme
* docs: update attributes to better show corresponding mutually exclusive groups
2024-07-21 12:36:54 +02:00
Manuel Schmid 2262061145 docs: update attributes to better show corresponding mutually exclusive groups 2024-07-21 12:36:04 +02:00
Manuel Schmid 56928b769b docs: update attributes and add add inline prompt features section to readme 2024-07-21 12:31:17 +02:00
Manuel Schmid 2e8cff296e fix: correctly debug preprocessor again (#3332)
fixes https://github.com/lllyasviel/Fooocus/issues/3327
as discussed in https://github.com/lllyasviel/Fooocus/discussions/3323

add missing inheritance for EarlyReturnException from BaseException to correctly throw and catch
2024-07-21 11:49:28 +02:00
Manuel Schmid f597bf1ab6 fix: allow reading of metadata from jpeg, jpg and webp again (#3301)
also massively improves metadata read speed by switching from filepath (tempfile) to pil, which allows direct processing
2024-07-17 23:30:51 +02:00
27 changed files with 388 additions and 141 deletions
+3 -3
View File
@@ -16,9 +16,9 @@ body:
description: | description: |
Please perform basic debugging to see if your configuration is the cause of the issue. Please perform basic debugging to see if your configuration is the cause of the issue.
Basic debug procedure Basic debug procedure
 2. Update Fooocus - sometimes things just need to be updated  1. Update Fooocus - sometimes things just need to be updated
 3. Backup and remove your config.txt - check if the issue is caused by bad configuration  2. Backup and remove your config.txt - check if the issue is caused by bad configuration
 5. Try a fresh installation of Fooocus in a different directory - see if a clean installation solves the issue  3. Try a fresh installation of Fooocus in a different directory - see if a clean installation solves the issue
Before making a issue report please, check that the issue hasn't been reported recently. Before making a issue report please, check that the issue hasn't been reported recently.
options: options:
- label: The issue has not been resolved by following the [troubleshooting guide](https://github.com/lllyasviel/Fooocus/blob/main/troubleshoot.md) - label: The issue has not been resolved by following the [troubleshooting guide](https://github.com/lllyasviel/Fooocus/blob/main/troubleshoot.md)
+4 -1
View File
@@ -17,7 +17,7 @@ args_parser.parser.add_argument("--disable-offload-from-vram", action="store_tru
args_parser.parser.add_argument("--theme", type=str, help="launches the UI with light or dark theme", default=None) args_parser.parser.add_argument("--theme", type=str, help="launches the UI with light or dark theme", default=None)
args_parser.parser.add_argument("--disable-image-log", action='store_true', args_parser.parser.add_argument("--disable-image-log", action='store_true',
help="Prevent writing images and logs to hard drive.") help="Prevent writing images and logs to the outputs folder.")
args_parser.parser.add_argument("--disable-analytics", action='store_true', args_parser.parser.add_argument("--disable-analytics", action='store_true',
help="Disables analytics for Gradio.") help="Disables analytics for Gradio.")
@@ -28,6 +28,9 @@ args_parser.parser.add_argument("--disable-metadata", action='store_true',
args_parser.parser.add_argument("--disable-preset-download", action='store_true', args_parser.parser.add_argument("--disable-preset-download", action='store_true',
help="Disables downloading models for presets", default=False) help="Disables downloading models for presets", default=False)
args_parser.parser.add_argument("--disable-enhance-output-sorting", action='store_true',
help="Disables enhance output sorting for final image gallery.")
args_parser.parser.add_argument("--enable-auto-describe-image", action='store_true', args_parser.parser.add_argument("--enable-auto-describe-image", action='store_true',
help="Enables automatic description of uov and enhance image when prompt is empty", default=False) help="Enables automatic description of uov and enhance image when prompt is empty", default=False)
+2 -2
View File
@@ -216,9 +216,9 @@ def is_url(url_or_filename):
def load_checkpoint(model,url_or_filename): def load_checkpoint(model,url_or_filename):
if is_url(url_or_filename): if is_url(url_or_filename):
cached_file = download_cached_file(url_or_filename, check_hash=False, progress=True) cached_file = download_cached_file(url_or_filename, check_hash=False, progress=True)
checkpoint = torch.load(cached_file, map_location='cpu') checkpoint = torch.load(cached_file, map_location='cpu', weights_only=True)
elif os.path.isfile(url_or_filename): elif os.path.isfile(url_or_filename):
checkpoint = torch.load(url_or_filename, map_location='cpu') checkpoint = torch.load(url_or_filename, map_location='cpu', weights_only=True)
else: else:
raise RuntimeError('checkpoint url or path is invalid') raise RuntimeError('checkpoint url or path is invalid')
+2 -2
View File
@@ -78,9 +78,9 @@ def blip_nlvr(pretrained='',**kwargs):
def load_checkpoint(model,url_or_filename): def load_checkpoint(model,url_or_filename):
if is_url(url_or_filename): if is_url(url_or_filename):
cached_file = download_cached_file(url_or_filename, check_hash=False, progress=True) cached_file = download_cached_file(url_or_filename, check_hash=False, progress=True)
checkpoint = torch.load(cached_file, map_location='cpu') checkpoint = torch.load(cached_file, map_location='cpu', weights_only=True)
elif os.path.isfile(url_or_filename): elif os.path.isfile(url_or_filename):
checkpoint = torch.load(url_or_filename, map_location='cpu') checkpoint = torch.load(url_or_filename, map_location='cpu', weights_only=True)
else: else:
raise RuntimeError('checkpoint url or path is invalid') raise RuntimeError('checkpoint url or path is invalid')
state_dict = checkpoint['model'] state_dict = checkpoint['model']
+1 -1
View File
@@ -19,7 +19,7 @@ def init_detection_model(model_name, half=False, device='cuda', model_rootpath=N
url=model_url, model_dir='facexlib/weights', progress=True, file_name=None, save_dir=model_rootpath) url=model_url, model_dir='facexlib/weights', progress=True, file_name=None, save_dir=model_rootpath)
# TODO: clean pretrained model # TODO: clean pretrained model
load_net = torch.load(model_path, map_location=lambda storage, loc: storage) load_net = torch.load(model_path, map_location=lambda storage, loc: storage, weights_only=True)
# remove unnecessary 'module.' # remove unnecessary 'module.'
for k, v in deepcopy(load_net).items(): for k, v in deepcopy(load_net).items():
if k.startswith('module.'): if k.startswith('module.'):
+1 -1
View File
@@ -17,7 +17,7 @@ def init_parsing_model(model_name='bisenet', half=False, device='cuda', model_ro
model_path = load_file_from_url( model_path = load_file_from_url(
url=model_url, model_dir='facexlib/weights', progress=True, file_name=None, save_dir=model_rootpath) url=model_url, model_dir='facexlib/weights', progress=True, file_name=None, save_dir=model_rootpath)
load_net = torch.load(model_path, map_location=lambda storage, loc: storage) load_net = torch.load(model_path, map_location=lambda storage, loc: storage, weights_only=True)
model.load_state_dict(load_net, strict=True) model.load_state_dict(load_net, strict=True)
model.eval() model.eval()
model = model.to(device) model = model.to(device)
+1 -1
View File
@@ -104,7 +104,7 @@ def load_ip_adapter(clip_vision_path, ip_negative_path, ip_adapter_path):
offload_device = torch.device('cpu') offload_device = torch.device('cpu')
use_fp16 = model_management.should_use_fp16(device=load_device) use_fp16 = model_management.should_use_fp16(device=load_device)
ip_state_dict = torch.load(ip_adapter_path, map_location="cpu") ip_state_dict = torch.load(ip_adapter_path, map_location="cpu", weights_only=True)
plus = "latents" in ip_state_dict["image_proj"] plus = "latents" in ip_state_dict["image_proj"]
cross_attention_dim = ip_state_dict["ip_adapter"]["1.to_k_ip.weight"].shape[1] cross_attention_dim = ip_state_dict["ip_adapter"]["1.to_k_ip.weight"].shape[1]
sdxl = cross_attention_dim == 2048 sdxl = cross_attention_dim == 2048
+1 -1
View File
@@ -1 +1 @@
version = '2.5.0' version = '2.5.3'
+4
View File
@@ -17,6 +17,7 @@
"Content Type": "Content Type", "Content Type": "Content Type",
"Photograph": "Photograph", "Photograph": "Photograph",
"Art/Anime": "Art/Anime", "Art/Anime": "Art/Anime",
"Apply Styles": "Apply Styles",
"Describe this Image into Prompt": "Describe this Image into Prompt", "Describe this Image into Prompt": "Describe this Image into Prompt",
"Image Size and Recommended Size": "Image Size and Recommended Size", "Image Size and Recommended Size": "Image Size and Recommended Size",
"Upscale or Variation:": "Upscale or Variation:", "Upscale or Variation:": "Upscale or Variation:",
@@ -68,6 +69,9 @@
"Read wildcards in order": "Read wildcards in order", "Read wildcards in order": "Read wildcards in order",
"Black Out NSFW": "Black Out NSFW", "Black Out NSFW": "Black Out NSFW",
"Use black image if NSFW is detected.": "Use black image if NSFW is detected.", "Use black image if NSFW is detected.": "Use black image if NSFW is detected.",
"Save only final enhanced image": "Save only final enhanced image",
"Save Metadata to Images": "Save Metadata to Images",
"Adds parameters to generated images allowing manual regeneration.": "Adds parameters to generated images allowing manual regeneration.",
"\ud83d\udcda History Log": "\uD83D\uDCDA History Log", "\ud83d\udcda History Log": "\uD83D\uDCDA History Log",
"Image Style": "Image Style", "Image Style": "Image Style",
"Fooocus V2": "Fooocus V2", "Fooocus V2": "Fooocus V2",
@@ -8,7 +8,7 @@ class CLIPEmbeddingNoiseAugmentation(ImageConcatWithNoiseAugmentation):
if clip_stats_path is None: if clip_stats_path is None:
clip_mean, clip_std = torch.zeros(timestep_dim), torch.ones(timestep_dim) clip_mean, clip_std = torch.zeros(timestep_dim), torch.ones(timestep_dim)
else: else:
clip_mean, clip_std = torch.load(clip_stats_path, map_location="cpu") clip_mean, clip_std = torch.load(clip_stats_path, map_location="cpu", weights_only=True)
self.register_buffer("data_mean", clip_mean[None, :], persistent=False) self.register_buffer("data_mean", clip_mean[None, :], persistent=False)
self.register_buffer("data_std", clip_std[None, :], persistent=False) self.register_buffer("data_std", clip_std[None, :], persistent=False)
self.time_embed = Timestep(timestep_dim) self.time_embed = Timestep(timestep_dim)
+1 -1
View File
@@ -326,7 +326,7 @@ def load_embed(embedding_name, embedding_directory, embedding_size, embed_key=No
except: except:
embed_out = safe_load_embed_zip(embed_path) embed_out = safe_load_embed_zip(embed_path)
else: else:
embed = torch.load(embed_path, map_location="cpu") embed = torch.load(embed_path, map_location="cpu", weights_only=True)
except Exception as e: except Exception as e:
print(traceback.format_exc()) print(traceback.format_exc())
print() print()
@@ -377,15 +377,15 @@ class VQAutoEncoder(nn.Module):
) )
if model_path is not None: if model_path is not None:
chkpt = torch.load(model_path, map_location="cpu") chkpt = torch.load(model_path, map_location="cpu", weights_only=True)
if "params_ema" in chkpt: if "params_ema" in chkpt:
self.load_state_dict( self.load_state_dict(
torch.load(model_path, map_location="cpu")["params_ema"] torch.load(model_path, map_location="cpu", weights_only=True)["params_ema"]
) )
logger.info(f"vqgan is loaded from: {model_path} [params_ema]") logger.info(f"vqgan is loaded from: {model_path} [params_ema]")
elif "params" in chkpt: elif "params" in chkpt:
self.load_state_dict( self.load_state_dict(
torch.load(model_path, map_location="cpu")["params"] torch.load(model_path, map_location="cpu", weights_only=True)["params"]
) )
logger.info(f"vqgan is loaded from: {model_path} [params]") logger.info(f"vqgan is loaded from: {model_path} [params]")
else: else:
@@ -273,8 +273,8 @@ class GFPGANBilinear(nn.Module):
if decoder_load_path: if decoder_load_path:
self.stylegan_decoder.load_state_dict( self.stylegan_decoder.load_state_dict(
torch.load( torch.load(
decoder_load_path, map_location=lambda storage, loc: storage decoder_load_path, map_location=lambda storage, loc: storage,
)["params_ema"] weights_only=True)["params_ema"]
) )
# fix decoder without updating params # fix decoder without updating params
if fix_decoder: if fix_decoder:
@@ -373,8 +373,8 @@ class GFPGANv1(nn.Module):
if decoder_load_path: if decoder_load_path:
self.stylegan_decoder.load_state_dict( self.stylegan_decoder.load_state_dict(
torch.load( torch.load(
decoder_load_path, map_location=lambda storage, loc: storage decoder_load_path, map_location=lambda storage, loc: storage,
)["params_ema"] weights_only=True)["params_ema"]
) )
# fix decoder without updating params # fix decoder without updating params
if fix_decoder: if fix_decoder:
@@ -284,8 +284,8 @@ class GFPGANv1Clean(nn.Module):
if decoder_load_path: if decoder_load_path:
self.stylegan_decoder.load_state_dict( self.stylegan_decoder.load_state_dict(
torch.load( torch.load(
decoder_load_path, map_location=lambda storage, loc: storage decoder_load_path, map_location=lambda storage, loc: storage,
)["params_ema"] weights_only=True)["params_ema"]
) )
# fix decoder without updating params # fix decoder without updating params
if fix_decoder: if fix_decoder:
+57 -28
View File
@@ -9,7 +9,7 @@ patch_all()
class AsyncTask: class AsyncTask:
def __init__(self, args): def __init__(self, args):
from modules.flags import Performance, MetadataScheme, ip_list, controlnet_image_count from modules.flags import Performance, MetadataScheme, ip_list, disabled
from modules.util import get_enabled_loras from modules.util import get_enabled_loras
from modules.config import default_max_lora_number from modules.config import default_max_lora_number
import args_manager import args_manager
@@ -95,12 +95,13 @@ class AsyncTask:
self.inpaint_advanced_masking_checkbox = args.pop() self.inpaint_advanced_masking_checkbox = args.pop()
self.invert_mask_checkbox = args.pop() self.invert_mask_checkbox = args.pop()
self.inpaint_erode_or_dilate = args.pop() self.inpaint_erode_or_dilate = args.pop()
self.save_final_enhanced_image_only = args.pop() if not args_manager.args.disable_image_log else False
self.save_metadata_to_images = args.pop() if not args_manager.args.disable_metadata else False self.save_metadata_to_images = args.pop() if not args_manager.args.disable_metadata else False
self.metadata_scheme = MetadataScheme( self.metadata_scheme = MetadataScheme(
args.pop()) if not args_manager.args.disable_metadata else MetadataScheme.FOOOCUS args.pop()) if not args_manager.args.disable_metadata else MetadataScheme.FOOOCUS
self.cn_tasks = {x: [] for x in ip_list} self.cn_tasks = {x: [] for x in ip_list}
for _ in range(controlnet_image_count): for _ in range(modules.config.default_controlnet_image_count):
cn_img = args.pop() cn_img = args.pop()
cn_stop = args.pop() cn_stop = args.pop()
cn_weight = args.pop() cn_weight = args.pop()
@@ -153,12 +154,14 @@ class AsyncTask:
enhance_inpaint_erode_or_dilate, enhance_inpaint_erode_or_dilate,
enhance_mask_invert enhance_mask_invert
]) ])
self.should_enhance = self.enhance_checkbox and (self.enhance_uov_method != disabled.casefold() or len(self.enhance_ctrls) > 0)
self.images_to_enhance_count = 0
self.enhance_stats = {}
async_tasks = [] async_tasks = []
class EarlyReturnException: class EarlyReturnException(BaseException):
pass pass
@@ -277,7 +280,7 @@ def worker():
def process_task(all_steps, async_task, callback, controlnet_canny_path, controlnet_cpds_path, current_task_id, def process_task(all_steps, async_task, callback, controlnet_canny_path, controlnet_cpds_path, current_task_id,
denoising_strength, final_scheduler_name, goals, initial_latent, steps, switch, positive_cond, denoising_strength, final_scheduler_name, goals, initial_latent, steps, switch, positive_cond,
negative_cond, task, loras, tiled, use_expansion, width, height, base_progress, preparation_steps, negative_cond, task, loras, tiled, use_expansion, width, height, base_progress, preparation_steps,
total_count, show_intermediate_results): total_count, show_intermediate_results, persist_image=True):
if async_task.last_stop is not False: if async_task.last_stop is not False:
ldm_patched.modules.model_management.interrupt_current_processing() ldm_patched.modules.model_management.interrupt_current_processing()
if 'cn' in goals: if 'cn' in goals:
@@ -314,9 +317,8 @@ def worker():
if modules.config.default_black_out_nsfw or async_task.black_out_nsfw: if modules.config.default_black_out_nsfw or async_task.black_out_nsfw:
progressbar(async_task, current_progress, 'Checking for NSFW content ...') progressbar(async_task, current_progress, 'Checking for NSFW content ...')
imgs = default_censor(imgs) imgs = default_censor(imgs)
progressbar(async_task, current_progress, progressbar(async_task, current_progress, f'Saving image {current_task_id + 1}/{total_count} to system ...')
f'Saving image {current_task_id + 1}/{total_count} to system ...') img_paths = save_and_log(async_task, height, imgs, task, use_expansion, width, loras, persist_image)
img_paths = save_and_log(async_task, height, imgs, task, use_expansion, width, loras)
yield_result(async_task, img_paths, current_progress, async_task.black_out_nsfw, False, yield_result(async_task, img_paths, current_progress, async_task.black_out_nsfw, False,
do_not_show_finished_images=not show_intermediate_results or async_task.disable_intermediate_results) do_not_show_finished_images=not show_intermediate_results or async_task.disable_intermediate_results)
@@ -332,7 +334,7 @@ def worker():
async_task.adaptive_cfg async_task.adaptive_cfg
) )
def save_and_log(async_task, height, imgs, task, use_expansion, width, loras) -> list: def save_and_log(async_task, height, imgs, task, use_expansion, width, loras, persist_image=True) -> list:
img_paths = [] img_paths = []
for x in imgs: for x in imgs:
d = [('Prompt', 'prompt', task['log_positive_prompt']), d = [('Prompt', 'prompt', task['log_positive_prompt']),
@@ -387,7 +389,7 @@ def worker():
d.append(('Metadata Scheme', 'metadata_scheme', d.append(('Metadata Scheme', 'metadata_scheme',
async_task.metadata_scheme.value if async_task.save_metadata_to_images else async_task.save_metadata_to_images)) async_task.metadata_scheme.value if async_task.save_metadata_to_images else async_task.save_metadata_to_images))
d.append(('Version', 'version', 'Fooocus v' + fooocus_version.version)) d.append(('Version', 'version', 'Fooocus v' + fooocus_version.version))
img_paths.append(log(x, d, metadata_parser, async_task.output_format, task)) img_paths.append(log(x, d, metadata_parser, async_task.output_format, task, persist_image))
return img_paths return img_paths
@@ -687,13 +689,20 @@ def worker():
task_styles = async_task.style_selections.copy() task_styles = async_task.style_selections.copy()
if use_style: if use_style:
placeholder_replaced = False
for j, s in enumerate(task_styles): for j, s in enumerate(task_styles):
if s == random_style_name: if s == random_style_name:
s = get_random_style(task_rng) s = get_random_style(task_rng)
task_styles[j] = s task_styles[j] = s
p, n = apply_style(s, positive=task_prompt) p, n, style_has_placeholder = apply_style(s, positive=task_prompt)
if style_has_placeholder:
placeholder_replaced = True
positive_basic_workloads = positive_basic_workloads + p positive_basic_workloads = positive_basic_workloads + p
negative_basic_workloads = negative_basic_workloads + n negative_basic_workloads = negative_basic_workloads + n
if not placeholder_replaced:
positive_basic_workloads = [task_prompt] + positive_basic_workloads
else: else:
positive_basic_workloads.append(task_prompt) positive_basic_workloads.append(task_prompt)
@@ -958,7 +967,7 @@ def worker():
inpaint_engine, inpaint_respective_field, inpaint_strength, inpaint_engine, inpaint_respective_field, inpaint_strength,
prompt, negative_prompt, final_scheduler_name, goals, height, img, mask, prompt, negative_prompt, final_scheduler_name, goals, height, img, mask,
preparation_steps, steps, switch, tiled, total_count, use_expansion, use_style, preparation_steps, steps, switch, tiled, total_count, use_expansion, use_style,
use_synthetic_refiner, width, show_intermediate_results=True): use_synthetic_refiner, width, show_intermediate_results=True, persist_image=True):
base_model_additional_loras = [] base_model_additional_loras = []
inpaint_head_model_path = None inpaint_head_model_path = None
inpaint_parameterized = inpaint_engine != 'None' # inpaint_engine = None, improve detail inpaint_parameterized = inpaint_engine != 'None' # inpaint_engine = None, improve detail
@@ -979,7 +988,7 @@ def worker():
progressbar(async_task, current_progress, 'Checking for NSFW content ...') progressbar(async_task, current_progress, 'Checking for NSFW content ...')
img = default_censor(img) img = default_censor(img)
progressbar(async_task, current_progress, f'Saving image {current_task_id + 1}/{total_count} to system ...') progressbar(async_task, current_progress, f'Saving image {current_task_id + 1}/{total_count} to system ...')
uov_image_path = log(img, d, output_format=async_task.output_format) uov_image_path = log(img, d, output_format=async_task.output_format, persist_image=persist_image)
yield_result(async_task, uov_image_path, current_progress, async_task.black_out_nsfw, False, yield_result(async_task, uov_image_path, current_progress, async_task.black_out_nsfw, False,
do_not_show_finished_images=not show_intermediate_results or async_task.disable_intermediate_results) do_not_show_finished_images=not show_intermediate_results or async_task.disable_intermediate_results)
return current_progress, img, prompt, negative_prompt return current_progress, img, prompt, negative_prompt
@@ -1013,7 +1022,8 @@ def worker():
final_scheduler_name, goals, initial_latent, steps, switch, final_scheduler_name, goals, initial_latent, steps, switch,
task_enhance['c'], task_enhance['uc'], task_enhance, loras, task_enhance['c'], task_enhance['uc'], task_enhance, loras,
tiled, use_expansion, width, height, current_progress, tiled, use_expansion, width, height, current_progress,
preparation_steps, total_count, show_intermediate_results) preparation_steps, total_count, show_intermediate_results,
persist_image)
del task_enhance['c'], task_enhance['uc'] # Save memory del task_enhance['c'], task_enhance['uc'] # Save memory
return current_progress, imgs[0], prompt, negative_prompt return current_progress, imgs[0], prompt, negative_prompt
@@ -1021,7 +1031,7 @@ def worker():
def enhance_upscale(all_steps, async_task, base_progress, callback, controlnet_canny_path, controlnet_cpds_path, def enhance_upscale(all_steps, async_task, base_progress, callback, controlnet_canny_path, controlnet_cpds_path,
current_task_id, denoising_strength, done_steps_inpainting, done_steps_upscaling, enhance_steps, current_task_id, denoising_strength, done_steps_inpainting, done_steps_upscaling, enhance_steps,
prompt, negative_prompt, final_scheduler_name, height, img, preparation_steps, switch, tiled, prompt, negative_prompt, final_scheduler_name, height, img, preparation_steps, switch, tiled,
total_count, use_expansion, use_style, use_synthetic_refiner, width): total_count, use_expansion, use_style, use_synthetic_refiner, width, persist_image=True):
# reset inpaint worker to prevent tensor size issues and not mix upscale and inpainting # reset inpaint worker to prevent tensor size issues and not mix upscale and inpainting
inpaint_worker.current_task = None inpaint_worker.current_task = None
@@ -1039,7 +1049,7 @@ def worker():
controlnet_cpds_path, current_progress, current_task_id, denoising_strength, False, controlnet_cpds_path, current_progress, current_task_id, denoising_strength, False,
'None', 0.0, 0.0, prompt, negative_prompt, final_scheduler_name, 'None', 0.0, 0.0, prompt, negative_prompt, final_scheduler_name,
goals_enhance, height, img, None, preparation_steps, steps, switch, tiled, total_count, goals_enhance, height, img, None, preparation_steps, steps, switch, tiled, total_count,
use_expansion, use_style, use_synthetic_refiner, width) use_expansion, use_style, use_synthetic_refiner, width, persist_image=persist_image)
except ldm_patched.modules.model_management.InterruptProcessingException: except ldm_patched.modules.model_management.InterruptProcessingException:
if async_task.last_stop == 'skip': if async_task.last_stop == 'skip':
@@ -1156,6 +1166,8 @@ def worker():
current_progress += 1 current_progress += 1
progressbar(async_task, current_progress, 'Image processing ...') progressbar(async_task, current_progress, 'Image processing ...')
should_enhance = async_task.enhance_checkbox and (async_task.enhance_uov_method != flags.disabled.casefold() or len(async_task.enhance_ctrls) > 0)
if 'vary' in goals: if 'vary' in goals:
async_task.uov_input_image, denoising_strength, initial_latent, width, height, current_progress = apply_vary( async_task.uov_input_image, denoising_strength, initial_latent, width, height, current_progress = apply_vary(
async_task, async_task.uov_method, denoising_strength, async_task.uov_input_image, switch, async_task, async_task.uov_method, denoising_strength, async_task.uov_input_image, switch,
@@ -1261,8 +1273,8 @@ def worker():
int(current_progress + async_task.callback_steps), int(current_progress + async_task.callback_steps),
f'Sampling step {step + 1}/{total_steps}, image {current_task_id + 1}/{total_count} ...', y)]) f'Sampling step {step + 1}/{total_steps}, image {current_task_id + 1}/{total_count} ...', y)])
should_enhance = async_task.enhance_checkbox and (async_task.enhance_uov_method != flags.disabled.casefold() or len(async_task.enhance_ctrls) > 0) show_intermediate_results = len(tasks) > 1 or async_task.should_enhance
show_intermediate_results = len(tasks) > 1 or should_enhance persist_image = not async_task.should_enhance or not async_task.save_final_enhanced_image_only
for current_task_id, task in enumerate(tasks): for current_task_id, task in enumerate(tasks):
progressbar(async_task, current_progress, f'Preparing task {current_task_id + 1}/{async_task.image_number} ...') progressbar(async_task, current_progress, f'Preparing task {current_task_id + 1}/{async_task.image_number} ...')
@@ -1275,7 +1287,8 @@ def worker():
initial_latent, async_task.steps, switch, task['c'], initial_latent, async_task.steps, switch, task['c'],
task['uc'], task, loras, tiled, use_expansion, width, task['uc'], task, loras, tiled, use_expansion, width,
height, current_progress, preparation_steps, height, current_progress, preparation_steps,
async_task.image_number, show_intermediate_results) async_task.image_number, show_intermediate_results,
persist_image)
current_progress = int(preparation_steps + (100 - preparation_steps) / float(all_steps) * async_task.steps * (current_task_id + 1)) current_progress = int(preparation_steps + (100 - preparation_steps) / float(all_steps) * async_task.steps * (current_task_id + 1))
images_to_enhance += imgs images_to_enhance += imgs
@@ -1293,7 +1306,7 @@ def worker():
execution_time = time.perf_counter() - execution_start_time execution_time = time.perf_counter() - execution_start_time
print(f'Generating and saving time: {execution_time:.2f} seconds') print(f'Generating and saving time: {execution_time:.2f} seconds')
if not should_enhance: if not async_task.should_enhance:
print(f'[Enhance] Skipping, preconditions aren\'t met') print(f'[Enhance] Skipping, preconditions aren\'t met')
stop_processing(async_task, processing_start_time) stop_processing(async_task, processing_start_time)
return return
@@ -1302,9 +1315,14 @@ def worker():
active_enhance_tabs = len(async_task.enhance_ctrls) active_enhance_tabs = len(async_task.enhance_ctrls)
should_process_enhance_uov = async_task.enhance_uov_method != flags.disabled.casefold() should_process_enhance_uov = async_task.enhance_uov_method != flags.disabled.casefold()
enhance_uov_before = False
enhance_uov_after = False
if should_process_enhance_uov: if should_process_enhance_uov:
active_enhance_tabs += 1 active_enhance_tabs += 1
enhance_uov_before = async_task.enhance_uov_processing_order == flags.enhancement_uov_before
enhance_uov_after = async_task.enhance_uov_processing_order == flags.enhancement_uov_after
total_count = len(images_to_enhance) * active_enhance_tabs total_count = len(images_to_enhance) * active_enhance_tabs
async_task.images_to_enhance_count = len(images_to_enhance)
base_progress = current_progress base_progress = current_progress
current_task_id = -1 current_task_id = -1
@@ -1312,19 +1330,23 @@ def worker():
done_steps_inpainting = 0 done_steps_inpainting = 0
enhance_steps, _, _, _ = apply_overrides(async_task, async_task.original_steps, height, width) enhance_steps, _, _, _ = apply_overrides(async_task, async_task.original_steps, height, width)
exception_result = None exception_result = None
for img in images_to_enhance: for index, img in enumerate(images_to_enhance):
async_task.enhance_stats[index] = 0
enhancement_image_start_time = time.perf_counter() enhancement_image_start_time = time.perf_counter()
last_enhance_prompt = async_task.prompt last_enhance_prompt = async_task.prompt
last_enhance_negative_prompt = async_task.negative_prompt last_enhance_negative_prompt = async_task.negative_prompt
if should_process_enhance_uov and async_task.enhance_uov_processing_order == flags.enhancement_uov_before: if enhance_uov_before:
current_task_id += 1 current_task_id += 1
persist_image = not async_task.save_final_enhanced_image_only or active_enhance_tabs == 0
current_task_id, done_steps_inpainting, done_steps_upscaling, img, exception_result = enhance_upscale( current_task_id, done_steps_inpainting, done_steps_upscaling, img, exception_result = enhance_upscale(
all_steps, async_task, base_progress, callback, controlnet_canny_path, controlnet_cpds_path, all_steps, async_task, base_progress, callback, controlnet_canny_path, controlnet_cpds_path,
current_task_id, denoising_strength, done_steps_inpainting, done_steps_upscaling, enhance_steps, current_task_id, denoising_strength, done_steps_inpainting, done_steps_upscaling, enhance_steps,
async_task.prompt, async_task.negative_prompt, final_scheduler_name, height, img, preparation_steps, async_task.prompt, async_task.negative_prompt, final_scheduler_name, height, img, preparation_steps,
switch, tiled, total_count, use_expansion, use_style, use_synthetic_refiner, width) switch, tiled, total_count, use_expansion, use_style, use_synthetic_refiner, width, persist_image)
async_task.enhance_stats[index] += 1
if exception_result == 'continue': if exception_result == 'continue':
continue continue
elif exception_result == 'break': elif exception_result == 'break':
@@ -1336,6 +1358,8 @@ def worker():
current_progress = int(base_progress + (100 - preparation_steps) / float(all_steps) * (done_steps_upscaling + done_steps_inpainting)) current_progress = int(base_progress + (100 - preparation_steps) / float(all_steps) * (done_steps_upscaling + done_steps_inpainting))
progressbar(async_task, current_progress, f'Preparing enhancement {current_task_id + 1}/{total_count} ...') progressbar(async_task, current_progress, f'Preparing enhancement {current_task_id + 1}/{total_count} ...')
enhancement_task_start_time = time.perf_counter() enhancement_task_start_time = time.perf_counter()
is_last_enhance_for_image = (current_task_id + 1) % active_enhance_tabs == 0 and not enhance_uov_after
persist_image = not async_task.save_final_enhanced_image_only or is_last_enhance_for_image
extras = {} extras = {}
if enhance_mask_model == 'sam': if enhance_mask_model == 'sam':
@@ -1366,13 +1390,13 @@ def worker():
async_task.yields.append(['preview', (current_progress, 'Loading ...', mask)]) async_task.yields.append(['preview', (current_progress, 'Loading ...', mask)])
yield_result(async_task, mask, current_progress, async_task.black_out_nsfw, False, yield_result(async_task, mask, current_progress, async_task.black_out_nsfw, False,
async_task.disable_intermediate_results) async_task.disable_intermediate_results)
async_task.enhance_stats[index] += 1
print(f'[Enhance] {dino_detection_count} boxes detected') print(f'[Enhance] {dino_detection_count} boxes detected')
print(f'[Enhance] {sam_detection_count} segments detected in boxes') print(f'[Enhance] {sam_detection_count} segments detected in boxes')
print(f'[Enhance] {sam_detection_on_mask_count} segments applied to mask') print(f'[Enhance] {sam_detection_on_mask_count} segments applied to mask')
if enhance_mask_model == 'sam' and ( if enhance_mask_model == 'sam' and (dino_detection_count == 0 or not async_task.debugging_dino and sam_detection_on_mask_count == 0):
dino_detection_count == 0 or not async_task.debugging_dino and sam_detection_on_mask_count == 0):
print(f'[Enhance] No "{enhance_mask_dino_prompt_text}" detected, skipping') print(f'[Enhance] No "{enhance_mask_dino_prompt_text}" detected, skipping')
continue continue
@@ -1385,7 +1409,8 @@ def worker():
enhance_inpaint_engine, enhance_inpaint_respective_field, enhance_inpaint_strength, enhance_inpaint_engine, enhance_inpaint_respective_field, enhance_inpaint_strength,
enhance_prompt, enhance_negative_prompt, final_scheduler_name, goals_enhance, height, img, mask, enhance_prompt, enhance_negative_prompt, final_scheduler_name, goals_enhance, height, img, mask,
preparation_steps, enhance_steps, switch, tiled, total_count, use_expansion, use_style, preparation_steps, enhance_steps, switch, tiled, total_count, use_expansion, use_style,
use_synthetic_refiner, width) use_synthetic_refiner, width, persist_image=persist_image)
async_task.enhance_stats[index] += 1
if (should_process_enhance_uov and async_task.enhance_uov_processing_order == flags.enhancement_uov_after if (should_process_enhance_uov and async_task.enhance_uov_processing_order == flags.enhancement_uov_after
and async_task.enhance_uov_prompt_type == flags.enhancement_uov_prompt_type_last_filled): and async_task.enhance_uov_prompt_type == flags.enhancement_uov_prompt_type_last_filled):
@@ -1412,14 +1437,18 @@ def worker():
if exception_result == 'break': if exception_result == 'break':
break break
if should_process_enhance_uov and async_task.enhance_uov_processing_order == flags.enhancement_uov_after: if enhance_uov_after:
current_task_id += 1 current_task_id += 1
# last step in enhance, always save
persist_image = True
current_task_id, done_steps_inpainting, done_steps_upscaling, img, exception_result = enhance_upscale( current_task_id, done_steps_inpainting, done_steps_upscaling, img, exception_result = enhance_upscale(
all_steps, async_task, base_progress, callback, controlnet_canny_path, controlnet_cpds_path, all_steps, async_task, base_progress, callback, controlnet_canny_path, controlnet_cpds_path,
current_task_id, denoising_strength, done_steps_inpainting, done_steps_upscaling, enhance_steps, current_task_id, denoising_strength, done_steps_inpainting, done_steps_upscaling, enhance_steps,
last_enhance_prompt, last_enhance_negative_prompt, final_scheduler_name, height, img, last_enhance_prompt, last_enhance_negative_prompt, final_scheduler_name, height, img,
preparation_steps, switch, tiled, total_count, use_expansion, use_style, use_synthetic_refiner, preparation_steps, switch, tiled, total_count, use_expansion, use_style, use_synthetic_refiner,
width) width, persist_image)
async_task.enhance_stats[index] += 1
if exception_result == 'continue': if exception_result == 'continue':
continue continue
elif exception_result == 'break': elif exception_result == 'break':
+109 -6
View File
@@ -403,12 +403,36 @@ default_performance = get_config_item_or_set_default(
validator=lambda x: x in Performance.values(), validator=lambda x: x in Performance.values(),
expected_type=str expected_type=str
) )
default_image_prompt_checkbox = get_config_item_or_set_default(
key='default_image_prompt_checkbox',
default_value=False,
validator=lambda x: isinstance(x, bool),
expected_type=bool
)
default_enhance_checkbox = get_config_item_or_set_default(
key='default_enhance_checkbox',
default_value=False,
validator=lambda x: isinstance(x, bool),
expected_type=bool
)
default_advanced_checkbox = get_config_item_or_set_default( default_advanced_checkbox = get_config_item_or_set_default(
key='default_advanced_checkbox', key='default_advanced_checkbox',
default_value=False, default_value=False,
validator=lambda x: isinstance(x, bool), validator=lambda x: isinstance(x, bool),
expected_type=bool expected_type=bool
) )
default_developer_debug_mode_checkbox = get_config_item_or_set_default(
key='default_developer_debug_mode_checkbox',
default_value=False,
validator=lambda x: isinstance(x, bool),
expected_type=bool
)
default_image_prompt_advanced_checkbox = get_config_item_or_set_default(
key='default_image_prompt_advanced_checkbox',
default_value=False,
validator=lambda x: isinstance(x, bool),
expected_type=bool
)
default_max_image_number = get_config_item_or_set_default( default_max_image_number = get_config_item_or_set_default(
key='default_max_image_number', key='default_max_image_number',
default_value=32, default_value=32,
@@ -469,6 +493,65 @@ default_inpaint_engine_version = get_config_item_or_set_default(
validator=lambda x: x in modules.flags.inpaint_engine_versions, validator=lambda x: x in modules.flags.inpaint_engine_versions,
expected_type=str expected_type=str
) )
default_selected_image_input_tab_id = get_config_item_or_set_default(
key='default_selected_image_input_tab_id',
default_value=modules.flags.default_input_image_tab,
validator=lambda x: x in modules.flags.input_image_tab_ids,
expected_type=str
)
default_uov_method = get_config_item_or_set_default(
key='default_uov_method',
default_value=modules.flags.disabled,
validator=lambda x: x in modules.flags.uov_list,
expected_type=str
)
default_controlnet_image_count = get_config_item_or_set_default(
key='default_controlnet_image_count',
default_value=4,
validator=lambda x: isinstance(x, int) and x > 0,
expected_type=int
)
default_ip_images = {}
default_ip_stop_ats = {}
default_ip_weights = {}
default_ip_types = {}
for image_count in range(default_controlnet_image_count):
image_count += 1
default_ip_images[image_count] = get_config_item_or_set_default(
key=f'default_ip_image_{image_count}',
default_value=None,
validator=lambda x: x is None or isinstance(x, str) and os.path.exists(x),
expected_type=str
)
default_ip_types[image_count] = get_config_item_or_set_default(
key=f'default_ip_type_{image_count}',
default_value=modules.flags.default_ip,
validator=lambda x: x in modules.flags.ip_list,
expected_type=str
)
default_end, default_weight = modules.flags.default_parameters[default_ip_types[image_count]]
default_ip_stop_ats[image_count] = get_config_item_or_set_default(
key=f'default_ip_stop_at_{image_count}',
default_value=default_end,
validator=lambda x: isinstance(x, float) and 0 <= x <= 1,
expected_type=float
)
default_ip_weights[image_count] = get_config_item_or_set_default(
key=f'default_ip_weight_{image_count}',
default_value=default_weight,
validator=lambda x: isinstance(x, float) and 0 <= x <= 2,
expected_type=float
)
default_inpaint_advanced_masking_checkbox = get_config_item_or_set_default(
key='default_inpaint_advanced_masking_checkbox',
default_value=False,
validator=lambda x: isinstance(x, bool),
expected_type=bool
)
default_inpaint_method = get_config_item_or_set_default( default_inpaint_method = get_config_item_or_set_default(
key='default_inpaint_method', key='default_inpaint_method',
default_value=modules.flags.inpaint_option_default, default_value=modules.flags.inpaint_option_default,
@@ -526,12 +609,6 @@ default_enhance_tabs = get_config_item_or_set_default(
validator=lambda x: isinstance(x, int) and 1 <= x <= 5, validator=lambda x: isinstance(x, int) and 1 <= x <= 5,
expected_type=int expected_type=int
) )
default_enhance_checkbox = get_config_item_or_set_default(
key='default_enhance_checkbox',
default_value=False,
validator=lambda x: isinstance(x, bool),
expected_type=bool
)
default_enhance_uov_method = get_config_item_or_set_default( default_enhance_uov_method = get_config_item_or_set_default(
key='default_enhance_uov_method', key='default_enhance_uov_method',
default_value=modules.flags.disabled, default_value=modules.flags.disabled,
@@ -562,6 +639,12 @@ default_black_out_nsfw = get_config_item_or_set_default(
validator=lambda x: isinstance(x, bool), validator=lambda x: isinstance(x, bool),
expected_type=bool expected_type=bool
) )
default_save_only_final_enhanced_image = get_config_item_or_set_default(
key='default_save_only_final_enhanced_image',
default_value=False,
validator=lambda x: isinstance(x, bool),
expected_type=bool
)
default_save_metadata_to_images = get_config_item_or_set_default( default_save_metadata_to_images = get_config_item_or_set_default(
key='default_save_metadata_to_images', key='default_save_metadata_to_images',
default_value=False, default_value=False,
@@ -584,6 +667,13 @@ metadata_created_by = get_config_item_or_set_default(
example_inpaint_prompts = [[x] for x in example_inpaint_prompts] example_inpaint_prompts = [[x] for x in example_inpaint_prompts]
example_enhance_detection_prompts = [[x] for x in example_enhance_detection_prompts] example_enhance_detection_prompts = [[x] for x in example_enhance_detection_prompts]
default_invert_mask_checkbox = get_config_item_or_set_default(
key='default_invert_mask_checkbox',
default_value=False,
validator=lambda x: isinstance(x, bool),
expected_type=bool
)
default_inpaint_mask_model = get_config_item_or_set_default( default_inpaint_mask_model = get_config_item_or_set_default(
key='default_inpaint_mask_model', key='default_inpaint_mask_model',
default_value='isnet-general-use', default_value='isnet-general-use',
@@ -612,6 +702,19 @@ default_inpaint_mask_sam_model = get_config_item_or_set_default(
expected_type=str expected_type=str
) )
default_describe_apply_prompts_checkbox = get_config_item_or_set_default(
key='default_describe_apply_prompts_checkbox',
default_value=True,
validator=lambda x: isinstance(x, bool),
expected_type=bool
)
default_describe_content_type = get_config_item_or_set_default(
key='default_describe_content_type',
default_value=[modules.flags.describe_type_photo],
validator=lambda x: all(k in modules.flags.describe_types for k in x),
expected_type=list
)
config_dict["default_loras"] = default_loras = default_loras[:default_max_lora_number] + [[True, 'None', 1.0] for _ in range(default_max_lora_number - len(default_loras))] config_dict["default_loras"] = default_loras = default_loras[:default_max_lora_number] + [[True, 'None', 1.0] for _ in range(default_max_lora_number - len(default_loras))]
# mapping config to meta parameter # mapping config to meta parameter
+1 -1
View File
@@ -231,7 +231,7 @@ def get_previewer(model):
if vae_approx_filename in VAE_approx_models: if vae_approx_filename in VAE_approx_models:
VAE_approx_model = VAE_approx_models[vae_approx_filename] VAE_approx_model = VAE_approx_models[vae_approx_filename]
else: else:
sd = torch.load(vae_approx_filename, map_location='cpu') sd = torch.load(vae_approx_filename, map_location='cpu', weights_only=True)
VAE_approx_model = VAEApprox() VAE_approx_model = VAEApprox()
VAE_approx_model.load_state_dict(sd) VAE_approx_model.load_state_dict(sd)
del sd del sd
+6 -4
View File
@@ -67,6 +67,9 @@ default_vae = 'Default (model)'
refiner_swap_method = 'joint' refiner_swap_method = 'joint'
default_input_image_tab = 'uov_tab'
input_image_tab_ids = ['uov_tab', 'ip_tab', 'inpaint_tab', 'describe_tab', 'enhance_tab', 'metadata_tab']
cn_ip = "ImagePrompt" cn_ip = "ImagePrompt"
cn_ip_face = "FaceSwap" cn_ip_face = "FaceSwap"
cn_canny = "PyraCanny" cn_canny = "PyraCanny"
@@ -91,8 +94,9 @@ inpaint_option_detail = 'Improve Detail (face, hand, eyes, etc.)'
inpaint_option_modify = 'Modify Content (add objects, change background, etc.)' inpaint_option_modify = 'Modify Content (add objects, change background, etc.)'
inpaint_options = [inpaint_option_default, inpaint_option_detail, inpaint_option_modify] inpaint_options = [inpaint_option_default, inpaint_option_detail, inpaint_option_modify]
desc_type_photo = 'Photograph' describe_type_photo = 'Photograph'
desc_type_anime = 'Art/Anime' describe_type_anime = 'Art/Anime'
describe_types = [describe_type_photo, describe_type_anime]
sdxl_aspect_ratios = [ sdxl_aspect_ratios = [
'704*1408', '704*1344', '768*1344', '768*1280', '832*1216', '832*1152', '704*1408', '704*1344', '768*1344', '768*1280', '832*1216', '832*1152',
@@ -113,8 +117,6 @@ metadata_scheme = [
(f'{MetadataScheme.A1111.value} (plain text)', MetadataScheme.A1111.value), (f'{MetadataScheme.A1111.value} (plain text)', MetadataScheme.A1111.value),
] ]
controlnet_image_count = 4
class OutputFormat(Enum): class OutputFormat(Enum):
PNG = 'png' PNG = 'png'
+1 -1
View File
@@ -196,7 +196,7 @@ class InpaintWorker:
if inpaint_head_model is None: if inpaint_head_model is None:
inpaint_head_model = InpaintHead() inpaint_head_model = InpaintHead()
sd = torch.load(inpaint_head_model_path, map_location='cpu') sd = torch.load(inpaint_head_model_path, map_location='cpu', weights_only=True)
inpaint_head_model.load_state_dict(sd) inpaint_head_model.load_state_dict(sd)
feed = torch.cat([ feed = torch.cat([
+3 -4
View File
@@ -604,9 +604,8 @@ def get_metadata_parser(metadata_scheme: MetadataScheme) -> MetadataParser:
raise NotImplementedError raise NotImplementedError
def read_info_from_image(filepath) -> tuple[str | None, MetadataScheme | None]: def read_info_from_image(file) -> tuple[str | None, MetadataScheme | None]:
with Image.open(filepath) as image: items = (file.info or {}).copy()
items = (image.info or {}).copy()
parameters = items.pop('parameters', None) parameters = items.pop('parameters', None)
metadata_scheme = items.pop('fooocus_scheme', None) metadata_scheme = items.pop('fooocus_scheme', None)
@@ -615,7 +614,7 @@ def read_info_from_image(filepath) -> tuple[str | None, MetadataScheme | None]:
if parameters is not None and is_json(parameters): if parameters is not None and is_json(parameters):
parameters = json.loads(parameters) parameters = json.loads(parameters)
elif exif is not None: elif exif is not None:
exif = image.getexif() exif = file.getexif()
# 0x9286 = UserComment # 0x9286 = UserComment
parameters = exif.get(0x9286, None) parameters = exif.get(0x9286, None)
# 0x927C = MakerNote # 0x927C = MakerNote
+2 -2
View File
@@ -21,8 +21,8 @@ def get_current_html_path(output_format=None):
return html_name return html_name
def log(img, metadata, metadata_parser: MetadataParser | None = None, output_format=None, task=None) -> str: def log(img, metadata, metadata_parser: MetadataParser | None = None, output_format=None, task=None, persist_image=True) -> str:
path_outputs = modules.config.temp_path if args_manager.args.disable_image_log else modules.config.path_outputs path_outputs = modules.config.temp_path if args_manager.args.disable_image_log or not persist_image else modules.config.path_outputs
output_format = output_format if output_format else modules.config.default_output_format output_format = output_format if output_format else modules.config.default_output_format
date_string, local_temp_filename, only_name = generate_temp_filename(folder=path_outputs, extension=output_format) date_string, local_temp_filename, only_name = generate_temp_filename(folder=path_outputs, extension=output_format)
os.makedirs(os.path.dirname(local_temp_filename), exist_ok=True) os.makedirs(os.path.dirname(local_temp_filename), exist_ok=True)
+1 -1
View File
@@ -59,7 +59,7 @@ def get_random_style(rng: Random) -> str:
def apply_style(style, positive): def apply_style(style, positive):
p, n = styles[style] p, n = styles[style]
return p.replace('{prompt}', positive).splitlines(), n.splitlines() return p.replace('{prompt}', positive).splitlines(), n.splitlines(), '{prompt}' in p
def get_words(arrays, total_mult, index): def get_words(arrays, total_mult, index):
+1 -1
View File
@@ -17,7 +17,7 @@ def perform_upscale(img):
if model is None: if model is None:
model_filename = downloading_upscale_model() model_filename = downloading_upscale_model()
sd = torch.load(model_filename) sd = torch.load(model_filename, weights_only=True)
sdo = OrderedDict() sdo = OrderedDict()
for k, v in sd.items(): for k, v in sd.items():
sdo[k.replace('residual_block_', 'RDB')] = v sdo[k.replace('residual_block_', 'RDB')] = v
+49 -15
View File
@@ -371,15 +371,14 @@ entry_with_update.py [-h] [--listen [IP]] [--port PORT]
[--hf-mirror HF_MIRROR] [--hf-mirror HF_MIRROR]
[--external-working-path PATH [PATH ...]] [--external-working-path PATH [PATH ...]]
[--output-path OUTPUT_PATH] [--output-path OUTPUT_PATH]
[--temp-path TEMP_PATH] [--temp-path TEMP_PATH] [--cache-path CACHE_PATH]
[--cache-path CACHE_PATH] [--in-browser] [--in-browser] [--disable-in-browser]
[--disable-in-browser]
[--gpu-device-id DEVICE_ID] [--gpu-device-id DEVICE_ID]
[--async-cuda-allocation | --disable-async-cuda-allocation] [--async-cuda-allocation | --disable-async-cuda-allocation]
[--disable-attention-upcast] [--disable-attention-upcast]
[--all-in-fp32 | --all-in-fp16] [--all-in-fp32 | --all-in-fp16]
[--unet-in-bf16 | --unet-in-fp16 | --unet-in-fp8-e4m3fn | --unet-in-fp8-e5m2] [--unet-in-bf16 | --unet-in-fp16 | --unet-in-fp8-e4m3fn | --unet-in-fp8-e5m2]
[--vae-in-fp16 | --vae-in-fp32 | --vae-in-bf16] [--vae-in-fp16 | --vae-in-fp32 | --vae-in-bf16]
[--vae-in-cpu] [--vae-in-cpu]
[--clip-in-fp8-e4m3fn | --clip-in-fp8-e5m2 | --clip-in-fp16 | --clip-in-fp32] [--clip-in-fp8-e4m3fn | --clip-in-fp8-e5m2 | --clip-in-fp16 | --clip-in-fp32]
[--directml [DIRECTML_DEVICE]] [--directml [DIRECTML_DEVICE]]
@@ -387,30 +386,65 @@ entry_with_update.py [-h] [--listen [IP]] [--port PORT]
[--preview-option [none,auto,fast,taesd]] [--preview-option [none,auto,fast,taesd]]
[--attention-split | --attention-quad | --attention-pytorch] [--attention-split | --attention-quad | --attention-pytorch]
[--disable-xformers] [--disable-xformers]
[--always-gpu | --always-high-vram | --always-normal-vram | [--always-gpu | --always-high-vram | --always-normal-vram | --always-low-vram | --always-no-vram | --always-cpu [CPU_NUM_THREADS]]
--always-low-vram | --always-no-vram | --always-cpu [CPU_NUM_THREADS]]
[--always-offload-from-vram] [--always-offload-from-vram]
[--pytorch-deterministic] [--disable-server-log] [--pytorch-deterministic] [--disable-server-log]
[--debug-mode] [--is-windows-embedded-python] [--debug-mode] [--is-windows-embedded-python]
[--disable-server-info] [--multi-user] [--share] [--disable-server-info] [--multi-user] [--share]
[--preset PRESET] [--disable-preset-selection] [--preset PRESET] [--disable-preset-selection]
[--language LANGUAGE] [--language LANGUAGE]
[--disable-offload-from-vram] [--theme THEME] [--disable-offload-from-vram] [--theme THEME]
[--disable-image-log] [--disable-analytics] [--disable-image-log] [--disable-analytics]
[--disable-metadata] [--disable-preset-download] [--disable-metadata] [--disable-preset-download]
[--enable-describe-uov-image] [--disable-enhance-output-sorting]
[--enable-auto-describe-image]
[--always-download-new-model] [--always-download-new-model]
[--rebuild-hash-cache [CPU_NUM_THREADS]]
``` ```
## Inline Prompt Features
### Wildcards
Example prompt: `__color__ flower`
Processed for positive and negative prompt.
Selects a random wildcard from a predefined list of options, in this case the `wildcards/color.txt` file.
The wildcard will be replaced with a random color (randomness based on seed).
You can also disable randomness and process a wildcard file from top to bottom by enabling the checkbox `Read wildcards in order` in Developer Debug Mode.
Wildcards can be nested and combined, and multiple wildcards can be used in the same prompt (example see `wildcards/color_flower.txt`).
### Array Processing
Example prompt: `[[red, green, blue]] flower`
Processed only for positive prompt.
Processes the array from left to right, generating a separate image for each element in the array. In this case 3 images would be generated, one for each color.
Increase the image number to 3 to generate all 3 variants.
Arrays can not be nested, but multiple arrays can be used in the same prompt.
Does support inline LoRAs as array elements!
### Inline LoRAs
Example prompt: `flower <lora:sunflowers:1.2>`
Processed only for positive prompt.
Applies a LoRA to the prompt. The LoRA file must be located in the `models/loras` directory.
## Advanced Features ## Advanced Features
[Click here to browse the advanced features.](https://github.com/lllyasviel/Fooocus/discussions/117) [Click here to browse the advanced features.](https://github.com/lllyasviel/Fooocus/discussions/117)
## Forks
Fooocus also has many community forks, just like SD-WebUI's [vladmandic/automatic](https://github.com/vladmandic/automatic) and [anapnoe/stable-diffusion-webui-ux](https://github.com/anapnoe/stable-diffusion-webui-ux), for enthusiastic users who want to try! Fooocus also has many community forks, just like SD-WebUI's [vladmandic/automatic](https://github.com/vladmandic/automatic) and [anapnoe/stable-diffusion-webui-ux](https://github.com/anapnoe/stable-diffusion-webui-ux), for enthusiastic users who want to try!
| Fooocus' forks | | Fooocus' forks |
| - | | - |
| [fenneishi/Fooocus-Control](https://github.com/fenneishi/Fooocus-Control) </br>[runew0lf/RuinedFooocus](https://github.com/runew0lf/RuinedFooocus) </br> [MoonRide303/Fooocus-MRE](https://github.com/MoonRide303/Fooocus-MRE) </br> [metercai/SimpleSDXL](https://github.com/metercai/SimpleSDXL) </br> and so on ... | | [fenneishi/Fooocus-Control](https://github.com/fenneishi/Fooocus-Control) </br>[runew0lf/RuinedFooocus](https://github.com/runew0lf/RuinedFooocus) </br> [MoonRide303/Fooocus-MRE](https://github.com/MoonRide303/Fooocus-MRE) </br> [metercai/SimpleSDXL](https://github.com/metercai/SimpleSDXL) </br> [mashb1t/Fooocus](https://github.com/mashb1t/Fooocus) </br> and so on ... |
See also [About Forking and Promotion of Forks](https://github.com/lllyasviel/Fooocus/discussions/699). See also [About Forking and Promotion of Forks](https://github.com/lllyasviel/Fooocus/discussions/699).
+20
View File
@@ -1,3 +1,23 @@
# [2.5.3](https://github.com/lllyasviel/Fooocus/releases/tag/v2.5.3)
* Only load weights from non-safetensors files, preventing harmful code injection
* Add checkbox for applying/resetting styles when describing images, also allowing multiple describe content types
# [2.5.2](https://github.com/lllyasviel/Fooocus/releases/tag/v2.5.2)
* Fix not adding positive prompt when styles didn't have a {prompt} placeholder in the positive prompt
* Extend config settings for input image, see list in [PR](https://github.com/lllyasviel/Fooocus/pull/3382)
# [2.5.1](https://github.com/lllyasviel/Fooocus/releases/tag/v2.5.1)
* Update download URL in readme
* Increase speed of metadata loading
* Fix reading of metadata from jpeg, jpg and webp (exif)
* Fix debug preprocessor
* Update attributes and add inline prompt features section to readme
* Add checkbox, config and handling for saving only the final enhanced image. Use config `default_save_only_final_enhanced_image`, default False.
* Add sorting of final images when enhanced is enabled. Use argument `--disable-enhance-output-sorting` to disable.
# [2.5.0](https://github.com/lllyasviel/Fooocus/releases/tag/v2.5.0) # [2.5.0](https://github.com/lllyasviel/Fooocus/releases/tag/v2.5.0)
This version includes various package updates. If the auto-update doesn't work you can do one of the following: This version includes various package updates. If the auto-update doesn't work you can do one of the following:
+108 -55
View File
@@ -73,6 +73,9 @@ def generate_clicked(task: worker.AsyncTask):
gr.update(visible=True, value=product), \ gr.update(visible=True, value=product), \
gr.update(visible=False) gr.update(visible=False)
if flag == 'finish': if flag == 'finish':
if not args_manager.args.disable_enhance_output_sorting:
product = sort_enhance_images(product, task)
yield gr.update(visible=False), \ yield gr.update(visible=False), \
gr.update(visible=False), \ gr.update(visible=False), \
gr.update(visible=False), \ gr.update(visible=False), \
@@ -90,6 +93,25 @@ def generate_clicked(task: worker.AsyncTask):
return return
def sort_enhance_images(images, task):
if not task.should_enhance or len(images) <= task.images_to_enhance_count:
return images
sorted_images = []
walk_index = task.images_to_enhance_count
for index, enhanced_img in enumerate(images[:task.images_to_enhance_count]):
sorted_images.append(enhanced_img)
if index not in task.enhance_stats:
continue
target_index = walk_index + task.enhance_stats[index]
if walk_index < len(images) and target_index <= len(images):
sorted_images += images[walk_index:target_index]
walk_index += task.enhance_stats[index]
return sorted_images
def inpaint_mode_change(mode, inpaint_engine_version): def inpaint_mode_change(mode, inpaint_engine_version):
assert mode in modules.flags.inpaint_options assert mode in modules.flags.inpaint_options
@@ -178,19 +200,19 @@ with shared.gradio_root:
stop_button.click(stop_clicked, inputs=currentTask, outputs=currentTask, queue=False, show_progress=False, _js='cancelGenerateForever') stop_button.click(stop_clicked, inputs=currentTask, outputs=currentTask, queue=False, show_progress=False, _js='cancelGenerateForever')
skip_button.click(skip_clicked, inputs=currentTask, outputs=currentTask, queue=False, show_progress=False) skip_button.click(skip_clicked, inputs=currentTask, outputs=currentTask, queue=False, show_progress=False)
with gr.Row(elem_classes='advanced_check_row'): with gr.Row(elem_classes='advanced_check_row'):
input_image_checkbox = gr.Checkbox(label='Input Image', value=False, container=False, elem_classes='min_check') input_image_checkbox = gr.Checkbox(label='Input Image', value=modules.config.default_image_prompt_checkbox, container=False, elem_classes='min_check')
enhance_checkbox = gr.Checkbox(label='Enhance', value=modules.config.default_enhance_checkbox, container=False, elem_classes='min_check') enhance_checkbox = gr.Checkbox(label='Enhance', value=modules.config.default_enhance_checkbox, container=False, elem_classes='min_check')
advanced_checkbox = gr.Checkbox(label='Advanced', value=modules.config.default_advanced_checkbox, container=False, elem_classes='min_check') advanced_checkbox = gr.Checkbox(label='Advanced', value=modules.config.default_advanced_checkbox, container=False, elem_classes='min_check')
with gr.Row(visible=False) as image_input_panel: with gr.Row(visible=modules.config.default_image_prompt_checkbox) as image_input_panel:
with gr.Tabs(): with gr.Tabs(selected=modules.config.default_selected_image_input_tab_id):
with gr.TabItem(label='Upscale or Variation') as uov_tab: with gr.Tab(label='Upscale or Variation', id='uov_tab') as uov_tab:
with gr.Row(): with gr.Row():
with gr.Column(): with gr.Column():
uov_input_image = grh.Image(label='Image', source='upload', type='numpy', show_label=False) uov_input_image = grh.Image(label='Image', source='upload', type='numpy', show_label=False)
with gr.Column(): with gr.Column():
uov_method = gr.Radio(label='Upscale or Variation:', choices=flags.uov_list, value=flags.disabled) uov_method = gr.Radio(label='Upscale or Variation:', choices=flags.uov_list, value=modules.config.default_uov_method)
gr.HTML('<a href="https://github.com/lllyasviel/Fooocus/discussions/390" target="_blank">\U0001F4D4 Documentation</a>') gr.HTML('<a href="https://github.com/lllyasviel/Fooocus/discussions/390" target="_blank">\U0001F4D4 Documentation</a>')
with gr.TabItem(label='Image Prompt') as ip_tab: with gr.Tab(label='Image Prompt', id='ip_tab') as ip_tab:
with gr.Row(): with gr.Row():
ip_images = [] ip_images = []
ip_types = [] ip_types = []
@@ -198,30 +220,29 @@ with shared.gradio_root:
ip_weights = [] ip_weights = []
ip_ctrls = [] ip_ctrls = []
ip_ad_cols = [] ip_ad_cols = []
for _ in range(flags.controlnet_image_count): for image_count in range(modules.config.default_controlnet_image_count):
image_count += 1
with gr.Column(): with gr.Column():
ip_image = grh.Image(label='Image', source='upload', type='numpy', show_label=False, height=300) ip_image = grh.Image(label='Image', source='upload', type='numpy', show_label=False, height=300, value=modules.config.default_ip_images[image_count])
ip_images.append(ip_image) ip_images.append(ip_image)
ip_ctrls.append(ip_image) ip_ctrls.append(ip_image)
with gr.Column(visible=False) as ad_col: with gr.Column(visible=modules.config.default_image_prompt_advanced_checkbox) as ad_col:
with gr.Row(): with gr.Row():
default_end, default_weight = flags.default_parameters[flags.default_ip] ip_stop = gr.Slider(label='Stop At', minimum=0.0, maximum=1.0, step=0.001, value=modules.config.default_ip_stop_ats[image_count])
ip_stop = gr.Slider(label='Stop At', minimum=0.0, maximum=1.0, step=0.001, value=default_end)
ip_stops.append(ip_stop) ip_stops.append(ip_stop)
ip_ctrls.append(ip_stop) ip_ctrls.append(ip_stop)
ip_weight = gr.Slider(label='Weight', minimum=0.0, maximum=2.0, step=0.001, value=default_weight) ip_weight = gr.Slider(label='Weight', minimum=0.0, maximum=2.0, step=0.001, value=modules.config.default_ip_weights[image_count])
ip_weights.append(ip_weight) ip_weights.append(ip_weight)
ip_ctrls.append(ip_weight) ip_ctrls.append(ip_weight)
ip_type = gr.Radio(label='Type', choices=flags.ip_list, value=flags.default_ip, container=False) ip_type = gr.Radio(label='Type', choices=flags.ip_list, value=modules.config.default_ip_types[image_count], container=False)
ip_types.append(ip_type) ip_types.append(ip_type)
ip_ctrls.append(ip_type) ip_ctrls.append(ip_type)
ip_type.change(lambda x: flags.default_parameters[x], inputs=[ip_type], outputs=[ip_stop, ip_weight], queue=False, show_progress=False) ip_type.change(lambda x: flags.default_parameters[x], inputs=[ip_type], outputs=[ip_stop, ip_weight], queue=False, show_progress=False)
ip_ad_cols.append(ad_col) ip_ad_cols.append(ad_col)
ip_advanced = gr.Checkbox(label='Advanced', value=False, container=False) ip_advanced = gr.Checkbox(label='Advanced', value=modules.config.default_image_prompt_advanced_checkbox, container=False)
gr.HTML('* \"Image Prompt\" is powered by Fooocus Image Mixture Engine (v1.0.1). <a href="https://github.com/lllyasviel/Fooocus/discussions/557" target="_blank">\U0001F4D4 Documentation</a>') gr.HTML('* \"Image Prompt\" is powered by Fooocus Image Mixture Engine (v1.0.1). <a href="https://github.com/lllyasviel/Fooocus/discussions/557" target="_blank">\U0001F4D4 Documentation</a>')
def ip_advance_checked(x): def ip_advance_checked(x):
@@ -234,11 +255,11 @@ with shared.gradio_root:
outputs=ip_ad_cols + ip_types + ip_stops + ip_weights, outputs=ip_ad_cols + ip_types + ip_stops + ip_weights,
queue=False, show_progress=False) queue=False, show_progress=False)
with gr.TabItem(label='Inpaint or Outpaint') as inpaint_tab: with gr.Tab(label='Inpaint or Outpaint', id='inpaint_tab') as inpaint_tab:
with gr.Row(): with gr.Row():
with gr.Column(): with gr.Column():
inpaint_input_image = grh.Image(label='Image', source='upload', type='numpy', tool='sketch', height=500, brush_color="#FFFFFF", elem_id='inpaint_canvas', show_label=False) inpaint_input_image = grh.Image(label='Image', source='upload', type='numpy', tool='sketch', height=500, brush_color="#FFFFFF", elem_id='inpaint_canvas', show_label=False)
inpaint_advanced_masking_checkbox = gr.Checkbox(label='Enable Advanced Masking Features', value=False) inpaint_advanced_masking_checkbox = gr.Checkbox(label='Enable Advanced Masking Features', value=modules.config.default_inpaint_advanced_masking_checkbox)
inpaint_mode = gr.Dropdown(choices=modules.flags.inpaint_options, value=modules.config.default_inpaint_method, label='Method') inpaint_mode = gr.Dropdown(choices=modules.flags.inpaint_options, value=modules.config.default_inpaint_method, label='Method')
inpaint_additional_prompt = gr.Textbox(placeholder="Describe what you want to inpaint.", elem_id='inpaint_additional_prompt', label='Inpaint Additional Prompt', visible=False) inpaint_additional_prompt = gr.Textbox(placeholder="Describe what you want to inpaint.", elem_id='inpaint_additional_prompt', label='Inpaint Additional Prompt', visible=False)
outpaint_selections = gr.CheckboxGroup(choices=['Left', 'Right', 'Top', 'Bottom'], value=[], label='Outpaint Direction') outpaint_selections = gr.CheckboxGroup(choices=['Left', 'Right', 'Top', 'Bottom'], value=[], label='Outpaint Direction')
@@ -249,9 +270,9 @@ with shared.gradio_root:
gr.HTML('* Powered by Fooocus Inpaint Engine <a href="https://github.com/lllyasviel/Fooocus/discussions/414" target="_blank">\U0001F4D4 Documentation</a>') gr.HTML('* Powered by Fooocus Inpaint Engine <a href="https://github.com/lllyasviel/Fooocus/discussions/414" target="_blank">\U0001F4D4 Documentation</a>')
example_inpaint_prompts.click(lambda x: x[0], inputs=example_inpaint_prompts, outputs=inpaint_additional_prompt, show_progress=False, queue=False) example_inpaint_prompts.click(lambda x: x[0], inputs=example_inpaint_prompts, outputs=inpaint_additional_prompt, show_progress=False, queue=False)
with gr.Column(visible=False) as inpaint_mask_generation_col: with gr.Column(visible=modules.config.default_inpaint_advanced_masking_checkbox) as inpaint_mask_generation_col:
inpaint_mask_image = grh.Image(label='Mask Upload', source='upload', type='numpy', tool='sketch', height=500, brush_color="#FFFFFF", mask_opacity=1, elem_id='inpaint_mask_canvas') inpaint_mask_image = grh.Image(label='Mask Upload', source='upload', type='numpy', tool='sketch', height=500, brush_color="#FFFFFF", mask_opacity=1, elem_id='inpaint_mask_canvas')
invert_mask_checkbox = gr.Checkbox(label='Invert Mask When Generating', value=False) invert_mask_checkbox = gr.Checkbox(label='Invert Mask When Generating', value=modules.config.default_invert_mask_checkbox)
inpaint_mask_model = gr.Dropdown(label='Mask generation model', inpaint_mask_model = gr.Dropdown(label='Mask generation model',
choices=flags.inpaint_mask_models, choices=flags.inpaint_mask_models,
value=modules.config.default_inpaint_mask_model) value=modules.config.default_inpaint_mask_model)
@@ -311,40 +332,41 @@ with shared.gradio_root:
example_inpaint_mask_dino_prompt_text], example_inpaint_mask_dino_prompt_text],
queue=False, show_progress=False) queue=False, show_progress=False)
with gr.TabItem(label='Describe') as desc_tab: with gr.Tab(label='Describe', id='describe_tab') as describe_tab:
with gr.Row(): with gr.Row():
with gr.Column(): with gr.Column():
desc_input_image = grh.Image(label='Image', source='upload', type='numpy', show_label=False) describe_input_image = grh.Image(label='Image', source='upload', type='numpy', show_label=False)
with gr.Column(): with gr.Column():
desc_method = gr.Radio( describe_methods = gr.CheckboxGroup(
label='Content Type', label='Content Type',
choices=[flags.desc_type_photo, flags.desc_type_anime], choices=flags.describe_types,
value=flags.desc_type_photo) value=modules.config.default_describe_content_type)
desc_btn = gr.Button(value='Describe this Image into Prompt') describe_apply_styles = gr.Checkbox(label='Apply Styles', value=modules.config.default_describe_apply_prompts_checkbox)
desc_image_size = gr.Textbox(label='Image Size and Recommended Size', elem_id='desc_image_size', visible=False) describe_btn = gr.Button(value='Describe this Image into Prompt')
describe_image_size = gr.Textbox(label='Image Size and Recommended Size', elem_id='describe_image_size', visible=False)
gr.HTML('<a href="https://github.com/lllyasviel/Fooocus/discussions/1363" target="_blank">\U0001F4D4 Documentation</a>') gr.HTML('<a href="https://github.com/lllyasviel/Fooocus/discussions/1363" target="_blank">\U0001F4D4 Documentation</a>')
def trigger_show_image_properties(image): def trigger_show_image_properties(image):
value = modules.util.get_image_size_info(image, modules.flags.sdxl_aspect_ratios) value = modules.util.get_image_size_info(image, modules.flags.sdxl_aspect_ratios)
return gr.update(value=value, visible=True) return gr.update(value=value, visible=True)
desc_input_image.upload(trigger_show_image_properties, inputs=desc_input_image, describe_input_image.upload(trigger_show_image_properties, inputs=describe_input_image,
outputs=desc_image_size, show_progress=False, queue=False) outputs=describe_image_size, show_progress=False, queue=False)
with gr.TabItem(label='Enhance') as enhance_tab: with gr.Tab(label='Enhance', id='enhance_tab') as enhance_tab:
with gr.Row(): with gr.Row():
with gr.Column(): with gr.Column():
enhance_input_image = grh.Image(label='Use with Enhance, skips image generation', source='upload', type='numpy') enhance_input_image = grh.Image(label='Use with Enhance, skips image generation', source='upload', type='numpy')
gr.HTML('<a href="https://github.com/lllyasviel/Fooocus/discussions/3281" target="_blank">\U0001F4D4 Documentation</a>') gr.HTML('<a href="https://github.com/lllyasviel/Fooocus/discussions/3281" target="_blank">\U0001F4D4 Documentation</a>')
with gr.TabItem(label='Metadata') as metadata_tab: with gr.Tab(label='Metadata', id='metadata_tab') as metadata_tab:
with gr.Column(): with gr.Column():
metadata_input_image = grh.Image(label='For images created by Fooocus', source='upload', type='filepath') metadata_input_image = grh.Image(label='For images created by Fooocus', source='upload', type='pil')
metadata_json = gr.JSON(label='Metadata') metadata_json = gr.JSON(label='Metadata')
metadata_import_button = gr.Button(value='Apply Metadata') metadata_import_button = gr.Button(value='Apply Metadata')
def trigger_metadata_preview(filepath): def trigger_metadata_preview(file):
parameters, metadata_scheme = modules.meta_parser.read_info_from_image(filepath) parameters, metadata_scheme = modules.meta_parser.read_info_from_image(file)
results = {} results = {}
if parameters is not None: if parameters is not None:
@@ -360,7 +382,7 @@ with shared.gradio_root:
with gr.Row(visible=modules.config.default_enhance_checkbox) as enhance_input_panel: with gr.Row(visible=modules.config.default_enhance_checkbox) as enhance_input_panel:
with gr.Tabs(): with gr.Tabs():
with gr.TabItem(label='Upscale or Variation'): with gr.Tab(label='Upscale or Variation'):
with gr.Row(): with gr.Row():
with gr.Column(): with gr.Column():
enhance_uov_method = gr.Radio(label='Upscale or Variation:', choices=flags.uov_list, enhance_uov_method = gr.Radio(label='Upscale or Variation:', choices=flags.uov_list,
@@ -385,7 +407,7 @@ with shared.gradio_root:
enhance_inpaint_engine_ctrls = [] enhance_inpaint_engine_ctrls = []
enhance_inpaint_update_ctrls = [] enhance_inpaint_update_ctrls = []
for index in range(modules.config.default_enhance_tabs): for index in range(modules.config.default_enhance_tabs):
with gr.TabItem(label=f'#{index + 1}') as enhance_tab_item: with gr.Tab(label=f'#{index + 1}') as enhance_tab_item:
enhance_enabled = gr.Checkbox(label='Enable', value=False, elem_classes='min_check', enhance_enabled = gr.Checkbox(label='Enable', value=False, elem_classes='min_check',
container=False) container=False)
@@ -527,7 +549,7 @@ with shared.gradio_root:
uov_tab.select(lambda: 'uov', outputs=current_tab, queue=False, _js=down_js, show_progress=False) uov_tab.select(lambda: 'uov', outputs=current_tab, queue=False, _js=down_js, show_progress=False)
inpaint_tab.select(lambda: 'inpaint', outputs=current_tab, queue=False, _js=down_js, show_progress=False) inpaint_tab.select(lambda: 'inpaint', outputs=current_tab, queue=False, _js=down_js, show_progress=False)
ip_tab.select(lambda: 'ip', outputs=current_tab, queue=False, _js=down_js, show_progress=False) ip_tab.select(lambda: 'ip', outputs=current_tab, queue=False, _js=down_js, show_progress=False)
desc_tab.select(lambda: 'desc', outputs=current_tab, queue=False, _js=down_js, show_progress=False) describe_tab.select(lambda: 'desc', outputs=current_tab, queue=False, _js=down_js, show_progress=False)
enhance_tab.select(lambda: 'enhance', outputs=current_tab, queue=False, _js=down_js, show_progress=False) enhance_tab.select(lambda: 'enhance', outputs=current_tab, queue=False, _js=down_js, show_progress=False)
metadata_tab.select(lambda: 'metadata', outputs=current_tab, queue=False, _js=down_js, show_progress=False) metadata_tab.select(lambda: 'metadata', outputs=current_tab, queue=False, _js=down_js, show_progress=False)
enhance_checkbox.change(lambda x: gr.update(visible=x), inputs=enhance_checkbox, enhance_checkbox.change(lambda x: gr.update(visible=x), inputs=enhance_checkbox,
@@ -671,9 +693,9 @@ with shared.gradio_root:
value=modules.config.default_sample_sharpness, value=modules.config.default_sample_sharpness,
info='Higher value means image and texture are sharper.') info='Higher value means image and texture are sharper.')
gr.HTML('<a href="https://github.com/lllyasviel/Fooocus/discussions/117" target="_blank">\U0001F4D4 Documentation</a>') gr.HTML('<a href="https://github.com/lllyasviel/Fooocus/discussions/117" target="_blank">\U0001F4D4 Documentation</a>')
dev_mode = gr.Checkbox(label='Developer Debug Mode', value=False, container=False) dev_mode = gr.Checkbox(label='Developer Debug Mode', value=modules.config.default_developer_debug_mode_checkbox, container=False)
with gr.Column(visible=False) as dev_tools: with gr.Column(visible=modules.config.default_developer_debug_mode_checkbox) as dev_tools:
with gr.Tab(label='Debug Tools'): with gr.Tab(label='Debug Tools'):
adm_scaler_positive = gr.Slider(label='Positive ADM Guidance Scaler', minimum=0.1, maximum=3.0, adm_scaler_positive = gr.Slider(label='Positive ADM Guidance Scaler', minimum=0.1, maximum=3.0,
step=0.001, value=1.5, info='The scaler multiplied to positive ADM (use 1.0 to disable). ') step=0.001, value=1.5, info='The scaler multiplied to positive ADM (use 1.0 to disable). ')
@@ -748,6 +770,10 @@ with shared.gradio_root:
inputs=black_out_nsfw, outputs=disable_preview, queue=False, inputs=black_out_nsfw, outputs=disable_preview, queue=False,
show_progress=False) show_progress=False)
if not args_manager.args.disable_image_log:
save_final_enhanced_image_only = gr.Checkbox(label='Save only final enhanced image',
value=modules.config.default_save_only_final_enhanced_image)
if not args_manager.args.disable_metadata: if not args_manager.args.disable_metadata:
save_metadata_to_images = gr.Checkbox(label='Save Metadata to Images', value=modules.config.default_save_metadata_to_images, save_metadata_to_images = gr.Checkbox(label='Save Metadata to Images', value=modules.config.default_save_metadata_to_images,
info='Adds parameters to generated images allowing manual regeneration.') info='Adds parameters to generated images allowing manual regeneration.')
@@ -969,6 +995,9 @@ with shared.gradio_root:
ctrls += freeu_ctrls ctrls += freeu_ctrls
ctrls += inpaint_ctrls ctrls += inpaint_ctrls
if not args_manager.args.disable_image_log:
ctrls += [save_final_enhanced_image_only]
if not args_manager.args.disable_metadata: if not args_manager.args.disable_metadata:
ctrls += [save_metadata_to_images, metadata_scheme] ctrls += [save_metadata_to_images, metadata_scheme]
@@ -995,8 +1024,8 @@ with shared.gradio_root:
load_parameter_button.click(modules.meta_parser.load_parameter_button_click, inputs=[prompt, state_is_generating, inpaint_mode], outputs=load_data_outputs, queue=False, show_progress=False) load_parameter_button.click(modules.meta_parser.load_parameter_button_click, inputs=[prompt, state_is_generating, inpaint_mode], outputs=load_data_outputs, queue=False, show_progress=False)
def trigger_metadata_import(filepath, state_is_generating): def trigger_metadata_import(file, state_is_generating):
parameters, metadata_scheme = modules.meta_parser.read_info_from_image(filepath) parameters, metadata_scheme = modules.meta_parser.read_info_from_image(file)
if parameters is None: if parameters is None:
print('Could not find metadata in the image!') print('Could not find metadata in the image!')
parsed_parameters = {} parsed_parameters = {}
@@ -1032,30 +1061,54 @@ with shared.gradio_root:
gr.Audio(interactive=False, value=notification_file, elem_id='audio_notification', visible=False) gr.Audio(interactive=False, value=notification_file, elem_id='audio_notification', visible=False)
break break
def trigger_describe(mode, img): def trigger_describe(modes, img, apply_styles):
if mode == flags.desc_type_photo: describe_prompts = []
from extras.interrogate import default_interrogator as default_interrogator_photo styles = set()
return default_interrogator_photo(img), ["Fooocus V2", "Fooocus Enhance", "Fooocus Sharp"]
if mode == flags.desc_type_anime:
from extras.wd14tagger import default_interrogator as default_interrogator_anime
return default_interrogator_anime(img), ["Fooocus V2", "Fooocus Masterpiece"]
return mode, ["Fooocus V2"]
desc_btn.click(trigger_describe, inputs=[desc_method, desc_input_image], if flags.describe_type_photo in modes:
outputs=[prompt, style_selections], show_progress=True, queue=True) from extras.interrogate import default_interrogator as default_interrogator_photo
describe_prompts.append(default_interrogator_photo(img))
styles.update(["Fooocus V2", "Fooocus Enhance", "Fooocus Sharp"])
if flags.describe_type_anime in modes:
from extras.wd14tagger import default_interrogator as default_interrogator_anime
describe_prompts.append(default_interrogator_anime(img))
styles.update(["Fooocus V2", "Fooocus Masterpiece"])
if len(styles) == 0 or not apply_styles:
styles = gr.update()
else:
styles = list(styles)
if len(describe_prompts) == 0:
describe_prompt = gr.update()
else:
describe_prompt = ', '.join(describe_prompts)
return describe_prompt, styles
describe_btn.click(trigger_describe, inputs=[describe_methods, describe_input_image, describe_apply_styles],
outputs=[prompt, style_selections], show_progress=True, queue=True) \
.then(fn=style_sorter.sort_styles, inputs=style_selections, outputs=style_selections, queue=False, show_progress=False) \
.then(lambda: None, _js='()=>{refresh_style_localization();}')
if args_manager.args.enable_auto_describe_image: if args_manager.args.enable_auto_describe_image:
def trigger_auto_describe(mode, img, prompt): def trigger_auto_describe(mode, img, prompt, apply_styles):
# keep prompt if not empty # keep prompt if not empty
if prompt == '': if prompt == '':
return trigger_describe(mode, img) return trigger_describe(mode, img, apply_styles)
return gr.update(), gr.update() return gr.update(), gr.update()
uov_input_image.upload(trigger_auto_describe, inputs=[desc_method, uov_input_image, prompt], uov_input_image.upload(trigger_auto_describe, inputs=[describe_methods, uov_input_image, prompt, describe_apply_styles],
outputs=[prompt, style_selections], show_progress=True, queue=True) outputs=[prompt, style_selections], show_progress=True, queue=True) \
.then(fn=style_sorter.sort_styles, inputs=style_selections, outputs=style_selections, queue=False, show_progress=False) \
.then(lambda: None, _js='()=>{refresh_style_localization();}')
enhance_input_image.upload(lambda: gr.update(value=True), outputs=enhance_checkbox, queue=False, show_progress=False) \ enhance_input_image.upload(lambda: gr.update(value=True), outputs=enhance_checkbox, queue=False, show_progress=False) \
.then(trigger_auto_describe, inputs=[desc_method, enhance_input_image, prompt], outputs=[prompt, style_selections], show_progress=True, queue=True) .then(trigger_auto_describe, inputs=[describe_methods, enhance_input_image, prompt, describe_apply_styles],
outputs=[prompt, style_selections], show_progress=True, queue=True) \
.then(fn=style_sorter.sort_styles, inputs=style_selections, outputs=style_selections, queue=False, show_progress=False) \
.then(lambda: None, _js='()=>{refresh_style_localization();}')
def dump_default_english_config(): def dump_default_english_config():
from modules.localization import dump_english_config from modules.localization import dump_english_config