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.
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(). SeeCameraDistortion.
- Name
name- Type
- str
- Description
Identifier string for the camera (e.g.,
"broadcast_near").
- Name
floor_homography- Type
- np.ndarray
- Description
Analytical
3x3homography 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
3x3inverse homography mapping(u, v, 1)image pixels directly to(X, Y, 1)court floor coordinates in meters.
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
Courtinstance. Defaults toCourt.fip_standard().
- Name
intrinsics- Type
- CameraIntrinsics | None
- Description
Optional known
CameraIntrinsics. IfNone, focal length is estimated automatically.
- Name
width_px- Type
- int
- Description
Video frame width in pixels (used when
intrinsicsisNone).
- Name
height_px- Type
- int
- Description
Video frame height in pixels (used when
intrinsicsisNone).
Calibrate from 4 Corners
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")
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
Courtinstance used to compute wall offsets. Defaults toCourt.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
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)
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(CENTEREDorCORNER_BASED).
- Name
clip_to_sensor- Type
- bool
- Description
If
True, returnsNonewhen(u, v)falls outside[0, width_px] x [0, height_px].
Usage
from padelkit import Camera
cam = Camera.broadcast_near()
uv = cam.world_to_image((0.0, 0.0, 0.88))
Output
(960.0, 521.48)
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
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)
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
Courtinstance to project. Defaults toCourt.fip_standard().
- Name
only_visible- Type
- bool
- Description
If
True, omits landmarks that fall outside the image frame.
Usage
from padelkit import Camera, Court
court = Court.fip_standard()
cam = Camera.broadcast_near(court=court)
landmarks_2d = cam.project_court_landmarks(court=court)
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
from padelkit import Camera
cam = Camera.broadcast_near()
floor_xyz = cam.project_pixel_to_plane((960.0, 567.42), plane_z=0.0)