xyz grid multi-resolution

This commit is contained in:
Vladimir Mandic
2024-09-21 14:30:53 -04:00
parent f059313333
commit 114df73efa
5 changed files with 54 additions and 46 deletions
+3
View File
@@ -19,6 +19,9 @@
- allow passing **processing args** directly:
params are set directly on main processing object and can be known or new params
example: `steps=10, steps=20; test=unknown`
- enable working with different resolutions
now you can adjust width/height in the grid just as any other param
- renamed options to include section name and adjusted cost of each option
- **interrogate**
- add additional blip models: *blip-base, blip-large, blip-t5-xl, blip-t5-xxl, opt-2.7b, opt-6.7b*
- change default params for better memory utilization
+1 -1
View File
@@ -12,7 +12,7 @@ import piexif
import piexif.helper
from PIL import Image, PngImagePlugin, ExifTags
from modules import sd_samplers, shared, script_callbacks, errors, paths
from modules.images_grid import image_grid, split_grid, combine_grid, check_grid_size, get_font, draw_grid_annotations, draw_prompt_matrix # pylint: disable=unused-import
from modules.images_grid import image_grid, split_grid, combine_grid, check_grid_size, get_font, draw_grid_annotations, draw_prompt_matrix, GridAnnotation # pylint: disable=unused-import
from modules.images_resize import resize_image # pylint: disable=unused-import
from modules.images_namegen import FilenameGenerator
+8 -8
View File
@@ -5,6 +5,9 @@ from PIL import Image, ImageFont, ImageDraw
from modules import shared, script_callbacks
Grid = namedtuple("Grid", ["tiles", "tile_w", "tile_h", "image_w", "image_h", "overlap"])
def check_grid_size(imgs):
mp = 0
for img in imgs:
@@ -34,16 +37,13 @@ def image_grid(imgs, batch_size=1, rows=None):
imgs = [i for i in imgs if i is not None] if imgs is not None else []
if len(imgs) == 0:
return None
w, h = imgs[0].size
w, h = max(i.width for i in imgs), max(i.height for i in imgs)
grid = Image.new('RGB', size=(params.cols * w, params.rows * h), color=shared.opts.grid_background)
for i, img in enumerate(params.imgs):
grid.paste(img, box=(i % params.cols * w, i // params.cols * h))
return grid
Grid = namedtuple("Grid", ["tiles", "tile_w", "tile_h", "image_w", "image_h", "overlap"])
def split_grid(image, tile_w=512, tile_h=512, overlap=64):
w = image.width
h = image.height
@@ -136,10 +136,10 @@ def draw_grid_annotations(im, width, height, hor_texts, ver_texts, margin=0, tit
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 = im.width // width
rows = im.height // height
assert cols == len(hor_texts), f'bad number of horizontal texts: {len(hor_texts)}; must be {cols}'
assert rows == len(ver_texts), f'bad number of vertical texts: {len(ver_texts)}; must be {rows}'
cols = len(hor_texts)
rows = len(ver_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()]]
+33 -31
View File
@@ -80,27 +80,30 @@ class SharedSettingsStackHelper(object):
axis_options = [
AxisOption("Nothing", str, do_nothing, fmt=format_nothing),
AxisOption("Prompt S/R", str, apply_prompt, fmt=format_value),
AxisOption("Model", str, apply_checkpoint, fmt=format_value, cost=1.0, choices=lambda: sorted(sd_models.checkpoints_list)),
AxisOption("UNET", str, apply_unet, cost=0.9, choices=lambda: ['None'] + list(sd_unet.unet_dict)),
AxisOption("VAE", str, apply_vae, cost=0.7, choices=lambda: ['None'] + list(sd_vae.vae_dict)),
AxisOption("LoRA", str, apply_lora, cost=0.5, choices=list_lora),
AxisOption("LoRA strength", float, apply_setting('extra_networks_default_multiplier')),
AxisOption("Text encoder", str, apply_te, cost=0.7, choices=shared_items.sd_te_items),
AxisOption("Styles", str, apply_styles, choices=lambda: [s.name for s in shared.prompt_styles.styles.values()]),
AxisOption("Seed", int, apply_field("seed")),
AxisOption("Steps", int, apply_field("steps")),
AxisOption("CFG scale", float, apply_field("cfg_scale")),
AxisOption("Guidance end", float, apply_field("cfg_end")),
AxisOption("Variation seed", int, apply_field("subseed")),
AxisOption("Variation strength", float, apply_field("subseed_strength")),
AxisOption("Clip skip", float, apply_clip_skip),
AxisOption("Denoising strength", float, apply_field("denoising_strength")),
AxisOption("Prompt order", str_permutations, apply_order, fmt=format_value_join_list),
AxisOption("Model dictionary", str, apply_dict, fmt=format_value, cost=1.0, choices=lambda: ['None'] + list(sd_models.checkpoints_list)),
AxisOption("Model args", str, apply_task_args),
AxisOption("Processing args", str, apply_processing),
AxisOptionImg2Img("Image mask weight", float, apply_field("inpainting_mask_weight")),
AxisOption("[Model] Model", str, apply_checkpoint, cost=1.0, fmt=format_value, 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] 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("[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')),
AxisOption("[Network] Styles", str, apply_styles, choices=lambda: [s.name for s in shared.prompt_styles.styles.values()]),
AxisOption("[Param] Width", int, apply_field("width")),
AxisOption("[Param] Height", int, apply_field("height")),
AxisOption("[Param] Seed", int, apply_field("seed")),
AxisOption("[Param] Steps", int, apply_field("steps")),
AxisOption("[Param] CFG scale", float, apply_field("cfg_scale")),
AxisOption("[Param] Guidance end", float, apply_field("cfg_end")),
AxisOption("[Param] Variation seed", int, apply_field("subseed")),
AxisOption("[Param] Variation strength", float, apply_field("subseed_strength")),
AxisOption("[Param] Clip skip", float, apply_clip_skip),
AxisOption("[Param] Denoising strength", float, apply_field("denoising_strength")),
AxisOptionImg2Img("[Param] Mask weight", float, apply_field("inpainting_mask_weight")),
AxisOption("[Process] Model args", str, apply_task_args),
AxisOption("[Process] Processing args", str, apply_processing),
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]),
AxisOption("[Sampler] Timestep spacing", str, apply_setting("schedulers_timestep_spacing"), choices=lambda: ['default', 'linspace', 'leading', 'trailing']),
@@ -113,16 +116,15 @@ axis_options = [
AxisOption("[Sampler] Shift", float, apply_setting("schedulers_shift")),
AxisOption("[Sampler] ETA", float, apply_setting("scheduler_eta")),
AxisOption("[Sampler] Solver order", int, apply_setting("schedulers_solver_order")),
AxisOption("[Second pass] Upscaler", str, apply_field("hr_upscaler"), choices=lambda: [*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]]),
AxisOption("[Second pass] Sampler", str, apply_hr_sampler_name, fmt=format_value, confirm=confirm_samplers, choices=lambda: [x.name for x in sd_samplers.samplers]),
AxisOption("[Second pass] Denoising strength", float, apply_field("denoising_strength")),
AxisOption("[Second pass] Hires steps", int, apply_field("hr_second_pass_steps")),
AxisOption("[Second pass] CFG scale", float, apply_field("image_cfg_scale")),
AxisOption("[Second pass] Guidance rescale", float, apply_field("diffusers_guidance_rescale")),
AxisOption("[Refiner] Model", str, apply_refiner, fmt=format_value, cost=1.0, choices=lambda: ['None'] + sorted(sd_models.checkpoints_list)),
AxisOption("[Refiner] Refiner start", float, apply_field("refiner_start")),
AxisOption("[Refiner] Refiner steps", float, apply_field("refiner_steps")),
AxisOption("[Postprocess] Upscaler", str, apply_upscaler, choices=lambda: [x.name for x in shared.sd_upscalers][1:]),
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] Denoising strength", float, apply_field("denoising_strength")),
AxisOption("[Refine] Hires steps", int, apply_field("hr_second_pass_steps")),
AxisOption("[Refine] CFG scale", float, apply_field("image_cfg_scale")),
AxisOption("[Refine] Guidance rescale", float, apply_field("diffusers_guidance_rescale")),
AxisOption("[Refine] Refiner start", float, apply_field("refiner_start")),
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] Face restore", str, apply_face_restore, fmt=format_value),
AxisOption("[HDR] Mode", int, apply_field("hdr_mode")),
+9 -6
View File
@@ -85,21 +85,24 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend
for i in range(z_count):
start_index = (i * len(xs) * len(ys)) + i
end_index = start_index + len(xs) * len(ys)
w, h = max(i.width for i in processed_result.images[start_index:end_index]), max(i.height for i in processed_result.images[start_index:end_index])
print('HERE', w, h, z_count)
if (not no_grid or include_sub_grids) and images.check_grid_size(processed_result.images[start_index:end_index]):
grid = images.image_grid(processed_result.images[start_index:end_index], rows=len(ys))
if draw_legend:
grid = images.draw_grid_annotations(grid, processed_result.images[start_index].size[0], processed_result.images[start_index].size[1], hor_texts, ver_texts, margin_size, title=title_texts[i])
grid = images.draw_grid_annotations(grid, w, h, hor_texts, ver_texts, margin_size, title=title_texts[i])
processed_result.images.insert(i, grid)
processed_result.all_prompts.insert(i, processed_result.all_prompts[start_index])
processed_result.all_seeds.insert(i, processed_result.all_seeds[start_index])
processed_result.infotexts.insert(i, processed_result.infotexts[start_index])
sub_grid_size = processed_result.images[0].size
"""
if not no_grid and images.check_grid_size(processed_result.images[:z_count]):
z_grid = images.image_grid(processed_result.images[:z_count], rows=1)
if draw_legend:
z_grid = images.draw_grid_annotations(z_grid, sub_grid_size[0], sub_grid_size[1], [[images.GridAnnotation()] for _ in z_labels], [[images.GridAnnotation()]])
z_grid = images.draw_grid_annotations(z_grid, w, h, [[images.GridAnnotation()] for _ in z_labels], [[images.GridAnnotation()]])
processed_result.images.insert(0, z_grid)
#processed_result.all_prompts.insert(0, processed_result.all_prompts[0])
#processed_result.all_seeds.insert(0, processed_result.all_seeds[0])
processed_result.infotexts.insert(0, processed_result.infotexts[0])
processed_result.all_prompts.insert(0, processed_result.all_prompts[0])
processed_result.all_seeds.insert(0, processed_result.all_seeds[0])
processed_result.infotexts.insert(0, processed_result.infotexts[0])
"""
return processed_result