Python SDK for camera calibration and projection transformations - handle lens distortion, coordinate transformations, and 3D ray casting with symbolic expressions.
Project description
camera-client
Python SDK for camera calibration and projection transformations. Transform coordinates between distorted image space, corrected image space, and real-world 3D coordinates using pre-computed calibration data.
Features
- Vectorized operations - Process multiple points simultaneously for high performance
- Multiple coordinate systems - Transform between source (distorted), corrected, and ground (3D world) coordinates
- Lens distortion handling - Correct for camera lens distortion using calibration lookup tables
- Ground plane projection - Project image coordinates to 3D world coordinates and vice versa
- Ray casting - Generate 3D rays from image coordinates for ray tracing and 3D reconstruction
- Sympy-based transformations - Fast compiled symbolic expressions for mathematical transformations
- NumPy-based - Fast array operations with minimal dependencies
Installation
Install from PyPI:
pip install camera-client
CLI Usage
Download camera calibration archives from URL:
# Download single archive
python -m camera_client get_camera_archive https://example.com/camera.npz
# Download from file with URLs (one per line, non-URL lines ignored)
python -m camera_client get_camera_archive -f urls.txt -o ./archives
Quick Start
import numpy as np
from camera_client import CameraProjection
# Load camera calibration data from NPZ archive
camera = CameraProjection.load("camera_calibration.npz")
# Transform multiple points (vectorized operations)
# Note: All methods require (N, 2) or (N, 3) shaped arrays
source_points = np.array([
[100, 200],
[300, 400],
[500, 600]
]) # Shape: (3, 2)
# Remove lens distortion
corrected_points = camera.src_to_ctd(source_points)
# Project to ground plane (height = 0)
ground_points = camera.src_to_gnd(source_points, h=0)
print(ground_points) # Returns (N, 3) array with [x, y, z] coordinates
Coordinate Systems
This library handles transformations between three coordinate systems:
- src (Source): Distorted image coordinates from the camera
- ctd (Corrected): Undistorted image coordinates after lens correction
- gnd (Ground): Real-world 3D coordinates (x, y, z)
Distorted Undistorted World 3D
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ │ │ │ │ │
│ Source (src) │ <──> │ Corrected (ctd) │ <──> │ Ground (gnd) │
│ │ │ │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Lens distortion Lens correction 3D projection
Usage Examples
Basic Coordinate Transformations
from camera_client import CameraProjection
import numpy as np
# Load calibration data
camera = CameraProjection.load("camera_calibration.npz")
# Source (distorted) to Corrected (undistorted)
src_points = np.array([[640, 480], [1280, 720]])
ctd_points = camera.src_to_ctd(src_points)
# Corrected back to Source
src_points_back = camera.ctd_to_src(ctd_points)
# Check round-trip accuracy
error = np.linalg.norm(src_points - src_points_back, axis=1)
print(f"Round-trip error: {error}")
3D Ground Projection
# Project image points to ground plane
src_points = np.array([[640, 480], [800, 600]])
# Project to ground at height = 0 (ground level)
ground_points = camera.src_to_gnd(src_points, h=0)
print(ground_points) # Shape: (2, 3) with [x, y, z] coordinates
# Project to elevated plane (e.g., 1.5 meters above ground)
elevated_points = camera.src_to_gnd(src_points, h=1.5)
# Different height for each point
heights = np.array([0, 1.5])
mixed_points = camera.src_to_gnd(src_points, h=heights)
Reverse Projection (3D to Image)
# Project 3D world coordinates back to image
world_points = np.array([
[10.0, 5.0, 0.0], # x, y, z in meters
[15.0, 8.0, 1.5]
])
# Get corrected image coordinates
ctd_points = camera.gnd_to_ctd(world_points)
# Get source (distorted) image coordinates
src_points = camera.gnd_to_src(world_points)
Batch Processing
# Process large batches of points efficiently
num_points = 10000
random_points = np.random.rand(num_points, 2) * [1920, 1080]
# Vectorized transformation (fast!)
corrected = camera.src_to_ctd(random_points)
ground = camera.src_to_gnd(random_points, h=0)
Ray Casting (3D Reconstruction)
# Get 3D rays from image points (useful for ray tracing, 3D reconstruction)
src_points = np.array([[640, 480], [800, 600]])
# Get ray directions from source (distorted) coordinates
rays = camera.src_to_ray(src_points)
print(rays.shape) # (2, 3) - normalized direction vectors
# Or from corrected coordinates
ctd_points = camera.src_to_ctd(src_points)
rays = camera.ctd_to_ray(ctd_points)
# Get camera position in world space (ray origin)
key_point = camera.get_key_point()
print(key_point.shape) # (3,) - [x, y, z] camera position
# Ray equation: point_on_ray = key_point + t * ray_direction
# All rays are normalized to unit length
Accessing Camera Properties
# Get camera dimensions
print(f"Image size: {camera.im_width} x {camera.im_height}")
print(f"Image WH: {camera.im_wh_size}")
print(f"Plan scale: {camera.plan_scale}")
API Reference
CameraProjection.load(archive_path)
Load camera calibration from NPZ file.
Parameters:
archive_path(str): Path to .npz calibration archive
Returns:
CameraProjectioninstance
src_to_ctd(points)
Transform from source (distorted) to corrected coordinates.
Parameters:
points(np.ndarray): Shape (N, 2) array of [x, y] coordinates
Returns:
np.ndarray: Shape (N, 2) corrected coordinates
Note: Input must be 2D array. For single point use np.array([[x, y]])
ctd_to_src(points)
Transform from corrected to source (distorted) coordinates.
Parameters:
points(np.ndarray): Shape (N, 2) array of [x, y] coordinates
Returns:
np.ndarray: Shape (N, 2) source coordinates
src_to_gnd(points, h)
Transform from source coordinates to 3D ground coordinates.
Parameters:
points(np.ndarray): Shape (N, 2) array of [x, y] coordinatesh(float or np.ndarray): Height(s) above ground. Scalar or shape (N,) array
Returns:
np.ndarray: Shape (N, 3) ground coordinates [x, y, z]
gnd_to_src(points)
Transform from 3D ground coordinates to source coordinates.
Parameters:
points(np.ndarray): Shape (N, 3) array of [x, y, z] coordinates
Returns:
np.ndarray: Shape (N, 2) source coordinates
ctd_to_gnd(points, h)
Transform from corrected coordinates to 3D ground coordinates.
Parameters:
points(np.ndarray): Shape (N, 2) array of [x, y] coordinatesh(float or np.ndarray): Height(s) above ground
Returns:
np.ndarray: Shape (N, 3) ground coordinates
gnd_to_ctd(points)
Transform from 3D ground coordinates to corrected coordinates.
Parameters:
points(np.ndarray): Shape (N, 3) array of [x, y, z] coordinates
Returns:
np.ndarray: Shape (N, 2) corrected coordinates
src_to_ray(points)
Generate 3D ray directions from source (distorted) image coordinates.
Parameters:
points(np.ndarray): Shape (N, 2) array of [x, y] coordinates
Returns:
np.ndarray: Shape (N, 3) normalized ray direction vectors
Note: All rays originate from the camera key-point (use get_key_point())
ctd_to_ray(points)
Generate 3D ray directions from corrected (undistorted) image coordinates.
Parameters:
points(np.ndarray): Shape (N, 2) array of [x, y] coordinates
Returns:
np.ndarray: Shape (N, 3) normalized ray direction vectors
get_key_point()
Get the camera position (key-point) in world space.
Returns:
np.ndarray: Shape (3,) array with [x, y, z] camera position
get_ctd_points_context(ctd_points)
Get scale context values for corrected (CTD) image points.
Parameters:
ctd_points(np.ndarray): Shape (N, 2) array of [x, y] corrected coordinates
Returns:
dict: Dictionary with keys:wscale(np.ndarray): Shape (N,) width scale valueshscale(np.ndarray): Shape (N,) height scale valuesvangle(np.ndarray): Shape (N,) vertical angle values (radians)
Note: Out-of-bounds points will have NaN values
Example:
ctd_points = np.array([[640, 480], [800, 600]])
context = camera.get_ctd_points_context(ctd_points)
print(context['wscale']) # Width scale at each point
print(context['hscale']) # Height scale at each point
print(context['vangle']) # Vertical angle at each point
get_src_points_context(src_points)
Get scale context values for source (distorted) image points.
Parameters:
src_points(np.ndarray): Shape (N, 2) array of [x, y] source coordinates
Returns:
dict: Dictionary with keys:wscale(np.ndarray): Shape (N,) width scale valueshscale(np.ndarray): Shape (N,) height scale valuesvangle(np.ndarray): Shape (N,) vertical angle values (radians)
Note: Internally converts source points to CTD coordinates first, then retrieves context
Example:
src_points = np.array([[640, 480], [800, 600]])
context = camera.get_src_points_context(src_points)
print(context['wscale']) # Width scale at each point
Calibration File Format
The calibration file is a NumPy .npz archive containing:
Lookup Tables
src2ctd: Source to corrected coordinate map (H x W x 2)ctd2src: Corrected to source coordinate map (H x W x 2)map_scale_h: Height scale values (H x W)map_scale_w: Width scale values (H x W)map_scale_vang: Vertical angle values (H x W)
Symbolic Expressions (stored as strings, parsed with SymPy)
exp_im2gnd: Image to ground coordinate transformationexp_gnd2im: Ground to image coordinate transformationexp_key_point: Camera key-point (position) in world spaceexp_im2ray: Image to ray direction transformation
Metadata
format_version: Version string of the data formatcamera_id: Integer identifier for the cameraplan_url: URL or path to the ground plan imageplan_scale: Scale factor for ground plane coordinates (pixels per meter)plan_width: Width of the ground plan in pixelsplan_height: Height of the ground plan in pixelsim_src_url: URL or path to the source (distorted) camera imageim_ctd_url: URL or path to the corrected (undistorted) camera imageim_width: Width of the camera image in pixelsim_height: Height of the camera image in pixelsctd_geometry: JSON object with geometry data in CTD coordinates (efov_polygon, counting_lines)
Requirements
- Python >= 3.7
- NumPy >= 1.20.0
- SymPy >= 1.10.0
Links
- Repository: https://github.com/avabr/camera-client
- Issues: https://github.com/avabr/camera-client/issues
- PyPI: https://pypi.org/project/camera-client/
License
MIT License - see LICENSE file for details.
Author
Alexander Abramov (extremal.ru@gmail.com)
Upload PyPi
rm dist/* && python -m build && python -m twine upload dist/*
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file camera_client-0.2.6.tar.gz.
File metadata
- Download URL: camera_client-0.2.6.tar.gz
- Upload date:
- Size: 14.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
441cfdc8c57e4814044668168ff1a7df1b4bd022f4560c4984b31bcae97afd50
|
|
| MD5 |
1f6a8e0594435d6bc84cebfe157b397a
|
|
| BLAKE2b-256 |
36f1de47ea62255140817a2e96e160ce15063ed515da988f78d0497f260cfc9b
|
File details
Details for the file camera_client-0.2.6-py3-none-any.whl.
File metadata
- Download URL: camera_client-0.2.6-py3-none-any.whl
- Upload date:
- Size: 12.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
705a9e0625bb3b352ccb0fe61275296039db725910cbd4f975272a47293f0f1c
|
|
| MD5 |
102ba9f8dbb821eebde298ed7ca2d81f
|
|
| BLAKE2b-256 |
2269d255d4912c6d1807230224441d201b370316c16ab99eba0ec75670941ad4
|