pycvcam.Cv2Distortion#
Cv2Distortion Class#
- class Cv2Distortion(parameters=None, constants=None, n_params=None)[source]#
Subclass of the
pycvcam.core.Distortionclass that represents the OpenCV distortion model.Note
This class represents the distortion transformation, which is the middle step of the process from the
world_pointsto theimage_points.The
Cv2Distortionmodel in the OpenCV model with radial, tangential and prism distortion.Lets consider
normalized_pointsin the camera normalized coordinate system \(\vec{x}_n = (x_n, y_n)\), the correspondingdistorted_pointsin the camera normalized coordinate system are given \(\vec{x}_d\) can be obtained by :\[\vec{x}_d = \text{distort}(\vec{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
n_paramsis given during instantiation, the given parameters are truncated or extended to the given number of parameters.- Parameters:
parameters (Optional[ArrayLike], optional) – The parameters of the distortion transformation. It should be a numpy array of shape (n_params,) containing the distortion coefficients ordered as described above. Default is None, which means no distortion is setted.
n_params (Optional[Integral], optional) – The number of parameters for the distortion model. If not specified, it will be inferred from the shape of the parameters array.
constants (None)
Accessing the parameters of Cv2Distortion objects#
The parameters and constants properties can be accessing using pycvcam.core.Transform methods.
Some additional convenience methods are provided to access commonly used parameters of the Cv2Distortion model:
Get the first radial distortion coefficient. |
|
Get the second radial distortion coefficient. |
|
Get the third radial distortion coefficient. |
|
Get the first fractional radial distortion coefficient. |
|
Get the second fractional radial distortion coefficient. |
|
Get the third fractional radial distortion coefficient. |
|
Get the first tangential distortion coefficient. |
|
Get the second tangential distortion coefficient. |
|
Get the first thin prism distortion coefficient. |
|
Get the second thin prism distortion coefficient. |
|
Get the third thin prism distortion coefficient. |
|
Get the fourth thin prism distortion coefficient. |
|
Get the x component of the perspective transformation. |
|
Get the y component of the perspective transformation. |
Performing distortion with Cv2Distortion objects#
The transform and inverse_transform methods can be used to perform distortion and undistortion using the Cv2Distortion model (as described in the pycvcam.core.Transform documentation).
The implementation of theses transformations and more details on the options available can be found in the following methods:
|
Compute the tilt matrix for the perspective transformation for N = 14 (only). |
|
Compute the transformation from the |
|
Compute the transformation from the |
|
Compute the inverse transformation from the |
Compute the inverse transformation from the |
Examples#
Create an distortion object with a specific number of parameters:
import numpy
from pycvcam import Cv2Distortion
parameters = numpy.array([0.1, 0.01, 0.02, 0.03, 0.001])
distortion = Cv2Distortion(parameters=parameters)
Then you can use the distortion object to transform normalized_points to distorted_points:
normalized_points = numpy.array([[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]]) # shape (n_points, 2)
result = distortion.transform(normalized_points)
distorted_points = result.distorted_points # Shape (n_points, 2)
print(distorted_points)
You can also access to the jacobian of the distortion transformation:
result = distortion.transform(normalized_points, dx=True, dp=True)
distorted_points_dx = result.jacobian_dx # Shape (n_points, 2, 2)
distorted_points_dp = result.jacobian_dp # Shape (n_points, 2, n_params = 5)
print(distorted_points_dx)
print(distorted_points_dp)
The inverse transformation can be computed using the inverse_transform method:
inverse_result = distortion.inverse_transform(distorted_points, dx=True, dp=True)
normalized_points = inverse_result.normalized_points # Shape (n_points, 2)
print(normalized_points)
Note
The jacobian with respect to the depth is not computed.
See also
For more information about the transformation process, see:
pycvcam.Cv2Distortion._transform()to transform thenormalized_pointstodistorted_points.pycvcam.Cv2Distortion._inverse_transform()to transform thedistorted_pointsback tonormalized_points.