🌀 2D Image FFT
Compute the 2D Fourier transform of an image and filter it in the frequency domain. See the log magnitude spectrum, apply low/high/band-pass or notch filters and watch the reconstruction.
About this simulation
This runs a genuine radix-2 Cooley-Tukey FFT in the browser — first along every row, then every column — turning a small test image into its 2D frequency spectrum. The dominant frequency and energy retained after filtering are computed live from that spectrum, and masking part of it before the inverse transform demonstrates the convolution theorem: multiplying in frequency space is equivalent to convolving in the spatial domain.
🔬 What it shows
Three linked views: the spatial test pattern, its log-magnitude frequency spectrum after fftshift (so the zero-frequency DC term sits at the centre), and the reconstruction after your chosen filter mask has zeroed part of that spectrum and been inverse-transformed back into an image.
🎮 How to use
Choose a Source pattern (stripes, circle, checkerboard, an "F" glyph or random noise) and a Frequency filter — Low-pass keeps only the centre and blurs, High-pass removes the centre and leaves edges, Band-pass keeps a ring, and Notch deletes the dominant spike to remove periodic stripes. Filter radius and Band width control the mask size, Show phase swaps to the phase spectrum, and Image size switches between 64×64 and a slower but sharper 128×128 transform.
💡 Did you know?
A direct 2D discrete Fourier transform costs O(N⁴) operations for an N×N image, but splitting it into N one-dimensional FFTs along rows and then columns — exactly what this simulation does — reduces that to O(N² log N), the same trick that makes JPEG-style compression and MRI reconstruction fast enough for everyday use.
Frequently asked questions
Why is the spectrum centred instead of having its bright spot in the corner?
The raw FFT output places the zero-frequency (DC) term at index [0,0], with frequency content wrapping around the edges of the array. The simulation applies an fftshift before drawing, swapping quadrants so the DC term sits in the middle and frequency increases outward in every direction, matching how spectra are conventionally displayed.
What's the difference between Low-pass, High-pass and Notch filtering?
Low-pass keeps frequencies within a chosen radius of the centre and zeroes the rest, blurring the image by discarding fine detail. High-pass does the opposite, keeping only the outer high-frequency ring and highlighting edges. Notch instead removes a thin ring around the image's single strongest frequency spike, ideal for erasing repeating stripe patterns without blurring anything else.
Why does Energy retained drop when I shrink the filter radius?
Energy retained is the fraction of the spectrum's total squared magnitude that survives inside your filter mask. A small Low-pass radius keeps only the DC term and a few low frequencies, discarding most of the spectrum's energy — exactly why aggressive low-pass filtering produces such a heavily blurred reconstruction.
What does the phase spectrum actually show?
Toggling Show phase replaces each pixel's magnitude with the angle of its complex FFT coefficient, remapped to grey levels. Phase encodes where each frequency's pattern sits in the image rather than how strong it is — swapping only the phase between two images is enough to make the result look structurally like the phase donor, not the magnitude donor.
Why does the stripes pattern give a spectrum with just a few bright dots?
A pure sinusoidal stripe pattern is, by definition, built from a single spatial frequency, so its FFT is almost entirely zero except for a symmetric pair of bright spikes at plus and minus that frequency, plus the DC term at the centre. Natural images produce far more spread-out spectra because they mix many frequencies and orientations at once.
Frequently Asked Questions
What does the centre of a 2D FFT image represent?
The centre (after standard FFT shift) represents the DC or zero-frequency component — the average brightness of the entire image. Bright regions near the centre correspond to slowly varying (low-frequency) content like smooth backgrounds, while bright regions at the edges correspond to rapid variations like fine textures and sharp edges.
Why does the FFT of a natural image typically show a bright cross pattern?
Many photographs contain strong horizontal and vertical edges (door frames, horizons, text lines) that produce high-energy components along the horizontal and vertical frequency axes. Additionally, the FFT treats the image as a periodic tile, and discontinuities at the borders of the image create artificial high-frequency components along the axes.
How is filtering performed in the frequency domain?
Multiply the FFT of the image by a filter mask (ones in the pass-band, zeros in the stop-band, or a smooth transition), then apply the inverse FFT to return to the spatial domain. This is computationally equivalent to convolution in the spatial domain but much faster for large kernels via the convolution theorem.
What is the difference between FFT magnitude and phase?
The magnitude spectrum tells you which spatial frequencies are present and with what strength. The phase spectrum encodes where those frequency components are located in the image. Swapping the magnitude of one image with another's while keeping the phase produces an image that looks like the image whose phase was used, demonstrating that phase carries most of the structural information.
How does JPEG compression use frequency analysis?
JPEG divides the image into 8×8 pixel blocks and applies the discrete cosine transform (a relative of the FFT) to each. The resulting coefficients are quantised — coarser quantisation for high-frequency coefficients that the human eye is less sensitive to — and entropy-coded. Decompression reverses the process, recovering an approximation of the original image.
See an image, its 2D Fourier magnitude spectrum, and the result of frequency-domain filtering. A real radix-2 FFT runs on rows then columns; low-pass blurs, high-pass keeps edges, and a notch removes periodic stripes.
3D · Three.js / WebGL renderer · 60 FPS target · runs fully client-side, no install