lllyasviel/Fooocus · error · FaceWarpException

Must have (output_size - outer_padding)= some_scale * (crop_

Error message

Must have (output_size - outer_padding)= some_scale * (crop_size * (1.0 + inner_padding_factor)

What it means

The reference 5-point layout must preserve the crop's aspect ratio: (output_size - outer_padding) must be a uniform scale of the crop size (after inner padding). The function checks size_bf_outer_pad[0]*crop[1] == size_bf_outer_pad[1]*crop[0]; a mismatch means the requested output stretches the face non-uniformly, which raises FaceWarpException.

Source

Thrown at extras/facexlib/detection/align_trans.py:96

    if ((inner_padding_factor > 0 or outer_padding[0] > 0 or outer_padding[1] > 0) and output_size is None):
        output_size = tmp_crop_size * \
            (1 + inner_padding_factor * 2).astype(np.int32)
        output_size += np.array(outer_padding)
    if not (outer_padding[0] < output_size[0] and outer_padding[1] < output_size[1]):
        raise FaceWarpException('Not (outer_padding[0] < output_size[0] and outer_padding[1] < output_size[1])')

    # 1) pad the inner region according inner_padding_factor
    if inner_padding_factor > 0:
        size_diff = tmp_crop_size * inner_padding_factor * 2
        tmp_5pts += size_diff / 2
        tmp_crop_size += np.round(size_diff).astype(np.int32)

    # 2) resize the padded inner region
    size_bf_outer_pad = np.array(output_size) - np.array(outer_padding) * 2

    if size_bf_outer_pad[0] * tmp_crop_size[1] != size_bf_outer_pad[1] * tmp_crop_size[0]:
        raise FaceWarpException('Must have (output_size - outer_padding)'
                                '= some_scale * (crop_size * (1.0 + inner_padding_factor)')

    scale_factor = size_bf_outer_pad[0].astype(np.float32) / tmp_crop_size[0]
    tmp_5pts = tmp_5pts * scale_factor
    #    size_diff = tmp_crop_size * (scale_factor - min(scale_factor))
    #    tmp_5pts = tmp_5pts + size_diff / 2
    tmp_crop_size = size_bf_outer_pad

    # 3) add outer_padding to make output_size
    reference_5point = tmp_5pts + np.array(outer_padding)
    tmp_crop_size = output_size

    return reference_5point


def get_affine_transform_matrix(src_pts, dst_pts):
    """
    Function:

View on GitHub (pinned to ae05379cc9)

Solutions

  1. Use an output_size with the same aspect ratio as the (inner-padded) crop, e.g. square crop -> square output
  2. Compute output_size from the documented relation: output_size = crop_size*(1+2*inner_padding_factor) + outer_padding (as the function itself does when output_size is None)
  3. Leave output_size=None and let the function derive the consistent size

Example fix

// before
get_reference_facial_points((256,256), 0, (0,0), True, output_size=(512,384))

// after
get_reference_facial_points((256,256), 0, (0,0), True, output_size=None)  # derives 512x512
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
crop = np.asarray(crop_size, dtype=np.int32)
size_bf_pad = np.asarray(output_size) - 2 * np.asarray(outer_padding)
assert size_bf_pad[0] * crop[1] == size_bf_pad[1] * crop[0], 'aspect ratio mismatch'
# or simply derive: output_size = tuple(crop * (1 + 2*inner_padding_factor) + outer_padding)

Prevention

When it happens

Trigger: Requesting output_size=(512,384) for a square (e.g. 256x256) crop with symmetric padding — the proportions differ; any non-uniform resize baked into the alignment reference.

Common situations: Hardcoding rectangular output sizes for face restoration models that expect square input (GFPGAN uses 512x512); changing crop_size to non-square while keeping a square output_size; asymmetric outer_padding.

Related errors


AI-assisted analysis of lllyasviel/Fooocus@ae05379cc9 (2026-08-15). Data as JSON: /api/errors/759c8d9263b6868e. Report an issue: GitHub.