Skip to content

IntrinsicCalibrator

SUMMARY

IntrinsicCalibrator recovers a single camera's intrinsic matrix and distortion coefficients from a stack of calibration-board images. One class dispatches on whichever target you pass it, no separate class per board type.

The Skill

python
from telekinesis.axon import IntrinsicCalibrator, IntrinsicOptions

The Code

python
from telekinesis.axon import IntrinsicCalibrator, IntrinsicOptions
from telekinesis.axon.targets import CharucoTarget

target = CharucoTarget(squares_x=6, squares_y=9, square_length=0.012, marker_length=0.009)

options = IntrinsicOptions()
options.per_view_error_threshold = 0.8

calibrator = IntrinsicCalibrator(target, options)
result = calibrator.calibrate(images)

result.ok                     # bool
result.intrinsic_matrix       # (3, 3) np.ndarray
result.distortion_coefficients
result.reprojection_error
result.successful_indices
result.low_view_error_indices

Theory

IntrinsicCalibrator fits a pinhole camera model: a 3x3 intrinsic matrix K (focal lengths fx, fy and principal point cx, cy) plus a set of radial and tangential distortion coefficients that describe how the real lens deviates from an ideal pinhole. Given a set of images of a target with known geometry, cv::calibrateCamera solves for K, the distortion coefficients, and a per-view extrinsic pose (rvec, tvec) jointly, by minimizing the reprojection error: the pixel distance between each detected corner and where the fitted model predicts that corner should land.

reprojection_error (the mean over all views) and per_view_errors (one value per view) are the two numbers that tell you how well the model fits, see Best Practices for how to read them.

Pinhole camera model: image plane, focal length, principal point, and an undistorted vs. distorted image comparison

Initialization

python
IntrinsicCalibrator(target, options=IntrinsicOptions())
ParameterTypeDescription
targetChessboardTarget | CharucoTarget | ArucoTargetCalibration target, see All Supported Targets.
optionsIntrinsicOptionsSolver tunables, see IntrinsicOptions.

Skills

SkillDescription
CalibrateDetect the target in every image and run cv::calibrateCamera.
Find CornersDetect the target in a set of images with no calibration solve.

See also IntrinsicCalibrator State to read back the target, options, and detections of the last calibrate() call.

Best Practices

  • Capture 15-20+ views. Fewer views under-constrains the distortion coefficients; beyond ~20-25 good views, additional frames give diminishing returns unless you're specifically trying to cover more of the frame.
  • Cover the whole frame, not just the center. Distortion is smallest near the principal point and largest toward the edges and corners, a dataset where the board only ever appears centered will fit K reasonably but leave the distortion coefficients poorly constrained. Deliberately place the board in each corner and along each edge across your capture set.
  • Vary tilt, not just position. A set of fronto-parallel views (board always facing the camera) is close to degenerate for separating focal length from distance. Tilt the board at varied angles relative to the optical axis across the dataset.
  • Vary distance too, within the range you'll actually operate at, don't calibrate entirely at one working distance and expect the fit to generalize to another.
  • Avoid motion blur and inconsistent exposure. A blurred or poorly-exposed corner detection is worse than a missing one; per_view_error_threshold in IntrinsicOptions and the resulting low_view_error_indices help you find and exclude these after the fact.
  • Watch for a gap between reprojection_error and individual per_view_errors. A low mean with one or two much higher per-view outliers usually means a bad detection on those frames (motion blur, glare, partial occlusion) rather than a systemic problem, drop them and recalibrate rather than accepting a mean pulled down by otherwise-good views.