Skip to content
AI360XpertBeta

Stereo Vision

Two cameras separated by a known baseline see the same point shifted by a disparity, and that shift triangulates depth with no active sensor.

Two cameras 12 centimeters apart image one point with a 35 pixel shift, and dividing focal length times baseline by that shift triangulates 2.4 meters of depth.
Two cameras 12 centimeters apart image one point with a 35 pixel shift, and dividing focal length times baseline by that shift triangulates 2.4 meters of depth.

Why Does This Exist?

One camera flattens the world: a toy car nearby and a real car far away can project to identical pixels, and no amount of staring at a single image recovers the missing scale. Active sensors answer with lasers or projected patterns, but they cost more, fail in bright sunlight, and need power budgets a small robot may not have. Stereo vision answers with a second ordinary camera. Two views separated by a known baseline distance disagree by a measurable shift, and that disagreement triangulates depth passively, outdoors, on cheap hardware.

The geometry behind the search lives in epipolar geometry and stereo matching, the single-camera counterpart in depth estimation, and the moving-camera generalization in structure from motion. This page covers calibration plus rectification, the matching step, the triangulation formula with a hand-computed example, and the two conditions that break it.

Think of It Like This

The thumb and eye experiment

Hold a thumb at arm's length, close one eye, and note which background object it covers. Switch eyes and the thumb jumps sideways against the background. Bring the thumb to your nose and the jump grows huge; aim at a far wall and it nearly vanishes. Big jump means close, small jump means far.

The two eyes are the cameras, the jump is the disparity in pixels, and the brain's distance sense is the triangulation formula below.

The analogy stops at the brain. Eyes swivel, focus, and fuse effortlessly, while cameras need calibration plus rectification before any matching works, and a blank wall that your brain still places correctly leaves the algorithm with nothing to match.

How It Actually Works

Calibrate, rectify, then match

Before any depth math, both cameras are calibrated: the focal length ff in pixels and the baseline BB between camera centers must be known. Images are then rectified, projected onto a common plane so matching points share horizontal rows. Rectification shrinks correspondence from a 2D whole-image search to a 1D walk along one row. Matching then finds, for each left-image pixel at xLx_L, the same feature in the right image at xRx_R, using block comparison or learned matchers, and records the disparity d=xL−xRd = x_L - x_R in pixels.

The depth formula

Similar triangles through the two camera centers give Z=f⋅B/dZ = f \cdot B / d, where ZZ is depth, ff is focal length in pixels, BB is baseline in world units, and dd is disparity in pixels. Depth runs inverse to disparity: double the shift, halve the distance.

Worked example: one point, two depths

Take f=700f = 700 pixels and B=0.12B = 0.12 meters, so f⋅B=84f \cdot B = 84. A point with disparity d=35d = 35 pixels sits at Z=84/35=2.4Z = 84 / 35 = 2.4 meters. A second point with d=7d = 7 pixels sits at Z=84/7=12.0Z = 84 / 7 = 12.0 meters. The nonlinearity bites at range: a one-pixel matching error on the far point gives 84/6=14.084 / 6 = 14.0 or 84/8=10.584 / 8 = 10.5 meters, a spread of 3.53.5 meters from a single pixel. Close work is precise; distant work degrades fast, which is why baselines grow with the operating range.

Code

def stereo_depth(disparity_px, focal_px=700.0, baseline_m=0.12):    """Triangulate depth in meters from disparity in pixels."""    return focal_px * baseline_m / disparity_px

for d in (35, 7, 6, 8):    print(d, stereo_depth(d))# -> 35 2.4# -> 7 12.0# -> 6 14.0# -> 8 10.5

Watch Out For

Matching on textureless surfaces

Blank walls, smooth floors, and clear skies give the matcher uniform neighborhoods with no distinctive feature to lock onto. The symptom is holes or wild spikes in the disparity map exactly over the plainest regions. Confirm scenes carry texture, or project artificial pattern onto them, before trusting the depth output.

Trusting far-field depth like near-field depth

Because ZZ runs as 1/d1/d, error balloons with distance: the worked example turns one pixel into 3.53.5 meters of spread at 1212 meters. The symptom is confident-looking distant obstacles that drift meters between frames. Size the baseline to the operating range and down-weight or discard far-field readings in planning.

The Quick Version

  • Two calibrated cameras turn a pixel shift d=xL−xRd = x_L - x_R into depth Z=f⋅B/dZ = f \cdot B / d.
  • Rectification reduces matching from a 2D search to a 1D walk along image rows.
  • With f=700f = 700 and B=0.12B = 0.12, disparities of 3535 and 77 pixels mean 2.42.4 and 12.012.0 meters.
  • One-pixel errors cost centimeters nearby but meters far away.
  • Textureless regions and darkness starve the matcher, so verify texture before trusting depth.