skimage2.transform.AffineTransform#

class skimage2.transform.AffineTransform(matrix=None, *, scale=None, shear=None, rotation=None, translation=None, dimensionality=None)[source]#

Bases: ProjectiveTransform

Affine transformation.

In what follows, x refers to coordinates from the first coordinate axis, and y refers to coordinates from the second coordinate axis.

The transform has the following form:

X = a0 * x + a1 * y + a2
  =   sx * x * [cos(rotation) + tan(shear_y) * sin(rotation)]
    - sy * y * [tan(shear_x) * cos(rotation) + sin(rotation)]
    + translation_x

Y = b0 * x + b1 * y + b2
  =   sx * x * [sin(rotation) - tan(shear_y) * cos(rotation)]
    - sy * y * [tan(shear_x) * sin(rotation) - cos(rotation)]
    + translation_y

where sx and sy are scale factors in the x (first coordinate axis) and y (second coordinate axis) directions.

This is equivalent to applying the operations in the following order:

  1. Scale

  2. Shear

  3. Rotate

  4. Translate

The homogeneous transformation matrix is:

[[a0  a1  a2]
 [b0  b1  b2]
 [0   0    1]]

In 2D, the transformation parameters can be given as the homogeneous transformation matrix, above, or as the implicit parameters, scale, rotation, shear, and translation in x (a2) and y (b2). For 3D and higher, only the matrix form is allowed.

In narrower transforms, such as the Euclidean (only rotation and translation) or Similarity (rotation, translation, and a global scale factor) transforms, it is possible to specify 3D transforms using implicit parameters also.

Parameters:
matrix(D+1, D+1) array_like, optional

Homogeneous transformation matrix. If this matrix is provided, it is an error to provide any of scale, rotation, shear, or translation.

scale{s as float or (sx, sy) as array, list or tuple}, optional

Scale factor(s). If a single value, it will be assigned to both sx and sy. Only available for 2D.

Added in version 0.17: Added support for supplying a single scalar value.

shearfloat or 2-tuple of float, optional

The x and y shear angles, clockwise, by which these axes are rotated around the origin [2]. If a single value is given, take that to be the x shear angle, with the y angle remaining 0. Only available in 2D.

rotationfloat, optional

Rotation angle, clockwise, as radians. Only available for 2D.

translation(tx, ty) as array, list or tuple, optional

Translation parameters. Only available for 2D.

dimensionalityint, optional

Fallback number of dimensions for transform when none of matrix, scale, rotation, shear or translation are specified. If any of scale, rotation, shear or translation are specified, must equal 2 (the default).

Attributes:
params(D+1, D+1) array

Homogeneous transformation matrix.

Raises:
ValueError

If both matrix and any of the other parameters are provided.

References

[1]

Wikipedia, “Affine transformation”, https://en.wikipedia.org/wiki/Affine_transformation#Image_transformation

[2]

Wikipedia, “Shear mapping”, https://en.wikipedia.org/wiki/Shear_mapping

Examples

>>> import numpy as np
>>> import _skimage2 as ski2

Define a transform with an homogeneous transformation matrix:

>>> tform = ski2.transform.AffineTransform(np.diag([2., 3., 1.]))
>>> tform.params
array([[2., 0., 0.],
       [0., 3., 0.],
       [0., 0., 1.]])

Define a transform with parameters:

>>> tform = ski2.transform.AffineTransform(scale=4, rotation=0.2)
>>> np.round(tform.params, 2)
array([[ 3.92, -0.79,  0.  ],
       [ 0.79,  3.92,  0.  ],
       [ 0.  ,  0.  ,  1.  ]])

You can estimate a transformation to map between source and destination points:

>>> src = np.array([[150, 150],
...                 [250, 100],
...                 [150, 200]])
>>> dst = np.array([[200, 200],
...                 [300, 150],
...                 [150, 400]])
>>> tform = ski2.transform.AffineTransform.from_estimate(src, dst)
>>> np.allclose(tform.params, [[   0.5,   -1. ,  275. ],
...                            [   1.5,    4. , -625. ],
...                            [   0. ,    0. ,    1. ]])
True

Apply the transformation to some image data.

>>> img = ski2.data.astronaut()
>>> warped = ski2.transform.warp(img, inverse_map=tform.inverse)

The estimation can fail - for example, if all the input or output points are the same. If this happens, you will get a transform that is not “truthy” - meaning that bool(tform) is False:

>>> # A successfully estimated model is truthy (applying ``bool()``
>>> # gives ``True``):
>>> if tform:
...     print("Estimation succeeded.")
Estimation succeeded.
>>> # Not so for a degenerate transform with identical points.
>>> bad_src = np.ones((3, 2))
>>> bad_tform = ski2.transform.AffineTransform.from_estimate(
...      bad_src, dst)
>>> if not bad_tform:
...     print("Estimation failed.")
Estimation failed.

Trying to use this failed estimation transform result will give a suitable error:

>>> bad_tform.params
Traceback (most recent call last):
  ...
FailedEstimationAccessError: No attribute "params" for failed estimation ...
__init__(matrix=None, *, scale=None, shear=None, rotation=None, translation=None, dimensionality=None)[source]#
property dimensionality#

The dimensionality of the transformation.

estimate(src, dst, weights=None)[source]#

Estimate the transformation from a set of corresponding points.

Deprecated since version 0.26: estimate is deprecated since version 0.26 and will be removed in version 2.2. Please use AffineTransform.from_estimate class constructor instead.

You can determine the over-, well- and under-determined parameters with the total least-squares method.

Number of source and destination coordinates must match.

In what follows, x refers to coordinates from the first coordinate axis, and y refers to coordinates from the second coordinate axis.

The transformation is defined as:

X = (a0*x + a1*y + a2) / (c0*x + c1*y + 1)
Y = (b0*x + b1*y + b2) / (c0*x + c1*y + 1)

These equations can be transformed to the following form:

0 = a0*x + a1*y + a2 - c0*x*X - c1*y*X - X
0 = b0*x + b1*y + b2 - c0*x*Y - c1*y*Y - Y

which exist for each set of corresponding points, so we have a set of N * 2 equations. The coefficients appear linearly so we can write A x = 0, where:

A   = [[x y 1 0 0 0 -x*X -y*X -X]
       [0 0 0 x y 1 -x*Y -y*Y -Y]
        ...
        ...
      ]
x.T = [a0 a1 a2 b0 b1 b2 c0 c1 c3]

In case of total least-squares the solution of this homogeneous system of equations is the right singular vector of A which corresponds to the smallest singular value normed by the coefficient c3.

Weights can be applied to each pair of corresponding points to indicate, particularly in an overdetermined system, if point pairs have higher or lower confidence or uncertainties associated with them. From the matrix treatment of least squares problems, these weight values are normalized, square-rooted, then built into a diagonal matrix, by which A is multiplied.

In case of the affine transformation the coefficients c0 and c1 are 0. Thus the system of equations is:

A   = [[x y 1 0 0 0 -X]
       [0 0 0 x y 1 -Y]
        ...
        ...
      ]
x.T = [a0 a1 a2 b0 b1 b2 c3]
Parameters:
srcarray_like of shape (N, 2)

Source coordinates.

dstarray_like of shape (N, 2)

Destination coordinates.

weightsarray_like of shape (N,), optional

Relative weight values for each pair of points.

Returns:
successbool

True, if model estimation succeeds.

classmethod from_estimate(dst, weights=None)[source]#

Estimate the transformation from a set of corresponding points.

You can determine the over-, well- and under-determined parameters with the total least-squares method.

Number of source and destination coordinates must match.

In what follows, x refers to coordinates from the first coordinate axis, and y refers to coordinates from the second coordinate axis.

The transformation is defined as:

X = (a0*x + a1*y + a2) / (c0*x + c1*y + 1)
Y = (b0*x + b1*y + b2) / (c0*x + c1*y + 1)

These equations can be transformed to the following form:

0 = a0*x + a1*y + a2 - c0*x*X - c1*y*X - X
0 = b0*x + b1*y + b2 - c0*x*Y - c1*y*Y - Y

which exist for each set of corresponding points, so we have a set of N * 2 equations. The coefficients appear linearly so we can write A x = 0, where:

A   = [[x y 1 0 0 0 -x*X -y*X -X]
       [0 0 0 x y 1 -x*Y -y*Y -Y]
        ...
        ...
      ]
x.T = [a0 a1 a2 b0 b1 b2 c0 c1 c3]

In case of total least-squares the solution of this homogeneous system of equations is the right singular vector of A which corresponds to the smallest singular value normed by the coefficient c3.

Weights can be applied to each pair of corresponding points to indicate, particularly in an overdetermined system, if point pairs have higher or lower confidence or uncertainties associated with them. From the matrix treatment of least squares problems, these weight values are normalized, square-rooted, then built into a diagonal matrix, by which A is multiplied.

In case of the affine transformation the coefficients c0 and c1 are 0. Thus the system of equations is:

A   = [[x y 1 0 0 0 -X]
       [0 0 0 x y 1 -Y]
        ...
        ...
      ]
x.T = [a0 a1 a2 b0 b1 b2 c3]
Parameters:
srcarray_like of shape (N, 2)

Source coordinates.

dstarray_like of shape (N, 2)

Destination coordinates.

weightsarray_like of shape (N,), optional

Relative weight values for each pair of points.

Returns:
tfSelf or FailedEstimation

An instance of the transformation if the estimation succeeded. Otherwise, we return a special FailedEstimation object to signal a failed estimation. Testing the truth value of the failed estimation object will return False. E.g.

tf = AffineTransform.from_estimate(...)
if not tf:
    raise RuntimeError(f"Failed estimation: {tf}")
classmethod identity(dimensionality=None)[source]#

Identity transform

Parameters:
dimensionality{None, int}, optional

Dimensionality of identity transform.

Returns:
tformtransform

Transform such that np.all(tform(pts) == pts).

property inverse#

Return a transform object representing the inverse.

residuals(src, dst)[source]#

Determine residuals of transformed destination coordinates.

For each transformed source coordinate the Euclidean distance to the respective destination coordinate is determined.

Parameters:
srcndarray of shape (N, 2)

Source coordinates.

dstndarray of shape (N, 2)

Destination coordinates.

Returns:
residualsndarray of shape (N,)

Residual for coordinate.

property rotation#
property scale#
scaling = 'rms'#
property shear#
property translation#