mirror of
https://github.com/vladmandic/automatic
synced 2026-09-18 16:54:33 +02:00
fix xyz grid
This commit is contained in:
+6
-5
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user