Geometry & 3D Vision

Semi-Global Matching (SGM)

A dense stereo algorithm that approximates a global smoothness energy by summing one-dimensional dynamic-programming path costs from several directions through every pixel.

intermediate

Semi-global matching (SGM) computes a dense disparity map from a rectified stereo pair by approximately minimizing a global energy: a matching cost per pixel plus penalties for disparity changes between neighbors. It runs one-dimensional dynamic programming along straight paths from several directions into every pixel and sums the results. Hirschmüller introduced it in 2005 and described it in full in a 2008 journal paper. Its accuracy at object borders, linear running time, and regular structure made it widely used, from aerial mapping to driver assistance; OpenCV ships a variant as StereoSGBM. Stereo matching places it among other stereo methods.

Problem

Pixel-wise matching costs are ambiguous: with noise or weak texture, a wrong disparity often costs less than the right one. Window aggregation assumes constant disparity inside the window and blurs object borders. Global methods add a smoothness term and minimize over the whole image, but minimizing even the simple Potts energy is NP-hard (Boykov, Veksler, and Zabih, 2001), and most top-ranked global methods of the time took from 20 seconds to over a minute per image pair. Dynamic programming minimizes such an energy exactly along one scanline in polynomial time, but rows optimized independently produce horizontal streaks. SGM keeps the pixel-wise cost and the global energy and replaces the 2D minimization with many cheap 1D ones.

Inputs and Outputs

  • Input: two images with known epipolar geometry, a disparity range, and the penalties P1P_1 and P2P_2. Hirschmüller’s formulation only needs a function that traces the epipolar line of each pixel, so it also works on pushbroom images that cannot be rectified; most implementations assume rectified images.
  • Output: a sub-pixel disparity map for the base image, with pixels that fail a left–right check marked invalid.

Intuition

Along one image row, dynamic programming finds the cheapest path through the cost volume when a path pays the matching cost at every pixel, a small fee for a one-step disparity change, and a larger fee for a jump. SGM computes such path costs along rows, columns, and diagonals ending at every pixel, giving each pixel a smoothed opinion about every disparity from each direction. Summing the directions spreads evidence from textured areas into ambiguous ones from all sides, without favoring one direction as scanline methods do. Only the path costs are kept, not the paths.

Algorithm

  1. Matching cost. Compute a pixel-wise cost C(p,d)C(\mathbf{p}, d) for every base-image pixel and disparity, filling an H×W×DH \times W \times D volume.
  2. Path aggregation. For each direction r\mathbf{r} (8 or 16 of them), start at the image border and traverse the image, computing the path cost Lr(p,d)L_\mathbf{r}(\mathbf{p}, d) from the previous pixel’s costs with the recurrence below.
  3. Summation. Add the path costs of all directions into S(p,d)S(\mathbf{p}, d).
  4. Disparity selection. At each pixel take the disparity with the lowest SS (winner-take-all) and refine it to sub-pixel precision with a parabola through the costs at d−1d - 1, dd, and d+1d + 1.
  5. Second map. Compute the match image’s disparity map, either from the same SS along the epipolar line or, slightly better, by repeating steps 1–4 with the images swapped.
  6. Consistency check. Filter both maps with a 3×33 \times 3 median and invalidate base-image pixels whose disparity differs by more than one from the disparity of their match.

Optional post-processing in the 2008 paper removes small isolated disparity segments and interpolates invalidated pixels.

Mathematical Formulation

Following the 2008 paper, the base image is IbI_b, the match image ImI_m, and DD the disparity image, with DpD_\mathbf{p} the disparity at pixel p\mathbf{p}. The energy is

E(D)=∑p(C(p,Dp)+∑q∈NpP1 T[∣Dp−Dq∣=1]+∑q∈NpP2 T[∣Dp−Dq∣>1]),E(D) = \sum_\mathbf{p} \Big( C(\mathbf{p}, D_\mathbf{p}) + \sum_{\mathbf{q} \in N_\mathbf{p}} P_1 \, \mathrm{T}\big[|D_\mathbf{p} - D_\mathbf{q}| = 1\big] + \sum_{\mathbf{q} \in N_\mathbf{p}} P_2 \, \mathrm{T}\big[|D_\mathbf{p} - D_\mathbf{q}| > 1\big] \Big),

where NpN_\mathbf{p} is the neighborhood of p\mathbf{p} and T[⋅]\mathrm{T}[\cdot] is 1 when its argument is true and 0 otherwise. The small penalty P1P_1 lets disparity change by one between neighbors, which accommodates slanted and curved surfaces. The constant penalty P2P_2 charges every larger jump the same, however large, so true discontinuities stay affordable.

Along a path in direction r\mathbf{r}, the cost of reaching pixel p\mathbf{p} at disparity dd is

Lr(p,d)=C(p,d)+min⁡(Lr(p−r,d),  Lr(p−r,d−1)+P1,  Lr(p−r,d+1)+P1,  min⁡iLr(p−r,i)+P2)−min⁡kLr(p−r,k).L_\mathbf{r}(\mathbf{p}, d) = C(\mathbf{p}, d) + \min\Big( L_\mathbf{r}(\mathbf{p} - \mathbf{r}, d), \; L_\mathbf{r}(\mathbf{p} - \mathbf{r}, d - 1) + P_1, \; L_\mathbf{r}(\mathbf{p} - \mathbf{r}, d + 1) + P_1, \; \min_i L_\mathbf{r}(\mathbf{p} - \mathbf{r}, i) + P_2 \Big) - \min_k L_\mathbf{r}(\mathbf{p} - \mathbf{r}, k).

Without the last term, this is the energy E(D)E(D) minimized along one path. The subtracted minimum is the same for every dd, so it does not change which disparity wins; it only bounds the values by Cmax+P2C_\text{max} + P_2. The aggregated cost is

S(p,d)=∑rLr(p,d),Dp=arg⁡min⁡dS(p,d).S(\mathbf{p}, d) = \sum_\mathbf{r} L_\mathbf{r}(\mathbf{p}, d), \qquad D_\mathbf{p} = \arg\min_d S(\mathbf{p}, d).

The recurrence does not enforce the ordering or visibility constraints of classical scanline dynamic programming, which paths off the epipolar line cannot express; Hirschmüller likens it to the scanline optimization of Scharstein and Szeliski (2002). Occlusions are instead detected by the left–right check: with q\mathbf{q} the match of p\mathbf{p} under DbpD_{b\mathbf{p}}, the disparity is kept if ∣Dbp−Dmq∣≤1|D_{b\mathbf{p}} - D_{m\mathbf{q}}| \le 1 and set invalid otherwise.

Matching costs

SGM works with any pixel-wise cost. The 2008 paper uses either the sampling-insensitive absolute difference of Birchfield and Tomasi or a cost based on mutual information (MI), which models the joint distribution of corresponding intensities and so tolerates complex radiometric differences. MI needs a disparity map to estimate that distribution, so it is computed hierarchically (HMI), starting from a random map at 1/16 resolution; Hirschmüller estimated the theoretical overhead at about 14%. The census transform of Zabih and Woodfill (1994), compared by Hamming distance, became a common alternative: in Hirschmüller and Scharstein’s (2009) evaluation of matching costs under radiometric changes, census had the best and most robust overall performance.

Parameters

  • P1P_1 and P2P_2, with P2≥P1P_2 \ge P_1. A larger P2P_2 removes more noise but smooths across real discontinuities. Both are in the units of the matching cost, and one setting rarely suits every scene.
  • Adaptive P2P_2. Because depth edges usually coincide with intensity edges, the paper sets P2=P2′/∣Ibp−Ibq∣P_2 = P_2' / |I_{b\mathbf{p}} - I_{b\mathbf{q}}| for neighboring base-image pixels, still keeping P2≥P1P_2 \ge P_1, so jumps are cheaper where the image has an edge.
  • Number of paths. The paper requires at least 8 and recommends 16 for good coverage of the image; the extra directions are realized by alternating one horizontal or vertical step with one diagonal step.
  • Disparity range DD, which sets memory and run time.

Complexity

Each pixel is visited once per path at O(D)O(D) cost, since the previous pixel’s minimum is computed once and reused for every dd, so the time is O(WHD)O(WHD). Memory is also O(WHD)O(WHD): the paper stores CC and SS as 16-bit W×H×DW \times H \times D arrays, scaling costs to 11 bits so that the sum over 16 paths, at most 16(Cmax+P2)16(C_\text{max} + P_2), cannot overflow. Hirschmüller reported 1.8 seconds for the Middlebury Teddy pair on a 2.2 GHz Opteron, with the aggregation in SSE2 instructions, and processed images too large for memory in overlapping tiles.

The recurrence uses only additions, comparisons, and minimums in a regular pattern, which suits parallel hardware. Ernst and Hirschmüller (2008) implemented SGM with mutual information on a GPU. Gehrig, Eberli, and Meyer (2009) implemented an 8-path variant with a zero-mean SAD cost on an FPGA for driver assistance and reported 25 Hz on a 680×400680 \times 400 region of 750×480750 \times 480 images, with up to 128 disparities and less than 3 W of power.

Implementation

The example builds a noisy random-dot stereogram, a background at disparity 3 and a raised square at disparity 10 carrying a 12×1212 \times 12 textureless patch, and compares winner-take-all on single-pixel absolute differences with winner-take-all after aggregation along 2, 4, and 8 directions. A pixel is bad when its disparity is off by more than one; occluded pixels and the left border are excluded.

import numpy as np

rng = np.random.default_rng(0)
H, W, D = 64, 96, 16
d_bg, d_sq = 3, 10                  # disparities of background and raised square
top, bot, a, b = 16, 48, 36, 76     # square in left-image coordinates

# Random-dot stereogram: left pixel (x, y) shows the same point as right pixel (x - d, y).
bg = rng.random((H, W + D))
sq = rng.random((H, W + D))
sq[26:38, 50:62] = 0.5              # a textureless patch on the square
x = np.arange(W)
left = bg[:, x].copy()
left[top:bot, a:b] = sq[top:bot, a:b]
right = bg[:, x + d_bg].copy()
right[top:bot, a - d_sq:b - d_sq] = sq[top:bot, a:b]
gt = np.full((H, W), d_bg)
gt[top:bot, a:b] = d_sq
left += 0.1 * rng.standard_normal(left.shape)
right += 0.1 * rng.standard_normal(right.shape)

# Pixel-wise matching cost C(p, d) = |I_L(x, y) - I_R(x - d, y)|.
C = np.full((H, W, D), 1.0)
for d in range(D):
    C[:, d:, d] = np.abs(left[:, d:] - right[:, :W - d])

def path_cost(C, dx, dy, P1, P2):
    """L_r for direction r = (dx, dy), Eq. (13) of Hirschmüller (2008)."""
    L = np.zeros_like(C)
    def step(Lprev, Cp):
        m = Lprev.min(axis=-1, keepdims=True)
        up = np.pad(Lprev, [(0, 0), (1, 1)], constant_values=np.inf)
        best = np.minimum.reduce([Lprev, up[:, :-2] + P1, up[:, 2:] + P1,
                                  np.broadcast_to(m + P2, Lprev.shape)])
        return Cp + best - m
    if dy == 0:                     # horizontal path: sweep columns
        xs = range(W) if dx > 0 else range(W - 1, -1, -1)
        prev = None
        for xi in xs:
            L[:, xi] = C[:, xi] if prev is None else step(L[:, prev], C[:, xi])
            prev = xi
    else:                           # vertical or diagonal path: sweep rows
        ys = range(H) if dy > 0 else range(H - 1, -1, -1)
        prev = None
        for yi in ys:
            if prev is None:
                L[yi] = C[yi]
            else:
                src = np.clip(x - dx, 0, W - 1)    # predecessor column p - r
                Lp = L[prev][src]
                Lp[(x - dx < 0) | (x - dx >= W)] = 0  # path starts at the border
                L[yi] = step(Lp, C[yi])
            prev = yi
    return L

def sgm(C, dirs, P1=0.1, P2=0.6):
    return sum(path_cost(C, dx, dy, P1, P2) for dx, dy in dirs)

dirs8 = [(1, 0), (-1, 0), (0, 1), (0, -1), (1, 1), (-1, 1), (1, -1), (-1, -1)]
occ = np.zeros((H, W), bool)        # background hidden behind the square in the right image
occ[top:bot] = (x - d_bg >= a - d_sq) & (x - d_bg < b - d_sq) & (gt[top:bot] == d_bg)
valid = ~occ
valid[:, :D] = False                # no full disparity range near the left border
flat = np.zeros((H, W), bool)
flat[26:38, 50:62] = True

for name, S in [("WTA on raw costs", C),
                ("SGM, 2 paths (L-R)", sgm(C, dirs8[:2])),
                ("SGM, 4 paths", sgm(C, dirs8[:4])),
                ("SGM, 8 paths", sgm(C, dirs8))]:
    disp = S.argmin(axis=2)         # winner-take-all on the (aggregated) costs
    bad = np.abs(disp - gt) > 1
    print(f"{name:20s} bad pixels: all {bad[valid].mean():6.1%}, "
          f"textureless patch {bad[flat].mean():6.1%}")

Output:

WTA on raw costs     bad pixels: all  69.6%, textureless patch  70.1%
SGM, 2 paths (L-R)   bad pixels: all   5.5%, textureless patch  25.0%
SGM, 4 paths         bad pixels: all   2.0%, textureless patch  16.7%
SGM, 8 paths         bad pixels: all   1.8%, textureless patch   4.9%

With single-pixel costs and this much noise, winner-take-all gets most pixels wrong. The two horizontal paths alone, which amount to scanline optimization, cut the error to 5.5%, but the textureless patch is reached only from its left and right edges and a quarter of it stays wrong. Vertical and diagonal paths bring in evidence from more sides: with 8 paths, 1.8% of all pixels and 4.9% of the patch are bad. The example omits sub-pixel refinement and the left–right check; the stereo matching example demonstrates the latter.

OpenCV’s StereoSGBM

OpenCV’s cv::StereoSGBM (4.x) is a documented modification of Hirschmüller’s algorithm. It matches blocks rather than single pixels (blockSize = 1 restores pixels), uses the Birchfield–Tomasi cost on a clipped horizontal derivative of the image, plus a down-weighted intensity term, instead of mutual information, and adds a uniqueness test, quadratic sub-pixel interpolation, speckle filtering, and a left–right check (disp12MaxDiff). The default MODE_SGBM makes a single pass over the image and aggregates 5 directions; MODE_HH runs the full two-pass algorithm with 8 directions at the cost of O(WHD)O(W H D) memory. P1 and P2 are given in the units of the block cost, and OpenCV’s sample uses 88 and 3232 times the number of channels times blockSize². Output disparities are fixed-point values scaled by 16, as described under disparity.

Properties and Behavior

  • Sharp borders. Because the cost is pixel-wise and the smoothness term is the only coupling between pixels, SGM avoids the blurring of object borders and fine structures that window aggregation causes.
  • Sub-pixel accuracy. In the Middlebury comparison of October 2006, Hirschmüller reported SGM and its variant C-SGM among the best methods at a 1-pixel error threshold and the best at 0.5 pixels, which he attributed to their sub-pixel accuracy.
  • Not a true minimizer. The result is not the minimum of E(D)E(D) and depends on the set of directions.

Limitations

  • Streaking. Summing independent 1D optimizations leaves characteristic low-amplitude streaks along the path directions (Facciolo, de Franchis, and Meinhardt, 2015).
  • Large textureless regions. When an untextured background surrounds a foreground object or touches the image border, paths entering from different surfaces disagree and the discontinuity becomes fuzzy; Hirschmüller added an intensity-consistent post-processing step for this case.
  • Slanted surfaces. It follows from the energy that SGM favors fronto-parallel surfaces: a slanted surface, such as the road ahead of a car, becomes a staircase of integer disparities that pays P1P_1 at every step, so penalties high enough to suppress noise also flatten it.

Variants

  • More global matching (MGM). Facciolo, de Franchis, and Meinhardt (2015), building on an interpretation of SGM as min-sum belief propagation, let each path step also draw on the neighboring pixel of the previous scanline, so each directional cost depends on a quadrant of the image rather than a line. They reported a five-fold reduction of SGM’s energy gap to reference optimizers and the removal of its streaks, with little computational overhead.
  • Learned penalties. SGM-Nets (Seki and Pollefeys, 2017) predict the penalties from an image patch and its position with a convolutional network, separately for positive and negative disparity changes.
  • Learned aggregation. GA-Net (Zhang et al., 2019) includes a semi-global aggregation layer, described as a differentiable approximation of SGM, inside an end-to-end network as a cheaper alternative to stacks of 3D convolutions.
  • Learned costs. MC-CNN (Žbontar and LeCun, 2016) replaces the hand-crafted matching cost with a learned patch comparison and keeps SGM in its post-processing.
  • Multiple views. The 2008 paper matches the base image against each further image separately and fuses the disparity maps.

Related

  • Cost Volume

    A tensor of matching costs or similarities between each pixel of one image and its candidate correspondences in another, indexed by pixel position and candidate disparity, displacement, or depth.

  • Stereo Vision

    Recovering depth from two images taken by cameras with a known relative pose, by measuring how far each point shifts between the views.

  • Stereo Rectification

    Warping a pair of stereo images by one homography each so that corresponding epipolar lines become the same image row, turning the correspondence search into a scan along rows.

  • Depth Map

    An image whose pixels store the distance to the scene, usually the depth Z along the optical axis, so that each pixel with a known camera can be lifted to a 3D point.

  • Middlebury Benchmarks

    Small, high-accuracy stereo and optical flow benchmarks from Middlebury College and Microsoft Research that defined how dense correspondence methods were evaluated in the 2000s.

  • Stereo Processing by Semiglobal Matching and Mutual Information

    Heiko Hirschmüller's 2005 CVPR paper and 2008 TPAMI journal paper that introduced semi-global matching, a dense stereo method combining a pixel-wise mutual information cost with a smoothness energy approximated along many one-dimensional paths.

References

  1. Hirschmüller, H. (2005). Accurate and Efficient Stereo Processing by Semi-Global Matching and Mutual Information. Proceedings of the IEEE Computer Society Conference on Computer Vision and Pattern Recognition (CVPR), 2, 807–814.
  2. Hirschmüller, H. (2008). Stereo Processing by Semiglobal Matching and Mutual Information. IEEE Transactions on Pattern Analysis and Machine Intelligence, 30(2), 328–341.
  3. Scharstein, D. & Szeliski, R. (2002). A Taxonomy and Evaluation of Dense Two-Frame Stereo Correspondence Algorithms. International Journal of Computer Vision, 47(1–3), 7–42.
  4. Boykov, Y., Veksler, O. & Zabih, R. (2001). Fast Approximate Energy Minimization via Graph Cuts. IEEE Transactions on Pattern Analysis and Machine Intelligence, 23(11), 1222–1239.
  5. Zabih, R. & Woodfill, J. (1994). Non-parametric Local Transforms for Computing Visual Correspondence. European Conference on Computer Vision (ECCV), Lecture Notes in Computer Science, 151–158.
  6. Hirschmüller, H. & Scharstein, D. (2009). Evaluation of Stereo Matching Costs on Images with Radiometric Differences. IEEE Transactions on Pattern Analysis and Machine Intelligence, 31(9), 1582–1599.
  7. Ernst, I. & Hirschmüller, H. (2008). Mutual Information Based Semi-Global Stereo Matching on the GPU. Advances in Visual Computing (ISVC), Lecture Notes in Computer Science, 228–239.
  8. Gehrig, S. K., Eberli, F. & Meyer, T. (2009). A Real-Time Low-Power Stereo Vision Engine Using Semi-Global Matching. Computer Vision Systems (ICVS), Lecture Notes in Computer Science, 134–143.
  9. Žbontar, J. & LeCun, Y. (2016). Stereo Matching by Training a Convolutional Neural Network to Compare Image Patches. Journal of Machine Learning Research, 17(65), 1–32.
  10. Facciolo, G., de Franchis, C. & Meinhardt, E. (2015). MGM: A Significantly More Global Matching for Stereovision. Proceedings of the British Machine Vision Conference (BMVC), 90.1–90.12.
  11. Seki, A. & Pollefeys, M. (2017). SGM-Nets: Semi-Global Matching with Neural Networks. Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 6640–6649.
  12. Zhang, F., Prisacariu, V., Yang, R. & Torr, P. H. S. (2019). GA-Net: Guided Aggregation Net for End-To-End Stereo Matching. Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR), 185–194.