pydistort.Cv2Distortion#
- class pydistort.Cv2Distortion(parameters: ndarray | None = None, Nparams: Integral | None = None)[source]#
Class to apply distortion with the OpenCV distortion model.
Distort the given
normalized_points
using the distortion model to obtain thedistorted_points
.\[x_D = \text{distort}(x_N, \lambda_1, \lambda_2, \lambda_3, \ldots)\]The model of OpenCV is the following one:
\[\begin{split}\begin{bmatrix} x_D \\ y_D \end{bmatrix} = \begin{bmatrix} x_N \frac{1+k_1 r^2 + k_2 r^4 + k_3 r^6}{1 + k_4 r^2 + k_5 r^4 + k_6 r^6} + 2p_1 x_N y_N + p_2 (r^2 + 2x_N^2) + s_1 r^2 + s_2 r^4 \\ y_N \frac{1+k_1 r^2 + k_2 r^4 + k_3 r^6}{1 + k_4 r^2 + k_5 r^4 + k_6 r^6} + p_1 (r^2 + 2y_N^2) + 2p_2 x_N y_N + s_3 r^2 + s_4 r^4 \end{bmatrix}\end{split}\]where \(r^2 = x_N^2 + y_N^2\) and \(k_i\) are the radial distortion coefficients, \(p_i\) are the tangential distortion coefficients and \(s_i\) are the thin prism distortion coefficients.
Then a perspective transformation is applied using \(\tau_x\) and \(\tau_y\) to obtain the final distorted points.
\[\begin{split}\begin{bmatrix} x_D \\ y_D \\ 1 \end{bmatrix} = \begin{bmatrix} R_{33}(\tau) & 0 & -R_{13}(\tau) \\ 0 & R_{33}(\tau) & -R_{23}(\tau) \\ 0 & 0 & 1 \end{bmatrix} R(\tau) \begin{bmatrix} x_D \\ y_D \\ 1 \end{bmatrix}\end{split}\]where :
\[\begin{split}R(\tau) = \begin{bmatrix} cos(\tau_y) & sin(\tau_x)sin(\tau_y) & -cos(\tau_x)sin(\tau_y) \\ 0 & cos(\tau_x) & sin(\tau_x) \\ sin(\tau_y) & -sin(\tau_x)cos(\tau_y) & cos(\tau_x)cos(\tau_y) \end{bmatrix}\end{split}\]and \(R_{ij}(\tau)\) are the elements of the rotation matrix.
See also
https://docs.opencv.org/3.4/d9/d0c/group__calib3d.html for the OpenCV documentation
OpenCV can use various models for distortion,
N = 4 parameters : \((k_1, k_2, p_1, p_2)\) : radial and tangential distortion
N = 5 parameters : \((k_1, k_2, p_1, p_2, k_3)\) : radial and tangential distortion with third order radial distortion
N = 8 parameters : \((k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6)\) : radial and tangential distortion with fractional radial distortion
N = 12 parameters : \((k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6, s_1, s_2, s_3, s_4)\) : radial and tangential distortion with thin prism distortion
N = 14 parameters : \((k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6, s_1, s_2, s_3, s_4, \tau_x, \tau_y)\) : radial and tangential distortion with thin prism distortion and perspective transformation
If the number of input parameters is not equal to the number of parameters required by the model, the other parameters are set to 0.
Warning
If the number of parameters
Nparams
is given during instantiation, the given parameters are truncated or extended to the given number of parameters.- Parameters:
parameters (numpy.ndarray, optional) – The parameters of the distortion model. If None, no distortion is applied. The default is None.
Nparams (int, optional) – The number of parameters of the distortion model. If None, the number of parameters is set to the number of parameters of the model. The default is None. Must be in [0, 4, 5, 8, 12, 14] if given.
Examples
Create an distortion object with a given model:
import numpy as np from pydistort import Cv2Distortion # Create a distortion object with 8 parameters distortion = Cv2Distortion(np.array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8])) # Model with 8 parameters
Then you can use the distortion object to distort
normalized_points
:normalized_points = np.array([[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]]) # shape (3, 2) result = distortion.transform(normalized_points): #alias distort is also available distorted_points = result.distorted_points # shape (3, 2) -> distorted points in (normalized) image coordinates print(distorted_points)
You can also access to the jacobian of the distortion transformation:
result = distortion.transform(distorted_points, dx=True, dp=True) distorted_points_dx = result.jacobian_dx # Jacobian of the image points with respect to the distorted points # Shape (..., 2, 3) distorted_points_dp = result.jacobian_dp # Jacobian of the image points with respect to the intrinsic parameters # Shape (..., 2, Nparams)
The parameters are ordered as given in the model description above.
- property Nparams: int#
Get the number of parameters of the distortion model.
- Returns:
The number of parameters of the distortion model.
- Return type:
int
- _abc_impl = <_abc._abc_data object>#
- _compute_tilt_matrix(dp: bool = True, inv: bool = True) Tuple[ndarray, ndarray | None, ndarray | None, ndarray | None] [source]#
Compute the tilt matrix for the perspective transformation for N = 14 (only).
The tilt matrix is computed using the following equation:
\[R_{\text{tilt}}{\tau} = R_Z[R_Y R_X] R_Y R_X\]where \(R_X\) and \(R_Y\) are the rotation matrices along X and Y respectively, and \(R_Z\) is the rotation matrix along Z.
\[\begin{split}R_X = \begin{pmatrix} 1 & 0 & 0 \\ 0 & \cos(\tau_x) & \sin(\tau_x) \\ 0 & -\sin(\tau_x) & \cos(\tau_x) \end{pmatrix}\end{split}\]\[\begin{split}R_Y = \begin{pmatrix} \cos(\tau_y) & 0 & -\sin(\tau_y) \\ 0 & 1 & 0 \\ \sin(\tau_y) & 0 & \cos(\tau_y) \end{pmatrix}\end{split}\]and we note that the rotation matrix along Z is given by:
\[\begin{split}R_z[R] = \begin{pmatrix} R_{33} & 0 & -R_{13} \\ 0 & R_{33} & -R_{23} \\ 0 & 0 & 1 \end{pmatrix}\end{split}\]The derivatives of the tilt matrix with respect to \(\tau_x\) and \(\tau_y\) are also computed. The derivatives are computed using the following equations:
\[\frac{\partial R_{\text{tilt}}}{\partial \tau_x} = R_Z [R_Y \frac{\partial R_X}{\partial \tau_x}, 0] R_Y R_X + R_Z [R_Y R_X, 1] R_Y \frac{\partial R_X}{\partial \tau_x}\]\[\frac{\partial R_{\text{tilt}}}{\partial \tau_y} = R_Z [\frac{\partial R_Y}{\partial \tau_y} R_X, 0] R_Y R_X + R_Z [R_Y R_X, 1] \frac{\partial R_Y}{\partial \tau_y} R_X\]Finnally, the inverse of the tilt matrix is computed using the following equation:
\[R_{\text{tilt}}^{-1} = (Ry Rx).T @ invRz[Ry Rx]\]Where \(invRz\) is the inverse of the rotation matrix along Z given by:
\[\begin{split}(R_z[R])^{-1} = \begin{pmatrix} 1/R_{33} & 0 & R_{13}/R_{33} \\ 0 & 1/R_{33} & R_{23}/R_{33} \\ 0 & 0 & 1 \end{pmatrix}\end{split}\]Note
If the model is not set to 14 parameters, the method returns a identity matrix and the derivatives are set to zero.
- Parameters:
dp (bool, optional) – If True, the derivatives of the tilt matrix are computed. The default is True. If False, the derivatives are set to None.
inv (bool, optional) – If True, the inverse of the tilt matrix is computed. The default is True. If False, the inverse of the tilt matrix is set to None.
- Returns:
numpy.ndarray – The tilt matrix.
numpy.ndarray – The derivative of the tilt matrix with respect to \(\tau_x\) if
dp
is True, else None.numpy.ndarray – The derivative of the tilt matrix with respect to \(\tau_y\) if
dp
is True, else None.numpy.ndarray – The inverse of the tilt matrix if
inv
is True, else None.
- _inverse_transform(distorted_points: ndarray, *, dx: bool = False, dp: bool = False, opencv: bool = False, max_iter: int = 10, eps: float = 1e-08) tuple[ndarray, ndarray | None, ndarray | None] [source]#
This method is called by the
pydistort.Transform.inverse_transform()
method to perform the inverse distortion transformation. This method allows to transform thedistorted_points
to thenormalized_points
using the distortion model.Note
For
_inverse_transform
the input must have shape (Npoints, 2) with float64 type. The output has shape (Npoints, 2) and the jacobian are always None.To achieve the undistortion, an iterative algorithm is used to find the normalized points that correspond to the distorted points. The algorithm is based on the following equations:
\[\begin{split}\begin{bmatrix} x_N [\text{it }k+1]\\ y_N [\text{it }k+1] \end{bmatrix} = \begin{bmatrix} (x_D - \Delta x [\text{it }k]) / \text{Rad} [\text{it }k] \\ (y_D - \Delta y [\text{it }k]) / \text{Rad}[\text{it }k] \end{bmatrix}\end{split}\]Where \(\Delta x [\text{it }k]\) and :math:Delta y [text{it }k] are the tangential and prism distortion contributions to the distorted points computed at iteration :math:k. And \(\text{Rad} [\text{it }k]\) is the radial distortion contribution to the distorted points computed at iteration :math:k.
\[\begin{split}\begin{bmatrix} \Delta x \Delta y \end{bmatrix} = \begin{bmatrix} 2 p_1 x_N y_N + p_2 (r^2 + 2x_N^2) + s_1 r^2 + s_2 r^4 \\ 2 p_2 x_N y_N + p_1 (r^2 + 2y_N^2) + s_3 r^2 + s_4 r^4 \end{bmatrix}\end{split}\]\[\begin{split}\begin{bmatrix} \text{Rad}_x \\ \text{Rad}_y \end{bmatrix} = \begin{bmatrix} \frac{1+k_1 r^2 + k_2 r^4 + k_3 r^6}{1 + k_4 r^2 + k_5 r^4 + k_6 r^6} \\ \frac{1+k_1 r^2 + k_2 r^4 + k_3 r^6}{1 + k_4 r^2 + k_5 r^4 + k_6 r^6} \end{bmatrix}\end{split}\]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.
To achieve the inverse distortion transformation using openCV, set the
opencv
parameter to True.Warning
Both OpenCV and the internal method use an iterative algorithm to find the normalized points that correspond to the distorted points. In fact the jacobian with respect to the normalized points is not computed for this inverse transform (always None).
- Parameters:
distorted_points (numpy.ndarray) – Array of distorted points to be transformed with shape (Npoints, 2).
dx (bool, optional) – [ALWAYS False]
dp (bool, optional) – [ALWAYS False]
opencv (bool, optional) – If True, the inverse distortion transformation is achieved using the OpenCV function
undistortPoints
. If False, the inverse distortion transformation is achieved using the internal method. Default is False.max_iter (int, optional) – The maximum number of iterations for the optimization algorithm. Default is 10. Use only if
opencv
is False.eps (float, optional) – The tolerance for the optimization algorithm. Default is 1e-8. Use only if
opencv
is False.
- Returns:
normalized_points (numpy.ndarray) – The transformed normalized points in normalized coordinates. It will be a 2D array of shape (Npoints, 2).
jacobian_dx (Optional[numpy.ndarray]) – [ALWAYS None]
jacobian_dp (Optional[numpy.ndarray]) – [ALWAYS None]
- _inverse_transform_opencv(distorted_points: ndarray, *, dx: bool = False, dp: bool = False) tuple[ndarray, ndarray | None, ndarray | None] [source]#
This method is called by the
pydistort.Transform.inverse_transform()
method to perform the inverse distortion transformation using OpenCVundistortPoints
function. To use this method, set theopencv
parameter to True in thepydistort.Transform.inverse_transform()
method.Note
For
_inverse_transform_opencv
the input must have shape (Npoints, 2) with float64 type. The output has shape (Npoints, 2) and the jacobian are always None.The equation used for the transformation is given in the main documentation of the class.
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:
distorted_points (numpy.ndarray) – Array of distorted points to be transformed with shape (Npoints, 2).
dx (bool, optional) – [ALWAYS False]
dp (bool, optional) – [ALWAYS False]
- Returns:
normalized_points (numpy.ndarray) – The transformed normalized points in normalized coordinates. It will be a 2D array of shape (Npoints, 2).
jacobian_dx (Optional[numpy.ndarray]) – [ALWAYS None]
jacobian_dp (Optional[numpy.ndarray]) – [ALWAYS None]
- _transform(normalized_points: ndarray, *, dx: bool = False, dp: bool = False, opencv: bool = False) tuple[ndarray, ndarray | None, ndarray | None] [source]#
This method is called by the
pydistort.Transform.transform()
method to perform the distortion transformation. This method allows to transform thenormalized_points
to thedistorted_points
using the distortion model.Note
For
_transform
the input must have shape (Npoints, 2) with float64 type. The output has shape (Npoints, 2) for the image points and (Npoints, 2, 2) for the jacobian with respect to the normalized points and (Npoints, 2, 4) for the jacobian with respect to the distortion parameters.The equation used for the transformation is given in the main documentation of the class.
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.
To achieve the distortion transformation using openCV, set the
opencv
parameter to True. (jacobian_dx
will not be computed in this case).- 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 distorted points with respect to the normalized points is computed. Default is False. The output will be a 2D array of shape (Npoints, 2, 2).
dp (bool, optional) – If True, the Jacobian of the distorted points with respect to the distortion parameters is computed. Default is False. The output will be a 2D array of shape (Npoints, 2, Nparams).
opencv (bool, optional) – If True, the distortion transformation is achieved using the OpenCV function
projectPoints
. If False, the distortion transformation is achieved using the internal method. Default is False.
- Returns:
distorted_points (numpy.ndarray) – The transformed distorted points in normalized coordinates. It will be a 2D array of shape (Npoints, 2).
jacobian_dx (Optional[numpy.ndarray]) – The Jacobian of the distorted points with respect to the normalized points if
dx
is True. Otherwise None. It will be a 2D array of shape (Npoints, 2, 2).jacobian_dp (Optional[numpy.ndarray]) – The Jacobian of the distorted points with respect to the distortion parameters if
dp
is True. Otherwise None. It will be a 2D array of shape (Npoints, 2, Nparams).
- _transform_opencv(normalized_points: 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 distortion transformation using OpenCVprojectPoints
function. To use this method, set theopencv
parameter to True in thepydistort.Transform.transform()
method.Note
For
_transform_opencv
the input must have shape (Npoints, 2) with float64 type. The output has shape (Npoints, 2) for the image points and (Npoints, 2, Nparams) for the jacobian with respect to the distortion parameters.The equation used for the transformation is given in the main documentation of the class.
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.
The jacobian with respect to the normalized points is not computed in this case (always None).
- Parameters:
normalized_points (numpy.ndarray) – Array of normalized points to be transformed with shape (Npoints, 2).
dx (bool, optional) – [ALWAYS False]
dp (bool, optional) – If True, the Jacobian of the distorted points with respect to the distortion parameters is computed. Default is False. The output will be a 2D array of shape (Npoints, 2, Nparams).
- Returns:
distorted_points (numpy.ndarray) – The transformed distorted points in normalized coordinates. It will be a 2D array of shape (Npoints, 2).
jacobian_dx (Optional[numpy.ndarray]) – [ALWAYS None]
jacobian_dp (Optional[numpy.ndarray]) – The Jacobian of the distorted points with respect to the distortion parameters if
dp
is True. Otherwise None. It will be a 2D array of shape (Npoints, 2, Nparams).
- is_set() bool [source]#
Check if the distortion model is set.
- Returns:
True if the distortion model is set, False otherwise.
- Return type:
bool
- property k1: float#
Get the first radial distortion coefficient.
Warning
An error is raised if the number of parameters is less than 4. Set the number of parameters to 4 or more before getting the value.
- Returns:
The first radial distortion coefficient.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 4.
- property k2: float#
Get the second radial distortion coefficient.
Warning
An error is raised if the number of parameters is less than 4. Set the number of parameters to 4 or more before getting the value.
- Returns:
The second radial distortion coefficient.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 4.
- property k3: float | None#
Get the third radial distortion coefficient.
Warning
An error is raised if the number of parameters is less than 5. Set the number of parameters to 5 or more before getting the value.
- Returns:
The third radial distortion coefficient.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 5.
- property k4: float | None#
Get the first fractional radial distortion coefficient.
Warning
An error is raised if the number of parameters is less than 8. Set the number of parameters to 8 or more before getting the value.
- Returns:
The first fractional radial distortion coefficient.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 8.
- property k5: float | None#
Get the second fractional radial distortion coefficient.
Warning
An error is raised if the number of parameters is less than 8. Set the number of parameters to 8 or more before getting the value.
- Returns:
The second fractional radial distortion coefficient.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 8.
- property k6: float | None#
Get the third fractional radial distortion coefficient.
Warning
An error is raised if the number of parameters is less than 8. Set the number of parameters to 8 or more before getting the value.
- Returns:
The third fractional radial distortion coefficient.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 8.
- property p1: float#
Get the first tangential distortion coefficient.
Warning
An error is raised if the number of parameters is less than 4. Set the number of parameters to 4 or more before getting the value.
- Returns:
The first tangential distortion coefficient.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 4.
- property p2: float#
Get the second tangential distortion coefficient.
Warning
An error is raised if the number of parameters is less than 4. Set the number of parameters to 4 or more before getting the value.
- Returns:
The second tangential distortion coefficient.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 4.
- property parameters: ndarray | None#
Get the parameters of the distortion model.
- Returns:
The parameters of the distortion model.
- Return type:
numpy.ndarray
- property s1: float | None#
Get the first thin prism distortion coefficient.
Warning
An error is raised if the number of parameters is less than 12. Set the number of parameters to 12 or more before getting the value.
- Returns:
The first thin prism distortion coefficient.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 12.
- property s2: float | None#
Get the second thin prism distortion coefficient.
Warning
An error is raised if the number of parameters is less than 12. Set the number of parameters to 12 or more before getting the value.
- Returns:
The second thin prism distortion coefficient.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 12.
- property s3: float | None#
Get the third thin prism distortion coefficient.
Warning
An error is raised if the number of parameters is less than 12. Set the number of parameters to 12 or more before getting the value.
- Returns:
The third thin prism distortion coefficient.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 12.
- property s4: float | None#
Get the fourth thin prism distortion coefficient.
Warning
An error is raised if the number of parameters is less than 12. Set the number of parameters to 12 or more before getting the value.
- Returns:
The fourth thin prism distortion coefficient.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 12.
- property tau_x: float | None#
Get the x component of the perspective transformation.
Warning
An error is raised if the number of parameters is less than 14. Set the number of parameters to 14 or more before getting the value.
- Returns:
The x component of the perspective transformation.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 14.
- property tau_y: float | None#
Get the y component of the perspective transformation.
Warning
An error is raised if the number of parameters is less than 14. Set the number of parameters to 14 or more before getting the value.
- Returns:
The y component of the perspective transformation.
- Return type:
float
- Raises:
ValueError – If the number of parameters is less than 14.