Camera System & 3D Projection

The padelkit.camera module provides a mathematically rigorous, vectorized projective camera engine designed for padel computer vision, synthetic dataset generation, and 3D state estimation.

Coordinate Systems Overview

PadelKit connects three coordinate frames seamlessly:

  • Name
    1. World Frame (Meters)
    Type
    (X, Y, Z)
    Description

    Matches the standard Court geometry system (CoordinateSystem.CENTERED by default): (0, 0, 0) lies at the center of the net on the floor, +X points right across the court width, +Y points forward towards the far back wall, and +Z points vertically upwards.

  • Name
    2. Camera Frame (OpenCV / CV)
    Type
    (X_cam, Y_cam, Z_cam)
    Description

    Origin at the optical center of the lens. +X_cam points right across image columns, +Y_cam points down across image rows, and +Z_cam points forward along the optical axis into the court. Also exposes opengl_camera_to_world_matrix (+Y up, -Z forward) for direct compatibility with Three.js and Blender.

  • Name
    3. Image Sensor Plane (Pixels)
    Type
    (u, v)
    Description

    Origin (0, 0) at the top-left corner of the image sensor, with u in [0, width_px] and v in [0, height_px].

3D Camera Frustum and Coordinate Systems
3D broadcast_near camera viewing frustum pyramid, preset camera locations, and the World -> Camera -> Sensor coordinate transformation chain.

Quick Example: Projecting the 17 Court Landmarks

1080p Sensor Plane Landmark Projection
1920 × 1080 sensor plane showing all 17 projected CourtLandmark pixel positions, principal point (cx, cy), and calibration matrix K.

Using a built-in broadcast camera preset, you can project all 17 3D CourtLandmark points onto a 1080p image sensor in two lines of code, and unproject any 2D pixel detection back onto the 3D court floor (Z = 0).

3D-to-2D & 2D-to-3D

guide
Camera
from padelkit import Camera, Court

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

# 1. Project all 17 3D landmarks to 2D image pixels
landmarks_px = cam.project_court_landmarks(court=court)
center_uv = landmarks_px["center"]

# 2. Intersect a 2D pixel ray with the court floor (Z = 0.0)
floor_xyz = cam.project_pixel_to_plane(center_uv, plane_z=0.0)

# 3. Or calibrate a Camera directly from 4+ labeled 2D landmarks in a video
cal_cam = Camera.from_landmarks({
    "floor_near_left":  landmarks_px["floor_near_left"],
    "floor_near_right": landmarks_px["floor_near_right"],
    "floor_far_right":  landmarks_px["floor_far_right"],
    "floor_far_left":   landmarks_px["floor_far_left"],
})

Output

# center_uv (pixels)
(960.0, 567.42)

# floor_xyz (meters)
(0.0, 0.0, 0.0)

Core Camera Components

  • Name
    Camera
    Type
    class
    Description

    Top-level camera model combining CameraIntrinsics, CameraExtrinsics, and CameraDistortion. Provides presets and projection/unprojection methods. See Camera.

  • Name
    CameraIntrinsics
    Type
    dataclass
    Description

    Sensor resolution (width_px, height_px), focal lengths (fx, fy), principal point (cx, cy), and calibration matrix K. See CameraIntrinsics.

  • Name
    CameraExtrinsics
    Type
    dataclass
    Description

    6-DoF position and orientation in 3D space, constructible via from_look_at(), from_euler(), or from_rt(). See CameraExtrinsics.

  • Name
    CameraDistortion
    Type
    dataclass
    Description

    Forward and iterative inverse optical distortion supporting Pinhole, Brown-Conrady (k1, k2, p1, p2, k3), and Kannala-Brandt Fisheye (k1, k2, k3, k4) lenses. See CameraDistortion.

Was this page helpful?