pinhole-radtan is the most commonly used camera model.
in this case pinhole refers to intrinsics (focal length and principal point). This alone could express the lambda which maps x,y,z points in 3D space to u,v 2D points on the image plane - i.e. a simple pinhole camera with no lens, just an infinitesimally small point aperture.
# a pure function:
u, v <= x, y, z
radtan refers to distortion coefficients (k1, k2, p1, p2) which model the effects of a lens mapping points in 2D space incident on the image plane after the influence of the lens, to where those points would have landed with no lens (i.e. a simple pinhole camera)..
# a pure function:
u', v' <= u, v
consuming Kalibr calibration output
we take the raw data from Kalibr and transform it into a pydantic model in our schema.
cam0:
cam_overlaps: [1, 2, 3, 4, 5]
camera_model: pinhole
distortion_coeffs: [0.047671970231275874, -0.052126945675713646, 0.00035674261728729675, -0.00024633230889745236]
distortion_model: radtan
intrinsics: [982.4521342422584, 981.4319920949041, 1161.8729899564785, 649.9965088472593]
resolution: [2304, 1296]
rostopic: /cam0/image_raw
distortion_coeffs
radtan distortion_coeffs is (as per https://github.com/ethz-asl/kalibr/wiki/supported-models):
- k1 (second order radial distortion)
- k2 (fourth order radial distortion)
- p1 (tangential distortion)
- p2 (tangential distortion)
i.e.
distortion_coeffs: [0.047671970231275874, -0.052126945675713646, 0.00035674261728729675, -0.00024633230889745236]
// k1 = 0.047671970231275874
// k2 = -0.052126945675713646
// p1 = 0.00035674261728729675
// p2 = -0.00024633230889745236
as related by equation:
x_distorted = x(1 + k1*r² + k2*r⁴) + 2p1*xy + p2(r² + 2x²)
y_distorted = y(1 + k1*r² + k2*r⁴) + p1(r² + 2y²) + 2p2*xy
intrinsics
pinhole intrinsics is (as per https://github.com/ethz-asl/kalibr/wiki/supported-models):
- fx (focal length x)
- fy (focal length y)
- cx (principal point x)
- cy (principal point y)
i.e.
intrinsics: [982.4521342422584, 981.4319920949041, 1161.8729899564785, 649.9965088472593]
// fx = 982.4521342422584
// fy = 981.4319920949041
// cx = 1161.8729899564785
// cy = 649.9965088472593
The pinhole intrinsics equation projects 3D camera coordinates to 2D pixel coordinates:
u = fx * (X/Z) + cx
v = fy * (Y/Z) + cy
run a test which imports kalibr data into our schema
From the schema/ uv project root:
uv run -p 3.12 --package camera-schema pytest -q Camera/tests/test_CameraPinholeRadtan.py -s