← Back to all work

Calibration · Numerical optimization · Python/C++/CUDA

Owning the calibration engine

End-to-end ownership of a production 3D scanner's calibration: the solvers that turn images of a known target into the camera and pattern models everything downstream depends on.

Challenge

Every downstream stage — decoding, depth, registration, reconstruction — inherits calibration's errors. The incumbent solver leaned on generic least-squares, absorbed model mismatch into outsized distortion coefficients, and was not reproducible run to run.

Contribution

Rebuilt the solvers around analytical Jacobians — the fit's derivatives worked out by hand rather than approximated numerically — unit-tested, driven by Gauss–Newton with Levenberg–Marquardt damping, and guarded by robust outlier rejection: points flagged by their deviation from the median (MAD), then refit with iteratively reweighted least squares (IRLS). Made the fit bit-deterministic — identical input, bit-identical output — replaced the linear dot-trajectory model with the correct Möbius form, the curve perspective actually produces (0.112 → 0.050 px median residual), and proved one fitted parameter algebraically unidentifiable — no data could ever determine it — pinning it rather than letting it wander.

Outcome

Pattern RMS around 3.5 µm, with 90% of patterns under 5 µm. Recovered scanners the incumbent solver could not calibrate — calibration RMS 35 px → 0.025 px in one case, pattern RMS 8.3 mm → 0.011 mm in another — and traced a scan-distortion mode to that solver absorbing an error that belonged elsewhere by fitting unequal horizontal and vertical focal lengths (unconstrained fx≠fy).

Client work is described at a technical, client-agnostic level.