Affine¶
- class menpo.transform.homogeneous.affine.Affine(h_matrix, copy=True, skip_checks=False)[source]¶
-
Base class for all n-dimensional affine transformations. Provides methods to break the transform down into it’s constituent scale/rotation/translation, to view the homogeneous matrix equivalent, and to chain this transform with other affine transformations.
Parameters: h_matrix : (n_dims + 1, n_dims + 1) ndarray
The homogeneous matrix of the affine transformation.
copy : bool, optional
If False avoid copying h_matrix for performance.
skip_checks : bool, optional
If True avoid sanity checks on h_matrix for performance.
- apply(x, **kwargs)¶
Applies this transform to x.
If x is Transformable, x will be handed this transform object to transform itself non-destructively (a transformed copy of the object will be returned).
If not, x is assumed to be an ndarray. The transformation will be non-destructive, returning the transformed version.
Any kwargs will be passed to the specific transform _apply() method.
Parameters: x : Transformable or (n_points, n_dims) ndarray
The array or object to be transformed.
kwargs : dict
Passed through to _apply().
Returns: transformed : type(x)
The transformed object or array
- apply_inplace(x, **kwargs)¶
Applies this transform to a Transformable x destructively.
Any kwargs will be passed to the specific transform _apply() method.
Parameters: x : Transformable
The Transformable object to be transformed.
kwargs : dict
Passed through to _apply().
Returns: transformed : type(x)
The transformed object
- as_vector(**kwargs)¶
Returns a flattened representation of the object as a single vector.
Returns: vector : (N,) ndarray
The core representation of the object, flattened into a single vector. Note that this is always a view back on to the original object, but is not writable.
- compose_after(transform)¶
A Transform that represents this transform composed after the given transform:
c = a.compose_after(b) c.apply(p) == a.apply(b.apply(p))
a and b are left unchanged.
This corresponds to the usual mathematical formalism for the compose operator, o.
An attempt is made to perform native composition, but will fall back to a TransformChain as a last resort. See composes_with for a description of how the mode of composition is decided.
Parameters: transform : Transform
Transform to be applied before self
Returns: transform : Transform or TransformChain
If the composition was native, a single new Transform will be returned. If not, a TransformChain is returned instead.
- compose_after_inplace(transform)¶
Update self so that it represents this transform composed after the given transform:
a_orig = deepcopy(a) a.compose_after_inplace(b) a.apply(p) == a_orig.apply(b.apply(p))
a is permanently altered to be the result of the composition. b is left unchanged.
Parameters: transform : composes_inplace_with
Transform to be applied before self
Raises: ValueError :
If transform isn’t an instance of composes_inplace_with
- compose_before(transform)¶
A Transform that represents this transform composed before the given transform:
c = a.compose_before(b) c.apply(p) == b.apply(a.apply(p))
a and b are left unchanged.
An attempt is made to perform native composition, but will fall back to a TransformChain as a last resort. See composes_with for a description of how the mode of composition is decided.
Parameters: transform : Transform
Transform to be applied after self
Returns: transform : Transform or TransformChain
If the composition was native, a single new Transform will be returned. If not, a TransformChain is returned instead.
- compose_before_inplace(transform)¶
Update self so that it represents this transform composed before the given transform:
a_orig = deepcopy(a) a.compose_before_inplace(b) a.apply(p) == b.apply(a_orig.apply(p))
a is permanently altered to be the result of the composition. b is left unchanged.
Parameters: transform : composes_inplace_with
Transform to be applied after self
Raises: ValueError :
If transform isn’t an instance of composes_inplace_with
- copy()¶
An efficient copy of this Homogeneous family transform (i.e. one with the same homogeneous matrix).
If you need all state to be perfectly replicated, consider using deepcopy() instead.
Returns: transform : type(self)
A copy fo the transform with the same h_matrix.
- d_dp(points)[source]¶
The first order derivative of this Affine transform wrt parameter changes evaluated at points.
The Jacobian generated (for 2D) is of the form:
x 0 y 0 1 0 0 x 0 y 0 1
This maintains a parameter order of:
W(x;p) = [1 + p1 p3 p5] [x] [p2 1 + p4 p6] [y] [1]
Parameters: points : (n_points, n_dims) ndarray
The set of points to calculate the jacobian for.
Returns: (n_points, n_params, n_dims) ndarray :
The jacobian wrt parametrization
- d_dx(points)[source]¶
The first order derivative of this Affine transform wrt spatial changes evaluated at points.
The Jacobian for a given point (for 2D) is of the form:
Jx = [(1 + a), -b ] Jy = [ b, (1 + a)] J = [Jx, Jy] = [[(1 + a), -b], [b, (1 + a)]]
where a and b come from:
- W(x;p) = [1 + a -b tx] [x]
- [b 1 + a ty] [y]
- [1]
Hence it is simply the linear component of the transform.
Parameters: points: ndarray shape (n_points, n_dims) :
The spatial points at which the derivative should be evaluated.
Returns: d_dx: (1, n_dims, n_dims) ndarray :
The jacobian wrt spatial changes.
d_dx[0, j, k] is the scalar differential change that the j’th dimension of the i’th point experiences due to a first order change in the k’th dimension.
Note that because the jacobian is constant across space the first axis is length 1 to allow for broadcasting.
- decompose()[source]¶
Decompose this transform into discrete Affine Transforms.
Useful for understanding the effect of a complex composite transform.
Returns: transforms : list of DiscreteAffine
Equivalent to this affine transform, such that:
reduce(lambda x,y: x.chain(y), self.decompose()) == self
- from_vector(vector)¶
Build a new instance of the object from it’s vectorized state.
self is used to fill out the missing state required to rebuild a full object from it’s standardized flattened state. This is the default implementation, which is which is a deepcopy of the object followed by a call to from_vector_inplace(). This method can be overridden for a performance benefit if desired.
Parameters: vector : (n_parameters,) ndarray
Flattened representation of the object.
Returns: transform : type(self)
An new instance of this class.
- from_vector_inplace(p)[source]¶
Updates this Affine in-place from the new parameters. See from_vector for details of the parameter format
- pseudoinverse_vector(vector)¶
The vectorized pseudoinverse of a provided vector instance. Syntactic sugar for:
self.from_vector(vector).pseudoinverse.as_vector()
Can be much faster than the explict call as object creation can be entirely avoided in some cases.
Parameters: vector : (n_parameters,) ndarray
A vectorized version of self
Returns: pseudoinverse_vector : (n_parameters,) ndarray
The pseudoinverse of the vector provided
- set_h_matrix(value, copy=True, skip_checks=False)¶
Updates h_matrix, optionally performing sanity checks.
Note that it won’t always be possible to manually specify the h_matrix through this method, specifically if changing the h_matrix could change the nature of the transform. See h_matrix_is_mutable for how you can discover if the h_matrix is allowed to be set for a given class.
Parameters: value : ndarray
The new homogeneous matrix to set
copy : bool, optional
If False do not copy the h_matrix. Useful for performance.
skip_checks : bool, optional
If True skip checking. Useful for performance.
Raises: NotImplementedError :
If h_matrix_is_mutable returns False.
- composes_with¶
Any Homogeneous can compose with any other Homogeneous.
- h_matrix_is_mutable¶
True iff set_h_matrix() is permitted on this type of transform. If this returns False calls to :meth:``set_h_matrix` will raise a NonImplimentedError.
Type: bool
- linear_component[source]¶
The linear component of this affine transform.
Type: (n_dims, n_dims) ndarray
- n_parameters[source]¶
n_dims * (n_dims + 1) parameters - every element of the matrix bar the homogeneous part.
Type: int Examples
2D Affine: 6 parameters:
[p1, p3, p5] [p2, p4, p6]
3D Affine: 12 parameters:
[p1, p4, p7, p10] [p2, p5, p8, p11] [p3, p6, p9, p12]
- pseudoinverse¶
The pseudoinverse of the transform - that is, the transform that results from swapping source and target, or more formally, negating the transforms parameters. If the transform has a true inverse this is returned instead.
Type: type(self)