Cal3DS2 adds radial and tangential distortion to a default affine calibration matrix K. It combines five pinhole intrinsics with GTSAM’s Brown–Conrady-style distortion model for lenses with moderate distortion.
import gtsam
import numpy as npInitialization¶
The explicit constructor makes the model and parameter order visible. A default constructor is also available, but calibrated values are preferable in real projection code.
calibration = gtsam.Cal3DS2(
800.0, 790.0, 0.0, 320.0, 240.0,
1.0e-3, -1.0e-5, 2.0e-4, -1.0e-4,
)
print(calibration)Calibration parameters¶
k1() and k2() are radial coefficients; p1() and p2() are tangential coefficients. k() returns all four distortion values. vector() collects the optimized parameters, while K() returns the intrinsic matrix associated with the linear part of the model.
print("intrinsic matrix:")
print(calibration.K())
print("radial:", calibration.k1(), calibration.k2())
print("tangential:", calibration.p1(), calibration.p2())
print("all parameters:", calibration.vector())Calibrating and uncalibrating points¶
uncalibrate() maps normalized image coordinates to pixels and applies this model’s distortion. calibrate() performs the inverse mapping iteratively. Their round trip is the most direct way to check parameter conventions.
normalized = np.array([0.12, -0.08])
pixel = calibration.uncalibrate(normalized)
recovered = calibration.calibrate(pixel)
print("pixel:", pixel)
print("recovered normalized point:", recovered)
np.testing.assert_allclose(recovered, normalized, atol=1e-7)Manifold operations¶
Calibration objects participate in nonlinear optimization through retract() and localCoordinates(). The tangent coordinates follow the order returned by vector() for the parameters that this model optimizes.
delta = np.array([1.0, -1.0, 0.01, 0.2, -0.2, 1e-5, -1e-6, 1e-5, -1e-5])
perturbed = calibration.retract(delta)
recovered_delta = calibration.localCoordinates(perturbed)
print("parameter increment:", recovered_delta)
np.testing.assert_allclose(recovered_delta, delta, atol=1e-9)