Skip to content

CameraCalibration

SUMMARY

Intrinsic calibration parameters for a single camera: image resolution, a distortion model, and a (3, 3) intrinsic matrix.

python
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

FieldTypeDescription
widthintImage width in pixels, in [0, 2**32 - 1].
heightintImage height in pixels, in [0, 2**32 - 1].
distortion_modelstr | DistortionModelThe distortion model — a DistortionModel member, or its matching string value (e.g. "plumb_bob"). Determines the required length of distortion_parameters.
distortion_parametersnp.ndarray | list[float]Distortion parameters, shape (M,), where M must equal distortion_model.parameter_count (5 for plumb_bob, 8 for rational_polynomial).
intrinsic_matrixnp.ndarray | list[float]Row-major intrinsic camera matrix, shape (3, 3) (or a flattened length-9 sequence).

Raises

ExceptionCondition
TypeErrorwidth/height isn't int-convertible, or distortion_parameters/intrinsic_matrix can't be converted to a float64 array
ValueErrorwidth/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

AttributeTypeDescription
widthintImage width in pixels.
heightintImage height in pixels.
distortion_modelstrDistortion model name -- always the plain string value (DistortionModel(...).value), even though construction also accepts a DistortionModel member directly.
distortion_parametersnp.ndarrayDefensive copy of the distortion parameters, shape (M,), float64.
intrinsic_matrixnp.ndarrayDefensive 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

MethodDescription
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

OperationBehavior
cc == otherTrue 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

python
"""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()