Camera

Camera is the primary projective camera model in PadelKit. It combines CameraIntrinsics, CameraExtrinsics, and CameraDistortion to project 3D world coordinates onto 2D image sensors and unproject 2D pixel detections back into 3D rays and court planes.

3D Camera Frustum and Court Presets
Projective Camera model showing the broadcast_near viewing frustum, optical axis ray, and built-in court camera presets.

Properties

  • Name
    intrinsics
    Type
    CameraIntrinsics
    Description

    The internal sensor and focal length parameters. See CameraIntrinsics.

  • Name
    extrinsics
    Type
    CameraExtrinsics
    Description

    The 3D position and rotation pose of the camera. See CameraExtrinsics.

  • Name
    distortion
    Type
    CameraDistortion
    Description

    The optical lens distortion configuration. Defaults to CameraDistortion.none(). See CameraDistortion.

  • Name
    name
    Type
    str
    Description

    Identifier string for the camera (e.g., "broadcast_near").

  • Name
    floor_homography
    Type
    np.ndarray
    Description

    Analytical 3x3 homography matrix mapping centered court floor coordinates (X, Y, 1) in meters to (u, v, 1) image pixels.

  • Name
    inverse_floor_homography
    Type
    np.ndarray
    Description

    Analytical 3x3 inverse homography mapping (u, v, 1) image pixels directly to (X, Y, 1) court floor coordinates in meters.


classmethodCamera.from_landmarks()

Calibrate from 2D Video Landmarks

Calibrates a complete 3D Camera (CameraIntrinsics + 6-DoF CameraExtrinsics) directly from 4 or more 2D CourtLandmark pixel coordinates observed in a video frame.

If intrinsics is omitted, Camera.from_landmarks() automatically estimates the focal length from the court's perspective vanishing points and jointly refines focal length and 6-DoF camera pose via Levenberg-Marquardt reprojection minimization.

Arguments

  • Name
    landmarks_2d
    Type
    Mapping[str | CourtLandmark, Sequence[float]]
    Description

    Dictionary mapping at least 4 landmark names (e.g., "floor_near_left", "floor_near_right", "floor_far_right", "floor_far_left", or 3D wall corners "wall_top_far_left") to their (u, v) pixel coordinates.

  • Name
    court
    Type
    Court | None
    Description

    Reference Court instance. Defaults to Court.fip_standard().

  • Name
    intrinsics
    Type
    CameraIntrinsics | None
    Description

    Optional known CameraIntrinsics. If None, focal length is estimated automatically.

  • Name
    width_px
    Type
    int
    Description

    Video frame width in pixels (used when intrinsics is None).

  • Name
    height_px
    Type
    int
    Description

    Video frame height in pixels (used when intrinsics is None).

Calibrate from 4 Corners

classmethod
from_landmarks
from padelkit import Camera, Court

court = Court.fip_standard()

# 4 court floor corners labeled on a 1920x1080 broadcast video
corners_px = {
    "floor_near_left":  (228.5, 924.1),
    "floor_near_right": (1691.5, 924.1),
    "floor_far_right":  (1274.2, 342.8),
    "floor_far_left":   (645.8, 342.8),
}

cam = Camera.from_landmarks(corners_px, court=court)
rmse = cam.reprojection_error(corners_px, court=court)
print(f"Position: {cam.extrinsics.position} | RMSE: {rmse:.4f} px")

classmethodCamera.from_preset()

Preset Initialization

Creates a Camera from any standardized CameraPreset around a regulation padel court, or via dedicated shortcuts such as Camera.broadcast_near(), Camera.broadcast_far(), and Camera.overhead_zenith().

Arguments

  • Name
    preset
    Type
    CameraPreset | str
    Description

    The preset identifier (e.g., CameraPreset.BROADCAST_NEAR, "overhead_zenith", "corner_near_left").

  • Name
    court
    Type
    Court | None
    Description

    Optional Court instance used to compute wall offsets. Defaults to Court.fip_standard().

  • Name
    width_px
    Type
    int
    Description

    Image width in pixels.

  • Name
    height_px
    Type
    int
    Description

    Image height in pixels.

  • Name
    distortion
    Type
    CameraDistortion | None
    Description

    Optional lens distortion model.

Presets

classmethod
from_preset
from padelkit import Camera, CameraPreset

# Standard broadcast view behind the near glass wall
cam_broadcast = Camera.broadcast_near()

# Overhead zenith tactical camera (14.5m above the net)
cam_zenith = Camera.overhead_zenith()

# High corner action-camera view
cam_corner = Camera.from_preset(CameraPreset.CORNER_NEAR_LEFT)

methodcamera.world_to_image()

Project a 3D point

Projects a single 3D world point (X, Y, Z) (in meters) onto (u, v) pixel coordinates, applying lens distortion automatically. Returns None if the point lies behind the camera (Z_cam <= 0).

Arguments

  • Name
    point_3d
    Type
    tuple[float, float, float] | Sequence[float]
    Description

    The 3D point (X, Y, Z) in meters.

  • Name
    coordinate_system
    Type
    CoordinateSystem
    Description

    Reference frame of point_3d (CENTERED or CORNER_BASED).

  • Name
    clip_to_sensor
    Type
    bool
    Description

    If True, returns None when (u, v) falls outside [0, width_px] x [0, height_px].

Usage

method
world_to_image
from padelkit import Camera

cam = Camera.broadcast_near()
uv = cam.world_to_image((0.0, 0.0, 0.88))

Output

(960.0, 521.48)

methodcamera.project_points()

Vectorized 3D Batch Projection

Vectorized NumPy projection of an array of (N, 3) 3D points. Returns (uv_pixels, visible_mask).

Arguments

  • Name
    points_3d
    Type
    np.ndarray | Sequence[Sequence[float]]
    Description

    Array of 3D points with shape (N, 3).

  • Name
    coordinate_system
    Type
    CoordinateSystem
    Description

    Reference frame of points_3d.

Returns

  • Name
    uv_pixels
    Type
    np.ndarray
    Description

    Float64 array of shape (N, 2) containing (u, v) pixel coordinates.

  • Name
    visible_mask
    Type
    np.ndarray
    Description

    Boolean array of shape (N,) indicating points in front of the camera and inside the sensor frame.

Usage

method
project_points
import numpy as np
from padelkit import Camera

cam = Camera.broadcast_near()
trajectory_3d = np.array([
    [0.0, -5.0, 1.2],
    [0.0,  0.0, 1.8],
    [0.0,  5.0, 0.5],
])
uv, visible = cam.project_points(trajectory_3d)

methodcamera.project_court_landmarks()

Project 17 Court Landmarks

Projects all 17 standardized 3D CourtLandmark positions onto the camera's 2D image sensor.

Keyword Arguments

  • Name
    court
    Type
    Court | None
    Description

    The Court instance to project. Defaults to Court.fip_standard().

  • Name
    only_visible
    Type
    bool
    Description

    If True, omits landmarks that fall outside the image frame.

Usage

method
project_court_landmarks
from padelkit import Camera, Court

court = Court.fip_standard()
cam = Camera.broadcast_near(court=court)
landmarks_2d = cam.project_court_landmarks(court=court)

methodcamera.project_pixel_to_plane()

Unproject Pixel to 3D Plane

Removes lens distortion from a 2D pixel (u, v), casts a 3D ray from the camera center, and computes its exact intersection (X, Y, plane_z) with any horizontal plane Z = plane_z (such as the court floor Z = 0.0).

Arguments

  • Name
    pixel_2d
    Type
    tuple[float, float] | Sequence[float]
    Description

    The (u, v) pixel coordinate in the image.

  • Name
    plane_z
    Type
    float
    Description

    Height Z (in meters) of the horizontal intersection plane.

Usage

method
project_pixel_to_plane
from padelkit import Camera

cam = Camera.broadcast_near()
floor_xyz = cam.project_pixel_to_plane((960.0, 567.42), plane_z=0.0)

Was this page helpful?