fix xyz grid

This commit is contained in:
Vladimir Mandic
2024-09-26 09:24:08 -04:00
parent 0391577443
commit b8055d1527
6 changed files with 69 additions and 78 deletions
+6 -5
View File
@@ -265,11 +265,11 @@ class Script(scripts.Script):
y_opt.apply(pc, y, ys)
z_opt.apply(pc, z, zs)
try:
res = processing.process_images(pc)
processed = processing.process_images(pc)
except Exception as e:
shared.log.error(f"XYZ grid: Failed to process image: {e}")
errors.display(e, 'XYZ grid')
res = None
processed = None
subgrid_index = 1 + iz # Sets subgrid infotexts
if grid_infotext[subgrid_index] is None and ix == 0 and iy == 0:
pc.extra_generation_params = copy(pc.extra_generation_params)
@@ -284,7 +284,7 @@ class Script(scripts.Script):
pc.extra_generation_params["Y Values"] = y_values
if y_opt.label in ["[Param] Seed", "[Param] Variation seed"] and not no_fixed_seeds:
pc.extra_generation_params["Fixed Y Values"] = ", ".join([str(y) for y in ys])
grid_infotext[subgrid_index] = processing.create_infotext(pc, pc.all_prompts, pc.all_seeds, pc.all_subseeds, grid=f'{len(x_values)}x{len(y_values)}')
grid_infotext[subgrid_index] = processing.create_infotext(pc, pc.all_prompts, pc.all_seeds, pc.all_subseeds, grid=f'{len(xs)}x{len(ys)}')
if grid_infotext[0] is None and ix == 0 and iy == 0 and iz == 0: # Sets main grid infotext
pc.extra_generation_params = copy(pc.extra_generation_params)
if z_opt.label != 'Nothing':
@@ -292,8 +292,9 @@ class Script(scripts.Script):
pc.extra_generation_params["Z Values"] = z_values
if z_opt.label in ["[Param] Seed", "[Param] Variation seed"] and not no_fixed_seeds:
pc.extra_generation_params["Fixed Z Values"] = ", ".join([str(z) for z in zs])
grid_infotext[0] = processing.create_infotext(pc, pc.all_prompts, pc.all_seeds, pc.all_subseeds, grid=f'{len(z_values)}x{len(x_values)}x{len(y_values)}')
return res
grid_text = f'{len(zs)}x{len(xs)}x{len(ys)}' if len(zs) > 0 else f'{len(xs)}x{len(ys)}'
grid_infotext[0] = processing.create_infotext(pc, pc.all_prompts, pc.all_seeds, pc.all_subseeds, grid=grid_text)
return processed
with SharedSettingsStackHelper():
processed = draw_xyz_grid(
+13 -16
View File
@@ -85,29 +85,26 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend
t1 = time.time()
grid = None
for i in range(len(zs)):
start_index = (i * len(xs) * len(ys)) + i
end_index = start_index + len(xs) * len(ys)
to_process = processed_result.images[start_index:end_index]
for i in range(len(zs)): # create grid
idx0 = (i * len(xs) * len(ys)) + i # starting index of images in subgrid
idx1 = (len(xs) * len(ys)) + idx0 # ending index of images in subgrid
to_process = processed_result.images[idx0:idx1]
w, h = max(i.width for i in to_process), max(i.height for i in to_process)
if (not no_grid or include_sub_grids) and images.check_grid_size(to_process):
grid = images.image_grid(to_process, rows=len(ys))
if draw_legend:
grid = images.draw_grid_annotations(grid, w, h, hor_texts, ver_texts, margin_size, title=title_texts[i])
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])
t2 = time.time()
shared.log.info(f'XYZ grid complete: images={list_size} size={grid.size if grid is not None else None} time={t1-t0:.2f} save={t2-t1:.2f}')
"""
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, w, h, [[images.GridAnnotation()] for _ in z_labels], [[images.GridAnnotation()]])
processed_result.images.insert(0, z_grid)
processed_result.all_prompts.insert(i, processed_result.all_prompts[idx0])
processed_result.all_seeds.insert(i, processed_result.all_seeds[idx0])
processed_result.infotexts.insert(i, processed_result.infotexts[idx0])
if len(zs) > 1 and not no_grid and images.check_grid_size(processed_result.images[:len(zs)]): # create grid-of-grids
grid = images.image_grid(processed_result.images[:len(zs)], rows=1)
processed_result.images.insert(0, 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])
"""
t2 = time.time()
shared.log.info(f'XYZ grid complete: images={list_size} size={grid.size if grid is not None else None} time={t1-t0:.2f} save={t2-t1:.2f}')
return processed_result
+39 -51
View File
@@ -54,13 +54,13 @@ class Script(scripts.Script):
fill_z_button = ToolButton(value=symbols.fill, elem_id="xyz_grid_fill_z_tool_button", visible=False)
with gr.Row():
with gr.Column():
csv_mode = gr.Checkbox(label='Text inputs', value=False, elem_id=self.elem_id("csv_mode"), container=False)
draw_legend = gr.Checkbox(label='Legend', value=True, elem_id=self.elem_id("draw_legend"), container=False)
no_fixed_seeds = gr.Checkbox(label='Random seeds', value=False, elem_id=self.elem_id("no_fixed_seeds"), container=False)
draw_legend = gr.Checkbox(label='Draw legend', value=True, elem_id=self.elem_id("draw_legend"), container=False)
csv_mode = gr.Checkbox(label='Use text inputs', value=False, elem_id=self.elem_id("csv_mode"), container=False)
no_fixed_seeds = gr.Checkbox(label='Use random seeds', value=False, elem_id=self.elem_id("no_fixed_seeds"), container=False)
with gr.Column():
no_grid = gr.Checkbox(label='Skip grid', value=False, elem_id=self.elem_id("no_xyz_grid"), container=False)
include_lone_images = gr.Checkbox(label='Sub-images', value=False, elem_id=self.elem_id("include_lone_images"), container=False)
include_sub_grids = gr.Checkbox(label='Sub-grids', value=False, elem_id=self.elem_id("include_sub_grids"), container=False)
include_grid = gr.Checkbox(label='Create main grid', value=True, elem_id=self.elem_id("no_xyz_grid"), container=False)
include_subgrids = gr.Checkbox(label='Create partial grids', value=False, elem_id=self.elem_id("include_sub_grids"), container=False)
include_images = gr.Checkbox(label='Include images', value=False, elem_id=self.elem_id("include_lone_images"), container=False)
with gr.Row():
margin_size = gr.Slider(label="Grid margins", minimum=0, maximum=500, value=0, step=2, elem_id=self.elem_id("margin_size"))
with gr.Row():
@@ -139,14 +139,14 @@ class Script(scripts.Script):
(z_values_dropdown, lambda params:get_dropdown_update_from_params("Z",params)),
)
return [enabled, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, csv_mode, draw_legend, no_fixed_seeds, no_grid, include_lone_images, include_sub_grids, margin_size]
return [enabled, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, margin_size]
def process(self, p, enabled, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, csv_mode, draw_legend, no_fixed_seeds, no_grid, include_lone_images, include_sub_grids, margin_size): # pylint: disable=W0221
def process(self, p, enabled, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, margin_size): # pylint: disable=W0221
global active, cache # pylint: disable=W0603
if not enabled or active:
return
cache = None
active = True
shared.log.debug(f'XYZ grid: x_type={x_type}|x_values={x_values}|x_values_dropdown={x_values_dropdown}|y_type={y_type}|{y_values}={y_values}|{y_values_dropdown}={y_values_dropdown}|z_type={z_type}|z_values={z_values}|z_values_dropdown={z_values_dropdown}|draw_legend={draw_legend}|include_lone_images={include_lone_images}|include_sub_grids={include_sub_grids}|no_grid={no_grid}|margin_size={margin_size}')
if not no_fixed_seeds:
processing.fix_seed(p)
if not shared.opts.return_grid:
@@ -267,7 +267,7 @@ class Script(scripts.Script):
second_axes_processed = 'x'
else:
second_axes_processed = 'y'
grid_infotext = [None] * (1 + len(zs))
grid_infotext = []
def cell(x, y, z, ix, iy, iz):
if shared.state.interrupted:
@@ -279,13 +279,12 @@ class Script(scripts.Script):
y_opt.apply(pc, y, ys)
z_opt.apply(pc, z, zs)
try:
res = processing.process_images(pc)
processed = processing.process_images(pc)
except Exception as e:
shared.log.error(f"XYZ grid: Failed to process image: {e}")
errors.display(e, 'XYZ grid')
res = None
subgrid_index = 1 + iz # Sets subgrid infotexts
if grid_infotext[subgrid_index] is None and ix == 0 and iy == 0:
processed = None
if ix == 0 and iy == 0: # create subgrid info text
pc.extra_generation_params = copy(pc.extra_generation_params)
pc.extra_generation_params['Script'] = self.title()
if x_opt.label != 'Nothing':
@@ -298,17 +297,18 @@ class Script(scripts.Script):
pc.extra_generation_params["Y Values"] = y_values
if y_opt.label in ["[Param] Seed", "[Param] Variation seed"] and not no_fixed_seeds:
pc.extra_generation_params["Fixed Y Values"] = ", ".join([str(y) for y in ys])
grid_infotext[subgrid_index] = processing.create_infotext(pc, pc.all_prompts, pc.all_seeds, pc.all_subseeds, grid=f'{len(x_values)}x{len(y_values)}')
if grid_infotext[0] is None and ix == 0 and iy == 0 and iz == 0: # Sets main grid infotext
info = processing.create_infotext(pc, pc.all_prompts, pc.all_seeds, pc.all_subseeds, grid=f'{len(xs)}x{len(ys)}')
grid_infotext.append(info)
if ix == 0 and iy == 0 and iz == 0 and len(zs) > 1: # create main grid info text
pc.extra_generation_params = copy(pc.extra_generation_params)
if z_opt.label != 'Nothing':
pc.extra_generation_params["Z Type"] = z_opt.label
pc.extra_generation_params["Z Values"] = z_values
if z_opt.label in ["[Param] Seed", "[Param] Variation seed"] and not no_fixed_seeds:
pc.extra_generation_params["Fixed Z Values"] = ", ".join([str(z) for z in zs])
grid_text = f'{len(z_values)}x{len(x_values)}x{len(y_values)}' if len(z_values) > 0 else f'{len(x_values)}x{len(y_values)}'
grid_infotext[0] = processing.create_infotext(pc, pc.all_prompts, pc.all_seeds, pc.all_subseeds, grid=grid_text)
return res
info = processing.create_infotext(pc, pc.all_prompts, pc.all_seeds, pc.all_subseeds, grid=f'{len(zs)}x{len(xs)}x{len(ys)}')
grid_infotext.insert(0, info)
return processed
with SharedSettingsStackHelper():
processed = draw_xyz_grid(
@@ -321,51 +321,39 @@ class Script(scripts.Script):
z_labels=[z_opt.format_value(p, z_opt, z) for z in zs],
cell=cell,
draw_legend=draw_legend,
include_lone_images=include_lone_images,
include_sub_grids=include_sub_grids,
include_lone_images=include_images,
include_sub_grids=include_subgrids,
first_axes_processed=first_axes_processed,
second_axes_processed=second_axes_processed,
margin_size=margin_size,
no_grid=no_grid,
no_grid=not include_grid,
)
if not processed.images:
active = False
return processed # It broke, no further handling needed.
z_count = len(zs)
processed.infotexts[:1+z_count] = grid_infotext[:1+z_count] # Set the grid infotexts to the real ones with extra_generation_params (1 main grid + z_count sub-grids)
if not include_lone_images:
# TODO broken logic to delete sub-images
if no_grid and include_sub_grids:
processed.images = processed.images[:z_count] # we don't have the main grid image, and need zero additional sub-images
else:
processed.images = processed.images[:z_count+1] # we either have the main grid image, or need one sub-images
if shared.opts.grid_save: # Auto-save main and sub-grids:
grid_count = z_count + (1 if not no_grid and z_count > 1 else 0)
for g in range(grid_count):
adj_g = g-1 if g > 0 else g
info = processed.infotexts[g]
prompt = processed.all_prompts[adj_g]
seed = processed.all_seeds[adj_g]
_fn, _txt, _exif = images.save_image(processed.images[g], p.outpath_grids, "grid", info=info, extension=shared.opts.grid_format, prompt=prompt, seed=seed, grid=True, p=processed)
# TODO broken logic to delete sub-grids
if not include_sub_grids: # Done with sub-grids, drop all related information:
for _sg in range(z_count):
# images stucture: main-grid, sub-grid1, sub-grid2, ..., image-1, image-2, ...
z_count = len(processed.images) - (len(zs) * len(ys) * len(xs)) # how many grids are there: main grid + sub-grids
processed.infotexts[:z_count] = grid_infotext[:z_count] # replace grid info texts
if not include_images:
processed.images = processed.images[:z_count]
if shared.opts.grid_save: # auto-save main and sub-grids:
for i in range(z_count):
info = processed.infotexts[i]
prompt = processed.all_prompts[i]
seed = processed.all_seeds[i]
_fn, _txt, _exif = images.save_image(processed.images[i], p.outpath_grids, "grid", info=info, extension=shared.opts.grid_format, prompt=prompt, seed=seed, grid=True, p=processed)
if not include_subgrids and z_count > 1: # delete sub-grids
for _sg in range(z_count - 1):
del processed.images[1]
del processed.all_prompts[1]
del processed.all_seeds[1]
del processed.infotexts[1]
elif no_grid:
del processed.infotexts[0]
p.do_not_save_grid = True
p.do_not_save_samples = True
active = False
cache = processed
# TODO main processing loop auto-creates grid out of all returned images so we end up with grid of grids + images which we don't need, need to skip that
return processed
def process_images(self, p, enabled, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, csv_mode, draw_legend, no_fixed_seeds, no_grid, include_lone_images, include_sub_grids, margin_size): # pylint: disable=W0221, W0613
global cache # pylint: disable=W0603
if cache is not None and hasattr(cache, 'images'):
samples = cache.images.copy()
cache = None
return samples
return None
def process_images(self, p, enabled, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, margin_size): # pylint: disable=W0221, W0613
return cache