Distortion Estimation from Homography Residuals

After estimating intrinsics via Zhang's method (which assumes distortion-free observations), the residuals between observed and predicted pixel positions encode the lens distortion. This chapter derives a linear method to estimate Brown-Conrady distortion coefficients from these residuals.

Problem Statement

Given:

  • Camera intrinsics (from Zhang's method)
  • homographies from the calibration board to the image
  • Point correspondences: board points and observed pixels

Find: Distortion coefficients .

Assumptions:

  • is a reasonable estimate (possibly biased by distortion)
  • Distortion is moderate (the linear approximation holds)
  • The homographies were computed from distorted pixel observations

Derivation

Ideal vs. Observed Coordinates

For each correspondence in view , the ideal (undistorted) pixel position predicted by the homography is:

Convert both observed and ideal pixels to normalized coordinates:

The residual in normalized coordinates encodes the distortion effect:

Linearized Distortion Model

The Brown-Conrady distortion applied to point with produces a displacement:

This is linear in the distortion coefficients .

Building the Linear System

For each correspondence, write the and components:

where are the ideal normalized coordinates and are the observed residuals.

Stacking all correspondences from all views gives an overdetermined system:

where is (or smaller if some coefficients are fixed), and .

Solving

The least-squares solution is:

In practice, this is solved via SVD of for numerical stability.

Options

#![allow(unused)]
fn main() {
pub struct DistortionFitOptions {
    pub fix_tangential: bool,  // Fix p1 = p2 = 0
    pub fix_k3: bool,          // Fix k3 = 0 (default: true)
    pub iters: u32,            // Undistortion iterations
}
}
  • fix_k3 (default true): Removes from the system, reducing to a 4-parameter or 2-parameter model. Recommended unless the lens has strong higher-order radial distortion.
  • fix_tangential (default false): Removes , estimating only radial distortion. Useful when tangential distortion is known to be negligible.

When parameters are fixed, the corresponding columns are removed from .

Accuracy

This linear estimate is typically within 10-50% of the true distortion values. The accuracy depends on:

  • Quality of : If intrinsics are biased (from distorted observations), the estimated distortion absorbs some of the bias
  • Number of points: More correspondences improve the overdetermined system
  • Point distribution: Points across the full image area constrain distortion better than points clustered near the center (where distortion is small)

This accuracy is sufficient for initializing non-linear refinement.

API

#![allow(unused)]
fn main() {
let dist = estimate_distortion_from_homographies(
    &k_matrix, &views, opts
)?;
}

Returns BrownConrady5 with the estimated coefficients.

OpenCV equivalence: OpenCV estimates distortion jointly with intrinsics inside cv::calibrateCamera. The separate distortion estimation step is specific to calibration-rs's initialization approach.