Part X — Computer Vision: CNNs, ResNets, Object Detection & Segmentation · Chapter 1

Convolution & 2D spatial filtering

Hook

Part III's layers connected every input to every neuron. For an image, that throws away something a filter can use directly: where things are.

Intuition
0330033003300330
window at (0, 0) — response = 0

This image is just a dark-to-light edge. Slide the window across it. The response is near zero on either flat side, but spikes right where the edge actually is — the same small filter, reused at every position, looking for the exact same pattern everywhere.

Formalize

A convolution slides a small filter (the kernel) across an image and, at every position, computes one number — the sum of the kernel multiplied elementwise with the patch underneath it:

feature(r,c)=i,jkernel(i,j)image(r+i,c+j)\text{feature}(r,c) = \sum_{i,j} \text{kernel}(i,j) \cdot \text{image}(r+i,\, c+j)
  • feature(r,c)\text{feature}(r,c) — the output feature-map value at row rr, column cc.
  • kernel(i,j)\text{kernel}(i,j) — the learned filter weight at offset (i,j)(i,j) within the small window.
  • image(r+i,c+j)\text{image}(r+i,\, c+j) — the input image's pixel value at the position the kernel currently overlaps.
  • r,cr, c — the row and column of the output position being computed.
  • i,ji, j — the row and column offsets that range over the kernel's own window.
  1. One kernel, reused everywhere

    The same 9 kernel numbers are reused at all 16 positions here — the identical filter weights get multiplied against every patch of the image as the window slides across it.

  2. Why sharing makes sense

    That's the whole idea: a pattern worth detecting in one corner of an image is worth detecting anywhere else in it too, so the filter doesn't need its own separate weights for every location.

Play
0330033003300330
window at (2, 0) — response = 0

Drag the row slider alone — the response doesn't change at all. This particular filter only cares about columns, because the edge it's built to find runs vertically. Drag the column slider and the response swings from 00 to 33 and back to 00, tracing the edge exactly.

Worked example
  1. Window position (0, 1) — on the edge

    The patch under the kernel is columns 1-3 of the image: two dark pixels (00) and one light pixel (11), in every one of the 3 rows. The kernel row (1,0,1)(-1, 0, 1) gives (1)(0)+(0)(0)+(1)(1)=1(-1)(0) + (0)(0) + (1)(1) = 1 per row, times 3 rows =3= 3 — the maximum possible response, because the patch is a perfect textbook edge.

  2. Window position (0, 3) — off the edge

    One column over, the patch is three light pixels: (1)(1)+(0)(1)+(1)(1)=0(-1)(1)+(0)(1)+(1)(1) = 0 per row — no edge in that patch, no response.

Checkpoint

Slide the window to a position where the filter’s response reaches its maximum, 3.

0330033003300330
window at (0, 0) — response = 0
Move a slider to try it
Summary
feature(r,c)=i,jkernel(i,j)image(r+i,c+j)\text{feature}(r,c) = \sum_{i,j} \text{kernel}(i,j) \cdot \text{image}(r+i,\, c+j)

A trained network doesn't get handed an edge detector — it learns kernel values like these from data, the same backprop from Part III, just computing a gradient for each of the kernel's few shared weights instead of one weight per connection. The next chapter asks what to do with the feature map this produces, which is almost as large as the image itself.