Live Camera and Video Calibration

Overview

This script performs camera calibration using either: pigiuzt

  • a live USB camera feed
  • a prerecorded MP4 video
  • both sources when available

It detects a chessboard pattern in incoming frames, refines the detected corners, collects calibration points, and computes intrinsic camera parameters once enough frames have been gathered.


Purpose

The goal of this script is to estimate the internal camera parameters and lens distortion coefficients so that future frames can be undistorted and used more reliably in vision pipelines.


Calibration Settings

The script uses the following configuration:

  • Chessboard pattern size: 9 x 6
  • Square size: 25.0 mm
  • Minimum frames: 10
  • RMS threshold: 1.0
  • Frame sampling interval: every 10 frames

These values are defined at the top of the script.


Inputs

Live Camera

The live camera is opened with:

cap_cam = cv.VideoCapture(0, cv.CAP_DSHOW)

Video File

The prerecorded video is loaded from:

video_path = r"C:\Users\ahmed\Documents\vio-pipeline\code\image-recognition\calibration-photos\videos\VID00041.mp4"
cap_video = cv.VideoCapture(video_path)

Processing Pipeline

The script follows this sequence:

  1. Open the camera and video file
  2. Check which sources are available
  3. Read frames from the available source(s)
  4. Convert each frame to grayscale
  5. Detect chessboard corners using OpenCV
  6. Refine corner positions with subpixel accuracy
  7. Store 3D object points and 2D image points
  8. Perform camera calibration using cv.calibrateCamera
  9. Save calibration results if RMS error is below the threshold
  10. Optionally show undistorted video after calibration

Chessboard Detection

The chessboard corners are detected with:

found_video, corners_video = cv.findChessboardCorners(gray_video, pattern_size)

and similarly for the live camera feed.

To improve accuracy, the detected corners are refined using:

cv.cornerSubPix(...)

Calibration Output

When calibration succeeds, the script prints:

  • RMS reprojection error
  • camera matrix
  • distortion coefficients

If the RMS error is good enough, the calibration is saved to:

output/live_calibration.npz

This file contains:

  • camera_matrix
  • dist_coefs
  • rms
  • image_size
  • pattern_size
  • square_size

Undistortion Preview

Once calibration has been completed, the script can display an undistorted version of the video stream:

undistorted_video = cv.undistort(frame_video, camera_matrix, dist_coefs)
cv.imshow("Undistorted MP4", undistorted_video)

This gives a quick visual demonstration of the calibration result.


Controls

During execution:

  • Press c to start calibration using the currently collected frames
  • Press q to quit the program

Running the Script

Run the script from the project root:

python code/image-recognition/live_calibrate.py

Notes

  • The chessboard must be clearly visible in the frame.
  • Better calibration is achieved when the chessboard appears in different positions and angles.
  • Repeated nearly identical frames are avoided by sampling only every 10 frames.
  • Calibration quality is evaluated using RMS reprojection error.

Future Improvements

Possible improvements include:

  • making the video path configurable from the command line
  • saving separate calibration files for different cameras
  • adding side-by-side original vs undistorted display
  • documenting the output format in more detail