sudo apt update
sudo apt install -y python3-venv python3-tk libgl1 libglib2.0-0python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip wheel
pip install -r requirements.txtOr use the helper script:
bash setup.shPySpin is usually provided by the FLIR Spinnaker SDK (not standard PyPI).
pip install /path/to/spinnaker_python-*.whlsource .venv/bin/activate
python run_calibration_gui.pyBefore launching the GUI, you can verify PySpin + camera capture:
python calib_app/flir_self_test.pyProbe images are saved under:
calib_app/workspace/runtime_probe/
- Use
Auto Detect FLIRor manually enter serial numbers. - Set checkerboard parameters:
Board Cols,Board Rows,Square Size.- Default is
Cols=6,Rows=5. - Default
Square Sizeis0.08(8 cm). - Set extrinsic options in GUI:
Compute Extrinsics,Min Common Frames,Reference Serial(optional). - The last saved values in
calib_app/calibration_config.jsonare loaded at startup.
- Default is
- Click
Open Live Capture. - Capture window behavior:
- Real-time per-camera preview (checkerboard corners are drawn, text is not overlaid on image).
- Per-camera status is shown below each preview (
No frame,Board detected,Board not detected). Save Setbutton (orC/SPACE) saves one synchronized set for all cameras.- Each live-capture run creates a new session folder under capture root (e.g.,
.../calib/session_20260224_235959/<serial>/) to avoid mixing datasets. Close Capturebutton (orQ/ESC) closes the live session safely.- Checkerboard detection runs at a throttled rate for smoother multi-camera preview; a full detection check is run again when saving.
- If
Require board detect to saveis enabled, save happens only when all cameras detect the board. - Live capture uses low-latency stream mode (
NewestOnly) and ignores transient frame timeouts to reduce preview lag. - The log shows per-camera transport info (
link_speed,throughput_limit,resulting_fps). - If
link_speedis near12500000 B/s, the link is effectively around 100Mbps-class throughput; multi-camera realtime will be unstable.
- Click
Run Calibration.- Per-camera intrinsic calibration is always computed.
- Extrinsic calibration is also computed (reference camera -> each other camera) when enough common checkerboard detections exist across the same image filenames.
- You can open
Live Undistort View(above the log panel) to see real-time undistorted streams using the latest saved calibration maps.
- After calibration, undistortion previews are generated in:
calib_app/workspace/outputs*/undistort_preview/
- Uses synchronized/common filenames (e.g.,
set_00012.png) detected in both cameras. - For each target camera,
stereoCalibrate(..., FIX_INTRINSIC)is run against a reference camera. - If common detections are fewer than
min_common_frames_for_extrinsic, that pair is skipped. - Results are saved under
extrinsicsincalibration_summary.json.
Config keys in calib_app/calibration_config.json:
compute_extrinsics(default:true)min_common_frames_for_extrinsic(default:8)extrinsic_reference_serial(default:null, meaning first camera in inventory)
calib_app/batch_calibrate.py uses:
- One shared output camera matrix (
K*) - Valid-area intersection across all cameras
- A centered common ROI for final crop
This keeps the final output FOV consistent across cameras.
- Launcher:
run_calibration_gui.py - App code:
calib_app/ - Captured images:
calib_app/workspace/data/calib/<serial>/ - Calibration outputs:
calib_app/workspace/outputs*/