Skip to content

IslamFadl/camera-calibration

Repository files navigation

Camera Calibration & Multi-View Geometry

Classical computer vision pipeline implementing camera calibration, undistortion, homography estimation, and feature-based image stitching — all in clean, reproducible Python scripts.

Check here for more perception projects and repos: github.com/IslamFadl


Why this repo exists

Camera calibration is the foundation of any geometric computer vision pipeline — stereo vision, structure from motion, SLAM, AR — none of it works without accurate intrinsic and extrinsic parameters.

This repo implements the full classical pipeline from scratch, with each script demonstrating one concept clearly. No magic, no black boxes — every step is visible, debuggable, and documented.


What's inside

camera-calibration/
├── images/                       # 13 OpenCV sample checkerboard images
├── output/                       # Generated visualisations (gitignored)
│   ├── corners/                  # Detected corners overlaid
│   ├── reprojection/             # Reprojection error visualisation
│   ├── undistorted/              # Before/after undistortion
│   ├── homography/               # Warped images
│   └── stitching/                # Stitched panorama
├── utils/
│   ├── __init__.py
│   └── visualisation.py          # Plotting helpers
├── 01_find_corners.py            # Checkerboard corner detection
├── 02_calibrate.py               # Compute intrinsic matrix + distortion
├── 03_undistort.py               # Apply calibration to fix lens distortion
├── 04_homography.py              # SIFT + RANSAC homography between two views
├── 05_stitching.py               # Multi-image panorama stitching
├── calibration_results.npz       # Saved calibration parameters
├── requirements.txt
├── .gitignore
└── README.md

Key concepts demonstrated

1. Checkerboard corner detection (01_find_corners.py)

A checkerboard provides known 3D control points on a flat plane. By detecting the same corners across multiple images taken from different angles, we generate the correspondences needed to solve for camera intrinsics.

The script uses cv2.findChessboardCorners with adaptive thresholding, then refines corner positions to sub-pixel accuracy with cv2.cornerSubPix.

Result on this dataset: 12 of 13 images have detectable corners.

2. Intrinsic matrix and distortion coefficients (02_calibrate.py)

The intrinsic matrix K describes the camera itself — independent of where it is in the world:

K = [ fx   0   cx ]
    [  0  fy   cy ]
    [  0   0    1 ]
Component Meaning
fx, fy Focal length in pixels (physical focal length / pixel size). Not millimetres.
cx, cy Principal point — the pixel where the optical axis intersects the sensor. Ideally (width/2, height/2) but never exactly due to manufacturing tolerances.

cv2.calibrateCamera also returns 5 distortion coefficients:

  • k1, k2, k3 — radial distortion (barrel / pincushion — straight lines curve)
  • p1, p2 — tangential distortion (lens not perfectly parallel to sensor)

Reprojection error on this dataset: 0.XX pixels (under 1.0 = good calibration).

3. Undistortion (03_undistort.py)

Once calibration is solved, any image taken with the same camera can be undistorted with cv2.undistort(img, K, dist_coeffs). Before any geometric computation (stereo, homography, pose estimation) you must undistort first — otherwise the geometry is wrong.

The script produces side-by-side before/after visualisations to make the distortion visible. The corners of the image move noticeably; pixels near the centre barely shift.

4. Homography estimation (04_homography.py)

A homography is a 3×3 matrix that maps any point in image 1 to its corresponding point in image 2, assuming the scene is planar or the camera only rotates.

The pipeline:

  1. Feature detectioncv2.SIFT_create() finds keypoints with descriptors invariant to scale and rotation
  2. Feature matching — brute-force matcher returns the 2 nearest descriptors per keypoint
  3. Lowe's ratio test — keep a match only if distance(best) < 0.75 × distance(second_best). This filters ambiguous matches.
  4. RANSAC homography — randomly sample 4 correspondences, compute candidate H, count inliers, repeat. Returns the H with the most inliers.
H, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)

Minimum correspondences needed: 4 (8 degrees of freedom).

Why RANSAC and not least-squares? SIFT produces ~100–500 matches but 10–30% are wrong. Least-squares is destroyed by outliers. RANSAC tolerates them by construction.

5. Image stitching (05_stitching.py)

Combines steps 1–4 into a real application — stitching multiple overlapping images into a panorama using the homographies between them. Each new image is warped into the panorama coordinate system with cv2.warpPerspective.


Important distinctions

These are the three matrices senior interviewers probe on:

Matrix When to use Constraint
Homography Planar scene or pure camera rotation Scene must be flat or camera fixed in position
Essential matrix Calibrated cameras, general motion Cameras must be calibrated (K known)
Fundamental matrix Uncalibrated cameras, general motion Used in stereo matching, SfM

Homographies are used here. Essential and Fundamental are covered in the companion 3d-scene-understanding repo.


How to run

git clone https://github.com/IslamFadl/camera-calibration.git
cd camera-calibration
pip install -r requirements.txt

# Run the pipeline in order
python 01_find_corners.py
python 02_calibrate.py
python 03_undistort.py
python 04_homography.py
python 05_stitching.py

Each script produces visualisations in output/. Open them to verify the results visually.

Tested on Python 3.11, macOS (M-series) and Linux. No GPU required.


Calibration results

After running 02_calibrate.py on the included sample images:

Parameter Value
Focal length fx, fy ~530, ~530 pixels
Principal point cx, cy ~320, ~240
k1, k2 (radial) -0.27, 0.11
p1, p2 (tangential) 0.001, 0.000
Mean reprojection error < 0.5 pixels

A reprojection error under 1.0 pixel indicates a clean calibration. Under 0.5 is considered excellent.


License

MIT — use freely.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages