BookNotesSlidesP-sets Syllabusdraft · v0.2.49.1
◀▲⌂▶
💬Comments welcome. To leave a note, select any text and click the note / highlight button that pops up — or open the panel with the tab at the top-right (‹). Notes are visible only inside our private review group.
💡 In a hurry? Jump to this chapter’s 1 big lesson ↓

13.6 Non-local means and BM3D⧉

A brick wall supplies many patches with similar mortar lines. Along a straight boundary, neighboring patches contain nearly the same edge. These repetitions let a denoiser use measurements from other parts of one photograph. Non-local means finds them by comparing patches; BM3D also transforms groups of matched patches to separate their common structure from noise.

The connection to Chapter 13.2, Denoising by averaging is useful but conditional. If several locations had exactly the same clean value and independent noise, averaging them would give the familiar variance reduction. Actual patches differ in shading, geometry, and texture, and the algorithm selects them using noisy data. Matching errors introduce bias; overlapping patches and adaptive selection complicate the variance. A match count alone does not predict the denoising gain.

13.6.1 A photograph repeats itself⧉

A single observed value says little about whether two locations depict the same structure. A patch supplies the surrounding edge orientation, texture, and color. Comparing these measurements together makes a match more discriminating, although it cannot prove that two clean patches agree.

Let $P_p y$ extract a patch of $m$ scalar samples around pixel $p$. For distinct patch centers, define the mean squared distance

$$d^2(p,q)=\frac1m\lVert P_p y-P_q y\rVert_2^2.$$

Under additive independent noise of variance $\sigma^2$, with corresponding samples drawn from distinct pixels,

$$\mathbb E[d^2(p,q)\mid x]=\frac1m\lVert P_p x-P_q x\rVert_2^2+2\sigma^2.$$

For two identical, nonoverlapping clean patches under Gaussian noise, the variance of this distance is $8\sigma^4/m$. Larger patches therefore stabilize this particular statistic. Overlap correlates its terms, and a larger patch is less likely to match a genuinely different part of the scene. The formula is not a universal $\sqrt m$ improvement in matching accuracy.

fig-selfsimilarity-map
Figure 13.6.1. Interactive. Click a patch anywhere in a photograph and the panel highlights every other patch in the image that matches it, with the match strength as a heat map, and reports the effective number of matches. On a brick wall or a fence the map lights up across the whole image; on a unique object it collapses to a small blob; on a face it finds the other eye. A noise slider degrades the image and the map degrades with it, which shows directly why a patch size that is too small stops finding matches as noise rises. Interactive: click to choose the reference patch, set patch size, search radius and noise level; the readout gives the number of usable matches and the noise reduction they can buy.

13.6.2 Non-local means: similarity as the weight⧉

Non-local means (Buades et al. 2005) averages observed values with weights derived from patch similarity. One common version compensates for the expected noise contribution:

$$\begin{aligned} w(p,q)&=\exp\!\left[-\frac{\max(d^2(p,q)-2\sigma^2,0)}{h^2}\right],\\ Z(p)&=\sum_{q\in S_p}w(p,q),\qquad \hat x_p=\frac{1}{Z(p)}\sum_{q\in S_p}w(p,q)y_q. \end{aligned}$$

Here $S_p$ is a bounded search window and $h>0$ has the same intensity units as $\sigma$. The normalization by $m$ in the distance is essential: subtracting $2\sigma^2$ from an unnormalized sum would use the wrong noise scale. The subtraction and truncation are a practical weighting rule, not an unbiased estimator of similarity.

Algorithm 13.6.1
for p in image:
    w = empty_map()
    candidates = search_window(p) excluding p
    for q in candidates:
        d2 = mean((patch(y,p) - patch(y,q))**2)
        w[q] = exp(-max(d2 - 2*sigma**2, 0) / h**2)
    if candidates is empty:
        out[p] = y[p]
        continue
    w[p] = max(w[q] for q in candidates)
    if sum(w.values()) == 0:
        out[p] = y[p]
        continue
    out[p] = sum(w[q]*y[q] for q in candidates plus p) / sum(w.values())

This self-weight convention prevents an exact self-match from overwhelming much smaller neighboring weights. If the candidate set is empty or all weights underflow to zero, return $y_p$. Use a consistent boundary extension when extracting patches. For color images, distances can combine channels and the same weights can filter all channels, with the noise model adjusted for their variances and correlations.

Larger search windows cost more and offer more accidental matches as well as useful ones. Larger $h$ accepts less similar patches and smooths more strongly. Patchwise variants estimate whole patches and aggregate their overlaps. These details distinguish implementations of Chapter 10.2, Non-local means that otherwise share the same equation.

The method also carries a bias. It averages a patch with the patches that resemble it, so it pulls the image slightly toward its own repeated structures, and details with no match elsewhere, a crack in one brick, a single hair, get fewer effective samples and either stay noisy or are smoothed toward their nearest look-alikes. This is the first appearance of a failure mode that every method borrowing evidence from elsewhere in the image shares: good at what repeats, weaker at what does not.

The direct search repeats much of its arithmetic. For a fixed displacement, form an image of squared differences between the input and its shifted copy. A box sum, implemented with a summed-area table Crow 1984 or separable running sums, then gives all patch distances for that displacement. This reduces the cost of comparing large patches. A bounded search window limits the number of displacements; a pilot denoising pass can help select candidates, provided the final average still uses the intended measurements. These accelerations change different parts of the computation and can be combined.

13.6.3 BM3D: group, transform, shrink, aggregate⧉

BM3D (Dabov et al. 2007) combines patch matching with Chapter 13.4, Pyramid and wavelet denoising. For each reference patch it selects similar patches, stacks them, applies a transform within each patch and along the stack, shrinks the coefficients, and transforms back. The third dimension indexes patches; it is not a spatial axis in the photograph.

If the patches were identical, an orthonormal transform along the stack with a constant first basis vector would concentrate their shared signal in that component. Real matches differ, so other components also contain signal. Shrinkage can retain these differences when they are sufficiently strong. It can also erase a genuine detail present in only one patch.

The method has two passes. The first uses hard thresholding and aggregates the reconstructed patches into a basic estimate. The second uses that estimate to select groups and estimate coefficient power, but filters groups extracted from the original noisy image. In a simplified orthonormal-transform description, its empirical Wiener gains are

$$g_i=\frac{|c_i^{\mathrm{basic}}|^2}{|c_i^{\mathrm{basic}}|^2+\sigma^2},\qquad \hat c_i=g_i c_i^{\mathrm{noisy}}.$$

A small pilot coefficient gives a small gain; a large one largely retains the noisy coefficient. With other transform normalizations, replace $\sigma^2$ by the appropriate coefficient noise variance. Group selection and overlapping samples make the actual statistics more complicated than this idealized expression.

fig-bm3d-flowchart
Figure 13.6.2. The two-stage BM3D pipeline as a schematic: group similar blocks across the search window → 3-D collaboratively filter the stack → aggregate the filtered blocks back. Each stage runs twice: first a hard-threshold shrinkage to form a basic estimate, then a Wiener filter that uses that basic estimate as its pilot. This is the structure behind the interactive demo below Dabov et al. 2007.
Algorithm 13.6.2
basic = aggregate(
    inverse_transform(hard_threshold(transform(group_from(y)), threshold))
    for each reference patch, with group matches found in y)

for each reference patch:
    positions = find_matches(basic)
    c_basic = transform(extract_group(basic, positions))
    c_noisy = transform(extract_group(y, positions))
    gains = abs(c_basic)**2 / (abs(c_basic)**2 + coefficient_noise_variance)
    accumulate(inverse_transform(gains * c_noisy), positions, group_weights)
out = accumulated_values / accumulated_weights

This outlines the data flow; a reproducible implementation must also specify transforms, matching thresholds, group sizes, spatial windows, and aggregation weights. Every reconstructed patch returns to its own original position. Overlapping estimates are combined with spatial and group reliability weights, then normalized. They share input pixels and are not independent new observations.

fig-bm3d-demo
Figure 13.6.3. Interactive. The three moves, made visible. Click a reference block in the noisy image and the demo finds its best matches across the search window and stacks them; the filmstrip shows that group before and after collaborative filtering: a 2-D DCT of each block and a 1-D DCT along the stack form one 3-D transform, and each of its coefficients survives only if it clears a hard threshold, which keeps what the group shares because shared content concentrates into a few large coefficients; the filtered blocks then go back to their positions and the overlaps are averaged. Move the reference into a repeating structure and the group fills with genuine matches, move it onto a unique object and the group is padded with poor ones, which is where the method's own bias becomes visible. The demonstration runs only BM3D's first, hard-thresholding stage and omits its second, Wiener-filtering stage. Interactive: click to place the reference block, set the threshold and the group size, and watch the group, the shrunk coefficients and the aggregated result update together.

Suppose four matched patches were exactly equal except for independent noise. Along the stack dimension, their common component is constant, while their differences contain only noise. An orthonormal transform separates that constant direction from difference directions. Shrinking the latter suppresses disagreement while retaining the common patch. Real matches are only approximate: a small edge displacement or a texture difference can also occupy a difference direction. BM3D's grouping, shrinkage, and overlap aggregation must therefore balance agreement against genuine variation. This explains why grouping quality matters as much as the transform itself.

13.6.4 The ceiling of hand-designed priors⧉

BM3D remains a useful comparison because it requires a noise level but no learned weights. It can exploit strong repetition within a test photograph even when that photograph differs from a training collection. Irregular fine texture, unique details, and unreliable matching at high noise remain difficult.

Levin, Nadler, Durand, and Freeman (Levin, Nadler, Durand & Freeman 2012) studied denoising limits through statistical models and large collections of natural-image patches. Their analysis relates attainable error to patch size and pixel correlations. Under their model, the best methods of the time were already close to the attainable error for small patches, so further cleverness within a small window had little left to gain, while the bound kept improving as patches grew. Such estimates depend on the image distribution and patch model; they are not a proof that BM3D is optimal or that all hand-designed priors have reached a universal limit. They motivate the use of broader context, which learned methods can exploit without explicitly searching for every matching patch.

💡 Big lesson (self-similarity is free redundancy)

Repeated structure supplies useful measurements within one image, so the averaging law of multiple frames is available inside a single photograph if the repetitions can be found. Comparing patches of $m$ samples rather than single pixels averages the noise in the comparison, which makes the match about $\sqrt m$ times more reliable for independent noise. The gain depends on how closely the clean patches agree and how reliably the noisy patches can be matched.

Recap: big lessons of this chapter

💡 Big lesson (self-similarity is free redundancy)

Repeated structure supplies useful measurements within one image, so the averaging law of multiple frames is available inside a single photograph if the repetitions can be found. Comparing patches of $m$ samples rather than single pixels averages the noise in the comparison, which makes the match about $\sqrt m$ times more reliable for independent noise. The gain depends on how closely the clean patches agree and how reliably the noisy patches can be matched.