CV Camera Calibration
Every camera lens bends light a little, and every sensor sits at a slightly different spot behind the lens. Calibration measures these quirks so software can correct them. Without calibration, straight walls look curved, distances come out wrong, and 3D reconstruction fails.
The Pinhole Camera Model
The pinhole model describes a camera as a tiny hole that projects the 3D world onto a flat sensor. A point in space lands on the sensor along a straight line through the hole.
3D point
*
\
\ pinhole sensor
\ | |
\________O_______________* image point
|
distance f = focal length
Intrinsic Parameters
Intrinsic parameters describe the camera itself. They stay fixed unless the lens changes zoom.
- Focal length in pixels along x and y: fx and fy
- Principal point: cx and cy, the pixel where the optical axis hits the sensor
- Skew: usually zero on modern sensors
Camera matrix K [ fx 0 cx ] [ 0 fy cy ] [ 0 0 1 ]
Distortion
Real lenses bend straight lines. Two main types appear in photos.
Barrel distortion No distortion Pincushion distortion ( | | ) | | | \ | | / ( | | ) | | | \ | | / ( | | ) | | | / | | \ Lines bulge outward Lines stay straight Lines pinch inward
Wide-angle and action cameras show strong barrel distortion. Calibration estimates distortion coefficients that undo the bending.
Extrinsic Parameters
Extrinsic parameters describe where the camera sits and which direction it faces in the world. They consist of a rotation and a translation, and they change whenever the camera moves.
The Chessboard Method
A chessboard works as a calibration target because its corners are easy to detect and the spacing between them is known exactly.
- Print a chessboard and glue it on a flat, stiff board
- Photograph the board from 15 to 25 angles and distances
- Detect the inner corners in every photo
- Feed the corner positions to the calibration function
- Save the camera matrix and distortion coefficients
Calibration in Code
import cv2
import numpy as np
import glob
pattern = (9, 6) # inner corners per row and column
square = 0.025 # square size in meters
objp = np.zeros((pattern[0] * pattern[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:pattern[0], 0:pattern[1]].T.reshape(-1, 2) * square
obj_points, img_points = [], []
for path in glob.glob("calib/*.jpg"):
gray = cv2.cvtColor(cv2.imread(path), cv2.COLOR_BGR2GRAY)
found, corners = cv2.findChessboardCorners(gray, pattern)
if found:
corners = cv2.cornerSubPix(
gray, corners, (11, 11), (-1, -1),
(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001))
obj_points.append(objp)
img_points.append(corners)
rms, K, dist, rvecs, tvecs = cv2.calibrateCamera(
obj_points, img_points, gray.shape[::-1], None, None)
print("Reprojection error:", rms)Undistorting Images
img = cv2.imread("wide_photo.jpg")
h, w = img.shape[:2]
new_K, roi = cv2.getOptimalNewCameraMatrix(K, dist, (w, h), 1, (w, h))
fixed = cv2.undistort(img, K, dist, None, new_K)The corrected image shows straight lines where the original bowed outward.
Judging Calibration Quality
Reprojection error measures how far detected corners land from the positions the model predicts. Values under 0.5 pixels indicate a solid calibration, and values above 1 pixel signal trouble.
Error (pixels) Verdict --------------- ----------------------------- under 0.3 excellent 0.3 to 0.5 good 0.5 to 1.0 acceptable for rough work over 1.0 redo with better photos
Tips for Better Results
- Cover the whole frame, including the corners where distortion peaks
- Tilt the board in many directions rather than only shifting it
- Keep the board flat and the image sharp
- Lock focus and zoom before shooting and during later use
- Delete photos that raise the error and recalibrate
Why Calibration Matters
Robots rely on it to judge distances. Measurement tools use it to convert pixels to millimeters. Stereo cameras need it for accurate depth. Augmented reality apps depend on it to pin virtual objects to real surfaces.
Practice Exercise
Print a chessboard and photograph it 20 times with your phone camera. Run the calibration script and record the reprojection error. Undistort a photo of a tiled wall and compare straight tile lines before and after correction.
Calibration for Phones and Webcams
Phone cameras apply software corrections that change from one mode to another, so calibrate in the exact mode you plan to use. Webcams with auto-focus shift the focal length during use. Lock the focus when the software allows it. Store the saved matrix in a file, and load it again whenever the same camera runs the application.
np.savez("camera.npz", K=K, dist=dist)
data = np.load("camera.npz")
K, dist = data["K"], data["dist"]