@ -658,14 +658,18 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
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 , * * 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 , * * kwargs ) :
super ( ) . __init__ ( * * kwargs )
self . enable_hr = enable_hr
self . denoising_strength = denoising_strength
self . firstphase_width = firstphase_width
self . firstphase_height = firstphase_height
self . truncate_x = 0
self . truncate_y = 0
self . hr_scale = hr_scale
self . hr_upscaler = hr_upscaler
if firstphase_width != 0 or firstphase_height != 0 :
print ( " firstphase_width/firstphase_height no longer supported; use hr_scale " , file = sys . stderr )
self . hr_scale = self . width / firstphase_width
self . width = firstphase_width
self . height = firstphase_height
def init ( self , all_prompts , all_seeds , all_subseeds ) :
if self . enable_hr :
@ -674,47 +678,29 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
else :
state . job_count = state . job_count * 2
self . extra_generation_params [ " First pass size " ] = f " { self . firstphase_width } x { self . firstphase_height } "
if self . firstphase_width == 0 or self . firstphase_height == 0 :
desired_pixel_count = 512 * 512
actual_pixel_count = self . width * self . height
scale = math . sqrt ( desired_pixel_count / actual_pixel_count )
self . firstphase_width = math . ceil ( scale * self . width / 64 ) * 64
self . firstphase_height = math . ceil ( scale * self . height / 64 ) * 64
firstphase_width_truncated = int ( scale * self . width )
firstphase_height_truncated = int ( scale * self . height )
else :
width_ratio = self . width / self . firstphase_width
height_ratio = self . height / self . firstphase_height
if width_ratio > height_ratio :
firstphase_width_truncated = self . firstphase_width
firstphase_height_truncated = self . firstphase_width * self . height / self . width
else :
firstphase_width_truncated = self . firstphase_height * self . width / self . height
firstphase_height_truncated = self . firstphase_height
self . truncate_x = int ( self . firstphase_width - firstphase_width_truncated ) / / opt_f
self . truncate_y = int ( self . firstphase_height - firstphase_height_truncated ) / / opt_f
self . extra_generation_params [ " Hires upscale " ] = self . hr_scale
if self . hr_upscaler is not None :
self . extra_generation_params [ " Hires upscaler " ] = self . hr_upscaler
def sample ( self , conditioning , unconditional_conditioning , seeds , subseeds , subseed_strength , prompts ) :
self . sampler = sd_samplers . create_sampler ( self . sampler_name , self . sd_model )
latent_scale_mode = shared . latent_upscale_modes . get ( self . hr_upscaler , None ) if self . hr_upscaler is not None else shared . latent_upscale_default_mode
if self . enable_hr and latent_scale_mode is None :
assert len ( [ x for x in shared . sd_upscalers if x . name == self . hr_upscaler ] ) > 0 , f " could not find upscaler named { self . hr_upscaler } "
x = create_random_tensors ( [ opt_C , self . height / / opt_f , self . width / / opt_f ] , seeds = seeds , subseeds = subseeds , subseed_strength = self . subseed_strength , seed_resize_from_h = self . seed_resize_from_h , seed_resize_from_w = self . seed_resize_from_w , p = self )
samples = self . sampler . sample ( self , x , conditioning , unconditional_conditioning , image_conditioning = self . txt2img_image_conditioning ( x ) )
if not self . enable_hr :
x = create_random_tensors ( [ opt_C , self . height / / opt_f , self . width / / opt_f ] , seeds = seeds , subseeds = subseeds , subseed_strength = self . subseed_strength , seed_resize_from_h = self . seed_resize_from_h , seed_resize_from_w = self . seed_resize_from_w , p = self )
samples = self . sampler . sample ( self , x , conditioning , unconditional_conditioning , image_conditioning = self . txt2img_image_conditioning ( x ) )
return samples
x = create_random_tensors ( [ opt_C , self . firstphase_height / / opt_f , self . firstphase_width / / opt_f ] , seeds = seeds , subseeds = subseeds , subseed_strength = self . subseed_strength , seed_resize_from_h = self . seed_resize_from_h , seed_resize_from_w = self . seed_resize_from_w , p = self )
samples = self . sampler . sample ( self , x , conditioning , unconditional_conditioning , image_conditioning = self . txt2img_image_conditioning ( x , self . firstphase_width , self . firstphase_height ) )
samples = samples [ : , : , self . truncate_y / / 2 : samples . shape [ 2 ] - self . truncate_y / / 2 , self . truncate_x / / 2 : samples . shape [ 3 ] - self . truncate_x / / 2 ]
target_width = int ( self . width * self . hr_scale )
target_height = int ( self . height * self . hr_scale )
""" saves image before applying hires fix, if enabled in options; takes as an argument either an image or batch with latent space images """
def save_intermediate ( image , index ) :
""" saves image before applying hires fix, if enabled in options; takes as an argument either an image or batch with latent space images """
if not opts . save or self . do_not_save_samples or not opts . save_images_before_highres_fix :
return
@ -723,11 +709,11 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
images . save_image ( image , self . outpath_samples , " " , seeds [ index ] , prompts [ index ] , opts . samples_format , suffix = " -before-highres-fix " )
if opts. use_scale_latent_for_hires_fix :
if latent_scale_mode is not None :
for i in range ( samples . shape [ 0 ] ) :
save_intermediate ( samples , i )
samples = torch . nn . functional . interpolate ( samples , size = ( self . height / / opt_f , self . width / / opt_f ) , mode = " bilinear " )
samples = torch . nn . functional . interpolate ( samples , size = ( target_ height / / opt_f , target_width / / opt_f ) , mode = latent_scale_mode )
# Avoid making the inpainting conditioning unless necessary as
# this does need some extra compute to decode / encode the image again.
@ -747,7 +733,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
save_intermediate ( image , i )
image = images . resize_image ( 0 , image , self . width , self . height )
image = images . resize_image ( 0 , image , target_width , target_height , upscaler_name = self . hr_upscaler )
image = np . array ( image ) . astype ( np . float32 ) / 255.0
image = np . moveaxis ( image , 2 , 0 )
batch_images . append ( image )
@ -764,7 +750,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
self . sampler = sd_samplers . create_sampler ( self . sampler_name , self . sd_model )
noise = create_random_tensors ( samples . shape [ 1 : ] , seeds = seeds , subseeds = subseeds , subseed_strength = subseed_strength , seed_resize_from_h= self . seed_resize_from_h , seed_resize_from_w = self . seed_resize_from_w , p= self )
noise = create_random_tensors ( samples . shape [ 1 : ] , seeds = seeds , subseeds = subseeds , subseed_strength = subseed_strength , p= self )
# GC now before running the next img2img to prevent running out of memory
x = None