pycvcam.distort_image#

distort_image(src, intrinsic, distortion, method='undistort', interpolation='linear', intrinsic_kwargs=None, inverse_intrinsic_kwargs=None, distortion_kwargs=None, inverse_distortion_kwargs=None)[source]#

Distort an image using the camera intrinsic and distortion coefficients.

The process to undistort an image is as follows:

  1. The output pixels are converted to a normalized coordinate system using the inverse intrinsic transformation.

  2. The normalized points are undistorted by the distortion model using the coefficients \(\{\lambda_1, \lambda_2, \lambda_3, \ldots\}\).

  3. The undistorted points are projected back to the input image coordinate system using the same intrinsic transformation.

  4. The distorted image is obtained by mapping the pixels from the original image to the distorted points.

The given image src is assumed to be in the image coordinate system and expressed in 2D coordinates with shape (H, W, [C], [D]). If the user gives an identity matrix K, it is equivalent to giving directly the normalized points.

Note

  • For an image the X dimension corresponds to the width and the Y dimension corresponds to the height.

  • Pixel [0, 1] is at XY = [1, 0] in the image coordinate system.

Linear interpolation is used for each method to compute the pixel values in the distorted image.

Fill Values for the output image are set to 0.0.

METHOD 1 : Undistort#

The mapping is performed using OpenCV’s cv2.remap function (or scipy.interpolate), which requires the source image and the mapping of pixel coordinates. The mapping of pixel coordinates is performed using the undistort method of the distortion model, which applies the inverse distortion to the normalized points.

In this case, the output pixels (distorted_image) are projected back to the input image coordinate system using the intrinsic matrix K. Then an interpolation is performed in the input image where the known points are a perfect regular grid of pixels !

Warning

  • Iterative non-linear optimization is used to find the undistorted points.

  • For scipy, output values are not positive integer values (even if the input image is integer).

Different interpolation methods can be used, such as “linear”, “nearest”, etc. The default is “linear”. The table below shows the available interpolation methods for METHOD 1:

Interpolation

Description

“linear”

Linear interpolation (default). Use cv2.INTER_LINEAR.

“nearest”

Nearest neighbor interpolation. Use cv2.INTER_NEAREST.

“cubic”

Bicubic interpolation. Use cv2.INTER_CUBIC.

“area”

Resampling using pixel area relation. Use cv2.INTER_AREA.

“lanczos4”

Lanczos interpolation over 8x8 pixel neighborhood. Use cv2.INTER_LANCZOS4.

“spline3”

Spline interpolation. Use scipy.interpolate.RectBivariateSpline for kx=ky=3

METHOD 2 : Distort#

The mapping is performed using scipy scipy.interpolate function, which requires the source image and the mapping of pixel coordinates. The mapping of pixel coordinates is performed using the distort method of the distortion model, which applies the distortion to the normalized points.

In this case, the input pixels (src) are projected to the output image coordinate system using the intrinsic matrix K. Then an interpolation is performed in the output image for all the output pixels where the known points are a irregular cloud of points.

Warning

  • Time computation is higher than the first method.

  • Output values are not integer values (even if the input image is integer), so the user must apply (numpy.round) to the output image to get integer values.

Different interpolation methods can be used, such as “linear”, etc. The default is “linear”. The table below shows the available interpolation methods for METHOD 2:

Interpolation

Description

“linear”

Linear interpolation (default). Use scipy.interpolate.LinearNDInterpolator

“nearest”

Nearest neighbor interpolation. Use scipy.interpolate.NearestNDInterpolator

“clough”

Piecewise cubic interpolation. Use scipy.interpolate.CloughTocher2DInterpolator.

param src:

The input image to be undistorted. Shape (H, W, …) where H is the height, W is the width.

type src:

ArrayLike

param intrinsic:

The intrinsic transformation to be applied to the image points. If None, a zero intrinsic is applied (i.e., identity transformation).

type intrinsic:

Optional[Intrinsic]

param distortion:

The distortion model to be applied. If None, no distortion is applied.

type distortion:

Optional[Distortion]

param method:

The method to use for undistortion. The value can be “undistort” or “distort”.

  • “undistort”: Uses OpenCV’s cv2.remap and the undistort method of the distortion model.

  • “distort”: Uses scipy.interpolate and the distort method of the distortion model.

type method:

str

param interpolation:

The interpolation method to be used for remapping the pixels. Default is “linear”.

type interpolation:

str, optional

param intrinsic_kwargs:

Additional keyword arguments to be passed to the intrinsic transformation (intrinsic._transform methods). Default is None.

type intrinsic_kwargs:

Optional[Dict]

param inverse_intrinsic_kwargs:

Additional keyword arguments to be passed to the inverse intrinsic transformation (intrinsic._inverse_transform methods). Default is None.

type inverse_intrinsic_kwargs:

Optional[Dict]

param distortion_kwargs:

Additional keyword arguments to be passed to the distortion transformation (distortion._transform methods). Default is None.

type distortion_kwargs:

Optional[Dict]

param inverse_distortion_kwargs:

Additional keyword arguments to be passed to the inverse distortion transformation (distortion._inverse_transform methods). Default is None.

type inverse_distortion_kwargs:

Optional[Dict]

returns:

The undistorted image. Shape (H, W, …) where H is the height.

rtype:

numpy.ndarray

Example

import numpy
from pycvcam import distort_image, Cv2Distortion, Cv2Intrinsic

# Define the intrinsic camera matrix
K = numpy.array([[1000.0, 0.0, 320.0],
                [0.0, 1000.0, 240.0],
                [0.0, 0.0, 1.0]])

# Create the intrinsic object
intrinsic = Cv2Intrinsic.from_matrix(K)

# Define the distortion model (optional)
distortion = Cv2Distortion([0.1, 0.2, 0.3, 0.4, 0.5])

# Load the image to be distorted
src = cv2.imread('image.jpg')

# Distort the image
distorted_image = distort_image(src, intrinsic=intrinsic, distortion=distortion)
Parameters:
Return type:

ndarray