On a black-and-white mask, erosion shaves the white shapes down. A pixel survives only if the whole structuring element fits inside white when centred on it — so shapes shrink, thin connections snap, and isolated specks of noise disappear entirely.
Task: write erode(binary_image, kernel) returning a new grid of 0s and 1s, the same size as the input.
For each output position, centre the kernel on it, then:
Look at every kernel cell that holds a 1. Those are the positions that must be checked; kernel 0s are ignored completely.
The output is 1 only if every one of those positions lands on a 1 in the image.
Otherwise the output is 0.
binary_image holds only 0 and 1. kernel is a square grid of 0s and 1s with an odd side length, anchored at its centre.
Treat everything outside the image as 0. A pixel near the border therefore has a kernel cell hanging over nothing, which counts as a miss, so the border erodes away. This is the standard convention and it's why eroding a solid white square leaves a smaller square.
The pairing to remember: erosion removes small white noise, and dilation (its opposite) removes small black holes. Apply erosion then dilation and you've cleaned up specks while restoring the surviving shapes to roughly their original size — an opening. The other order is a closing, which fills gaps instead.