Skip to main content
Open In Colab This section was written by Kaushik Kachireddy (pull request #81), with help from an AI coding agent (Claude Code) on the code. It reproduces the ideas of Chapter 29 of Foundations of Computer Vision by Antonio Torralba, Phillip Isola, and William T. Freeman. The book’s own figures are not reproduced here, because the book’s license covers only the work in full; links point to them instead. A graphical model factorizes a joint distribution over many variables into a product of local terms tied to the edges of a graph. For vision the variables are per-pixel labels (a depth, a segment, a clean intensity), and the graph encodes which labels should agree. This section builds:
  1. The MRF smoothness prior, sampled with Gibbs sampling.
  2. Exact belief propagation on a tree, reproducing the book’s numerical example (Figure 29.15) and checking it against brute-force marginalization.
  3. Loopy belief propagation on the image grid, for binary denoising.
  4. Segmentation of a photograph by loopy BP (the book’s version is Figure 29.4).
  5. Stereo along one scanline of a real stereo pair by BP (Figure 29.14), checked against ground truth.
The book uses its own photographs, a leaf and a canoe stereo pair. Here the same algorithms run on scikit-image’s coins image and on the Middlebury motorcycle stereo pair, which comes with ground-truth disparity.
Images replaced for licensing. The book is published under a CC BY-NC-ND license, which covers only the book as a whole and not its individual images, so this page does not republish the book’s photographs. License-free images stand in for them:If you use the book for non-commercial purposes, you can swap the originals back in: each line that loads a stand-in carries the original’s link in a comment.

The MRF prior: neighboring pixels agree

An undirected graphical model (Markov random field) puts a potential on every edge. The workhorse prior for images is the Ising / Potts model, which rewards neighboring pixels for taking the same label: p(x)∝exp⁡(β∑(i,j)∈E1[xi=xj]).p(\mathbf{x}) \propto \exp\Big(\beta \textstyle\sum_{(i,j)\in\mathcal{E}} \mathbb{1}[x_i = x_j]\Big). There is no data here: this is purely the prior. To see what it believes, draw samples with Gibbs sampling: repeatedly replace each pixel by a draw from its conditional given its four neighbors. Because the grid is bipartite, all black-square pixels are conditionally independent given the white-square ones, so a whole color can be updated at once (checkerboard sweeps). As the coupling β\beta grows, samples go from white noise to ever-larger smooth regions: exactly the ‘images are piecewise smooth’ assumption the rest of the chapter exploits.
Output from cell 3

Exact belief propagation on a tree

On a graph without loops, belief propagation computes the exact marginals. This part reproduces the book’s worked example (Fig 29.15): a chain x1−x2−x3x_1 - x_2 - x_3 with an observed node y2=0y_2 = 0 hanging off x2x_2. Every variable is binary and the potentials are exactly those printed in the figure: ψ12=(1.00.90.91.0),ψ23=(0.11.01.00.1),ϕ2=(1.00.10.11.0).\psi_{12}=\begin{pmatrix}1.0&0.9\\0.9&1.0\end{pmatrix},\quad\psi_{23}=\begin{pmatrix}0.1&1.0\\1.0&0.1\end{pmatrix},\quad\phi_{2}=\begin{pmatrix}1.0&0.1\\0.1&1.0\end{pmatrix}. Sum-product rule: a node collects the incoming messages, and the message it sends across an edge is ma→b(xb)=∑xaψab(xa,xb) ϕa(xa)∏c≠bmc→a(xa)m_{a\to b}(x_b)=\sum_{x_a}\psi_{ab}(x_a,x_b)\,\phi_a(x_a)\prod_{c\ne b}m_{c\to a}(x_a). A node’s marginal is the (normalized) product of all its incoming messages times its own evidence. Because this graph is a tree, BP must agree with brute-force marginalization over all 232^3 joint states: the code checks that it does.
Output from cell 5

Loopy belief propagation on the image grid

The image grid has loops, so BP is no longer exact: but loopy BP (just keep passing messages) works remarkably well in practice. For binary labels every message is a two-vector, which the code track by its log-odds m=log⁡m(1)m(0)m = \log\frac{m(1)}{m(0)}. Passing a log-odds belief bb through an Ising edge with coupling JJ gives the closed form mout=log⁡eJeb+e−Je−Jeb+eJ,m_{\text{out}} = \log\frac{e^{J}e^{b}+e^{-J}}{e^{-J}e^{b}+e^{J}}, which is applied to all edges of one orientation at once with array shifts. The first test is denoising: a clean binary image is corrupted by flipping 20% of the pixels; the per-pixel likelihood gives each node a data log-odds ±log⁡1−qq\pm\log\frac{1-q}{q}, and the Ising prior glues neighbors together.
Output from cell 7

Segmentation as a two-label MRF

The same machinery segments a photograph: label each pixel object or background. The book segments a leaf by its color; here the evidence is brightness, on an image of coins against a darker background. The local evidence is how much brighter each pixel is than the median, turned into log-odds. On its own it gives a ragged, speckled mask; the smoothness prior cleans it into solid regions with short boundaries.
Output from cell 10

Stereo along a scanline

Stereo makes the graphical-model picture concrete (Fig 29.14). Take one scanline from the rectified left and right views of a rectified stereo pair (the book uses a canoe; here, the Middlebury motorcycle). Each pixel position is a node whose label is a disparity (depth); the local evidence is how well the left patch matches the right patch shifted by that disparity, and the chain of nodes is tied by a smoothness prior. The code runs sum-product BP along the 1-D chain: a forward (left-to-right) sweep and a backward (right-to-left) sweep, then multiply them with the evidence to get the marginal posterior at every position. How to read the panels below (they mirror the book):
  • (a), (b) the same row of pixels seen by the right and left cameras.
  • (c) to (f) are position × depth images: the horizontal axis is position along the scanline (lined up with a,b) and the vertical axis is candidate depth (small disparity = far, large = near). Brighter = more probable. So each vertical slice is a probability-over-depth for one pixel.
  • (c) local evidence: how well the left patch matches the right patch at each depth. Textured regions give a sharp bright spot (confident); smooth surfaces are ambiguous (diffuse).
  • (d), (e) messages: belief passed left→right and right→left along the chain, carrying confident estimates into the ambiguous regions.
  • (f) posterior = evidence × both messages. The bright ridge is the recovered depth profile; it is overlaid as a line.
It is a deliberately simple matcher (windowed normalized correlation + a truncated-linear smoothness), so it captures the behavior of Fig 29.14 rather than the book’s exact pixels. Because this pair has ground-truth disparity, the code also measures the error.
Output from cell 12
Belief propagation makes the recovered profile smoother and carries confident depths across the ambiguous stretches, which shows as the lower jitter. The mean error against ground truth barely moves, because it is dominated by the textureless floor at the right end of the scanline: there, neither method has any evidence to work with, and a single chain of pixels cannot borrow it from neighboring rows. Full stereo methods run inference over the whole image grid for that reason.

Summary

  • A graphical model splits an image problem into local evidence (data terms) and a smoothness prior (edge potentials); inference combines them.
  • On a tree, sum-product BP is exact: it matched brute force to machine precision (29.15). On the looped image grid, loopy BP is approximate but effective for denoising, segmentation, and stereo.
  • BP is message passing: each node’s belief is the product of its neighbors’ messages and its own evidence. Smoothness lets confident, textured regions propagate into ambiguous, textureless ones.
  • These MRF and BP energies are the classical ancestors of today’s dense-prediction networks. The priors are now learned, but the evidence-plus-smoothness structure remains.