Brown-Conrady Distortion
Real lenses introduce geometric distortion: straight lines in the world project as curves in the image. The Brown-Conrady model captures the two dominant distortion effects — radial and tangential — as polynomial functions of the distance from the optical axis.
Distortion Model
Given undistorted normalized coordinates , the distorted coordinates are:
Radial distortion (barrel/pincushion):
Tangential distortion (decentering):
Combined:
The model has five parameters: radial coefficients and tangential coefficients .
OpenCV equivalence: This is identical to OpenCV's
distortPointswith the 5-parameter model(k1, k2, p1, p2, k3). Note OpenCV's parameter ordering differs from the mathematical ordering.
Physical Interpretation
- : barrel distortion (lines bow outward from center)
- : pincushion distortion (lines bow inward)
- : higher-order radial corrections
- : tangential distortion from imperfect lens-sensor alignment (lens elements not perfectly centered)
Typical values for industrial cameras: , , .
When to Fix
The sixth-order radial term is only significant for wide-angle lenses where reaches large values. For typical industrial cameras with moderate field of view:
- is poorly constrained by the data and often absorbs noise
- Estimating can cause overfitting, leading to worse extrapolation outside the calibration region
- The library defaults to
fix_k3: truein most problem configurations
Recommendation: Only estimate with high-quality data covering the full image area, or for lenses with field of view > 90°.
Undistortion (Inverse)
Given distorted coordinates , recovering undistorted coordinates requires inverting the distortion model. Since the forward model is a polynomial without a closed-form inverse, calibration-rs uses iterative fixed-point refinement:
This rearranges the distortion equation to isolate and iterates to convergence. The default is 8 iterations, which provides accuracy well below sensor noise for typical distortion magnitudes.
Convergence
The fixed-point iteration converges when the Jacobian of the distortion residual has spectral radius less than 1, which holds for physically realistic distortion values (small , relative to ). For extreme distortion, more iterations may be needed via the iters parameter.
OpenCV equivalence:
cv::undistortPointsperforms the same iterative inversion.
The DistortionModel Trait
#![allow(unused)] fn main() { pub trait DistortionModel<S: RealField> { fn distort(&self, n_undist: &Point2<S>) -> Point2<S>; fn undistort(&self, n_dist: &Point2<S>) -> Point2<S>; } }
The BrownConrady5<S> struct:
#![allow(unused)] fn main() { pub struct BrownConrady5<S: RealField> { pub k1: S, pub k2: S, pub k3: S, pub p1: S, pub p2: S, pub iters: u32, // undistortion iterations (default: 8) } }
NoDistortion is the identity implementation for distortion-free cameras.
Distortion in the Projection Pipeline
Distortion operates in normalized image coordinates (after pinhole projection, before intrinsics):
This is the standard convention: distortion is defined on the plane, not in pixel space. The advantage is that distortion parameters are independent of image resolution and focal length.