Blur an image, shrink it, and rebuild it exactly — a map of image filtering
Blur a photograph, throw away three quarters of its pixels, and you have every reason to expect that the detail you removed is gone for good. It is not. If you keep the right bookkeeping, the pixels come back exactly, and the same accounting is what lets you paste two photographs together with no seam and no ghost.
That surprising property is the spine of this map. Classical image filtering looks like a drawer full of unrelated tricks, blur, sharpen, denoise, match, pyramid, blend, and each is usually taught as its own recipe. The claim of this tutorial is that they are all the same decision made over and over: decide what survives. At every pixel, at every scale, at every frequency band, you are choosing which local information to keep and which to throw away. Once you see the decision, the operators stop being a menu and start being answers to specific questions. Every application failure you will meet, a staircase edge, a halo, a visible seam, is that decision made wrong, and it is visible precisely because the wrong choice has a signature.
We will follow a single image from the moment photons hit a sensor to the moment it is blended into a composite, and at each step we will predict the artifact before we run the next operator. That prediction habit is the only thing you really need to carry away.
Where do pixel values actually come from — and what gets lost before filtering even starts?
Before we can talk about which information survives, we have to know what a pixel is. The physics is simple and worth stating once, because it explains why later filters fight noise and aliasing at all.
A digital camera replaces film with a sensor array. Light leaves an illumination source, bounces off a scene, passes through an optical system, is projected onto an image plane, and finally gets digitized. The canonical textbook diagram of this chain is the one in Gonzalez and Woods, Digital Image Processing, a long-standing classic reference in the fieldDIP2e.

Caption: Five labeled stages connected by arrows carry a scene to a pixel grid: an energy source, a scene element, an imaging system, the projected image on the internal image plane, and finally the digitized output, where the projection has already been resolved into discrete cells. This is the physical origin of every array you will filter later in this tutorial.DIP2e
Two decisions happen at the end of that chain, and they are the only two. Gonzalez and Woods put the distinction as cleanly as anyone: digitizing the coordinate values is called sampling, and digitizing the amplitude values is called quantizationDIP3e. Sampling answers where do I measure. Quantization answers how finely do I record what I measured.
You can see both in one picture. Take a smooth continuous shape and project it onto a sensor grid. If you sample, you keep the value only at grid centers, and if you then quantize, each of those values is snapped to one of a finite set of intensity levels. The result is a coarse mosaic of flat blocks with visibly stepped edges.

Caption: The left panel is a continuous object imaged onto a sensor grid; the right panel is the same object after sampling and quantization, where each grid cell has collapsed to a single gray value. The stair-step boundary and the banding inside the shape are not rendering damage, they are the signature of the two decisions that were just made.
Two artifacts are born right here, and they will follow you for the rest of the tutorial. Staircase edges come from sampling: a slanted contour can only jump from cell to cell, so a smooth line becomes a flight of steps. Quantization banding comes from snapping continuous intensities onto a coarse ladder: a gentle gradient turns into flat plateaus with visible boundaries between them. Both are predictable, and both get worse as the sensor grid coarsens or the bit depth shrinks. Some of what modern filters do is genuine improvement, and some of it is repair work on decisions already made here.
Once digitized, the image has a standard shape. It is an $M \times N$ array of intensity values, with the origin at the top-left, so index $(0,0)$ is the first sample of the first row. A grayscale image is a single $M \times N$ plane; a color image stacks three such planes into an $H \times W \times 3$ array. The same picture has three useful readings, a 3-D surface where intensity is height, a visual intensity array, and a plain numerical matrix, and it is worth keeping the third one in mind because that is what your code actually touches.

Caption: Three equivalent views of the same image: as a surface with intensity as height, as a visual intensity array with the origin at top-left, and as a grid of numbers. The numerical view is the one a filter actually operates on, and it is the reason a filter can treat a photograph and a spreadsheet identically.DIP3e
For color, the three planes are captured through a color filter array on the sensor, where each cell admits only one band and the rest are reconstructed from neighbors.

Caption: Incoming light passes a filter layer before reaching the sensor array, and each cell registers one band, producing the alternating mosaic pattern of the top image. Color is later reconstructed as three full planes, so for this map it is enough to know that every operator runs the same computation on each plane independently.
That is the whole story we need from acquisition: color means three planes, and processing is per plane.
The takeaway for this chapter is a habit of blame. When you see a filtering failure, ask which of the two acquisition decisions was wrong before blaming the filter. A pixel is not a fact about the world. It is a record of where someone chose to measure and how finely they chose to record, and every later operator either exploits the traces of those choices or tries to patch them.
One operation, many kernels: what does a convolution actually decide?
You can already write a filter, so we will not spend time on the mechanics of sliding a window. The useful question is what the sliding window means.
At every pixel, a local operator combines a small neighborhood according to a set of weights. The weights live in a small matrix called the kernel, and the output is a weighted sum: $g(i,j) = \sum_{k,l} f(i+k, j+l), h(k,l)$, where $f$ is the input image and $h$ is the kernelDIP3e. Szeliski's textbook phrases the same thing as each output pixel being a weighted sum of nearby input pixels, and calls the kernel the filter coefficients or maskSzeliski2010.
The single most useful reading is this: a kernel is a ballot over neighbors. Each coefficient says how loudly that neighbor gets to vote on the output. A box kernel gives everyone the same vote. An identity kernel lets only the center pixel vote. A shift kernel moves the vote one cell over. A sharpening kernel lets the center vote positively and its immediate neighbors vote negatively. Nothing else is happening.
There is one naming subtlety. Correlation slides the kernel as-is; convolution flips it first. Convolution with an impulse reproduces the kernel, while correlation reflects it, and that is the cleanest one-line reason convolution is the "official" form for linear shift-invariant systems. In practice the distinction often disappears, because any symmetric kernel produces the same result either way. So for the operators in this map you can think of the two names as interchangeable without losing anything useful.
The kernel menu collapses into one language once you look at a matched set side by side. Szeliski's separable-filter figure shows five kernels, their 1-D horizontal factors, and the filtered output for each: a box, a bilinear kernel, a nominal "Gaussian", a Sobel, and a corner detector.
The payoff of that family is separability. A 2-D kernel that can be written as an outer product of a column vector and a row vector, $K = v,h^{\top}$, costs two 1-D passes instead of one 2-D pass, which drops the per-pixel cost from $O(K^2)$ to $O(K)$ as the window grows. You can see the decomposition as plain arithmetic: a 3×3 matrix that is exactly a column times a row.

Caption: The 3×3 kernel on the left factors into a 3×1 column vector times a 1×3 row vector on the right. When a kernel has this structure, the same two-pass trick applies to the Gaussian, to the box filter, and to the pyramid's generating kernel.
There is a second decision hiding in every filter, and it is the one that produces the artifact everyone blames on a bug: the border. At the edge of the image the window hangs off the array and there are simply no neighbors to vote. You must invent them, and the way you invent them changes the result. Zero padding darkens the edges, clamp padding stretches the border inward, mirror padding reflects it, wrap padding tiles the image. The effect is easiest to see after blurring.

Caption: Four ways to fill the pixels outside the image, and what each does after blurring. Zero padding leaves a dark halo at the border; the alternatives avoid it. This is not a bug in the blur, it is the padding decision made visible, and it is the first place the predict-the-artifact habit pays off.Szeliski2010
Two more operators complete the language. Sharpening takes the high-frequency detail you get by subtracting a blurred copy from the image and adds it back to the original in proportion — the unsharp-mask recipe — which is another way of saying "keep the center strong, subtract a little of the neighborhood". The effect is visible as crisper edges in a portrait, and it also previews the frequency story of the next chapter, where sharpening turns out to be the mirror image of blurring.

Caption: The same portrait before and after sharpening. Edges, hair, and fabric texture become crisper because the kernel now subtracts its neighbors from the center pixel rather than averaging them.
Sobel, meanwhile, is not a smoothing kernel at all but a small oriented derivative estimate, built from a horizontal central difference combined with a vertical smoothing, and it is the bridge from smoothing to edge detectionSzeliski2010. If you want the deeper treatment of kernel algebra, sliding-window mechanics, and array indexing, the atlas has a companion on Image Formation, Linear Filtering, and Denoising.
The takeaway is compact. A filter is not a bag of special effects, it is one sentence about how much weight each neighbor gets. And at the border, where there are no neighbors, you have to say what you meant, or the image will darken no matter which filter you ran.
Why one Gaussian does two jobs: the frequency-band view of blur and sharpen
So far we have judged kernels by their coefficients. There is a second view, and it is the one that unifies the rest of the map: judge them by which spatial frequencies they keep.
Spatial frequency is just how fast intensity changes across the image. Fine texture and sharp edges are high frequency; broad shading and overall color are low frequency. In that vocabulary, a Gaussian kernel is a low-pass filter: it keeps the slow variations and suppresses the fast ones. And sharpening, the identity minus a Gaussian, is a high-pass filter: it does the exact opposite. Blur and sharpen are not opposites in the sense of being unrelated. They are two readings of one Gaussian.
You can see it in a single frame. Below, a low-pass gain curve and a high-pass gain curve are drawn on the same axes as a function of frequency, and their sum reconstructs the original.

Caption: A low-pass curve keeps low frequencies and kills high ones; a high-pass curve does the reverse. Added together they recover the input. The same figure is also the schematic of two-band blending, which we will meet again when we join two images.
The clearest demonstration that these bands actually carry different information is the hybrid image. Take one image, keep only its low frequencies; take a second image, keep only its high frequencies; add them. The construction is exactly one line:
$$H = I_1 \cdot G_1 + I_2 \cdot (1 - G_2)$$
where $G_1$ and $G_2$ are Gaussian low-pass filters and $1 - G_2$ is the complementary high-passHybridImages. The two cut-off frequencies are the only parameters, and they decide how far you have to stand from the picture for your perception to flip.
Because human vision is coarse-to-fine, the low band dominates early and at a distance, while the high band wins up closeHybridImages. The same asymmetry lets low-frequency content hide high-frequency content, which is why a hybrid-font line becomes unreadable a few meters back while a control line that was only high-pass filtered stays legible.

Caption: The upper line is rendered in a hybrid font, so its low-frequency component dominates at a distance and the text becomes invisible; the lower control line was only high-pass filtered and stays readable. This is the perceptual proof that bands are not an engineering abstraction.HybridImages
One more observation, stated softly because it is a textbook-standard fact rather than a result anyone needs to derive here: for natural images, most of the energy in the magnitude spectrum sits near low frequencies, with the constant term usually the largest single contribution. That is why coarse structure dominates the visual impression, and it is also why a pyramid, which we will build soon, can throw away most pixels and still look recognizable.
The takeaway for this chapter is the question to ask before choosing a kernel. The detail and the base of an image live in different bands, so ask which band you intend to touch. That single question is blur versus sharpen made visible, and it is also the machinery the Laplacian pyramid will later store as data.
Denoising is a bet on the noise model — predict the artifact before you pick
Denoising is where the predict-the-artifact habit earns its keep, because the right filter depends entirely on how the noise was made. Get the noise model right and the artifact is predictable; get it wrong and the artifact is visible for exactly the same reason.
Start with the two models that cover most cases. Additive Gaussian noise is a small random perturbation added to every pixel, and it is the model you meet when a sensor or an amplifier is the culprit. Impulse noise, often called salt-and-pepper, is different: a few pixels are replaced with extreme values, black or white, and everything else is untouched. The distinction matters because the two models call for different statistics.
Gaussian smoothing is itself a denoiser. Averaging many noisy pixels reduces the variance of the noise, and it is a perfectly reasonable response to additive Gaussian noise. But it blurs as it cleans, because it cannot tell a noisy pixel from a genuine edge. Raise the smoothing and you trade noise for blur, which is the honest trade-off of every linear smoother.
Impulse noise wants a different answer. The median filter replaces the center pixel with the median of its neighborhood instead of the mean. Because the median is nonlinear and robust to outliers, a single black or white pixel simply does not move it, and the filter removes the speckle while leaving edges far more intact than a mean would. This is the first place where the operator is chosen not by taste but by the noise model.
For the cases where you want the noise gone without paying in blur, the bilateral filter is the canonical move. It multiplies two Gaussians together: a spatial weight that depends on how far a neighbor is, and a range weight that depends on how different its intensity is. Pixels that are close and similar vote; pixels that are close but very different do not. The formula is one normalization away from a weighted average:
$$h(x) = k^{-1}(x) \sum_{\xi} f(\xi), c(\xi; x), s(f(\xi); f(x))$$
where $c$ is the spatial (domain) weight and $s$ is the range weight, and the normalization $k(x)$ makes the weights sum to oneTomasiManduchi.
The whole edge-preservation mechanism lives in the range weight, and one figure makes it concrete. Picture a noisy step edge. Center the filter two pixels to the bright side, and plot the combined weight surface: it is a half-dome that reaches toward the bright side and collapses to zero on the dark side. The dark pixels are not down-weighted, they are effectively ignored, so they never vote and the edge survives.

Caption: A noisy step edge, the combined spatial-times-range weight surface centered on its bright side, and the result after filtering. The key detail is that the surface is not symmetric: the range weight has suppressed the entire dark side, which is why the transition stays sharp. Edge preservation here is a direct consequence of the range Gaussian, not of any explicit edge detection.TomasiManduchi
On a real photograph the same effect shows up as clean surfaces with the object outlines still crisp, which is the qualitative result the paper demonstrates.

Caption: A still life before and after bilateral filtering, with a zoomed detail of a tomato below. Surface noise disappears while the tomato outline stays sharp. This is before-and-after bilateral only, not a comparison against Gaussian blur.TomasiManduchi
Two later developments are worth knowing by name. Anisotropic diffusion is the iterative, PDE-based ancestor of this idea: it runs many small smoothing steps, but modulates the diffusion coefficient by the local gradient so smoothing slows down at edgesPeronaMalik. Bilateral is the non-iterative, kernel-form successor: one closed-form weighted average instead of a time-stepped PDE.
The guided filter is the modern update, and it reaches the same edge-preserving goal through a different formulation. Instead of an explicit spatial-times-range kernel, it assumes the output is a linear function of a guidance image inside each local window, $q_i = a_k I_i + b_k$, with the coefficients solved in closed form from local means and variancesGuidedFilter. Two properties make it attractive: the whole computation reduces to box filters, so the cost is linear in pixels and independent of window size, and for self-guidance it provably avoids the gradient reversal that bilateral can produce when a detail layer is magnified. That last point is the one to remember, because it is a case where the newer filter does not just run faster, it behaves better.

Caption: Two formulations of the same goal. On the left, bilateral filtering multiplies a spatial Gaussian by a range Gaussian; on the right, guided filtering fits a local linear model. The output is comparably smooth in both cases, and the difference is cost and edge behavior rather than intent.GuidedFilter

Caption: A synthetic 1-D signal, its base layer, its detail layer, and the magnified result. In the upper panel the bilateral detail layer flips sign at the edge, so the enhanced signal overshoots; in the lower panel the guided filter keeps the step monotonic. This is a 1-D illustration of detail enhancement, not a photograph.GuidedFilter
The takeaway is the diagnostic one. Before asking which filter, answer how the noise was made. Gaussian noise wants a Gaussian smoother and will show blur if you use too much; impulse noise wants the median and will show leftover speckle if you use a mean; strong edges want a range-aware filter and will show a halo if you use a plain blur. The wrong pick is not subtle, because the wrong pick always leaves a fingerprint.
Two pyramids, one idea: search at every scale, and store exactly what blur removes
Everything so far happened at the original resolution. The moment we need to handle scale, one resolution stops being enough, and the chapter splits into two questions: how do I search an image at many sizes, and how do I store an image at many sizes without losing anything. The surprise is that both answers are the same data structure read two different ways.
The scale problem surfaces immediately in template matching. You have a patch and a larger image, and you want to find the patch. Every similarity measure runs into the same wall: if the template appears at a different size than the one you cropped, no amount of clever matching will fix it, because the metric has no notion of scale. The fix is to search at many scales at once, and for that you need a stack of progressively smaller images. If you want the deeper treatment of matching metrics, invariances, response maps, and false detections, the atlas has a companion on Template Matching Metrics and Pyramid-Based Scale Search.
That stack is the Gaussian pyramid. Start with the full-resolution image, apply a small low-pass filter, and then keep only every second row and column. Repeat. Each level is roughly half the size of the one below, and each is a progressively smoother view of the original. The operation is called REDUCE, and its canonical one-dimensional picture is the dot diagram below.

Caption: Three levels of the pyramid drawn as rows of dots, with node spacing doubling from level to level and the same weighting pattern reused at every level. REDUCE (Burt 1981, reused in Burt & Adelson 1983 Fig. 1): each node of a higher level is the weighted average of nodes in the level below, so the representation is self-similar across octaves.BurtAdelson83
The low-pass before subsampling is not optional, it is the anti-aliasing step. Skip it and high-frequency content folds down into false low-frequency structure, and you get aliasing that no later filter can undo. This is the same predict-the-artifact habit from the border discussion, applied to scale instead of space.
What makes the pyramid practical rather than merely clever is the way it is computed. The same generating kernel, evaluated recursively on the previous level, produces kernels that differ in width but not in shape, all in one recursive pass. The algorithmic engine is Burt's 1981 fast filter transform, whose defining property is that a single recursive pass convolving an image with a set of kernels which differ in width but not in shape yields an entire family of smoothed copies at onceBurt1981. That recursion is the reason a pyramid is cheap enough to use as a search grid, and it is what cv2.pyrDown is actually running under the hood.
With a cheap stack in hand, coarse-to-fine search is straightforward. Align at a coarse level, where there are very few pixels and a whole-image search is nearly free; then refine inside a small window at the next level down, and keep refining. You spend most of your work at low resolution where work is cheap.
There is a real trade-off here, and it is worth saying plainly. Coarse levels have thrown away high-frequency detail, so a template whose identity depends on fine structure can be missed at the coarse level and never recovered, no matter how carefully you refine. Averaging does buy robustness to noise, but the search is only as good as the information the coarse level kept.
Now the pivot. When we blurred and subsampled, we discarded detail. Where did it go? The Laplacian pyramid is the answer: it stores, at each level, exactly the detail that the next coarser level lost. If $g_l$ is the Gaussian level, then
$$L_l = g_l - \text{EXPAND}(g_{l+1})$$
where EXPAND upsamples and interpolates the coarser level back to the current size, and the subtraction is the residualBurtAdelson83. The topmost level has nothing above it, so it is kept as-is.

Caption: The full encode and decode pipeline in one block diagram. On the encoding side, subtraction nodes carry the residual $L_l = g_l - \text{EXPAND}(g_{l+1})$; on the decoding side, addition nodes expand and recombine. Because the residual was defined as the exact difference, expand-and-add returns every original pixel: the original image can be recovered exactly. This is a tabular block diagram rather than a literal stack of pyramid levels.BurtAdelson83
This is the refutation of the intuition we started with. Blur, shrink, expand, and add, and you recover the original exactly, because $L_l$ was defined to be the exact residual rather than an approximation. Blurring and downsampling do destroy information, but the Laplacian pyramid keeps a receipt for every piece of it.
The trap worth naming head-on is treating the Gaussian pyramid and the Laplacian pyramid as two unrelated data structures. They are not. They are the search version and the storage version of the same band decomposition: one is a stack of increasingly low-pass images, the other is the set of residuals that takes you back. The same multiresolution spline machinery that stores the bands is what makes seamless compositing possible, and that is where we go next.
Seams vs ghosts: why a single transition width can never win
Compositing is where the predict-the-artifact habit gets its finale. Suppose you want to join two images, and you get to choose how wide a transition zone blends one into the other. If you want the deeper treatment of cut-and-paste, alpha masks, feathering, and transparency, the atlas has a companion on Alpha Feathering and Laplacian-Pyramid Blending for Seamless Compositing. Here we stay with the tension, because the tension is the whole point.
Make the transition too narrow, or skip it entirely, and you leave a visible seam, a hard or slightly soft edge where the two images meet. Widen it and the seam softens, but the transition zone now covers features from both images, and any feature that sits in the overlap appears twice, a ghost or double exposure. The key observation is that these two failures have opposite fixes. The seam wants a wide transition; the ghost wants a narrow one. No single width satisfies both, so a single-width compositor loses by construction.
You can watch all three outcomes plus the success case on one input pair.

Caption: Two synthetic star fields, and four attempts to join them. A hard cut leaves a visible seam; a narrow transition leaves a blurred seam; a wide transition doubles stars inside the zone into a ghost. The multiresolution spline avoids both, though local smoothing remains in the blended zone, so it is not a perfect seam-free result.Multispline83
The reason a single width fails is that a seam and a ghost live in different frequency bands. A coarse background offset between the two images is a low-frequency discrepancy: hiding it needs a slow, spatially wide transition. A point-like feature such as a star is high frequency: blending it even slightly produces a doubled copy, so it needs a transition that is nearly local. One width cannot be both wide and narrow.
The fix is to give each band its own width. The Laplacian pyramid from the previous chapter is exactly the tool, because it already separates an image into bands. At level $l$ of the pyramid the sample interval is $2^l$, and the natural transition width that fits the scale is about $3 \cdot 2^l$ pixels: large at coarse levels, small at fine levels. Low frequencies blend over long distances; high frequencies blend locally. That is the rule to carry away.
The recipe is the three-step multiresolution spline. Build a Laplacian pyramid for each of the two images. Build a third pyramid by choosing, per level, which image contributes there, using a coarser transition for the low bands and a nearly binary choice for the high bands. Then collapse the combined pyramid by the same expand-and-sum that reconstructs exactly. You can see the per-band behavior directly in the apple-and-orange decomposition: the high-frequency components barely cross the midline, while the low-frequency components extend far.

Caption: Rows are frequency bands, from high at the top down to the full reconstruction; columns are the apple half, the orange half, and their per-band sum. High-frequency components extend only slightly past the midline, while low frequencies extend considerably further. This is why the transition width has to be chosen per band rather than globally.Multispline83
This is the same band machinery from the frequency chapter, now doing real work. Recall the two-band schematic with the low-pass and high-pass gain curves and their composite; the panorama simplification of the spline is precisely a two-band version of it. Instead of a full pyramid, keep one smoothly blended low-frequency band and one high-frequency band selected by an essentially binary alpha. Brown and Lowe's panorama stitcher adopts the Burt and Adelson recipe exactly this way, motivated by exposure and gain differences between adjacent photographs that produce seams under single-scale weighted averagingBrownLowe07. That algorithm is not a museum piece: it ships in OpenCV as cv::detail::MultiBandBlender, the standard implementation of the multiband blending idea in modern stitching pipelines. A complementary family based on gradients exists for a different boundary problem, but its mechanics are a topic of its own.
The takeaway is that a seam and a ghost are not solved by feathering wide enough. They are solved by giving each frequency band its own transition width. The single-width compositor loses by construction, and the per-band, exactly-reconstructible Laplacian pyramid wins by the same accounting that made the previous chapter lossless.
One image, one notebook: the whole filter chain, from blur to seamless blend
Everything we have built fits into one runnable chain, and the chain is best understood as a single image passing through each chapter's decision in turn.
The OpenCV primitives that carry each step are the practical face of the theory, and their signatures are worth knowing because they encode decisions the papers leave implicit. cv2.GaussianBlur(src, ksize, sigmaX, sigmaY=0) is the chapter 2 ballot; if both sigmas are zero they are derived from the kernel size, and if only sigmaX is given it is copied to sigmaY. cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace) is the chapter 4 decision, where sigmaColor maps to the range Gaussian and sigmaSpace to the spatial one. cv2.pyrDown and cv2.pyrUp are the chapter 5 storage operators, and their fixed internal kernel is the separable 5×5 Gaussian with coefficients [1 4 6 4 1] normalized by 256, followed by even-row and even-column rejection on the way down and zero-insertion-then-blur on the way up. cv2.matchTemplate is the chapter 5 search primitive. cv2.Sobel is the oriented derivative from chapter 2OpenCV4x.
A minimal walk through the chain reads like this. Load the image and convert it to a working type. Blur it with a small Gaussian, which is the chapter 2 decision expressed as one call. Denoise with the bilateral filter, accepting that it only touches 8-bit or floating-point 1- and 3-channel images and that it cannot run in place, so you must allocate a separate destination. If the task is matching, run matchTemplate; remember that its result is always a single-channel CV_32F response map of size (W - w + 1) × (H - h + 1), and that you pick the minimum for the sum-of-squared-difference modes and the maximum for the correlation and coefficient modes. Build a pyramid with pyrDown, and reconstruct with pyrUp plus the stored residual. If you call Sobel, set ddepth = CV_16S for 8-bit input, because derivatives are signed and will otherwise be truncated to the 0-to-255 range. Finally, blend per band, either by the three-step spline or by the two-band simplification, and note that pyrUp accepts only the default border mode while pyrDown does not accept constant padding.
Two of those details are worth spelling out because they are the kind of thing the textbooks omit and the code will tell you about the hard way. The bilateral filter's non-in-place restriction and Sobel's signed-output requirement are not incidental, they are consequences of the operators themselves: bilateral needs the untouched neighborhood for every pixel, and a derivative genuinely does not fit in an unsigned byte. This is the practitioner's layer on top of the theory, and it is where a filter that "should work" turns into one that silently clips or writes over its own input.
The reason to organize the whole map as one chain, rather than as a list of recipes, is the closing self-check it enables. Look at any filtering failure now and you can say which layer's decision went wrong. A staircase at a boundary is a sampling decision. A darkened border is a padding decision. A halo around an edge is a range-weight decision. A blurred seam or a doubled feature is a per-band transition-width decision. Aliasing in a pyramid is a missing low-pass before subsampling. None of those are mysterious once you see that every operator is the same vote about what survives, cast at a different scale.
The whole map, then, is a handful of cv2 calls plus one habit. Predict the artifact before you choose the operator, and classical image filtering stops being a drawer of tricks and becomes a single coherent way of thinking about what to keep.
References
The core sources behind this map, listed in the order they appear in the atlas:
- The Laplacian Pyramid as a Compact Image Code (Burt & Adelson, IEEE Transactions on Communications, 1983) — https://persci.mit.edu/pub_pdfs/pyramid83.pdf
- Computer Vision: Algorithms and Applications (Szeliski, Springer) — http://szeliski.org/Book/
- Digital Image Processing, 3rd edition (Gonzalez & Woods, Prentice Hall, 2008) — https://www.imageprocessingplace.com/DIP-3E/dip3e_main_page.htm
- Digital Image Processing, 2nd edition (Gonzalez & Woods, Prentice Hall, 2002) — https://www.imageprocessingplace.com/DIP-2E/dip2e_main_page.htm
- Bilateral Filtering for Gray and Color Images (Tomasi & Manduchi, ICCV 1998) — https://users.cs.duke.edu/~tomasi/papers/tomasi/tomasiIccv98.pdf
- Hybrid Images (Oliva, Torralba & Schyns, ACM Transactions on Graphics, 2006) — https://dl.acm.org/doi/10.1145/1141911.1141919
- Scale-Space and Edge Detection Using Anisotropic Diffusion (Perona & Malik, IEEE TPAMI, 1990) — https://authors.library.caltech.edu/records/1p8h5-5x870/files/PERieeetpami90.pdf
- Guided Image Filtering (He, Sun & Tang, IEEE TPAMI, 2013) — https://people.csail.mit.edu/kaiming/publications/pami12guidedfilter.pdf
- Fast Filter Transforms for Image Processing (Burt, Computer Graphics and Image Processing, 1981) — https://doi.org/10.1016/0146-664X(81)90092-7
- A Multiresolution Spline with Application to Image Mosaics (Burt & Adelson, ACM Transactions on Graphics, 1983) — https://doi.org/10.1145/245.247
- Automatic Panoramic Image Stitching using Invariant Features (Brown & Lowe, IJCV, 2007) — https://link.springer.com/article/10.1007/s11263-006-0002-3
- OpenCV: Image Filtering (official API reference) — https://docs.opencv.org/4.x/d4/d86/group__imgproc__filter.html