pydistort.Extrinsic#

class pydistort.Extrinsic(rvec: ndarray | None = None, tvec: ndarray | None = None)[source]#

Note

This class represents the extrinsic transformation, which is the first step of the process.

The process to correspond a 3D-world point to a 2D-image point in the stenopic camera model is as follows:

  1. The world_3dpoints (\(X_W\)) are expressed in the camera coordinate system using the rotation and translation matrices to obtain the camera_3dpoints (\(X_C\)).

  2. The camera_3dpoints (\(X_C\)) are normalized by dividing by the third coordinate to obtain the normalized_points (\(x_N\)).

  3. The normalized_points (\(x_N\)) are distorted by the distortion model using the coefficients \(\{\lambda_1, \lambda_2, \lambda_3, \ldots\}\) to obtain the distorted_points (\(x_D\)).

  4. The distorted_points (\(x_D\)) are projected onto the image plane using the intrinsic matrix K to obtain the image_points (\(x_I\)).

This tranformation can be decomposed into 3 main steps:

  1. Extrinsic: Transform the world 3dpoints to normalized_points using the extrinsic parameters (rotation and translation).

  2. Distortion: Transform the normalized_points to distorted_points using the distortion model.

  3. Intrinsic: Transform the distorted_points to image_points using the intrinsic matrix K.

Note

To manage only world_3dpoints to camera_3dpoints, use the package py3dframe (Artezaru/py3dframe).

The equation used for the extrinsic transformation is:

\[\begin{split}\begin{align*} X_C &= R \cdot X_W + T \\ x_N &= \frac{X_C}{Z_C} \\ \end{align*}\end{split}\]

where \(R\) is the rotation matrix, \(T\) is the translation vector.

Note

To compute the translation vector and the rotation vector, you can use cv2.Rodrigues() or py3dframe.Frame with convention 0.

Parameters:
  • rvec (Optional[numpy.ndarray]) – The rotation vector of the camera. Shape (3,). If None, the rotation vector is not set.

  • tvec (Optional[numpy.ndarray]) – The translation vector of the camera. Shape (3,). If None, the translation vector is not set.

Example

Create an extrinsic object with a rotation vector and a translation vector:

import numpy as np
from pydistort import Extrinsic

rvec = np.array([0.1, 0.2, 0.3])
tvec = np.array([0.5, 0.5, 0.5])

extrinsic = Extrinsic(rvec, tvec)

Then you can use the extrinsic object to transform world_3dpoints to camera_points:

world_3dpoints = np.array([[1, 2, 3],
                           [4, 5, 6],
                           [7, 8, 9],
                           [10, 11, 12]])

result = extrinsic.transform(world_3dpoints)
normalized_points = result.normalized_points
print(normalized_points)

You can also access to the jacobian of the extrinsic transformation:

result = extrinsic.transform(world_3dpoints, dx=True, dp=True)
normalized_points_dx = result.jacobian_dx  # Shape (..., 2, 3)
normalized_points_dp = result.jacobian_dp  # Shape (..., 2, 6)
print(normalized_points_dx)
print(normalized_points_dp)

The inverse transformation can be computed using the inverse_transform method: By default, the depth is assumed to be 1.0 for all points, but you can provide a specific depth for each point with shape (…,).

depth = np.array([1.0, 2.0, 3.0, 4.0])  # Example depth values for each point

inverse_result = extrinsic.inverse_transform(normalized_points, dx=True, dp=True, depth=depth)
world_3dpoints = inverse_result.transformed_points  # Shape (..., 3)
print(world_3dpoints)

Note

The jacobian with respect to the depth is not computed.

See also

For more information about the transformation process, see:

property Nparams: int#

Property to return the number of parameters of the transformation.

The number of parameters must be a non-negative integer representing the number of parameters of the transformation.

Returns:

The number of parameters of the transformation.

Return type:

int

_abc_impl = <_abc._abc_data object>#
_inverse_transform(normalized_points: ndarray, *, dx: bool = False, dp: bool = False, depth: ndarray | None = None) tuple[ndarray, ndarray | None, ndarray | None][source]#

This method is called by the pydistort.Transform.inverse_transform() method to perform the inverse extrinsic transformation. This method allows to transform the normalized_points back to world_3dpoints using the extrinsic parameters (rotation and translation).

Note

For _inverse_transform the input must have shape (Npoints, 2) with float64 type. The output has shape (Npoints, 3) for the world 3D points and (Npoints, 3, 2)

The equation used for the transformation is:

\[[X_W, Y_W, Z_W]^T = R^{-1} \cdot ([X_N, Y_N, 1]^T \cdot Z_C - T)\]

where \(R^{-1}\) is the inverse of the rotation matrix, \(T\) is the translation vector.

The depth parameter is used to scale the normalized points to the world 3D points. By default, the depth is assumed to be 1.0 for all points, but you can provide a specific depth for each point with shape (…,).

Warning

This method is not designed to be used directly for the transformation of points. No checks are performed on the input points, so it is the user’s responsibility to ensure that the input points are valid.

Parameters:
  • normalized_points (numpy.ndarray) – Array of normalized points to be transformed with shape (Npoints, 2).

  • dx (bool, optional) – If True, the Jacobian of the world 3D points with respect to the input normalized points is computed. Default is False. The output will be a 2D array of shape (Npoints, 3, 2).

  • dp (bool, optional) – If True, the Jacobian of the world 3D points with respect to the pose parameters is computed. Default is False. The output will be a 2D array of shape (Npoints, 3, 6).

  • depth (Optional[numpy.ndarray], optional) – The depth of the points in the world coordinate system. If None, the depth is assumed to be 1.0 for all points. The shape should be (…,). If provided, it will be used to scale the normalized points to the world 3D points.

Returns:

  • world_3dpoints (numpy.ndarray) – The transformed world 3D points. It will be a 2D array of shape (Npoints, 3).

  • jacobian_dx (Optional[numpy.ndarray]) – The Jacobian of the world 3D points with respect to the input normalized points if dx is True. Otherwise None. It will be a 2D array of shape (Npoints, 3, 2) if transpose is False.

  • jacobian_dp (Optional[numpy.ndarray]) – The Jacobian of the world 3D points with respect to the pose parameters if dp is True. Otherwise None. It will be a 2D array of shape (Npoints, 3, 6) if transpose is False.

_transform(world_3dpoints: ndarray, *, dx: bool = False, dp: bool = False) tuple[ndarray, ndarray | None, ndarray | None][source]#

This method is called by the pydistort.Transform.transform() method to perform the extrinsic transformation. This method allows to transform the world_3dpoints to normalized_points using the extrinsic parameters (rotation and translation).

Note

For _transform the input must have shape (Npoints, 3) with float64 type. The output has shape (Npoints, 2) for the normalized points and (Npoints, 2, 3) for the jacobian with respect to the 3D world points and (Npoints, 2, 6) for the jacobian with respect to the extrinsic parameters.

The equation used for the transformation is:

\[[X_C, Y_C, Z_C]^T = R \cdot [X_W, Y_W, Z_W]^T + T\]
\[x_N = \frac{X_C}{Z_C}\]
\[y_N = \frac{Y_C}{Z_C}\]

where \(R\) is the rotation matrix, \(T\) is the translation vector.

Warning

This method is not designed to be used directly for the transformation of points. No checks are performed on the input points, so it is the user’s responsibility to ensure that the input points are valid.

Parameters:
  • world_3dpoints (numpy.ndarray) – Array of world 3dpoints to be transformed with shape (Npoints, 3).

  • dx (bool, optional) – If True, the Jacobian of the normalized points with respect to the input 3D world points is computed. Default is False. The output will be a 2D array of shape (Npoints, 2, 3).

  • dp (bool, optional) – If True, the Jacobian of the normalized points with respect to the pose parameters is computed. Default is False. The output will be a 2D array of shape (Npoints, 2, 6).

Returns:

  • normalized_points (numpy.ndarray) – The transformed image points in pixels. It will be a 2D array of shape (Npoints, 2).

  • jacobian_dx (Optional[numpy.ndarray]) – The Jacobian of the normalized points with respect to the input 3D world points if dx is True. Otherwise None. It will be a 2D array of shape (Npoints, 2, 2) if transpose is False.

  • jacobian_dp (Optional[numpy.ndarray]) – The Jacobian of the normalized points with respect to the pose parameters if dp is True. Otherwise None. It will be a 2D array of shape (Npoints, 2, 6) if transpose is False.

property frame: Frame | None#

Get or set the 3D frame of the extrinsic transformation.

The frame is a py3dframe.Frame object representing the 3D frame of the camera in the world coordinate system.

See also

Artezaru/py3dframe for more information about the Frame class.

Returns:

The 3D frame of the camera in the world coordinate system. (or None if not set)

Return type:

Optional[Frame]

property input_dim: int#

Property to return the input dimension of the transformation.

The input dimension must be a positive integer representing the number of dimensions of the input points.

Returns:

The number of dimensions of the input points.

Return type:

int

property inverse_result_class: type#

Property to return the class used for the result of the inverse transformation.

The default is InverseTransformResult, but subclasses can override this to return a different class.

Returns:

The class used for the result of the inverse transformation.

Return type:

type

is_set() bool[source]#

Check if the extrinsic parameters are set.

Returns:

True if both rotation vector and translation vector are set, False otherwise.

Return type:

bool

property output_dim: int#

Property to return the output dimension of the transformation.

The output dimension must be a positive integer representing the number of dimensions of the output points.

Returns:

The number of dimensions of the output points.

Return type:

int

property result_class: type#

Property to return the class used for the result of the transformation.

The default is TransformResult, but subclasses can override this to return a different class.

Returns:

The class used for the result of the transformation.

Return type:

type

property rmat: ndarray | None#
property rotation_matrix: ndarray | None#

Get or set the rotation matrix of the extrinsic transformation.

The rotation matrix is a numpy array of shape (3, 3) representing the rotation of the camera in the world coordinate system.

Note

The rotation matrix is computed using the Rodrigues formula. An alias for rotation_matrix is rmat.

Returns:

The rotation matrix of the camera in the world coordinate system. (or None if not set)

Return type:

Optional[numpy.ndarray]

property rotation_vector: ndarray | None#

Get or set the rotation vector rvec of the extrinsic transformation.

The rotation vector is a numpy array of shape (3,) representing the rotation of the camera in the world coordinate system.

Note

An alias for rotation_vector is rvec.

See also

Returns:

The rotation vector of the camera in the world coordinate system. (or None if not set)

Return type:

Optional[numpy.ndarray]

property rvec: ndarray | None#
property translation_vector: ndarray | None#

Get or set the translation vector tvec of the extrinsic transformation.

The translation vector is a numpy array of shape (3,) representing the translation of the camera in the world coordinate system.

Note

An alias for translation_vector is tvec.

See also

Returns:

The translation vector of the camera in the world coordinate system. (or None if not set)

Return type:

Optional[numpy.ndarray]

property tvec: ndarray | None#
class pydistort.ExtrinsicResult(transformed_points: ndarray, jacobian_dx: ndarray | None = None, jacobian_dp: ndarray | None = None)[source]#

Bases: TransformResult

Subclass of TransformResult to represent the result of the extrinsic transformation.

This class is used to store the result of transforming the world_3dpoints to normalized_points, and the optional Jacobians.

  • transformed_points: The transformed normalized points in the camera coordinate system.

  • jacobian_dx: The Jacobian of the normalized points with respect to the input 3D world points if dx is True. Otherwise None. Shape (…, 2, 3).

  • jacobian_dp: The Jacobian of the normalized points with respect to the pose parameters (rotation and translation) if dp is True. Otherwise None. Shape (…, 2, 6), where the last dimension represents (dr, dt).

Some properties are provided for convenience:

  • normalized_points: Alias for transformed_points to represent the transformed normalized points. Shape (…, 2).

  • jacobian_dr: Part of the Jacobian with respect to the rotation vector. Shape (…, 2, 3).

  • jacobian_dt: Part of the Jacobian with respect to the translation vector. Shape (…, 2, 3).

Warning

If transpose is set to True during the transformation, the output points will have shape (output_dim, …) instead of (…, output_dim), same for the Jacobian matrices.

property jacobian_dr: ndarray | None#

Get the Jacobian of the normalized points with respect to the rotation vector.

Returns:

The Jacobian with respect to rotation (dr). Shape (…, 2, 3).

Return type:

Optional[numpy.ndarray]

property jacobian_dt: ndarray | None#

Get the Jacobian of the normalized points with respect to the translation vector.

Returns:

The Jacobian with respect to translation (dt). Shape (…, 2, 3).

Return type:

Optional[numpy.ndarray]

property normalized_points: ndarray#

Get the transformed normalized points in the camera coordinate system.

Returns:

The transformed normalized points. Shape (…, 2).

Return type:

numpy.ndarray

class pydistort.InverseExtrinsicResult(transformed_points: ndarray, jacobian_dx: ndarray | None = None, jacobian_dp: ndarray | None = None)[source]#

Bases: InverseTransformResult

Subclass of InverseTransformResult to represent the result of the inverse extrinsic transformation.

This class is used to store the result of transforming the normalized_points back to world_3dpoints, and the optional Jacobians.

  • transformed_points: The transformed world 3D points. Shape (…, 3).

  • jacobian_dx: The Jacobian of the world 3D points with respect to the input normalized points if dx is True. Otherwise None. Shape (…, 3, 2).

  • jacobian_dp: The Jacobian of the world 3D points with respect to the pose parameters (rotation and translation) if dp is True. Otherwise None. Shape (…, 3, 6), where the last dimension represents (dr, dt).

Some properties are provided for convenience:

  • world_3dpoints: Alias for transformed_points to represent the transformed world 3D points. Shape (…, 3).

  • jacobian_dr: Part of the Jacobian with respect to the rotation vector. Shape (…, 3, 3).

  • jacobian_dt: Part of the Jacobian with respect to the translation vector. Shape (…, 3, 3).

Warning

If transpose is set to True during the inverse transformation, the output points will have shape (input_dim, …) instead of (…, input_dim), same for the Jacobian matrices.

property jacobian_dr: ndarray | None#

Get the Jacobian of the world 3D points with respect to the rotation vector.

Returns:

The Jacobian with respect to rotation (dr). Shape (…, 3, 3).

Return type:

Optional[numpy.ndarray]

property jacobian_dt: ndarray | None#

Get the Jacobian of the world 3D points with respect to the translation vector.

Returns:

The Jacobian with respect to translation (dt). Shape (…, 3, 3).

Return type:

Optional[numpy.ndarray]

property world_3dpoints: ndarray#

Get the transformed world 3D points.

Returns:

The transformed world 3D points. Shape (…, 3).

Return type:

numpy.ndarray