Convolution Explorer

Original

Filtered

Kernel (3 × 3)

Σ = 0

How a 3 × 3 convolution really works

1 Discrete convolution

For every pixel location (x, y) we slide the kernel over the image and compute

$$\;g(x,y)=\frac{1}{N}\sum_{i=-1}^{1}\sum_{j=-1}^{1} k(i,j)\;f\bigl(x+i,\;y+j\bigr)$$

where f is the original image, k the 3 × 3 kernel, g the filtered image and  \(N = \mathrm{norm}\).

The demo evaluates that equation on all three colour channels independently, so hues survive blurs and emboss.

2 Why the norm matters

Without the divisor N, even a simple blur would brighten the image – nine positive numbers sum to something bigger than the originals. Setting N = ∑ k(i,j) preserves the average brightness.

original blurred
Box‑Blur with norm = 9 keeps mid‑grey unchanged.

3 Negative weights & edges

Kernels whose weights sum to 0 act as high‑pass filters: positive cells amplify intensity jumps while negative cells suppress flat regions. That makes edges pop out:

$$\small \left[\begin{array}{rrr} -1&-1&-1\\[-4pt]-1&\phantom{-}8&-1\\[-4pt]-1&-1&-1 \end{array}\right] * f \;=\;\text{bright outline} $$

Flip all signs and you get a dark outline instead (our Outline preset).

4 Separable kernels

Some blurs (e.g. Gaussian) can be written as the outer product of two 1‑D vectors:

$$\small \begin{bmatrix}1\\2\\1\end{bmatrix} \begin{bmatrix}1&2&1\end{bmatrix} = \begin{bmatrix}1&2&1\\2&4&2\\1&2&1\end{bmatrix} $$

Convolving first along x, then along y runs in \(2 × 3\) operations per pixel instead of \(3 × 3 = 9\). Our demo keeps the maths transparent, but real‑time filters (camera apps, GPUs) always exploit that trick.

5 Stability & clamping

After summation we clamp each channel to 0‒255. That prevents overflow (“wraparound”) and underflow (“negative light”). With float textures you’d omit the clamp to keep full dynamic range for later passes.