HomeArticlesComputational Photography

Image Filters: Convolution, Sobel Edges and Gaussian Blur

Blur, sharpen, detect an edge — nearly every classic image filter is the same one operation, convolution, with a different small grid of numbers.

mysimulator teamUpdated June 2026≈ 8 min read▶ Open the simulation

Convolution: one operation, a hundred filters

A convolution kernel is a small grid of numbers — often 3x3 or 5x5 — that slides across every pixel of an image. At each position, it multiplies each kernel value by the underlying pixel value it overlaps, sums the products, and writes that sum as the new value of the centre pixel. Blur, sharpen, emboss and edge detection are all the exact same sliding-window operation; only the numbers in the kernel change.

live demo · a kernel sliding across a pixel grid● LIVE
output(x,y) = Σ Σ  kernel(i,j) · input(x+i, y+j)     for i,j in the kernel's footprint

3x3 box blur kernel (each weight = 1/9):     3x3 sharpen kernel:
  1/9  1/9  1/9                                0  -1   0
  1/9  1/9  1/9                               -1   5  -1
  1/9  1/9  1/9                                0  -1   0

Gaussian blur: weighting the neighbourhood by distance

A box blur (equal weights) smooths an image but produces visible square artefacts. A Gaussian blur instead weights nearby pixels by the 2D Gaussian (normal distribution) function, so pixels close to the centre count far more than distant ones, producing a smooth, natural-looking softness with no directional artefacts:

G(x, y) = (1 / (2πσ²)) · exp( -(x² + y²) / (2σ²) )

σ (sigma) controls the blur radius — larger σ = wider kernel = stronger blur

Because the 2D Gaussian is separable — it factors exactly into a horizontal 1D Gaussian times a vertical 1D Gaussian — an implementation never actually computes a full 2D kernel. It blurs every row with a 1D pass, then blurs every column of the result with the same 1D pass, turning an O(k²) per-pixel cost into O(2k), which is why Gaussian blur stays fast even at large radii.

Sobel: turning intensity change into an edge map

An edge is, by definition, a place where pixel intensity changes rapidly. The Sobel operator (1968) approximates the image gradient with two small kernels, one sensitive to horizontal change and one to vertical:

Gx (horizontal gradient):        Gy (vertical gradient):
 -1   0  +1                       -1  -2  -1
 -2   0  +2                        0   0   0
 -1   0  +1                       +1  +2  +1

edge magnitude = sqrt(Gx² + Gy²)
edge direction = atan2(Gy, Gx)

Running both kernels over every pixel and combining them gives an edge-strength map that lights up wherever intensity changes sharply in any direction — the basis for the more sophisticated Canny edge detector, which adds Gaussian blurring first (to suppress noise, since noise looks like tiny fake edges to Sobel), then non-maximum suppression to thin the edges to single-pixel lines, then a two-threshold hysteresis step to keep only genuinely connected edge chains.

When it is faster to filter in the frequency domain

Direct convolution of an n-pixel image with a k x k kernel costs O(n · k²) — every output pixel needs k² multiply-adds. The convolution theorem says convolution in the spatial domain is equivalent to simple element-wise multiplication in the frequency domain, so an image can instead be transformed with a 2D Fast Fourier Transform (O(n log n)), multiplied pointwise by the kernel's own transform, and transformed back. For a tiny 3x3 Sobel kernel this is not worth it — the constant overhead of three FFTs dominates — but for large kernels, roughly above 20 to 30 pixels wide, FFT-based filtering becomes significantly faster because its cost does not grow with kernel size the way direct convolution's does.

Frequently asked questions

Why does the Sobel operator use two kernels instead of one?

Because an edge can run in any direction, and a single kernel only responds strongly to gradients aligned with it. Sobel uses one kernel tuned to horizontal intensity changes (Gx) and one tuned to vertical changes (Gy), then combines them as magnitude = sqrt(Gx^2 + Gy^2) to get a direction-independent edge strength, and atan2(Gy, Gx) to recover the edge's orientation if needed.

Why is Gaussian blur used to reduce noise before edge detection?

Edge detectors work by amplifying rapid intensity changes, and random pixel noise is itself a rapid, high-frequency change, so applying Sobel or a similar operator directly to a noisy image produces a field of spurious tiny 'edges' from the noise, drowning out the real ones. A Gaussian blur is a low-pass filter: it smooths out high-frequency noise while leaving genuine, larger-scale edges mostly intact, which is why nearly every practical edge detector, including the Canny algorithm, blurs first.

When is it faster to filter an image using the FFT instead of direct convolution?

Direct convolution costs O(n·k^2) for an n-pixel image and a k*k kernel, while FFT-based filtering costs O(n log n) regardless of kernel size, because convolution in the spatial domain becomes simple multiplication in the frequency domain. For small kernels like a 3x3 Sobel operator, direct convolution wins because the constant overhead of two FFTs and an inverse FFT is not worth paying; for large kernels, roughly above about 20 to 30 pixels wide, the FFT approach becomes faster.

Try it live

Everything above runs in your browser — open Image Filters and change the parameters while it is running. Nothing is installed, nothing is uploaded, the whole model lives in one tab.

▶ Open Image Filters simulation

What did you find?

Add reproduction steps (optional)