2-D Fourier Transform Example — Gaussian Blob Image¶
This example creates a 128×128 test image containing three Gaussian blobs
at different positions and amplitudes, computes its 2-D FFT using
transforms.fft_2d_forward(), shifts the spectrum to centre DC with
numpy.fft.fftshift(), and visualises the log-magnitude spectrum.
Example Code¶
"""IMSL 2D Fourier Transform example: FFT of a 2D Gaussian blob image.
Creates a 2-D test image with three Gaussian blobs and computes its 2-D FFT
using :func:`transforms.fft_2d_forward`, then displays the log-magnitude
spectrum shifted to the DC-centre.
Outputs:
- SVG plot saved to test_output/example_imsl_2d_fft.svg
"""
from __future__ import annotations
from pathlib import Path
from typing import Dict
import matplotlib.pyplot as plt
import numpy as np
from transforms import fft_2d_forward
def _gaussian_blob(
grid_x: np.ndarray,
grid_y: np.ndarray,
cx: float,
cy: float,
sigma: float,
amplitude: float = 1.0,
) -> np.ndarray:
"""Generate a 2-D Gaussian blob on a coordinate grid.
Args:
grid_x (np.ndarray): 2-D array of x-coordinates (shape *(M, N)*).
grid_y (np.ndarray): 2-D array of y-coordinates (shape *(M, N)*).
cx (float): x-coordinate of the blob centre.
cy (float): y-coordinate of the blob centre.
sigma (float): Standard deviation (width) of the Gaussian in the same
units as *grid_x* / *grid_y*.
amplitude (float): Peak amplitude of the blob. Defaults to 1.0.
Returns:
np.ndarray: 2-D array of shape *(M, N)* with Gaussian values.
"""
return amplitude * np.exp(-((grid_x - cx) ** 2 + (grid_y - cy) ** 2) / (2 * sigma ** 2))
def run_demo_imsl_2d_fft() -> Dict[str, object]:
"""Run IMSL 2-D FFT example: spectrum of a multi-blob Gaussian image.
Constructs a 128×128 image consisting of three Gaussian blobs at different
positions and computes its 2-D FFT using :func:`transforms.fft_2d_forward`.
The log-magnitude spectrum is shifted to centre DC using
:func:`numpy.fft.fftshift`.
Args:
None
Returns:
Dict[str, object]: Result dict with keys ``image_shape`` (tuple),
``spectrum_peak`` (float), and ``plot_path`` (str).
"""
M, N = 128, 128
x = np.linspace(-1.0, 1.0, N)
y = np.linspace(-1.0, 1.0, M)
grid_x, grid_y = np.meshgrid(x, y)
image = (
_gaussian_blob(grid_x, grid_y, cx=0.0, cy=0.0, sigma=0.15, amplitude=1.0)
+ _gaussian_blob(grid_x, grid_y, cx=0.4, cy=0.3, sigma=0.08, amplitude=0.7)
+ _gaussian_blob(grid_x, grid_y, cx=-0.35, cy=-0.25, sigma=0.10, amplitude=0.5)
)
spectrum_2d = fft_2d_forward(image.astype(complex))
spectrum_shifted = np.fft.fftshift(spectrum_2d)
log_magnitude = np.log1p(np.abs(spectrum_shifted))
spectrum_peak = float(np.max(log_magnitude))
print("\nIMSL 2-D FFT Example")
print(f" Image shape : {image.shape}")
print(f" Spectrum peak (log-magnitude): {spectrum_peak:.4f}")
output_dir = Path("test_output")
output_dir.mkdir(parents=True, exist_ok=True)
plot_path = output_dir / "example_imsl_2d_fft.svg"
fig, axes = plt.subplots(1, 2, figsize=(11, 5))
im0 = axes[0].imshow(image, cmap="viridis", origin="lower", extent=[-1, 1, -1, 1])
fig.colorbar(im0, ax=axes[0], label="Amplitude")
axes[0].set_title("Original Image (Gaussian Blobs)")
axes[0].set_xlabel("x")
axes[0].set_ylabel("y")
im1 = axes[1].imshow(log_magnitude, cmap="inferno", origin="lower")
fig.colorbar(im1, ax=axes[1], label="log(1 + |F|)")
axes[1].set_title("2-D FFT Magnitude Spectrum (log scale, DC-centred)")
axes[1].set_xlabel("Frequency x")
axes[1].set_ylabel("Frequency y")
fig.tight_layout()
fig.savefig(plot_path, format="svg")
plt.close(fig)
return {
"image_shape": image.shape,
"spectrum_peak": spectrum_peak,
"plot_path": str(plot_path),
}
if __name__ == "__main__":
run_demo_imsl_2d_fft()
Plot Output¶
Left: original 128×128 image with three Gaussian blobs. Right: log-magnitude of the 2-D FFT spectrum, DC-centred, showing the spatial frequency content of the blobs.¶
Console Output¶
IMSL 2-D FFT Example
Image shape : (128, 128)
Spectrum peak (log-magnitude): 6.6985