Fourier Transform for Images
The Fourier transform rewrites a photo as a recipe of waves. Slow shading becomes central low notes and crisp detail becomes outer high notes.
Why Does This Exist?
Some defects are global: striped interference across a whole scan, repeating print texture, evenly rippled lighting. In pixel space they touch everything and resist local repair. The Fourier transform re-expresses the image as a sum of 2D waves, where a full-frame repeating stripe collapses into one bright spectral dot that you can erase directly.
It is the gateway to frequency-domain processing. Once there, low-pass, high-pass, and band-pass filters sculpt the spectrum, and the same round trip underlies blur analysis in spatial filtering and cleanup in image denoising.
Think of It Like This
Sheet music for a chord
A piano chord heard together is the photo: rich but tangled. Sheet music lists each note separately, which is the spectrum: every wave with its pitch, loudness, and direction. Fixing one buzzing string means erasing its note from the score and replaying, just as deleting one spectral dot removes stripes everywhere at once. The analogy stops at timing: sheet music keeps note order while the basic spectrum forgets where things sit.
How It Actually Works
The 2D Discrete Fourier Transform writes each pixel as a sum of complex exponentials across horizontal and vertical frequencies, and the Fast Fourier Transform (FFT) computes it fast. Center the spectrum and read it: the middle holds low frequencies (slow shading, overall brightness), the rim holds high frequencies (edges, grain), and direction in the spectrum runs perpendicular to stripes in the image. Magnitude shows how much of each wave is present, while phase holds positioning, and dropping phase scrambles structure beyond recognition.
Worked example
A uniform image of all 100s has total brightness . Its DC term, the zero-frequency coefficient, equals exactly 400, and every other coefficient is 0: pure average, no waves needed. Now stripe it as columns of 0 and 255, . DC becomes , and the remaining energy sits in the horizontal-frequency term with value . One pattern change moves energy from nowhere to a predictable address with magnitude 510.
Code
The point of this snippet is the round trip on the worked example: a tiny standard-library-only 2D DFT replays the DC of 400 and the stripe pair of 510 and -510, with no array packages involved.
def dft2(img): out = [[0] * 2 for _ in range(2)] for u in range(2): for v in range(2): s = 0 for x in range(2): for y in range(2): s += img[x][y] * ((-1) ** (u * x + v * y)) out[u][v] = s return out
print(dft2([[100, 100], [100, 100]]))# -> [[400, 0], [0, 0]]print(dft2([[0, 255], [0, 255]]))# -> [[510, -510], [0, 0]]The uniform image returns DC 400 with zeros elsewhere, while the striped image returns DC 510 plus in the horizontal term. Signs alternate because the basis waves take values of only plus or minus 1.
Watch Out For
Throwing away phase
Magnitude-only edits feel safe because the spectrum looks like the image fingerprint, but phase carries edge positions. The symptom of phase damage is ghost contours and smeared structure after reconstruction despite a healthy-looking magnitude. Filter magnitudes and keep phase intact, or rebuild from complex values you actually transformed.
Masking before centering the spectrum
Forgetting the shift that puts DC in the middle means a central mask deletes the wrong frequencies. The symptom is a filter that blurs when it should sharpen, or stripes that survive a notch aimed at them. Center first, mask second, and un-center before the inverse transform.
The Quick Version
- The 2D Fourier transform rewrites images as sums of directional waves.
- Spectrum center means slow shading; the rim means edges and grain.
- The worked pair proves it: uniform DC is 400, while stripes give DC 510 plus a horizontal term.
- Phase holds positions, so never discard or randomize it.
- The FFT makes the round trip fast enough for routine use.