CameraCalibration
SUMMARY
Intrinsic calibration parameters for a single camera: image resolution, a distortion model, and a (3, 3) intrinsic matrix.
from telekinesis import datatypes
calibration = datatypes.CameraCalibration(
width=1280,
height=720,
distortion_model="plumb_bob",
distortion_parameters=[-0.2, 0.1, 0.0, 0.0, 0.0],
intrinsic_matrix=[1000.0, 0.0, 640.0, 0.0, 1000.0, 360.0, 0.0, 0.0, 1.0],
)Parameters
| Field | Type | Description |
|---|---|---|
width | int | Image width in pixels, in [0, 2**32 - 1]. |
height | int | Image height in pixels, in [0, 2**32 - 1]. |
distortion_model | str | DistortionModel | The distortion model — a DistortionModel member, or its matching string value (e.g. "plumb_bob"). Determines the required length of distortion_parameters. |
distortion_parameters | np.ndarray | list[float] | Distortion parameters, shape (M,), where M must equal distortion_model.parameter_count (5 for plumb_bob, 8 for rational_polynomial). |
intrinsic_matrix | np.ndarray | list[float] | Row-major intrinsic camera matrix, shape (3, 3) (or a flattened length-9 sequence). |
Raises
| Exception | Condition |
|---|---|
TypeError | width/height isn't int-convertible, or distortion_parameters/intrinsic_matrix can't be converted to a float64 array |
ValueError | width/height falls outside [0, 2**32 - 1]; distortion_model isn't a valid DistortionModel member or matching string; distortion_parameters's length doesn't match distortion_model.parameter_count; intrinsic_matrix doesn't have exactly 9 elements; or distortion_parameters/intrinsic_matrix contains a non-finite value |
Attributes
| Attribute | Type | Description |
|---|---|---|
width | int | Image width in pixels. |
height | int | Image height in pixels. |
distortion_model | str | Distortion model name -- always the plain string value (DistortionModel(...).value), even though construction also accepts a DistortionModel member directly. |
distortion_parameters | np.ndarray | Defensive copy of the distortion parameters, shape (M,), float64. |
intrinsic_matrix | np.ndarray | Defensive copy of the intrinsic camera matrix, shape (3, 3), float64, row-major. |
None of these attributes have setters -- a CameraCalibration is immutable after construction. One caveat: construction doesn't defensively copy an already C-contiguous distortion_parameters/intrinsic_matrix input array, so mutating that original array in place afterward can still affect the instance; reading either attribute back always returns a fresh copy, so mutating that never affects the instance.
Methods
| Method | Description |
|---|---|
CameraCalibration.coerce(value) | Returns value unchanged if it's already a CameraCalibration; if it's a dict, constructs one via CameraCalibration(**value) (requires keys width, height, distortion_model, distortion_parameters, intrinsic_matrix). Raises TypeError for any other input. |
Operators
| Operation | Behavior |
|---|---|
cc == other | True only if other is also a CameraCalibration with equal width/height/distortion_model and elementwise-equal distortion_parameters/intrinsic_matrix. NotImplemented (so False) for any other type. |
hash(cc) | Not supported (__hash__ = None). |
repr(cc) | CameraCalibration(width=1280, height=720, distortion_model=<DistortionModel.PLUMB_BOB: 'plumb_bob'>) -- shows the internal DistortionModel member's own repr (not the plain string from the distortion_model property); distortion_parameters and intrinsic_matrix are omitted entirely. |
Visualization
datatypes.visualize(camera_calibration, entity_path=...) logs it as a rerun Pinhole camera, using intrinsic_matrix as image_from_camera and [width, height] as the image resolution, with camera_xyz=rr.ViewCoordinates.RDF (right-down-forward). distortion_model/distortion_parameters aren't used by the visualization -- rerun's Pinhole only renders an undistorted pinhole frustum. CameraCalibration has no registered label handler -- passing label= to visualize() is silently ignored (no error, no label rendered).
Example
"""Demonstrates the Telekinesis CameraCalibration datatype."""
import time
import rerun as rr
from loguru import logger
from telekinesis import datatypes
def camera_calibration_example():
"""Demonstrate creation, inspection, operations, visualization, and serialization."""
# ======================= Create ============================================
camera_calibration = datatypes.CameraCalibration(
width=1280,
height=720,
distortion_model="plumb_bob",
distortion_parameters=[-0.2, 0.1, 0.0, 0.0, 0.0],
intrinsic_matrix=[1000.0, 0.0, 640.0, 0.0, 1000.0, 360.0, 0.0, 0.0, 1.0],
)
logger.info(f"Created CameraCalibration: {camera_calibration}")
calibration_from_dict = datatypes.CameraCalibration.coerce(
{
"width": 640,
"height": 480,
"distortion_model": "plumb_bob",
"distortion_parameters": [0.0, 0.0, 0.0, 0.0, 0.0],
"intrinsic_matrix": [500.0, 0.0, 320.0, 0.0, 500.0, 240.0, 0.0, 0.0, 1.0],
}
)
logger.info(f"CameraCalibration coerced from dict: {calibration_from_dict}")
# distortion_model also accepts a DistortionModel member directly, with a
# parameter count matching that model (8 for rational_polynomial).
rational_calibration = datatypes.CameraCalibration(
width=1280,
height=720,
distortion_model=datatypes.DistortionModel.RATIONAL_POLYNOMIAL,
distortion_parameters=[-0.2, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
intrinsic_matrix=[1000.0, 0.0, 640.0, 0.0, 1000.0, 360.0, 0.0, 0.0, 1.0],
)
logger.info(f"Rational-polynomial CameraCalibration: {rational_calibration}")
# ======================= Inspect ===========================================
logger.info(f"width={camera_calibration.width}")
logger.info(f"height={camera_calibration.height}")
logger.info(f"distortion_model={camera_calibration.distortion_model}")
logger.info(f"distortion_parameters={camera_calibration.distortion_parameters}")
logger.info(f"intrinsic_matrix=\n{camera_calibration.intrinsic_matrix}")
logger.info(
f"DistortionModel.PLUMB_BOB.parameter_names="
f"{datatypes.DistortionModel.PLUMB_BOB.parameter_names}"
)
logger.info(
f"DistortionModel.RATIONAL_POLYNOMIAL.parameter_count="
f"{datatypes.DistortionModel.RATIONAL_POLYNOMIAL.parameter_count}"
)
# ======================= Operations =========================================
# intrinsic_matrix returns a defensive copy; mutating it does not affect the original.
intrinsic_matrix_view = camera_calibration.intrinsic_matrix
intrinsic_matrix_view[0, 0] = -1.0
logger.info(f"Original fx unaffected: {camera_calibration.intrinsic_matrix[0, 0]}")
logger.info(f"camera_calibration == camera_calibration: {camera_calibration == camera_calibration}")
logger.info(
f"camera_calibration == calibration_from_dict: "
f"{camera_calibration == calibration_from_dict}"
)
# ======================= Visualize =========================================
rr.init("camera_calibration_example", spawn=True)
datatypes.visualize(camera_calibration, entity_path="/camera_calibration")
# ======================= Serialize / Deserialize ===========================
start = time.perf_counter()
serialized = datatypes.serialize(camera_calibration)
serialization_ms = (time.perf_counter() - start) * 1000
start = time.perf_counter()
deserialized = datatypes.deserialize(serialized)["param_0"]
deserialization_ms = (time.perf_counter() - start) * 1000
logger.info(f"Deserialized CameraCalibration: {deserialized}")
logger.info(f"Round-trip successful: {camera_calibration == deserialized}")
logger.info(f"Serialization time: {serialization_ms:.3f} ms")
logger.info(f"Deserialization time: {deserialization_ms:.3f} ms")
if __name__ == "__main__":
camera_calibration_example()
