Convolution Kernels by Hand

Nine numbers decide whether an image blurs, sharpens or turns into an outline. Edit them and watch which.

Overview

One operation, many effects

Convolution is a single, simple op that makes a startling range of results based on nine numbers. Take a small grid of weights — the kernel — centre it on a pixel, times each weight by the pixel underneath it, and add the products together. That sum is the output pixel. Slide the kernel one step and do it again.

That is the whole method. Blurring, sharpening, edge spotting and embossing aren't different methods. They're the same method with different numbers in the grid.

Convolution Kernels by Hand

This module needs JavaScript: the images are computed in the page rather than downloaded.

Worth knowing

A kernel is a small grid of weights. The output pixel is the weighted sum of the input pixel and its neighbours.
If the weights sum to 1 the brightness is preserved. If they sum to 0 the result is a difference image, centred on grey.
Sobel X and Sobel Y are the same kernel rotated. Each finds edges running across it, not along it.
Every convolutional layer in a CNN does exactly this. The only difference is that it learns the nine numbers instead of being given them.

Convolution Kernels by Hand

Nine numbers, one sliding window, and most of classical image processing.

Reading a kernel

The identity kernel is the easiest to reason about:

0  0  0
0  1  0
0  0  0

each neighbour is times'd by zero, the centre pixel by one, so the output is the input unchanged. Now change the centre to 5 and set the four perp neighbours to −1:

 0 -1  0
-1  5 -1
 0 -1  0

The centre pixel is amplified and its neighbours are subtracted from it. Where the zone is flat, the subtraction cancels the amplification just and nothing happens. Where the centre differs from its surroundings — at an edge — the difference is exaggerated. That is sharpening, and it shows why sharpening amplifies noise: a noisy pixel is, by meaning, a pixel that differs from its neighbours.

The sum tells you what kind of filter it is

There are two families, and you can tell them apart by adding the weights up.

Weights summing to 1 preserve mean brightness. A box blur of nine ones cut by nine is the arithmetic mean of the zone. A Gaussian blur weights the centre more heavily than the corners. Both keep the image at the same total exposure because the total part of each pixel is unchanged.

Weights summing to 0 give a difference image. Flat regions become zero, because a constant times'd by weights that cancel gives nothing. Only where the image changes does any of it live. Since a result can be minus, these filters are often displayed with 128 added. This Is why edge images have that flat grey background.

KernelSumWhat survives
Identity1everything, unchanged
Box blur1 (after division)low-frequency detail
Sharpen1everything, with edges exaggerated
Sobel0edges in one direction
Laplacian0edges in every direction
Emboss1a directional shadow

Sobel: why there are two of them

The Sobel operator comes as a pair, and the pair is one kernel rotated by ninety degrees:

Sobel X          Sobel Y
-1  0  1        -1 -2 -1
-2  0  2         0  0  0
-1  0  1         1  2  1

Sobel X subtracts the column on the left from the column on the right. A vertical edge — where left and right differ — makes a large value. A flat edge makes nothing at all, because left and right are the same there. Sobel Y is the same arg with rows.

Run each on the visualisation above and the skew is obvious: the vertical sides of the rectangle appear under Sobel X and vanish under Sobel Y. In practice the two are mixed, often as the square root of the sum of their squares, to get an edge strength that doesn't care about direction.

The middle row being −2, 0, 2 rather than −1, 0, 1 is a small piece of smoothing built in: the pixel in line with the centre is weighted more than the main-lines, so a single noisy pixel has less sway than it would in a pure difference.

What happens at the border

A kernel centred on a corner pixel has five of its nine cells hanging over the edge of the image. a thing has to be decided, and the three common answers are to leave the border out (making a smaller output), to treat the missing pixels as zero, or to repeat the nearest real pixel outwards. The visualisation here repeats the edge pixel. This Is why the frame stays clean; zero-padding would darken it. The padding module works through what that choice costs inside a network.

Why this matters for CNNs

All above is fixed: someone chose the nine numbers and wrote them down. A convolutional layer in a neural network performs the the same op and differs in just one respect. The nine numbers are params, and gradient descent chooses them.

That is worth sitting with. When people say a CNN "learns to detect edges in the first layer", they mean that training drives some of the learned kernels towards a thing that looks very much like Sobel. Edges turn out to be a handy thing to measure. No one put Sobel there. The architecture only supplies the sliding window. The content of the window is found.

One output pixel, worked

A convolution is a weighted sum repeated at each spot, and the character of a kernel is legible from its numbers. Take the sharpen kernel — centre 5, the four perp neighbours −1, corners 0. And apply it where a centre pixel of 100 sits among neighbours of 90:

5×100 − 90 − 90 − 90 − 90 = 140

patchsharpen output
centre 100, neighbours 90 (an edge)140 — the difference exaggerated
centre 100, all neighbours 100 (flat)100 — unchanged

On flat ground the amplification of the centre and the subtraction of the neighbours cancel just, so nothing happens. Only where the centre differs from its surroundings does the output diverge. This Is why sharpening exaggerates edges and, for the same reason, amplifies noise. A noisy pixel *is* one that differs from its neighbours. The kernel's weight sum tells you its family: sum to 1 (identity, blur, sharpen) preserves brightness, sum to 0 (Sobel, Laplacian) makes a difference image that is flat-grey where nothing changes. A CNN's first layer runs just this op with the nine numbers as *learned* params — and training well drives some of them toward a thing very like Sobel, because edges turn out to be worth measuring, though no one put Sobel there.

Where it goes wrong with Convolution Kernels by Hand

Sharpening noise. Any kernel with minus weights amplifies pixel-to-pixel variation, and noise is pixel-to-pixel variation. Denoise first, sharpen second.

Losing to norm. A blur kernel of nine ones, applied without cutting by nine, makes an image nine times too bright — which, after clipping at 255, is a white rectangle.

given bigger is better. A 3×3 kernel sees a 3×3 region. To see further you either use a larger kernel. This Costs as n² more times, or stack a few small ones. This Is what modern architectures do and why receptive field is a concept worth having.

Questions people ask about Convolution Kernels by Hand

Is convolution the same as correlation? Strictly, convolution flips the kernel first and correlation does not. Most libraries, and every deep learning framework, actually compute correlation but still call it convolution.

Why do some kernels sum to 1 and others to 0? A sum of 1 keeps overall brightness, as in blur and sharpen. A sum of 0 gives a difference image that is zero on flat regions, as in Sobel and Laplacian.

Why does Sobel come as two kernels? One measures change along x and the other along y. Combining them gives edge strength from the magnitude and edge direction from the angle.

What happens at the image border? The kernel hangs off the edge, so you pad with zeros, replicate or reflect the edge pixels, or just shrink the output. The choice changes the result near the border.

How does this relate to a CNN layer? A convolutional layer runs the same sliding weighted sum. The difference is that the kernel values are learned by gradient descent rather than chosen by hand.

Why do the results sometimes look clipped or all black? Outputs can be negative or exceed 255, and an 8-bit image cannot hold them. Compute in float, then rescale or take the absolute value before display.

Slide a 3x3 grid over an image and watch what each one finds

A convolution is a weighted sum repeated at each spot. Six classic kernels are applied to the same small image here, with the math for one output pixel written out in full.

example_01.pyNumPy
Output

Six classic kernels are applied to the same image, and the kernel sum reveals the filter family.

example_02.pyNumPy
Output

Combining the two Sobel directions gives edge strength regardless of orientation, which is what a CNN's early layers learn to compute.

example_03.pyNumPy
Output

Combining the two Sobel directions gives gradient magnitude — the strength of an edge regardless of its orientation.

example_04.pyNumPy
Output

Check yourself

0 of 3

Answer without scrolling back up.

  1. A kernel's nine weights sum to zero. What does its output look like on a flat, uniform region?

  2. Why does Sobel X find vertical edges rather than horizontal ones?

  3. What is the only real difference between this and a CNN's convolutional layer?

Cheat sheet

Convolution Kernels by Hand

Slide a 3x3 kernel across an image by hand, multiply and sum at each position, and watch edge detection and blur fall out of nine numbers.

COMPUTER VISION · vizlearn.in/computer_vision/convolution_kernels.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.