A modular camera calibration system for stereo camera setups using ArUco markers and PiCamera2.
This is primarily for calibrating cameras on Raspberry Pi based devices, it should work for others for pure calibration but the capture parts will assume you've a Pi camera attached.
├── main.py # Entry point with CLI and config support
├── calibration.py # Core calibration logic
├── camera_capture.py # PiCamera2 capture functions
├── image_annotation.py # ArUco marker detection
├── config.ini # Configuration file
└── README.md # This file
If your device will be single purpose and you don't need to worry about dependency hell, have a look at Jeff Geerling's post to disable the library safety mechanism that's enabled by default.
Create a venv:
python3 -m venv env
source env/bin/activateAnd follow this guide to using PiCamera2 in a venv.
All settings can be configured via config.ini:
- Camera device indices (left/right)
- Exposure time and gain
- Image size and transformations
- Marker dictionary type
- Board dimensions
- Square and marker lengths
- Detection parameters
- Rectification alpha
- Fisheye balance
- Output file paths
- Margins and scale factors
Before running calibration operations, set up your environment:
# Create a sample configuration file
python main.py --action create-config
# Create the folder structure for storing images
python main.py --action setup-foldersYou can also create a custom config file:
python main.py --config my_config.ini --action create-config
python main.py --config my_config.ini --action setup-foldersThe calibration pipeline can be run using different actions:
# Capture images from left camera
python main.py --action capture-left
# Capture images from right camera
python main.py --action capture-right
# Capture stereo image pairs
python main.py --action capture-stereo
# Calibrate left camera
python main.py --action calibrate-left
# Calibrate left camera with fisheye model
python main.py --action calibrate-left --fisheye
# Calibrate right camera
python main.py --action calibrate-right
# Perform stereo calibration
python main.py --action stereo-calibrate
# Visualize overlap region for divergent cameras
python main.py --action visualize-overlap \
--left-image images/stereo/stereo_left_01.jpg \
--right-image images/stereo/stereo_right_01.jpg \
--stereo-calib calibration/stereo_calibration.yaml
# Preview stereo feed
python main.py --action previewIf you're using cameras with divergent (non-parallel) optical axes, see the Divergent Stereo Camera Guide for:
- Computing overlap masks showing the overlapping field of view
- Analyzing vergence angle and baseline distance
- Optimizing stereo rectification for divergent configurations
- Visualizing overlap regions on actual images
Specify a different config file:
python main.py --config my_config.ini --action capture-stereofrom calibration import Calibration
import configparser
# Load configuration
config = configparser.ConfigParser()
config.read('config.ini')
# Create calibration instance
calibrate = Calibration.from_config(config)
# Load existing calibrations
calibrate.load_calibrations()
# Perform operations
calibrate.capture_stereo_images()
calibrate.stereo_calibrate()- Setup - Initialize your environment:
python main.py --action create-config python main.py --action setup-folders
- Configure - Edit
config.iniwith your camera and marker settings - Capture - Collect calibration images:
- Individual cameras:
capture-left,capture-right - Stereo pairs:
capture-stereo
- Individual cameras:
- Calibrate - Process images:
- Individual:
calibrate-left,calibrate-right - Stereo:
stereo-calibrate
- Individual:
- Verify - Preview results with
preview
Calibration data is saved in your chosen format (NPZ, YAML, or both):
left.npz/.yaml- Left camera calibrationright.npz/.yaml- Right camera calibrationleft_fisheye.npz/.yaml- Left camera fisheye calibrationright_fisheye.npz/.yaml- Right camera fisheye calibrationstereo_calibration.npz/.yaml- Stereo calibration data with extrinsics
The stereo calibration file includes:
- Intrinsics: Camera matrices and distortion coefficients for both cameras
- Extrinsics: Rotation (R) and translation (T) between cameras
- Rectification: Maps for aligning image planes (R1, R2, P1, P2, Q)
- Overlap Masks: Binary masks showing overlapping field of view
- Metadata: Vergence angle, baseline distance, overlap statistics
For divergent cameras, additional masks are saved:
calibration/overlap_mask_left.png- Left camera overlap regioncalibration/overlap_mask_right.png- Right camera overlap regioncalibration/stereo_overlap_visualization.png- Visual overlay (when using visualize-overlap)