From 1b3f5405a3429af31fd0a96276e4ef56df8825aa Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Thu, 31 Jul 2025 09:56:36 -0400 Subject: [PATCH] fix batch processing Signed-off-by: Vladimir Mandic --- cli/docs.py | 2 +- modules/processing.py | 71 +++++++++++++++--------------- modules/prompt_parser_diffusers.py | 2 +- modules/shared.py | 4 +- 4 files changed, 39 insertions(+), 40 deletions(-) diff --git a/cli/docs.py b/cli/docs.py index 1295c3d8b..11200d206 100755 --- a/cli/docs.py +++ b/cli/docs.py @@ -78,7 +78,7 @@ class Page(): return 0.50 return 0.0 - + def get(self): try: with open(self.fn, 'r', encoding='utf-8') as f: diff --git a/modules/processing.py b/modules/processing.py index c574c814e..c61ad8f12 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -372,43 +372,42 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: else: image.info["parameters"] = info output_images.append(image) - - for i, image in enumerate(output_images): - is_grid = len(output_images) == p.batch_size * p.n_iter + 1 and i == 0 - # resize after - if p.selected_scale_tab_after == 1: - p.width_after, p.height_after = int(image.width * p.scale_by_after), int(image.height * p.scale_by_after) - if p.resize_mode_after != 0 and p.resize_name_after != 'None' and not is_grid: - image = images.resize_image(p.resize_mode_after, image, p.width_after, p.height_after, p.resize_name_after, context=p.resize_context_after) - - # save images - if shared.opts.samples_save and not p.do_not_save_samples and p.outpath_samples is not None: - info = create_infotext(p, p.prompts, p.seeds, p.subseeds, index=i) - if isinstance(image, list): - for img in image: - images.save_image(img, p.outpath_samples, "", p.seeds[i], p.prompts[i], shared.opts.samples_format, info=info, p=p) # main save image - else: - images.save_image(image, p.outpath_samples, "", p.seeds[i], p.prompts[i], shared.opts.samples_format, info=info, p=p) # main save image - - if hasattr(p, 'mask_for_overlay') and p.mask_for_overlay and any([shared.opts.save_mask, shared.opts.save_mask_composite, shared.opts.return_mask, shared.opts.return_mask_composite]): - image_mask = p.mask_for_overlay.convert('RGB') - image1 = image.convert('RGBA').convert('RGBa') - image2 = Image.new('RGBa', image.size) - mask = images.resize_image(3, p.mask_for_overlay, image.width, image.height).convert('L') - image_mask_composite = Image.composite(image1, image2, mask).convert('RGBA') - if shared.opts.save_mask: - images.save_image(image_mask, p.outpath_samples, "", p.seeds[i], p.prompts[i], shared.opts.samples_format, info=info, p=p, suffix="-mask") - if shared.opts.save_mask_composite: - images.save_image(image_mask_composite, p.outpath_samples, "", p.seeds[i], p.prompts[i], shared.opts.samples_format, info=info, p=p, suffix="-mask-composite") - if shared.opts.return_mask: - output_images.append(image_mask) - if shared.opts.return_mask_composite: - output_images.append(image_mask_composite) - - timer.process.record('post') + devices.torch_gc() del samples - devices.torch_gc() + for i, image in enumerate(output_images): + is_grid = len(output_images) == p.batch_size * p.n_iter + 1 and i == 0 + # resize after + if p.selected_scale_tab_after == 1: + p.width_after, p.height_after = int(image.width * p.scale_by_after), int(image.height * p.scale_by_after) + if p.resize_mode_after != 0 and p.resize_name_after != 'None' and not is_grid: + image = images.resize_image(p.resize_mode_after, image, p.width_after, p.height_after, p.resize_name_after, context=p.resize_context_after) + + # save images + if shared.opts.samples_save and not p.do_not_save_samples and p.outpath_samples is not None: + info = create_infotext(p, p.prompts, p.seeds, p.subseeds, index=i) + if isinstance(image, list): + for img in image: + images.save_image(img, p.outpath_samples, "", p.seeds[i], p.prompts[i], shared.opts.samples_format, info=info, p=p) # main save image + else: + images.save_image(image, p.outpath_samples, "", p.seeds[i], p.prompts[i], shared.opts.samples_format, info=info, p=p) # main save image + + if hasattr(p, 'mask_for_overlay') and p.mask_for_overlay and any([shared.opts.save_mask, shared.opts.save_mask_composite, shared.opts.return_mask, shared.opts.return_mask_composite]): + image_mask = p.mask_for_overlay.convert('RGB') + image1 = image.convert('RGBA').convert('RGBa') + image2 = Image.new('RGBa', image.size) + mask = images.resize_image(3, p.mask_for_overlay, image.width, image.height).convert('L') + image_mask_composite = Image.composite(image1, image2, mask).convert('RGBA') + if shared.opts.save_mask: + images.save_image(image_mask, p.outpath_samples, "", p.seeds[i], p.prompts[i], shared.opts.samples_format, info=info, p=p, suffix="-mask") + if shared.opts.save_mask_composite: + images.save_image(image_mask_composite, p.outpath_samples, "", p.seeds[i], p.prompts[i], shared.opts.samples_format, info=info, p=p, suffix="-mask-composite") + if shared.opts.return_mask: + output_images.append(image_mask) + if shared.opts.return_mask_composite: + output_images.append(image_mask_composite) + + timer.process.record('post') if not p.xyz: if hasattr(shared.sd_model, 'restore_pipeline') and (shared.sd_model.restore_pipeline is not None): @@ -462,5 +461,5 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: shared.log.debug(f'Processed: timers={timer.process.dct()}') shared.log.debug(f'Processed: memory={memstats.memory_stats()}') - devices.torch_gc(force=True, reason='final') + # devices.torch_gc(force=True, reason='final') return processed diff --git a/modules/prompt_parser_diffusers.py b/modules/prompt_parser_diffusers.py index a4f2fd4b6..3f50c40d5 100644 --- a/modules/prompt_parser_diffusers.py +++ b/modules/prompt_parser_diffusers.py @@ -437,7 +437,7 @@ def get_prompts_with_weights(pipe, prompt: str): sections += 1 if all_tokens > 0: avg_weight = avg_weight / all_tokens - shared.log.debug(f'Prompt tokenizer: parser={shared.opts.prompt_attention} len={len(prompt)} sections={sections} tokens={all_tokens} weights={min_weight:.2f}/{avg_weight:.2f}/{max_weight:.2f}') + debug(f'Prompt tokenizer: parser={shared.opts.prompt_attention} len={len(prompt)} sections={sections} tokens={all_tokens} weights={min_weight:.2f}/{avg_weight:.2f}/{max_weight:.2f}') except Exception: pass debug(f'Prompt: weights={texts_and_weights} time={(time.time() - t0):.3f}') diff --git a/modules/shared.py b/modules/shared.py index f41952cba..9b1003956 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -723,13 +723,13 @@ options_templates.update(options_section(('extra_networks', "Networks"), { "extra_networks_lora_sep": OptionInfo("

LoRA

", "", gr.HTML), "extra_networks_default_multiplier": OptionInfo(1.0, "Default strength", gr.Slider, {"minimum": 0.0, "maximum": 2.0, "step": 0.01}), - "lora_add_hashes_to_infotext": OptionInfo(False, "LoRA add hash info to metadata"), "lora_fuse_diffusers": OptionInfo(True, "LoRA fuse directly to model"), "lora_force_reload": OptionInfo(False, "LoRA force reload always"), "lora_force_diffusers": OptionInfo(False if not cmd_opts.use_openvino else True, "LoRA load using Diffusers method"), - "lora_maybe_diffusers": OptionInfo(False, "LoRA load using Diffusers method for selected models"), + "lora_maybe_diffusers": OptionInfo(False, "LoRA load using Diffusers method for selected models", gr.Checkbox, {"visible": False}), "lora_apply_tags": OptionInfo(0, "LoRA auto-apply tags", gr.Slider, {"minimum": -1, "maximum": 32, "step": 1}), "lora_in_memory_limit": OptionInfo(1, "LoRA memory cache", gr.Slider, {"minimum": 0, "maximum": 32, "step": 1}), + "lora_add_hashes_to_infotext": OptionInfo(False, "LoRA add hash info to metadata"), "lora_quant": OptionInfo("NF4","LoRA precision when quantized", gr.Radio, {"choices": ["NF4", "FP4"]}), "extra_networks_styles_sep": OptionInfo("

Styles

", "", gr.HTML),