Finds the rotation, scaling and translation of im1 relative to im0

    Parameters
    ----------
    im0: First image
    im1: Second image
    rmMean: Set to true to remove the mean (Default)

    Returns
    -------
    angle: The angle difference
    scale: The scale difference
    [y, x]: The offset
    im2: The rotated and translated second image

    Notes
    -----
    The algorithm uses gaussian fit for subpixel precision.

    The best case would be to have two squares images of the same size.
    The algorithm is faster if the size is a power of 2.

def register_images(im0, im1, *, rmMean=True, correctScale=True):
    """Finds the rotation, scaling and translation of im1 relative to im0

    Parameters
    ----------
    im0: First image
    im1: Second image
    rmMean: Set to true to remove the mean (Default)

    Returns
    -------
    angle: The angle difference
    scale: The scale difference
    [y, x]: The offset
    im2: The rotated and translated second image

    Notes
    -----
    The algorithm uses gaussian fit for subpixel precision.

    The best case would be to have two squares images of the same size.
    The algorithm is faster if the size is a power of 2.
    """
    # sanitize input
    im0 = np.asarray(im0, dtype=np.float32)
    im1 = np.asarray(im1, dtype=np.float32)
    if rmMean:
        # remove mean
        im0 = im0 - im0.mean()
        im1 = im1 - im1.mean()
    # Compute DFT (THe images are resized to the same size)
    f0, f1 = dft_optsize_same(im0, im1)
    # Get rotation and scale
    angle, scale = find_rotation_scale(f0, f1, isccs=True)
    # Avoid fluctiuations
    if not correctScale:
        if np.abs(1 - scale) > 0.05:
            warnings.warn("Scale should be corrected")
        scale = 1
    # apply rotation and scale
    im2 = rotate_scale(im1, angle, scale)
    f2 = dft_optsize(im2, shape=f0.shape)
    # Find offset
    y, x = find_shift_dft(f0, f2, isccs=True)
    return angle, scale, [y, x], im2