Skip to content

Corregistrator

siapy.transformations.corregistrator

map_affine_approx_2d

map_affine_approx_2d(points_ref: ndarray, points_mov: ndarray) -> ndarray

Affine transformation

PARAMETER DESCRIPTION
points_ref

TYPE: ndarray

points_mov

TYPE: ndarray

Source code in siapy/transformations/corregistrator.py
16
17
18
19
20
21
22
23
24
def map_affine_approx_2d(points_ref: np.ndarray, points_mov: np.ndarray) -> np.ndarray:
    """Affine transformation"""
    # U = T*X -> T = U*X'(X*X')^-1
    matx_2d = (
        points_ref.transpose()
        @ points_mov
        @ np.linalg.inv(points_mov.transpose() @ points_mov)
    )
    return matx_2d

affine_matx_2d

affine_matx_2d(scale: tuple[float, float] | Sequence[float] = (1, 1), trans: tuple[float, float] | Sequence[float] = (0, 0), rot: float = 0, shear: tuple[float, float] | Sequence[float] = (0, 0)) -> ndarray

Create arbitrary affine transformation matrix

PARAMETER DESCRIPTION
scale

TYPE: tuple[float, float] | Sequence[float] DEFAULT: (1, 1)

trans

TYPE: tuple[float, float] | Sequence[float] DEFAULT: (0, 0)

rot

TYPE: float DEFAULT: 0

shear

TYPE: tuple[float, float] | Sequence[float] DEFAULT: (0, 0)

Source code in siapy/transformations/corregistrator.py
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
def affine_matx_2d(
    scale: tuple[float, float] | Sequence[float] = (1, 1),
    trans: tuple[float, float] | Sequence[float] = (0, 0),
    rot: float = 0,
    shear: tuple[float, float] | Sequence[float] = (0, 0),
) -> np.ndarray:
    """Create arbitrary affine transformation matrix"""
    rot = rot * np.pi / 180
    matx_scale = np.array(((scale[0], 0, 0), (0, scale[1], 0), (0, 0, 1)))
    matx_trans = np.array(((1, 0, trans[0]), (0, 1, trans[1]), (0, 0, 1)))
    matx_rot = np.array(
        (
            (np.cos(rot), -np.sin(rot), 0),
            (np.sin(rot), np.cos(rot), 0),
            (0, 0, 1),
        )
    )
    matx_shear = np.array(((1, shear[0], 0), (shear[1], 1, 0), (0, 0, 1)))
    matx_2d = np.dot(matx_trans, np.dot(matx_shear, np.dot(matx_rot, matx_scale)))
    return matx_2d

align

align(pixels_ref: Pixels, pixels_mov: Pixels, *, eps: float = 1e-06, max_iter: int = 50, plot_progress: bool = False) -> tuple[ndarray, ndarray]

Align interactive corresponding points

PARAMETER DESCRIPTION
pixels_ref

TYPE: Pixels

pixels_mov

TYPE: Pixels

eps

TYPE: float DEFAULT: 1e-06

max_iter

TYPE: int DEFAULT: 50

plot_progress

TYPE: bool DEFAULT: False

Source code in siapy/transformations/corregistrator.py
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
def align(
    pixels_ref: Pixels,
    pixels_mov: Pixels,
    *,
    eps: float = 1e-6,
    max_iter: int = 50,
    plot_progress: bool = False,
) -> tuple[np.ndarray, np.ndarray]:
    """Align interactive corresponding points"""

    points_ref = pixels_ref.df_homogenious().to_numpy()
    points_mov = pixels_mov.df_homogenious().to_numpy()

    matrices = []
    errors = []
    idx = 0
    if plot_progress:
        points_mov_orig = points_mov
        fig = plt.figure()
        ax = fig.add_subplot(111)

    while True:
        points_ref_corr = np.array(points_ref)
        points_mov_corr = np.array(points_mov)

        matx_2d_combined = map_affine_approx_2d(points_ref_corr, points_mov_corr)
        points_mov = np.dot(points_mov, matx_2d_combined.transpose())

        matrices.append(matx_2d_combined)
        errors.append(
            np.sqrt(np.sum((points_ref_corr[:, :2] - points_mov_corr[:, :2]) ** 2))
        )
        idx = idx + 1

        # check for convergence
        matx_diff = np.abs(matx_2d_combined - affine_matx_2d())
        if idx > max_iter or np.all(matx_diff < eps):
            break

    matx_2d_combined = affine_matx_2d()  # initialize with identity matrix
    for matx_2d in matrices:
        if plot_progress:
            points_mov_corr = np.dot(points_mov_orig, matx_2d_combined.transpose())
            ax.clear()
            ax.plot(points_ref[:, 0], points_ref[:, 1], "ob")
            ax.plot(points_mov_corr[:, 0], points_mov_corr[:, 1], "om")
            fig.canvas.draw()
            plt.pause(1)

        # multiply all matrices to get the final transformation
        matx_2d_combined = np.dot(matx_2d, matx_2d_combined)

    errors_np = np.array(errors)

    return matx_2d_combined, errors_np

transform

transform(pixels: Pixels, transformation_matx: ndarray)

Transform pixels

PARAMETER DESCRIPTION
pixels

TYPE: Pixels

transformation_matx

TYPE: ndarray

Source code in siapy/transformations/corregistrator.py
106
107
108
109
110
111
112
def transform(pixels: Pixels, transformation_matx: np.ndarray):
    """Transform pixels"""
    points_transformed = np.dot(
        pixels.df_homogenious().to_numpy(), transformation_matx.transpose()
    )
    points_transformed = np.round(points_transformed[:, :2]).astype("int")
    return Pixels.from_iterable(points_transformed)