rework refiner
rework refiner
This commit is contained in:
		
							parent
							
								
									5e6b27a680
								
							
						
					
					
						commit
						132afcc2a2
					
				
							
								
								
									
										94
									
								
								fooocus_extras/vae_interpose.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								fooocus_extras/vae_interpose.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					# https://github.com/city96/SD-Latent-Interposer/blob/main/interposer.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import torch
 | 
				
			||||||
 | 
					import safetensors.torch as sf
 | 
				
			||||||
 | 
					import torch.nn as nn
 | 
				
			||||||
 | 
					import comfy.model_management
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from comfy.model_patcher import ModelPatcher
 | 
				
			||||||
 | 
					from modules.path import vae_approx_path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Block(nn.Module):
 | 
				
			||||||
 | 
					    def __init__(self, size):
 | 
				
			||||||
 | 
					        super().__init__()
 | 
				
			||||||
 | 
					        self.join = nn.ReLU()
 | 
				
			||||||
 | 
					        self.long = nn.Sequential(
 | 
				
			||||||
 | 
					            nn.Conv2d(size, size, kernel_size=3, stride=1, padding=1),
 | 
				
			||||||
 | 
					            nn.LeakyReLU(0.1),
 | 
				
			||||||
 | 
					            nn.Conv2d(size, size, kernel_size=3, stride=1, padding=1),
 | 
				
			||||||
 | 
					            nn.LeakyReLU(0.1),
 | 
				
			||||||
 | 
					            nn.Conv2d(size, size, kernel_size=3, stride=1, padding=1),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def forward(self, x):
 | 
				
			||||||
 | 
					        y = self.long(x)
 | 
				
			||||||
 | 
					        z = self.join(y + x)
 | 
				
			||||||
 | 
					        return z
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Interposer(nn.Module):
 | 
				
			||||||
 | 
					    def __init__(self):
 | 
				
			||||||
 | 
					        super().__init__()
 | 
				
			||||||
 | 
					        self.chan = 4
 | 
				
			||||||
 | 
					        self.hid = 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.head_join = nn.ReLU()
 | 
				
			||||||
 | 
					        self.head_short = nn.Conv2d(self.chan, self.hid, kernel_size=3, stride=1, padding=1)
 | 
				
			||||||
 | 
					        self.head_long = nn.Sequential(
 | 
				
			||||||
 | 
					            nn.Conv2d(self.chan, self.hid, kernel_size=3, stride=1, padding=1),
 | 
				
			||||||
 | 
					            nn.LeakyReLU(0.1),
 | 
				
			||||||
 | 
					            nn.Conv2d(self.hid, self.hid, kernel_size=3, stride=1, padding=1),
 | 
				
			||||||
 | 
					            nn.LeakyReLU(0.1),
 | 
				
			||||||
 | 
					            nn.Conv2d(self.hid, self.hid, kernel_size=3, stride=1, padding=1),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        self.core = nn.Sequential(
 | 
				
			||||||
 | 
					            Block(self.hid),
 | 
				
			||||||
 | 
					            Block(self.hid),
 | 
				
			||||||
 | 
					            Block(self.hid),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        self.tail = nn.Sequential(
 | 
				
			||||||
 | 
					            nn.ReLU(),
 | 
				
			||||||
 | 
					            nn.Conv2d(self.hid, self.chan, kernel_size=3, stride=1, padding=1)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def forward(self, x):
 | 
				
			||||||
 | 
					        y = self.head_join(
 | 
				
			||||||
 | 
					            self.head_long(x) +
 | 
				
			||||||
 | 
					            self.head_short(x)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        z = self.core(y)
 | 
				
			||||||
 | 
					        return self.tail(z)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vae_approx_model = None
 | 
				
			||||||
 | 
					vae_approx_filename = os.path.join(vae_approx_path, 'xl-to-v1_interposer-v3.1.safetensors')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def parse(x):
 | 
				
			||||||
 | 
					    global vae_approx_model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    x_origin = x['samples'].clone()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if vae_approx_model is None:
 | 
				
			||||||
 | 
					        model = Interposer()
 | 
				
			||||||
 | 
					        model.eval()
 | 
				
			||||||
 | 
					        sd = sf.load_file(vae_approx_filename)
 | 
				
			||||||
 | 
					        model.load_state_dict(sd)
 | 
				
			||||||
 | 
					        fp16 = comfy.model_management.should_use_fp16()
 | 
				
			||||||
 | 
					        if fp16:
 | 
				
			||||||
 | 
					            model = model.half()
 | 
				
			||||||
 | 
					        vae_approx_model = ModelPatcher(
 | 
				
			||||||
 | 
					            model=model,
 | 
				
			||||||
 | 
					            load_device=comfy.model_management.get_torch_device(),
 | 
				
			||||||
 | 
					            offload_device=torch.device('cpu')
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        vae_approx_model.dtype = torch.float16 if fp16 else torch.float32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    comfy.model_management.load_model_gpu(vae_approx_model)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    x = x_origin.to(device=vae_approx_model.load_device, dtype=vae_approx_model.dtype)
 | 
				
			||||||
 | 
					    x = vae_approx_model.model(x)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {'samples': x.to(x_origin)}
 | 
				
			||||||
@ -1 +1 @@
 | 
				
			|||||||
version = '2.1.49'
 | 
					version = '2.1.50'
 | 
				
			||||||
 | 
				
			|||||||
@ -59,8 +59,10 @@ lora_filenames = [
 | 
				
			|||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
vae_approx_filenames = [
 | 
					vae_approx_filenames = [
 | 
				
			||||||
    ('xlvaeapp.pth',
 | 
					    ('xlvaeapp.pth', 'https://huggingface.co/lllyasviel/misc/resolve/main/xlvaeapp.pth'),
 | 
				
			||||||
     'https://huggingface.co/lllyasviel/misc/resolve/main/xlvaeapp.pth')
 | 
					    ('vaeapp_sd15.pth', 'https://huggingface.co/lllyasviel/misc/resolve/main/vaeapp_sd15.pt'),
 | 
				
			||||||
 | 
					    ('xl-to-v1_interposer-v3.1.safetensors',
 | 
				
			||||||
 | 
					     'https://huggingface.co/lllyasviel/misc/resolve/main/xl-to-v1_interposer-v3.1.safetensors')
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -113,6 +113,7 @@ def worker():
 | 
				
			|||||||
        inpaint_worker.current_task = None
 | 
					        inpaint_worker.current_task = None
 | 
				
			||||||
        width, height = aspect_ratios[aspect_ratios_selection]
 | 
					        width, height = aspect_ratios[aspect_ratios_selection]
 | 
				
			||||||
        skip_prompt_processing = False
 | 
					        skip_prompt_processing = False
 | 
				
			||||||
 | 
					        refiner_swap_method = advanced_parameters.refiner_swap_method
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        raw_prompt = prompt
 | 
					        raw_prompt = prompt
 | 
				
			||||||
        raw_negative_prompt = negative_prompt
 | 
					        raw_negative_prompt = negative_prompt
 | 
				
			||||||
@ -352,11 +353,14 @@ def worker():
 | 
				
			|||||||
            initial_pixels = core.numpy_to_pytorch(uov_input_image)
 | 
					            initial_pixels = core.numpy_to_pytorch(uov_input_image)
 | 
				
			||||||
            progressbar(13, 'VAE encoding ...')
 | 
					            progressbar(13, 'VAE encoding ...')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            initial_latent = core.encode_vae(vae=pipeline.final_vae, pixels=initial_pixels, tiled=True)
 | 
					            initial_latent = core.encode_vae(
 | 
				
			||||||
 | 
					                vae=pipeline.final_vae if pipeline.final_refiner_vae is None else pipeline.final_refiner_vae,
 | 
				
			||||||
 | 
					                pixels=initial_pixels, tiled=True)
 | 
				
			||||||
            B, C, H, W = initial_latent['samples'].shape
 | 
					            B, C, H, W = initial_latent['samples'].shape
 | 
				
			||||||
            width = W * 8
 | 
					            width = W * 8
 | 
				
			||||||
            height = H * 8
 | 
					            height = H * 8
 | 
				
			||||||
            print(f'Final resolution is {str((height, width))}.')
 | 
					            print(f'Final resolution is {str((height, width))}.')
 | 
				
			||||||
 | 
					            refiner_swap_method = 'upscale'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if 'inpaint' in goals:
 | 
					        if 'inpaint' in goals:
 | 
				
			||||||
            if len(outpaint_selections) > 0:
 | 
					            if len(outpaint_selections) > 0:
 | 
				
			||||||
@ -386,6 +390,8 @@ def worker():
 | 
				
			|||||||
            inpaint_worker.current_task = inpaint_worker.InpaintWorker(image=inpaint_image, mask=inpaint_mask,
 | 
					            inpaint_worker.current_task = inpaint_worker.InpaintWorker(image=inpaint_image, mask=inpaint_mask,
 | 
				
			||||||
                                                                       is_outpaint=len(outpaint_selections) > 0)
 | 
					                                                                       is_outpaint=len(outpaint_selections) > 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            pipeline.final_unet.model.diffusion_model.in_inpaint = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # print(f'Inpaint task: {str((height, width))}')
 | 
					            # print(f'Inpaint task: {str((height, width))}')
 | 
				
			||||||
            # outputs.append(['results', inpaint_worker.current_task.visualize_mask_processing()])
 | 
					            # outputs.append(['results', inpaint_worker.current_task.visualize_mask_processing()])
 | 
				
			||||||
            # return
 | 
					            # return
 | 
				
			||||||
@ -398,7 +404,14 @@ def worker():
 | 
				
			|||||||
            inpaint_mask = core.numpy_to_pytorch(inpaint_worker.current_task.mask_ready[None])
 | 
					            inpaint_mask = core.numpy_to_pytorch(inpaint_worker.current_task.mask_ready[None])
 | 
				
			||||||
            inpaint_mask = torch.nn.functional.avg_pool2d(inpaint_mask, (8, 8))
 | 
					            inpaint_mask = torch.nn.functional.avg_pool2d(inpaint_mask, (8, 8))
 | 
				
			||||||
            inpaint_mask = torch.nn.functional.interpolate(inpaint_mask, (H, W), mode='bilinear')
 | 
					            inpaint_mask = torch.nn.functional.interpolate(inpaint_mask, (H, W), mode='bilinear')
 | 
				
			||||||
            inpaint_worker.current_task.load_latent(latent=inpaint_latent, mask=inpaint_mask)
 | 
					
 | 
				
			||||||
 | 
					            latent_after_swap = None
 | 
				
			||||||
 | 
					            if pipeline.final_refiner_vae is not None:
 | 
				
			||||||
 | 
					                progressbar(13, 'VAE SD15 encoding ...')
 | 
				
			||||||
 | 
					                latent_after_swap = core.encode_vae(vae=pipeline.final_refiner_vae, pixels=inpaint_pixels)['samples']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            inpaint_worker.current_task.load_latent(latent=inpaint_latent, mask=inpaint_mask,
 | 
				
			||||||
 | 
					                                                    latent_after_swap=latent_after_swap)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            progressbar(13, 'VAE inpaint encoding ...')
 | 
					            progressbar(13, 'VAE inpaint encoding ...')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -514,7 +527,7 @@ def worker():
 | 
				
			|||||||
                    denoise=denoising_strength,
 | 
					                    denoise=denoising_strength,
 | 
				
			||||||
                    tiled=tiled,
 | 
					                    tiled=tiled,
 | 
				
			||||||
                    cfg_scale=cfg_scale,
 | 
					                    cfg_scale=cfg_scale,
 | 
				
			||||||
                    refiner_swap_method=advanced_parameters.refiner_swap_method
 | 
					                    refiner_swap_method=refiner_swap_method
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                del task['c'], task['uc'], positive_cond, negative_cond  # Save memory
 | 
					                del task['c'], task['uc'], positive_cond, negative_cond  # Save memory
 | 
				
			||||||
 | 
				
			|||||||
@ -15,6 +15,7 @@ import comfy.utils
 | 
				
			|||||||
import comfy.controlnet
 | 
					import comfy.controlnet
 | 
				
			||||||
import modules.sample_hijack
 | 
					import modules.sample_hijack
 | 
				
			||||||
import comfy.samplers
 | 
					import comfy.samplers
 | 
				
			||||||
 | 
					import comfy.latent_formats
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from comfy.sd import load_checkpoint_guess_config
 | 
					from comfy.sd import load_checkpoint_guess_config
 | 
				
			||||||
from nodes import VAEDecode, EmptyLatentImage, VAEEncode, VAEEncodeTiled, VAEDecodeTiled, VAEEncodeForInpaint, \
 | 
					from nodes import VAEDecode, EmptyLatentImage, VAEEncode, VAEEncodeTiled, VAEDecodeTiled, VAEEncodeForInpaint, \
 | 
				
			||||||
@ -154,17 +155,21 @@ class VAEApprox(torch.nn.Module):
 | 
				
			|||||||
        return x
 | 
					        return x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VAE_approx_model = None
 | 
					VAE_approx_models = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@torch.no_grad()
 | 
					@torch.no_grad()
 | 
				
			||||||
@torch.inference_mode()
 | 
					@torch.inference_mode()
 | 
				
			||||||
def get_previewer():
 | 
					def get_previewer(model):
 | 
				
			||||||
    global VAE_approx_model
 | 
					    global VAE_approx_models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if VAE_approx_model is None:
 | 
					    from modules.path import vae_approx_path
 | 
				
			||||||
        from modules.path import vae_approx_path
 | 
					    is_sdxl = isinstance(model.model.latent_format, comfy.latent_formats.SDXL)
 | 
				
			||||||
        vae_approx_filename = os.path.join(vae_approx_path, 'xlvaeapp.pth')
 | 
					    vae_approx_filename = os.path.join(vae_approx_path, 'xlvaeapp.pth' if is_sdxl else 'vaeapp_sd15.pth')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if vae_approx_filename in VAE_approx_models:
 | 
				
			||||||
 | 
					        VAE_approx_model = VAE_approx_models[vae_approx_filename]
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
        sd = torch.load(vae_approx_filename, map_location='cpu')
 | 
					        sd = torch.load(vae_approx_filename, map_location='cpu')
 | 
				
			||||||
        VAE_approx_model = VAEApprox()
 | 
					        VAE_approx_model = VAEApprox()
 | 
				
			||||||
        VAE_approx_model.load_state_dict(sd)
 | 
					        VAE_approx_model.load_state_dict(sd)
 | 
				
			||||||
@ -179,6 +184,7 @@ def get_previewer():
 | 
				
			|||||||
            VAE_approx_model.current_type = torch.float32
 | 
					            VAE_approx_model.current_type = torch.float32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        VAE_approx_model.to(comfy.model_management.get_torch_device())
 | 
					        VAE_approx_model.to(comfy.model_management.get_torch_device())
 | 
				
			||||||
 | 
					        VAE_approx_models[vae_approx_filename] = VAE_approx_model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @torch.no_grad()
 | 
					    @torch.no_grad()
 | 
				
			||||||
    @torch.inference_mode()
 | 
					    @torch.inference_mode()
 | 
				
			||||||
@ -198,7 +204,10 @@ def get_previewer():
 | 
				
			|||||||
def ksampler(model, positive, negative, latent, seed=None, steps=30, cfg=7.0, sampler_name='dpmpp_fooocus_2m_sde_inpaint_seamless',
 | 
					def ksampler(model, positive, negative, latent, seed=None, steps=30, cfg=7.0, sampler_name='dpmpp_fooocus_2m_sde_inpaint_seamless',
 | 
				
			||||||
             scheduler='karras', denoise=1.0, disable_noise=False, start_step=None, last_step=None,
 | 
					             scheduler='karras', denoise=1.0, disable_noise=False, start_step=None, last_step=None,
 | 
				
			||||||
             force_full_denoise=False, callback_function=None, refiner=None, refiner_switch=-1,
 | 
					             force_full_denoise=False, callback_function=None, refiner=None, refiner_switch=-1,
 | 
				
			||||||
             previewer_start=None, previewer_end=None, noise_multiplier=1.0):
 | 
					             previewer_start=None, previewer_end=None, sigmas=None):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if sigmas is not None:
 | 
				
			||||||
 | 
					        sigmas = sigmas.clone().to(comfy.model_management.get_torch_device())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    latent_image = latent["samples"]
 | 
					    latent_image = latent["samples"]
 | 
				
			||||||
    if disable_noise:
 | 
					    if disable_noise:
 | 
				
			||||||
@ -207,14 +216,11 @@ def ksampler(model, positive, negative, latent, seed=None, steps=30, cfg=7.0, sa
 | 
				
			|||||||
        batch_inds = latent["batch_index"] if "batch_index" in latent else None
 | 
					        batch_inds = latent["batch_index"] if "batch_index" in latent else None
 | 
				
			||||||
        noise = comfy.sample.prepare_noise(latent_image, seed, batch_inds)
 | 
					        noise = comfy.sample.prepare_noise(latent_image, seed, batch_inds)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if noise_multiplier != 1.0:
 | 
					 | 
				
			||||||
        noise = noise * noise_multiplier
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    noise_mask = None
 | 
					    noise_mask = None
 | 
				
			||||||
    if "noise_mask" in latent:
 | 
					    if "noise_mask" in latent:
 | 
				
			||||||
        noise_mask = latent["noise_mask"]
 | 
					        noise_mask = latent["noise_mask"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    previewer = get_previewer()
 | 
					    previewer = get_previewer(model)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if previewer_start is None:
 | 
					    if previewer_start is None:
 | 
				
			||||||
        previewer_start = 0
 | 
					        previewer_start = 0
 | 
				
			||||||
@ -240,7 +246,7 @@ def ksampler(model, positive, negative, latent, seed=None, steps=30, cfg=7.0, sa
 | 
				
			|||||||
                                      denoise=denoise, disable_noise=disable_noise, start_step=start_step,
 | 
					                                      denoise=denoise, disable_noise=disable_noise, start_step=start_step,
 | 
				
			||||||
                                      last_step=last_step,
 | 
					                                      last_step=last_step,
 | 
				
			||||||
                                      force_full_denoise=force_full_denoise, noise_mask=noise_mask, callback=callback,
 | 
					                                      force_full_denoise=force_full_denoise, noise_mask=noise_mask, callback=callback,
 | 
				
			||||||
                                      disable_pbar=disable_pbar, seed=seed)
 | 
					                                      disable_pbar=disable_pbar, seed=seed, sigmas=sigmas)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        out = latent.copy()
 | 
					        out = latent.copy()
 | 
				
			||||||
        out["samples"] = samples
 | 
					        out["samples"] = samples
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,8 @@ import os
 | 
				
			|||||||
import torch
 | 
					import torch
 | 
				
			||||||
import modules.path
 | 
					import modules.path
 | 
				
			||||||
import comfy.model_management
 | 
					import comfy.model_management
 | 
				
			||||||
 | 
					import comfy.latent_formats
 | 
				
			||||||
 | 
					import modules.inpaint_worker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from comfy.model_base import SDXL, SDXLRefiner
 | 
					from comfy.model_base import SDXL, SDXLRefiner
 | 
				
			||||||
from modules.expansion import FooocusExpansion
 | 
					from modules.expansion import FooocusExpansion
 | 
				
			||||||
@ -63,8 +65,8 @@ def assert_model_integrity():
 | 
				
			|||||||
    if xl_refiner is not None:
 | 
					    if xl_refiner is not None:
 | 
				
			||||||
        if xl_refiner.unet is None or xl_refiner.unet.model is None:
 | 
					        if xl_refiner.unet is None or xl_refiner.unet.model is None:
 | 
				
			||||||
            error_message = 'You have selected an invalid refiner!'
 | 
					            error_message = 'You have selected an invalid refiner!'
 | 
				
			||||||
        elif not isinstance(xl_refiner.unet.model, SDXL) and not isinstance(xl_refiner.unet.model, SDXLRefiner):
 | 
					        # elif not isinstance(xl_refiner.unet.model, SDXL) and not isinstance(xl_refiner.unet.model, SDXLRefiner):
 | 
				
			||||||
            error_message = 'SD1.5 or 2.1 as refiner is not supported!'
 | 
					        #     error_message = 'SD1.5 or 2.1 as refiner is not supported!'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if error_message is not None:
 | 
					    if error_message is not None:
 | 
				
			||||||
        raise NotImplementedError(error_message)
 | 
					        raise NotImplementedError(error_message)
 | 
				
			||||||
@ -227,11 +229,15 @@ def refresh_everything(refiner_model_name, base_model_name, loras):
 | 
				
			|||||||
    final_clip = xl_base_patched.clip
 | 
					    final_clip = xl_base_patched.clip
 | 
				
			||||||
    final_vae = xl_base_patched.vae
 | 
					    final_vae = xl_base_patched.vae
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final_unet.model.diffusion_model.in_inpaint = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if xl_refiner is None:
 | 
					    if xl_refiner is None:
 | 
				
			||||||
        final_refiner_unet = None
 | 
					        final_refiner_unet = None
 | 
				
			||||||
        final_refiner_vae = None
 | 
					        final_refiner_vae = None
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        final_refiner_unet = xl_refiner.unet
 | 
					        final_refiner_unet = xl_refiner.unet
 | 
				
			||||||
 | 
					        final_refiner_unet.model.diffusion_model.in_inpaint = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final_refiner_vae = xl_refiner.vae
 | 
					        final_refiner_vae = xl_refiner.vae
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if final_expansion is None:
 | 
					    if final_expansion is None:
 | 
				
			||||||
@ -257,22 +263,63 @@ refresh_everything(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@torch.no_grad()
 | 
					@torch.no_grad()
 | 
				
			||||||
@torch.inference_mode()
 | 
					@torch.inference_mode()
 | 
				
			||||||
def vae_parse(x, tiled=False):
 | 
					def vae_parse(x, tiled=False, use_interpose=True):
 | 
				
			||||||
    if final_vae is None or final_refiner_vae is None:
 | 
					    if final_vae is None or final_refiner_vae is None:
 | 
				
			||||||
        return x
 | 
					        return x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    print('VAE parsing ...')
 | 
					    if use_interpose:
 | 
				
			||||||
    x = core.decode_vae(vae=final_vae, latent_image=x, tiled=tiled)
 | 
					        print('VAE interposing ...')
 | 
				
			||||||
    x = core.encode_vae(vae=final_refiner_vae, pixels=x, tiled=tiled)
 | 
					        import fooocus_extras.vae_interpose
 | 
				
			||||||
    print('VAE parsed ...')
 | 
					        x = fooocus_extras.vae_interpose.parse(x)
 | 
				
			||||||
 | 
					        print('VAE interposed ...')
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        print('VAE parsing ...')
 | 
				
			||||||
 | 
					        x = core.decode_vae(vae=final_vae, latent_image=x, tiled=tiled)
 | 
				
			||||||
 | 
					        x = core.encode_vae(vae=final_refiner_vae, pixels=x, tiled=tiled)
 | 
				
			||||||
 | 
					        print('VAE parsed ...')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return x
 | 
					    return x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@torch.no_grad()
 | 
				
			||||||
 | 
					@torch.inference_mode()
 | 
				
			||||||
 | 
					def calculate_sigmas_all(sampler, model, scheduler, steps):
 | 
				
			||||||
 | 
					    from comfy.samplers import calculate_sigmas_scheduler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    discard_penultimate_sigma = False
 | 
				
			||||||
 | 
					    if sampler in ['dpm_2', 'dpm_2_ancestral']:
 | 
				
			||||||
 | 
					        steps += 1
 | 
				
			||||||
 | 
					        discard_penultimate_sigma = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sigmas = calculate_sigmas_scheduler(model, scheduler, steps)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if discard_penultimate_sigma:
 | 
				
			||||||
 | 
					        sigmas = torch.cat([sigmas[:-2], sigmas[-1:]])
 | 
				
			||||||
 | 
					    return sigmas
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@torch.no_grad()
 | 
				
			||||||
 | 
					@torch.inference_mode()
 | 
				
			||||||
 | 
					def calculate_sigmas(sampler, model, scheduler, steps, denoise):
 | 
				
			||||||
 | 
					    if denoise is None or denoise > 0.9999:
 | 
				
			||||||
 | 
					        sigmas = calculate_sigmas_all(sampler, model, scheduler, steps)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        new_steps = int(steps / denoise)
 | 
				
			||||||
 | 
					        sigmas = calculate_sigmas_all(sampler, model, scheduler, new_steps)
 | 
				
			||||||
 | 
					        sigmas = sigmas[-(steps + 1):]
 | 
				
			||||||
 | 
					    return sigmas
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@torch.no_grad()
 | 
					@torch.no_grad()
 | 
				
			||||||
@torch.inference_mode()
 | 
					@torch.inference_mode()
 | 
				
			||||||
def process_diffusion(positive_cond, negative_cond, steps, switch, width, height, image_seed, callback, sampler_name, scheduler_name, latent=None, denoise=1.0, tiled=False, cfg_scale=7.0, refiner_swap_method='joint'):
 | 
					def process_diffusion(positive_cond, negative_cond, steps, switch, width, height, image_seed, callback, sampler_name, scheduler_name, latent=None, denoise=1.0, tiled=False, cfg_scale=7.0, refiner_swap_method='joint'):
 | 
				
			||||||
    assert refiner_swap_method in ['joint', 'separate', 'vae']
 | 
					    assert refiner_swap_method in ['joint', 'separate', 'vae', 'upscale']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if final_refiner_unet is not None:
 | 
				
			||||||
 | 
					        if isinstance(final_refiner_unet.model.latent_format, comfy.latent_formats.SD15) \
 | 
				
			||||||
 | 
					                and refiner_swap_method != 'upscale':
 | 
				
			||||||
 | 
					            refiner_swap_method = 'vae'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    print(f'[Sampler] refiner_swap_method = {refiner_swap_method}')
 | 
					    print(f'[Sampler] refiner_swap_method = {refiner_swap_method}')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if latent is None:
 | 
					    if latent is None:
 | 
				
			||||||
@ -302,6 +349,34 @@ def process_diffusion(positive_cond, negative_cond, steps, switch, width, height
 | 
				
			|||||||
        images = core.pytorch_to_numpy(decoded_latent)
 | 
					        images = core.pytorch_to_numpy(decoded_latent)
 | 
				
			||||||
        return images
 | 
					        return images
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if refiner_swap_method == 'upscale':
 | 
				
			||||||
 | 
					        target_model = final_refiner_unet
 | 
				
			||||||
 | 
					        if target_model is None:
 | 
				
			||||||
 | 
					            target_model = final_unet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sampled_latent = core.ksampler(
 | 
				
			||||||
 | 
					            model=target_model,
 | 
				
			||||||
 | 
					            positive=clip_separate(positive_cond, target_model=target_model.model, target_clip=final_clip),
 | 
				
			||||||
 | 
					            negative=clip_separate(negative_cond, target_model=target_model.model, target_clip=final_clip),
 | 
				
			||||||
 | 
					            latent=empty_latent,
 | 
				
			||||||
 | 
					            steps=steps, start_step=0, last_step=steps, disable_noise=False, force_full_denoise=True,
 | 
				
			||||||
 | 
					            seed=image_seed,
 | 
				
			||||||
 | 
					            denoise=denoise,
 | 
				
			||||||
 | 
					            callback_function=callback,
 | 
				
			||||||
 | 
					            cfg=cfg_scale,
 | 
				
			||||||
 | 
					            sampler_name=sampler_name,
 | 
				
			||||||
 | 
					            scheduler=scheduler_name,
 | 
				
			||||||
 | 
					            previewer_start=0,
 | 
				
			||||||
 | 
					            previewer_end=steps,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        target_model = final_refiner_vae
 | 
				
			||||||
 | 
					        if target_model is None:
 | 
				
			||||||
 | 
					            target_model = final_vae
 | 
				
			||||||
 | 
					        decoded_latent = core.decode_vae(vae=target_model, latent_image=sampled_latent, tiled=tiled)
 | 
				
			||||||
 | 
					        images = core.pytorch_to_numpy(decoded_latent)
 | 
				
			||||||
 | 
					        return images
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if refiner_swap_method == 'separate':
 | 
					    if refiner_swap_method == 'separate':
 | 
				
			||||||
        sampled_latent = core.ksampler(
 | 
					        sampled_latent = core.ksampler(
 | 
				
			||||||
            model=final_unet,
 | 
					            model=final_unet,
 | 
				
			||||||
@ -316,7 +391,7 @@ def process_diffusion(positive_cond, negative_cond, steps, switch, width, height
 | 
				
			|||||||
            sampler_name=sampler_name,
 | 
					            sampler_name=sampler_name,
 | 
				
			||||||
            scheduler=scheduler_name,
 | 
					            scheduler=scheduler_name,
 | 
				
			||||||
            previewer_start=0,
 | 
					            previewer_start=0,
 | 
				
			||||||
            previewer_end=switch,
 | 
					            previewer_end=steps,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        print('Refiner swapped by changing ksampler. Noise preserved.')
 | 
					        print('Refiner swapped by changing ksampler. Noise preserved.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -327,8 +402,8 @@ def process_diffusion(positive_cond, negative_cond, steps, switch, width, height
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        sampled_latent = core.ksampler(
 | 
					        sampled_latent = core.ksampler(
 | 
				
			||||||
            model=target_model,
 | 
					            model=target_model,
 | 
				
			||||||
            positive=clip_separate(positive_cond, target_model=target_model.model),
 | 
					            positive=clip_separate(positive_cond, target_model=target_model.model, target_clip=final_clip),
 | 
				
			||||||
            negative=clip_separate(negative_cond, target_model=target_model.model),
 | 
					            negative=clip_separate(negative_cond, target_model=target_model.model, target_clip=final_clip),
 | 
				
			||||||
            latent=sampled_latent,
 | 
					            latent=sampled_latent,
 | 
				
			||||||
            steps=steps, start_step=switch, last_step=steps, disable_noise=True, force_full_denoise=True,
 | 
					            steps=steps, start_step=switch, last_step=steps, disable_noise=True, force_full_denoise=True,
 | 
				
			||||||
            seed=image_seed,
 | 
					            seed=image_seed,
 | 
				
			||||||
@ -349,6 +424,18 @@ def process_diffusion(positive_cond, negative_cond, steps, switch, width, height
 | 
				
			|||||||
        return images
 | 
					        return images
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if refiner_swap_method == 'vae':
 | 
					    if refiner_swap_method == 'vae':
 | 
				
			||||||
 | 
					        sigmas = calculate_sigmas(sampler=sampler_name, scheduler=scheduler_name, model=final_unet.model, steps=steps, denoise=denoise)
 | 
				
			||||||
 | 
					        sigmas_a = sigmas[:switch]
 | 
				
			||||||
 | 
					        sigmas_b = sigmas[switch:]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if final_refiner_unet is not None:
 | 
				
			||||||
 | 
					            k1 = final_refiner_unet.model.latent_format.scale_factor
 | 
				
			||||||
 | 
					            k2 = final_unet.model.latent_format.scale_factor
 | 
				
			||||||
 | 
					            k = float(k1) / float(k2)
 | 
				
			||||||
 | 
					            sigmas_b = sigmas_b * k
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sigmas = torch.cat([sigmas_a, sigmas_b], dim=0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sampled_latent = core.ksampler(
 | 
					        sampled_latent = core.ksampler(
 | 
				
			||||||
            model=final_unet,
 | 
					            model=final_unet,
 | 
				
			||||||
            positive=positive_cond,
 | 
					            positive=positive_cond,
 | 
				
			||||||
@ -362,9 +449,10 @@ def process_diffusion(positive_cond, negative_cond, steps, switch, width, height
 | 
				
			|||||||
            sampler_name=sampler_name,
 | 
					            sampler_name=sampler_name,
 | 
				
			||||||
            scheduler=scheduler_name,
 | 
					            scheduler=scheduler_name,
 | 
				
			||||||
            previewer_start=0,
 | 
					            previewer_start=0,
 | 
				
			||||||
            previewer_end=switch,
 | 
					            previewer_end=steps,
 | 
				
			||||||
 | 
					            sigmas=sigmas
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        print('Refiner swapped by changing ksampler. Noise is not preserved.')
 | 
					        print('Fooocus VAE-based swap.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        target_model = final_refiner_unet
 | 
					        target_model = final_refiner_unet
 | 
				
			||||||
        if target_model is None:
 | 
					        if target_model is None:
 | 
				
			||||||
@ -373,10 +461,13 @@ def process_diffusion(positive_cond, negative_cond, steps, switch, width, height
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        sampled_latent = vae_parse(sampled_latent)
 | 
					        sampled_latent = vae_parse(sampled_latent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if modules.inpaint_worker.current_task is not None:
 | 
				
			||||||
 | 
					            modules.inpaint_worker.current_task.swap()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sampled_latent = core.ksampler(
 | 
					        sampled_latent = core.ksampler(
 | 
				
			||||||
            model=target_model,
 | 
					            model=target_model,
 | 
				
			||||||
            positive=clip_separate(positive_cond, target_model=target_model.model),
 | 
					            positive=clip_separate(positive_cond, target_model=target_model.model, target_clip=final_clip),
 | 
				
			||||||
            negative=clip_separate(negative_cond, target_model=target_model.model),
 | 
					            negative=clip_separate(negative_cond, target_model=target_model.model, target_clip=final_clip),
 | 
				
			||||||
            latent=sampled_latent,
 | 
					            latent=sampled_latent,
 | 
				
			||||||
            steps=steps, start_step=switch, last_step=steps, disable_noise=False, force_full_denoise=True,
 | 
					            steps=steps, start_step=switch, last_step=steps, disable_noise=False, force_full_denoise=True,
 | 
				
			||||||
            seed=image_seed,
 | 
					            seed=image_seed,
 | 
				
			||||||
@ -387,9 +478,12 @@ def process_diffusion(positive_cond, negative_cond, steps, switch, width, height
 | 
				
			|||||||
            scheduler=scheduler_name,
 | 
					            scheduler=scheduler_name,
 | 
				
			||||||
            previewer_start=switch,
 | 
					            previewer_start=switch,
 | 
				
			||||||
            previewer_end=steps,
 | 
					            previewer_end=steps,
 | 
				
			||||||
            noise_multiplier=1.2,
 | 
					            sigmas=sigmas
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if modules.inpaint_worker.current_task is not None:
 | 
				
			||||||
 | 
					            modules.inpaint_worker.current_task.swap()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        target_model = final_refiner_vae
 | 
					        target_model = final_refiner_vae
 | 
				
			||||||
        if target_model is None:
 | 
					        if target_model is None:
 | 
				
			||||||
            target_model = final_vae
 | 
					            target_model = final_vae
 | 
				
			||||||
 | 
				
			|||||||
@ -167,6 +167,7 @@ class InpaintWorker:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        # ending
 | 
					        # ending
 | 
				
			||||||
        self.latent = None
 | 
					        self.latent = None
 | 
				
			||||||
 | 
					        self.latent_after_swap = None
 | 
				
			||||||
        self.latent_mask = None
 | 
					        self.latent_mask = None
 | 
				
			||||||
        self.inpaint_head_feature = None
 | 
					        self.inpaint_head_feature = None
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
@ -191,9 +192,14 @@ class InpaintWorker:
 | 
				
			|||||||
        self.inpaint_head_feature = inpaint_head(feed)
 | 
					        self.inpaint_head_feature = inpaint_head(feed)
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def load_latent(self, latent, mask):
 | 
					    def load_latent(self, latent, mask, latent_after_swap=None):
 | 
				
			||||||
        self.latent = latent
 | 
					        self.latent = latent
 | 
				
			||||||
        self.latent_mask = mask
 | 
					        self.latent_mask = mask
 | 
				
			||||||
 | 
					        self.latent_after_swap = latent_after_swap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def swap(self):
 | 
				
			||||||
 | 
					        if self.latent_after_swap is not None:
 | 
				
			||||||
 | 
					            self.latent, self.latent_after_swap = self.latent_after_swap, self.latent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def color_correction(self, img):
 | 
					    def color_correction(self, img):
 | 
				
			||||||
        fg = img.astype(np.float32)
 | 
					        fg = img.astype(np.float32)
 | 
				
			||||||
 | 
				
			|||||||
@ -386,7 +386,7 @@ def patched_unet_forward(self, x, timesteps=None, context=None, y=None, control=
 | 
				
			|||||||
    self.current_step = 1.0 - timesteps.to(x) / 999.0
 | 
					    self.current_step = 1.0 - timesteps.to(x) / 999.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inpaint_fix = None
 | 
					    inpaint_fix = None
 | 
				
			||||||
    if inpaint_worker.current_task is not None:
 | 
					    if getattr(self, 'in_inpaint', False) and inpaint_worker.current_task is not None:
 | 
				
			||||||
        inpaint_fix = inpaint_worker.current_task.inpaint_head_feature
 | 
					        inpaint_fix = inpaint_worker.current_task.inpaint_head_feature
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    transformer_options["original_shape"] = list(x.shape)
 | 
					    transformer_options["original_shape"] = list(x.shape)
 | 
				
			||||||
 | 
				
			|||||||
@ -98,6 +98,11 @@ default_styles = get_config_item_or_set_default(
 | 
				
			|||||||
    default_value=['Fooocus V2', 'Default (Slightly Cinematic)'],
 | 
					    default_value=['Fooocus V2', 'Default (Slightly Cinematic)'],
 | 
				
			||||||
    validator=lambda x: isinstance(x, list) and all(y in modules.sdxl_styles.legal_style_names for y in x)
 | 
					    validator=lambda x: isinstance(x, list) and all(y in modules.sdxl_styles.legal_style_names for y in x)
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					default_negative_prompt = get_config_item_or_set_default(
 | 
				
			||||||
 | 
					    key='default_negative_prompt',
 | 
				
			||||||
 | 
					    default_value='low quality, bad hands, bad eyes, cropped, missing fingers, extra digit',
 | 
				
			||||||
 | 
					    validator=lambda x: isinstance(x, str)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
with open(config_path, "w", encoding="utf-8") as json_file:
 | 
					with open(config_path, "w", encoding="utf-8") as json_file:
 | 
				
			||||||
    json.dump(config_dict, json_file, indent=4)
 | 
					    json.dump(config_dict, json_file, indent=4)
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@ refiner_switch_step = -1
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@torch.no_grad()
 | 
					@torch.no_grad()
 | 
				
			||||||
@torch.inference_mode()
 | 
					@torch.inference_mode()
 | 
				
			||||||
def clip_separate(cond, target_model=None):
 | 
					def clip_separate(cond, target_model=None, target_clip=None):
 | 
				
			||||||
    c, p = cond[0]
 | 
					    c, p = cond[0]
 | 
				
			||||||
    if target_model is None or isinstance(target_model, SDXLRefiner):
 | 
					    if target_model is None or isinstance(target_model, SDXLRefiner):
 | 
				
			||||||
        c = c[..., -1280:].clone()
 | 
					        c = c[..., -1280:].clone()
 | 
				
			||||||
@ -25,6 +25,25 @@ def clip_separate(cond, target_model=None):
 | 
				
			|||||||
        p = {"pooled_output": p["pooled_output"].clone()}
 | 
					        p = {"pooled_output": p["pooled_output"].clone()}
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        c = c[..., :768].clone()
 | 
					        c = c[..., :768].clone()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final_layer_norm = target_clip.cond_stage_model.clip_l.transformer.text_model.final_layer_norm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final_layer_norm_origin_device = final_layer_norm.weight.device
 | 
				
			||||||
 | 
					        final_layer_norm_origin_dtype = final_layer_norm.weight.dtype
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        c_origin_device = c.device
 | 
				
			||||||
 | 
					        c_origin_dtype = c.dtype
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final_layer_norm.to(device='cpu', dtype=torch.float32)
 | 
				
			||||||
 | 
					        c = c.to(device='cpu', dtype=torch.float32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        c = torch.chunk(c, int(c.size(1)) // 77, 1)
 | 
				
			||||||
 | 
					        c = [final_layer_norm(ci) for ci in c]
 | 
				
			||||||
 | 
					        c = torch.cat(c, dim=1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final_layer_norm.to(device=final_layer_norm_origin_device, dtype=final_layer_norm_origin_dtype)
 | 
				
			||||||
 | 
					        c = c.to(device=c_origin_device, dtype=c_origin_dtype)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        p = {}
 | 
					        p = {}
 | 
				
			||||||
    return [[c, p]]
 | 
					    return [[c, p]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					# 2.1.50
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Begin to support sd1.5 as refiner. This method scale sigmas given SD15/Xl latent scale and is probably the most correct way to do it. I am going to write a discussion soon.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# 2.1.25
 | 
					# 2.1.25
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AMD support on Linux and Windows.
 | 
					AMD support on Linux and Windows.
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										7
									
								
								webui.py
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								webui.py
									
									
									
									
									
								
							@ -177,7 +177,8 @@ with shared.gradio_root:
 | 
				
			|||||||
                                                   value=default_aspect_ratio, info='width × height')
 | 
					                                                   value=default_aspect_ratio, info='width × height')
 | 
				
			||||||
                image_number = gr.Slider(label='Image Number', minimum=1, maximum=32, step=1, value=2)
 | 
					                image_number = gr.Slider(label='Image Number', minimum=1, maximum=32, step=1, value=2)
 | 
				
			||||||
                negative_prompt = gr.Textbox(label='Negative Prompt', show_label=True, placeholder="Type prompt here.",
 | 
					                negative_prompt = gr.Textbox(label='Negative Prompt', show_label=True, placeholder="Type prompt here.",
 | 
				
			||||||
                                             info='Describing objects that you do not want to see.')
 | 
					                                             info='Describing what you do not want to see.', lines=2,
 | 
				
			||||||
 | 
					                                             value=modules.path.default_negative_prompt)
 | 
				
			||||||
                seed_random = gr.Checkbox(label='Random', value=True)
 | 
					                seed_random = gr.Checkbox(label='Random', value=True)
 | 
				
			||||||
                image_seed = gr.Number(label='Seed', value=0, precision=0, visible=False)
 | 
					                image_seed = gr.Number(label='Seed', value=0, precision=0, visible=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -201,8 +202,8 @@ with shared.gradio_root:
 | 
				
			|||||||
                                                    label='Image Style')
 | 
					                                                    label='Image Style')
 | 
				
			||||||
            with gr.Tab(label='Model'):
 | 
					            with gr.Tab(label='Model'):
 | 
				
			||||||
                with gr.Row():
 | 
					                with gr.Row():
 | 
				
			||||||
                    base_model = gr.Dropdown(label='SDXL Base Model', choices=modules.path.model_filenames, value=modules.path.default_base_model_name, show_label=True)
 | 
					                    base_model = gr.Dropdown(label='Base Model (SDXL only)', choices=modules.path.model_filenames, value=modules.path.default_base_model_name, show_label=True)
 | 
				
			||||||
                    refiner_model = gr.Dropdown(label='SDXL Refiner', choices=['None'] + modules.path.model_filenames, value=modules.path.default_refiner_model_name, show_label=True)
 | 
					                    refiner_model = gr.Dropdown(label='Refiner (SDXL or SD 1.5)', choices=['None'] + modules.path.model_filenames, value=modules.path.default_refiner_model_name, show_label=True)
 | 
				
			||||||
                with gr.Accordion(label='LoRAs', open=True):
 | 
					                with gr.Accordion(label='LoRAs', open=True):
 | 
				
			||||||
                    lora_ctrls = []
 | 
					                    lora_ctrls = []
 | 
				
			||||||
                    for i in range(5):
 | 
					                    for i in range(5):
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user