mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 01:04:32 +02:00
fix(processing): round init images to a pipeline-declared multiple
The init-image snap rounds to the VAE factor, but the LLaDA pipeline needs 16 for its transformer patch and 32 when editing, since the source image is halved for the semantic encoder. The pipeline now declares patch_size for the shared rounding and init_image_multiple for input images, and get_vae_scale_factor honours the latter when an init image is present. check_inputs reads the same attributes.
This commit is contained in:
@@ -444,7 +444,7 @@ def set_pipeline_args(p, model, prompts:list, negative_prompts:list, prompts_2:l
|
||||
# handle missing resolution
|
||||
if args.get('image', None) is not None and ('width' not in args or 'height' not in args):
|
||||
if 'width' in possible and 'height' in possible:
|
||||
vae_scale_factor = sd_vae.get_vae_scale_factor(model)
|
||||
vae_scale_factor = sd_vae.get_vae_scale_factor(model, init_image=True)
|
||||
if isinstance(args['image'], torch.Tensor) or isinstance(args['image'], np.ndarray):
|
||||
if args['image'].shape[-1] == 3: # nhwc
|
||||
args['width'] = args['image'].shape[-2]
|
||||
|
||||
@@ -738,7 +738,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing):
|
||||
|
||||
def init(self, all_prompts=None, all_seeds=None, all_subseeds=None):
|
||||
if self.init_images is not None and len(self.init_images) > 0:
|
||||
vae_scale_factor = sd_vae.get_vae_scale_factor()
|
||||
vae_scale_factor = sd_vae.get_vae_scale_factor(init_image=True)
|
||||
if self.width is None or self.width == 0:
|
||||
self.width = int(vae_scale_factor * (self.init_images[0].width * self.scale_by // vae_scale_factor))
|
||||
if self.height is None or self.height == 0:
|
||||
|
||||
@@ -395,7 +395,7 @@ def resize_init_images(p):
|
||||
p.init_images = [p.image]
|
||||
if getattr(p, 'init_images', None) is not None and len(p.init_images) > 0:
|
||||
p.init_images = decode_images(p.init_images)
|
||||
vae_scale_factor = sd_vae.get_vae_scale_factor()
|
||||
vae_scale_factor = sd_vae.get_vae_scale_factor(init_image=True)
|
||||
tgt_width = vae_scale_factor * math.ceil(p.init_images[0].width / vae_scale_factor)
|
||||
tgt_height = vae_scale_factor * math.ceil(p.init_images[0].height / vae_scale_factor)
|
||||
if p.init_images[0].size != (tgt_width, tgt_height):
|
||||
|
||||
+6
-3
@@ -28,7 +28,7 @@ vae_scale_override = {
|
||||
}
|
||||
|
||||
|
||||
def get_vae_scale_factor(model: DiffusionPipeline | None = None):
|
||||
def get_vae_scale_factor(model: DiffusionPipeline | None = None, init_image: bool = False):
|
||||
if not shared.sd_loaded:
|
||||
vae_scale_factor = 8
|
||||
return vae_scale_factor
|
||||
@@ -58,9 +58,12 @@ def get_vae_scale_factor(model: DiffusionPipeline | None = None):
|
||||
patch_size = model.patch_size
|
||||
if isinstance(patch_size, (tuple, list)): # 3d patch sizes are (t, h, w); spatial term is last
|
||||
patch_size = patch_size[-1]
|
||||
multiple = vae_scale_factor * patch_size
|
||||
if init_image and model is not None and hasattr(model, 'init_image_multiple'): # a pipeline that downsamples its source image needs a larger multiple than its output
|
||||
multiple = max(multiple, int(model.init_image_multiple))
|
||||
if debug:
|
||||
log.trace(f'VAE: cls={model.__class__.__name__ if model else "None"} scale={vae_scale_factor} patch={patch_size}')
|
||||
return vae_scale_factor * patch_size
|
||||
log.trace(f'VAE: cls={model.__class__.__name__ if model else "None"} scale={vae_scale_factor} patch={patch_size} multiple={multiple}')
|
||||
return multiple
|
||||
|
||||
|
||||
def load_vae_dict(filename: str):
|
||||
|
||||
@@ -90,6 +90,8 @@ class LLaDAImagePipeline(DiffusionPipeline):
|
||||
|
||||
self.vae_scale_factor = 2 ** (len(self.vae.config.block_out_channels) - 1) if self.vae is not None else 8
|
||||
self.latent_scale_factor = self.vae_scale_factor * 2
|
||||
self.patch_size = 2 # transformer patch size, read by the host to round sizes to the latent multiple
|
||||
self.init_image_multiple = self.latent_scale_factor * 2 # editing feeds a half-resolution copy of the source image to the semantic encoder
|
||||
self.image_processor = VaeImageProcessor(vae_scale_factor=self.latent_scale_factor)
|
||||
|
||||
@classmethod
|
||||
@@ -383,7 +385,7 @@ class LLaDAImagePipeline(DiffusionPipeline):
|
||||
if generation_mode == "vq" and (height % 16 != 0 or width % 16 != 0):
|
||||
raise ValueError("`height` and `width` must be divisible by 16 in VQ mode.")
|
||||
|
||||
required_multiple = self.latent_scale_factor * (2 if generation_mode == "editing" else 1)
|
||||
required_multiple = self.init_image_multiple if generation_mode == "editing" else self.latent_scale_factor
|
||||
if height <= 0 or width <= 0 or height % required_multiple != 0 or width % required_multiple != 0:
|
||||
raise ValueError(f"`height` and `width` must be divisible by {required_multiple}.")
|
||||
if num_inference_steps < 1:
|
||||
|
||||
Reference in New Issue
Block a user