diff --git a/modules/img2img.py b/modules/img2img.py index a53e9cc66..50fc4524d 100644 --- a/modules/img2img.py +++ b/modules/img2img.py @@ -77,7 +77,7 @@ def process_batch(p, input_files, input_dir, output_dir, inpaint_mask_dir, args) shared.log.debug(f'Processed: {len(image_files)} Memory: {memory_stats()} batch') -def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_index: int, latent_index: int, mask_blur: int, mask_alpha: float, inpainting_fill: int, full_quality: bool, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, diffusers_guidance_rescale: float, refiner_start: float, clip_skip: int, denoising_strength: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, selected_scale_tab: int, height: int, width: int, scale_by: float, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_files: list, img2img_batch_input_dir: str, img2img_batch_output_dir: str, img2img_batch_inpaint_mask_dir: str, override_settings_texts, *args): # pylint: disable=unused-argument +def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_index: int, latent_index: int, mask_blur: int, mask_alpha: float, inpainting_fill: int, full_quality: bool, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, diffusers_guidance_rescale: float, refiner_steps: int, refiner_start: float, clip_skip: int, denoising_strength: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, selected_scale_tab: int, height: int, width: int, scale_by: float, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_files: list, img2img_batch_input_dir: str, img2img_batch_output_dir: str, img2img_batch_inpaint_mask_dir: str, override_settings_texts, *args): # pylint: disable=unused-argument if shared.sd_model is None: shared.log.warning('Model not loaded') @@ -171,6 +171,7 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s denoising_strength=denoising_strength, image_cfg_scale=image_cfg_scale, diffusers_guidance_rescale=diffusers_guidance_rescale, + refiner_steps=refiner_steps, refiner_start=refiner_start, inpaint_full_res=inpaint_full_res, inpaint_full_res_padding=inpaint_full_res_padding, diff --git a/modules/processing.py b/modules/processing.py index 6436f48c3..6642e50ca 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -151,6 +151,7 @@ class StableDiffusionProcessing: self.iteration = 0 self.is_hr_pass = False self.enable_hr = None + self.refiner_steps = 4 self.refiner_start = 0 self.ops = [] shared.opts.data['clip_skip'] = clip_skip @@ -851,7 +852,7 @@ def old_hires_fix_first_pass_dimensions(width, height): class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): sampler = None - def __init__(self, enable_hr: bool = False, denoising_strength: float = 0.75, firstphase_width: int = 0, firstphase_height: int = 0, hr_scale: float = 2.0, hr_upscaler: str = None, hr_second_pass_steps: int = 0, hr_resize_x: int = 0, hr_resize_y: int = 0, refiner_start: float = 0, refiner_prompt: str = '', refiner_negative: str = '', **kwargs): + def __init__(self, enable_hr: bool = False, denoising_strength: float = 0.75, firstphase_width: int = 0, firstphase_height: int = 0, hr_scale: float = 2.0, hr_upscaler: str = None, hr_second_pass_steps: int = 0, hr_resize_x: int = 0, hr_resize_y: int = 0, refiner_steps: int = 4, refiner_start: float = 0, refiner_prompt: str = '', refiner_negative: str = '', **kwargs): super().__init__(**kwargs) self.enable_hr = enable_hr @@ -871,6 +872,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): self.truncate_x = 0 self.truncate_y = 0 self.applied_old_hires_behavior_to = None + self.refiner_steps = refiner_steps self.refiner_start = refiner_start self.refiner_prompt = refiner_prompt self.refiner_negative = refiner_negative @@ -1018,7 +1020,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): sampler = None - def __init__(self, init_images: list = None, resize_mode: int = 0, denoising_strength: float = 0.3, image_cfg_scale: float = None, mask: Any = None, mask_blur: int = 4, inpainting_fill: int = 0, inpaint_full_res: bool = True, inpaint_full_res_padding: int = 0, inpainting_mask_invert: int = 0, initial_noise_multiplier: float = None, refiner_start: float = 0, refiner_prompt: str = '', refiner_negative: str = '', **kwargs): + def __init__(self, init_images: list = None, resize_mode: int = 0, denoising_strength: float = 0.3, image_cfg_scale: float = None, mask: Any = None, mask_blur: int = 4, inpainting_fill: int = 0, inpaint_full_res: bool = True, inpaint_full_res_padding: int = 0, inpainting_mask_invert: int = 0, initial_noise_multiplier: float = None, refiner_steps: int = 4, refiner_start: float = 0, refiner_prompt: str = '', refiner_negative: str = '', **kwargs): super().__init__(**kwargs) self.init_images = init_images self.resize_mode: int = resize_mode @@ -1037,6 +1039,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): self.mask = None self.nmask = None self.image_conditioning = None + self.refiner_steps = refiner_steps self.refiner_start = refiner_start self.refiner_prompt = refiner_prompt self.refiner_negative = refiner_negative diff --git a/modules/processing_diffusers.py b/modules/processing_diffusers.py index 36696a2e1..1cae7c970 100644 --- a/modules/processing_diffusers.py +++ b/modules/processing_diffusers.py @@ -261,15 +261,19 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro if shared.opts.diffusers_move_base and not shared.sd_model.has_accelerate: shared.sd_model.to(devices.device) + use_denoise_start = (is_refiner_enabled and not p.is_hr_pass and p.refiner_start > 0 and p.refiner_start < 1) + base_args = set_pipeline_args( model=shared.sd_model, prompts=prompts, negative_prompts=negative_prompts, prompts_2=[p.refiner_prompt] if len(p.refiner_prompt) > 0 else prompts, negative_prompts_2=[p.refiner_negative] if len(p.refiner_negative) > 0 else negative_prompts, - num_inference_steps=p.steps, + num_inference_steps=int(p.steps // (p.refiner_start if use_denoise_start else 1) + (1 if use_denoise_start else 0)), eta=shared.opts.eta_ddim, guidance_rescale=p.diffusers_guidance_rescale, + denoising_start=0 if use_denoise_start else None, + denoising_end=p.refiner_start if use_denoise_start else None, output_type='latent' if hasattr(shared.sd_model, 'vae') else 'np', is_refiner=False, clip_skip=p.clip_skip, @@ -303,7 +307,7 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro negative_prompts=negative_prompts, prompts_2=[p.refiner_prompt] if len(p.refiner_prompt) > 0 else prompts, negative_prompts_2=[p.refiner_negative] if len(p.refiner_negative) > 0 else negative_prompts, - num_inference_steps=int((p.hr_second_pass_steps // p.denoising_strength) + 1), + num_inference_steps=int(p.hr_second_pass_steps // p.denoising_strength + 1), eta=shared.opts.eta_ddim, guidance_rescale=p.diffusers_guidance_rescale, output_type='latent' if hasattr(shared.sd_model, 'vae') else 'np', @@ -341,7 +345,7 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro model=shared.sd_refiner, prompts=[p.refiner_prompt] if len(p.refiner_prompt) > 0 else prompts[i], negative_prompts=[p.refiner_negative] if len(p.refiner_negative) > 0 else negative_prompts[i], - num_inference_steps=p.hr_second_pass_steps, + num_inference_steps=int(p.refiner_steps // (1 - p.refiner_start)) if p.refiner_start > 0 and p.refiner_start < 1 else int(p.refiner_steps // p.denoising_strength + 1), eta=shared.opts.eta_ddim, strength=p.denoising_strength, guidance_scale=p.image_cfg_scale if p.image_cfg_scale is not None else p.cfg_scale, @@ -356,6 +360,7 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro ) refiner_output = shared.sd_refiner(**refiner_args) # pylint: disable=not-callable p.extra_generation_params['Image CFG scale'] = p.image_cfg_scale if p.image_cfg_scale is not None else None + p.extra_generation_params['Refiner steps'] = p.refiner_steps p.extra_generation_params['Refiner start'] = p.refiner_start p.extra_generation_params["Hires steps"] = p.hr_second_pass_steps diff --git a/modules/txt2img.py b/modules/txt2img.py index 663fe097f..db246d834 100644 --- a/modules/txt2img.py +++ b/modules/txt2img.py @@ -5,9 +5,9 @@ from modules.ui import plaintext_to_html from modules.memstats import memory_stats -def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_styles, steps: int, sampler_index: int, latent_index: int, full_quality: bool, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, diffusers_guidance_rescale: float, clip_skip: int, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, height: int, width: int, enable_hr: bool, denoising_strength: float, hr_scale: float, hr_upscaler: str, hr_second_pass_steps: int, hr_resize_x: int, hr_resize_y: int, refiner_start: int, refiner_prompt: str, refiner_negative: str, override_settings_texts, *args): # pylint: disable=unused-argument +def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_styles, steps: int, sampler_index: int, latent_index: int, full_quality: bool, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, diffusers_guidance_rescale: float, clip_skip: int, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, height: int, width: int, enable_hr: bool, denoising_strength: float, hr_scale: float, hr_upscaler: str, hr_second_pass_steps: int, hr_resize_x: int, hr_resize_y: int, refiner_steps: int, refiner_start: int, refiner_prompt: str, refiner_negative: str, override_settings_texts, *args): # pylint: disable=unused-argument - shared.log.debug(f'txt2img: id_task={id_task}|prompt={prompt}|negative_prompt={negative_prompt}|prompt_styles={prompt_styles}|steps={steps}|sampler_index={sampler_index}|latent_index={latent_index}|full_quality={full_quality}|restore_faces={restore_faces}|tiling={tiling}|n_iter={n_iter}|batch_size={batch_size}|cfg_scale={cfg_scale}|clip_skip={clip_skip}|seed={seed}|subseed={subseed}|subseed_strength={subseed_strength}|seed_resize_from_h={seed_resize_from_h}|seed_resize_from_w={seed_resize_from_w}||height={height}|width={width}|enable_hr={enable_hr}|denoising_strength={denoising_strength}|hr_scale={hr_scale}|hr_upscaler={hr_upscaler}|hr_second_pass_steps={hr_second_pass_steps}|hr_resize_x={hr_resize_x}|hr_resize_y={hr_resize_y}|image_cfg_scale={image_cfg_scale}|diffusers_guidance_rescale={diffusers_guidance_rescale}|refiner_start={refiner_start}||refiner_prompt={refiner_prompt}|refiner_negative={refiner_negative}|override_settings_texts={override_settings_texts}|args={args}') + shared.log.debug(f'txt2img: id_task={id_task}|prompt={prompt}|negative_prompt={negative_prompt}|prompt_styles={prompt_styles}|steps={steps}|sampler_index={sampler_index}|latent_index={latent_index}|full_quality={full_quality}|restore_faces={restore_faces}|tiling={tiling}|n_iter={n_iter}|batch_size={batch_size}|cfg_scale={cfg_scale}|clip_skip={clip_skip}|seed={seed}|subseed={subseed}|subseed_strength={subseed_strength}|seed_resize_from_h={seed_resize_from_h}|seed_resize_from_w={seed_resize_from_w}||height={height}|width={width}|enable_hr={enable_hr}|denoising_strength={denoising_strength}|hr_scale={hr_scale}|hr_upscaler={hr_upscaler}|hr_second_pass_steps={hr_second_pass_steps}|hr_resize_x={hr_resize_x}|hr_resize_y={hr_resize_y}|image_cfg_scale={image_cfg_scale}|diffusers_guidance_rescale={diffusers_guidance_rescale}|refiner_steps={refiner_steps}|refiner_start={refiner_start}||refiner_prompt={refiner_prompt}|refiner_negative={refiner_negative}|override_settings_texts={override_settings_texts}|args={args}') if shared.sd_model is None: shared.log.warning('Model not loaded') @@ -53,6 +53,7 @@ def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_styles, step hr_second_pass_steps=hr_second_pass_steps, hr_resize_x=hr_resize_x, hr_resize_y=hr_resize_y, + refiner_steps=refiner_steps, refiner_start=refiner_start, refiner_prompt=refiner_prompt, refiner_negative=refiner_negative, diff --git a/modules/ui.py b/modules/ui.py index 8a29e3487..730765aaf 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -395,7 +395,7 @@ def create_ui(startup_timer = None): hr_second_pass_steps, latent_index = create_sampler_and_steps_selection(modules.sd_samplers.samplers, "txt2img", False) with FormRow(elem_id="txt2img_hires_fix_row1", variant="compact"): denoising_strength = gr.Slider(minimum=0.05, maximum=1.0, step=0.01, label='Denoising strength', value=0.3, elem_id="txt2img_denoising_strength") - refiner_start = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, label='Denoise start', value=0.8, elem_id="txt2img_refiner_start") + refiner_steps = gr.Slider(minimum=0, maximum=99, step=1, label="Refiner steps", elem_id="txt2img_refiner_steps", value=4) with FormRow(elem_id="txt2img_hires_finalres", variant="compact"): hr_final_resolution = FormHTML(value="", elem_id="txtimg_hr_finalres", label="Upscaled resolution", interactive=False) with FormRow(elem_id="txt2img_hires_fix_row2", variant="compact"): @@ -410,6 +410,7 @@ def create_ui(startup_timer = None): with FormRow(elem_id="txt2img_refiner_row1", variant="compact"): image_cfg_scale = gr.Slider(minimum=1.1, maximum=30.0, step=0.1, label='Secondary CFG Scale', value=6.0, elem_id="txt2img_image_cfg_scale") diffusers_guidance_rescale = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, label='Guidance rescale', value=0.7, elem_id="txt2img_image_cfg_rescale") + refiner_start = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, label='Refiner start', value=0.8, elem_id="txt2img_refiner_start") with FormRow(elem_id="txt2img_refiner_row2", variant="compact"): refiner_prompt = gr.Textbox(value='', label='Secondary Prompt') with FormRow(elem_id="txt2img_refiner_row3", variant="compact"): @@ -453,7 +454,7 @@ def create_ui(startup_timer = None): height, width, show_second_pass, denoising_strength, hr_scale, hr_upscaler, hr_second_pass_steps, hr_resize_x, hr_resize_y, - refiner_start, refiner_prompt, refiner_negative, + refiner_steps, refiner_start, refiner_prompt, refiner_negative, override_settings, ] + custom_inputs, outputs=[ @@ -492,6 +493,7 @@ def create_ui(startup_timer = None): (clip_skip, "Clip skip"), (latent_index, "Latent sampler"), (denoising_strength, "Denoising strength"), + (refiner_steps, "Refiner steps"), (refiner_start, "Refiner start"), (full_quality, "Full quality"), (restore_faces, "Face restoration"), @@ -507,6 +509,7 @@ def create_ui(startup_timer = None): (hr_resize_y, "Hires resize-2"), (diffusers_guidance_rescale, "CFG rescale"), (image_cfg_scale, "Refiner CFG scale"), + (refiner_steps, "Refiner steps"), (refiner_start, "Refiner start"), (tiling, "Tiling"), (refiner_negative, "Negative2"), @@ -754,6 +757,7 @@ def create_ui(startup_timer = None): batch_count, batch_size, cfg_scale, image_cfg_scale, diffusers_guidance_rescale, + refiner_steps, refiner_start, clip_skip, denoising_strength, @@ -848,6 +852,7 @@ def create_ui(startup_timer = None): (clip_skip, "Clip skip"), (latent_index, "Latent sampler"), (denoising_strength, "Denoising strength"), + (refiner_steps, "Refiner steps"), (refiner_start, "Refiner start"), (full_quality, "Full quality"), (restore_faces, "Face restoration"), @@ -863,6 +868,7 @@ def create_ui(startup_timer = None): (hr_resize_y, "Hires resize-2"), (diffusers_guidance_rescale, "CFG rescale"), (image_cfg_scale, "Image CFG scale"), + (refiner_steps, "Refiner steps"), (refiner_start, "Refiner start"), (tiling, "Tiling"), (refiner_negative, "Negative2"),