namespace mrpt::img::camera_geometry::distortion

Overview

Low-level distortion and undistortion functions operating on normalized coordinates.

These functions work with normalized image coordinates (x,y) where a 3D point (X,Y,Z) in camera frame projects to (x,y) = (X/Z, Y/Z).

Use these functions when:

  • Implementing custom projection pipelines

  • Testing distortion models in isolation

  • Porting code from other computer vision libraries

  • Need fine-grained control over the distortion process

For typical use cases, prefer the high-level functions above.

namespace distortion {

// global functions

void apply_plumb_bob(
    double x,
    double y,
    const std::array<double, 8>& dist,
    double& xd,
    double& yd
    );

void apply_kannala_brandt(
    double x,
    double y,
    const std::array<double, 8>& dist,
    double& xd,
    double& yd
    );

void remove_plumb_bob(
    double xd,
    double yd,
    const std::array<double, 8>& dist,
    double& x,
    double& y,
    int iterations = 5
    );

void remove_kannala_brandt(
    double xd,
    double yd,
    const std::array<double, 8>& dist,
    double& x,
    double& y,
    int iterations = 10
    );

} // namespace distortion

Global Functions

void apply_plumb_bob(
    double x,
    double y,
    const std::array<double, 8>& dist,
    double& xd,
    double& yd
    )

Apply plumb_bob (radial-tangential) distortion to normalized coordinates.

Implements the Brown-Conrady distortion model:

\[\begin{split}\begin{aligned} r^2 &= x^2 + y^2 \\ \text{radial} &= \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} \\ x_d &= x \cdot \text{radial} + 2p_1 xy + p_2(r^2 + 2x^2) \\ y_d &= y \cdot \text{radial} + p_1(r^2 + 2y^2) + 2p_2 xy \end{aligned}\end{split}\]

Parameters:

x

[IN] Normalized x coordinate (X/Z)

y

[IN] Normalized y coordinate (Y/Z)

dist

[IN] Distortion coefficients [k1,k2,p1,p2,k3,k4,k5,k6]

xd

[OUT] Distorted x coordinate

yd

[OUT] Distorted y coordinate

See also:

remove_plumb_bob, apply_kannala_brandt

void apply_kannala_brandt(
    double x,
    double y,
    const std::array<double, 8>& dist,
    double& xd,
    double& yd
    )

Apply Kannala-Brandt fish-eye distortion to normalized coordinates.

Implements the model from “A Generic Camera Model and Calibration Method for Conventional, Wide-Angle, and Fish-Eye Lenses” (Kannala & Brandt, 2006):

\[\begin{split}\begin{aligned} r &= \sqrt{x^2 + y^2} \\ \theta &= \arctan(r) \\ \theta_d &= \theta(1 + k_1\theta^2 + k_2\theta^4 + k_3\theta^6 + k_4\theta^8) \\ x_d &= \frac{\theta_d}{r} x, \quad y_d = \frac{\theta_d}{r} y \end{aligned}\end{split}\]

Parameters:

x

[IN] Normalized x coordinate

y

[IN] Normalized y coordinate

dist

[IN] Distortion coefficients [k1,k2,_,_,k3,k4,_,_] (indices 2,3,6,7 unused)

xd

[OUT] Distorted x coordinate

yd

[OUT] Distorted y coordinate

See also:

remove_kannala_brandt, apply_plumb_bob

void remove_plumb_bob(
    double xd,
    double yd,
    const std::array<double, 8>& dist,
    double& x,
    double& y,
    int iterations = 5
    )

Remove plumb_bob distortion using iterative refinement.

Given distorted normalized coordinates (x_d, y_d), finds undistorted coordinates (x, y) such that apply_plumb_bob(x,y) ≈ (x_d, y_d).

Uses fixed-point iteration:

  1. Start with x = x_d, y = y_d

  2. Compute expected distortion at (x,y)

  3. Update: x_new = (x_d - tangential_x) / radial_factor

  4. Repeat until convergence or max iterations

5 iterations typically achieve sub-pixel accuracy for typical distortion magnitudes

Parameters:

xd

[IN] Distorted x coordinate

yd

[IN] Distorted y coordinate

dist

[IN] Distortion coefficients [k1,k2,p1,p2,k3,k4,k5,k6]

x

[OUT] Undistorted x coordinate

y

[OUT] Undistorted y coordinate

iterations

[IN] Number of refinement iterations (default: 5, typically sufficient)

See also:

apply_plumb_bob, remove_kannala_brandt

void remove_kannala_brandt(
    double xd,
    double yd,
    const std::array<double, 8>& dist,
    double& x,
    double& y,
    int iterations = 10
    )

Remove Kannala-Brandt fish-eye distortion using Newton-Raphson method.

Solves the nonlinear equation to invert the fish-eye model:

\[\theta_d = \theta(1 + k_1\theta^2 + k_2\theta^4 + k_3\theta^6 + k_4\theta^8)\]

Uses Newton-Raphson iteration:

\[\theta_{n+1} = \theta_n - \frac{f(\theta_n)}{f'(\theta_n)}\]

where \(f(\theta) = \theta \cdot \text{poly}(\theta) - \theta_d\)

Fish-eye models require more iterations than plumb_bob due to higher nonlinearity

Parameters:

xd

[IN] Distorted x coordinate

yd

[IN] Distorted y coordinate

dist

[IN] Distortion coefficients [k1,k2,_,_,k3,k4,_,_]

x

[OUT] Undistorted x coordinate

y

[OUT] Undistorted y coordinate

iterations

[IN] Number of Newton-Raphson iterations (default: 10)

See also:

apply_kannala_brandt, remove_plumb_bob