Sharp edges do not guarantee a unique stereo correspondence. If a surface repeats, shifting one image by a whole pattern period can make the wrong stripe match just as well as the right one. Converting that shift to depth produces a precise-looking number without establishing that the two image locations belong to the same physical feature.
This comes before the question of how much a one-pixel error changes depth. First the matcher must choose which feature goes with which. Luxonis’s stereo explanation describes disparity through corresponding image points and explains why passive stereo needs scene texture. The example below isolates a different problem from a blank wall: there is plenty of contrast, but the pattern repeats.
Four shifts, all with zero mismatch
Take ideal parallel cameras 60 mm apart, each with a 600 px focal length, looking at a flat panel 3 m away. Our synthetic panel is 1.8 m wide and carries alternating black and white strips, each 30 mm wide. A complete black–white period projects to 12 pixels. The true geometric disparity is also 12 pixels; these are deliberately chosen example dimensions, not camera specifications.

We compare a 61-sample horizontal window against right-image shifts from 0 through 36 pixels. The cost is simply the sum of absolute grayscale differences. In the executed standalone calculation, shifts 0, 12, 24 and 36 pixels all cost zero.
Those are different hypotheses. The positive shifts imply depths of 3, 1.5 and 1 m under this camera model. Zero disparity supplies no finite forward depth. Selecting the first or last tied entry would hide the ambiguity; the calculation leaves the selected depth undefined.
The panel is finite and every main comparison stays inside it. No texture is wrapped around an edge. An AI-operated Blender 5.2.2 LTS experiment constructed three panels and six ideal cameras: nine objects, 720 vertices and 180 faces. An independent audit checked their evaluated world/local vertices, matrices, face indices, emission attributes, camera settings, all 1,440 vertex projections and CSV rows against scalar pinhole geometry. It then reconstructed the sample profiles from the finite faces. The stored vertex projections agreed within explicit numerical comparison allowances; this does not establish physical camera accuracy. Matching costs use noiseless point samples of face attributes, not captured or rendered pixels. No camera, DepthAI or OpenCV matcher has been tested.

A search window can hide the right answer
Change only one black strip to white, breaking the local repetition. With the same full search and sample window, 12 pixels is now the sole zero-cost match. Make the panel uniformly white instead, and all 37 candidate shifts tie. The useful distinction is not just texture versus no texture: the visible pattern also needs to distinguish competing correspondences within the relevant search.
There is another trap. Keep the repeating panel but search only shifts 23, 24 and 25. Now 24 pixels is the unique zero-cost result, implying 1.5 m, because the actual 12-pixel match was never considered. A unique minimum within an incorrectly chosen range does not establish the correct physical identity.
| Declared condition | Minimum-cost shifts, px | Depth decision | Why |
|---|---|---|---|
| Repeating, full search | 0, 12, 24, 36 | No selected depth | Four equally good matches |
| One strip changed, full search | 12 | 3 m in this model | One zero-cost match in this window |
| Blank, full search | All 37 candidates | No selected depth | No distinguishing pattern |
| Repeating, only 23–25 searched | 24 | Wrong 1.5 m | True 12 px match was excluded |
OpenCV’s StereoSGBM declaration comments in the 4.13.0 source separately expose the disparity search range and a uniqueness margin between competing costs. Our small sum-of-differences calculation does not implement its algorithm, filters or confidence behavior. It demonstrates why those are separate questions rather than recommending parameter values.
Run this standard-library Python to reproduce the stated comparisons. The pixel samples lie at half-pixel offsets, away from the synthetic strip boundaries.
from math import floor
focal, baseline, depth = 600.0, 0.06, 3.0
samples = [i + 0.5 for i in range(-30, 31)]
def gray(camera_x, pixel_offset, pattern):
x = camera_x + pixel_offset * depth / focal
if not -0.9 < x < 0.9:
return None # Outside our finite panel; do not wrap it.
stripe = floor((x + 0.9) / 0.03)
if pattern == "blank":
return 1
return 1 if pattern == "unique" and stripe == 30 else stripe % 2
def match(pattern, shifts):
costs = {}
for shift in shifts:
pairs = [(gray(-baseline/2, u, pattern),
gray(baseline/2, u-shift, pattern)) for u in samples]
if all(a is not None and b is not None for a, b in pairs):
costs[shift] = sum(abs(a-b) for a, b in pairs)
best = min(costs.values())
return best, [d for d, cost in costs.items() if cost == best]
for pattern in ("periodic", "unique", "blank"):
best, shifts = match(pattern, range(37))
print(pattern, "cost:", best, "best shifts:", shifts)
assert match("periodic", range(37)) == (0, [0, 12, 24, 36])
assert match("unique", range(37)) == (0, [12])
# An incorrect search interval can hide the true 12 px match.
assert match("periodic", [23, 24, 25]) == (0, [24])
print("restricted-search depth:", focal * baseline / 24, "m")
print("zero-disparity depth:", None)
When diagnosing repeated structures, inspect competing correspondence costs and the allowed search range before interpreting a small winning cost as depth confidence. Our changed strip distinguishes the candidates only under this stated geometry, sample window and noiseless model. It is not a general texture treatment, a calibration procedure, or evidence of real sensor accuracy. Illumination, image sampling, occlusion and the actual matcher’s behavior require their own checks.
After a correspondence is chosen, the separate one-pixel depth sensitivity study explains how a coordinate change affects the resulting distance. If an OAK output is actually zero, the invalid-depth diagnostic guide addresses device validity and configuration. A wrong finite depth and a marked invalid pixel are different outcomes; this experiment does not predict which a real matcher will emit.