AI Hints
Home›Computer Vision Tutorial›Features and Camera Geometry
Computer Vision · Lesson 12 of 111

How Cameras Work

From the 3D world to pixels.

⏱ 2 min read▶ Video at 20:15🎓 Free
Watch this lesson in the Computer Vision courseWatch on YouTube ↗Full Computer Vision course

How big is that apple? A photo can't tell you. A small apple close by looks the same as a large one far away. To measure the real world, we have to understand how a camera turns three dimensions into two.

How Cameras Work
From the video: How Cameras Work
  • How big is that apple?
  • Near small equals far large
  • 3D to 2D loses depth

The pinhole camera

The simplest camera is a box with a tiny hole. Light from the top of a tree passes through the hole, and lands at the bottom of the back wall. So the image is upside down. Further objects look smaller, because rays are closer together. Every camera follows this model, more or less. And it explains why one image can't tell you distance.

Projecting points

We can write this as one matrix, called K. It holds the focal length, and the image centre. Multiply a three D point by K, and divide by its depth. Here are three points. The first two have the same x and y, but one's twice as far away. Run it. The far one lands closer to the centre of the image. That's why railway lines appear to meet in the distance.

project.pypython
import numpy as np

fx, fy, cx, cy = 800.0, 800.0, 320.0, 240.0
K = np.array([[fx, 0, cx], [0, fy, cy], [0, 0, 1]])

points = np.array([[0.1, 0.0, 2.0], [0.1, 0.0, 4.0], [-0.2, 0.1, 2.0]])

for X in points:
    u, v, w = K @ X
    print(f"3D {X}  ->  pixel ({u / w:.0f}, {v / w:.0f})")
Output
3D [0.1 0.  2. ]  ->  pixel (360, 240)
3D [0.1 0.  4. ]  ->  pixel (340, 240)
3D [-0.2  0.1  2. ]  ->  pixel (240, 280)

Calibrating a camera

How do you find K for a real camera? Take photos of a known pattern, usually a chessboard, from several angles. Calibrate camera works out the focal length, the centre, and the lens distortion. Here we simulate twelve views of a board, with a known camera. Run it. It recovers the focal length of eight hundred, and the centre, with a tiny error. Every serious measurement system starts with this step.

calibrate.pypython
import cv2
import numpy as np

objp = np.zeros((6 * 9, 3), np.float32)
objp[:, :2] = np.mgrid[0:9, 0:6].T.reshape(-1, 2)

K_true = np.array([[800, 0, 320], [0, 800, 240], [0, 0, 1]], float)
rng = np.random.default_rng(0)
objs, imgs = [], []
for _ in range(12):
    r = rng.uniform(-0.4, 0.4, 3)
    t = np.array([rng.uniform(-4, -2), rng.uniform(-3, -1), rng.uniform(12, 20)])
    pts, _ = cv2.projectPoints(objp, r, t, K_true, None)
    objs.append(objp); imgs.append(pts.astype(np.float32))

err, K, dist, _, _ = cv2.calibrateCamera(objs, imgs, (640, 480), None, None)
print("Focal length found:", K[0, 0].round(1))
print("Centre found:", K[0, 2].round(1), K[1, 2].round(1))
print("Pixel error:", round(err, 4))
Output
Focal length found: 800.0
Centre found: 320.0 240.0
Pixel error: 0.0

Summary

K turns the world into pixels, and calibration measures K. But one camera still can't see depth. You've got two eyes for a reason. Next, seeing in three dimensions.

Key takeaways
  • The pinhole model
  • K holds focal length and centre
  • Calibrate with a chessboard
Next up: Depth from Two Views — how stereo vision works