Image Formation and Resolution

The previous lecture established that any field at a plane \(z=0\) can be decomposed into plane waves via its Fourier transform, and that free-space propagation multiplies each component by the transfer function \(H(\nu_x,\nu_y;z) = e^{ik_z z}\). Here we apply this framework to the two central problems of optical imaging: how a lens performs an exact Fourier transform (enabling controlled spatial filtering), and how the finite aperture of any real system limits resolution through the point spread function and optical transfer function.

The Lens as a Fourier Transformer

The Fraunhofer result requires propagation distances \(z \gg \pi a^2/\lambda\) that are often impractically large. A thin lens solves this problem elegantly: it performs an exact Fourier transform at the finite distance of its focal length \(f\), with no approximation beyond the thin-lens and paraxial assumptions.

Derivation. Place an object with transmission \(t(x',y')\) in the front focal plane (at \(z=-f\), i.e. a distance \(f\) in front of the lens). For unit-amplitude plane-wave illumination the field just behind the object is \(U(x',y',{-f}) = t(x',y')\). Propagating this field by Fresnel from \(z=-f\) to the lens at \(z=0\), multiplying by the lens phase factor \(e^{-ik(x^2+y^2)/2f}\), and propagating a second Fresnel step from \(z=0\) to the back focal plane at \(z=+f\), the two quadratic phase factors — one from the Fresnel propagation and one from the lens — cancel exactly. The result is:

\[U_\text{back}(x,y) = \frac{e^{i2kf}}{i\lambda f}\,\hat{t}\!\left(\nu_x = \frac{x}{\lambda f},\;\nu_y = \frac{y}{\lambda f}\right)\]

The intensity at the back focal plane is therefore:

\[I_\text{back}(x,y) \propto \left|\hat{t}\!\left(\frac{x}{\lambda f},\frac{y}{\lambda f}\right)\right|^2\]

The back focal plane of a lens is the Fourier plane of its front focal plane. The spatial scale in the Fourier plane is \(\lambda f\): a high focal-length lens stretches the Fourier pattern across a larger area, while a short focal-length lens compresses it.

Code
N = 512
x_obj = np.linspace(-1, 1, N)
y_obj = np.linspace(-1, 1, N)
X_obj, Y_obj = np.meshgrid(x_obj, y_obj)

# Double slit object
slit_hw = 0.04   # slit half-width
sep     = 0.30   # slit centre separation
obj = np.zeros((N, N))
obj[(np.abs(X_obj - sep/2) < slit_hw) & (np.abs(Y_obj) < 0.4)] = 1.0
obj[(np.abs(X_obj + sep/2) < slit_hw) & (np.abs(Y_obj) < 0.4)] = 1.0

# Fourier transform -> field at back focal plane (ignoring constant phase prefactor)
obj_ft = np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(obj)))
I_focal = np.abs(obj_ft)**2

fig = plt.figure(figsize=get_size(12, 10))
gs = gridspec.GridSpec(2, 2, figure=fig)
ax0 = fig.add_subplot(gs[0, 0])
ax1 = fig.add_subplot(gs[0, 1])
ax2 = fig.add_subplot(gs[1, :])

ax0.imshow(obj, cmap='gray', extent=[-1, 1, -1, 1], origin='lower')
ax0.set_title('(a) Object (double slit)')
ax0.set_xlabel('x')
ax0.set_ylabel('y')

vmax = np.percentile(I_focal, 99.8)
ax1.imshow(I_focal, cmap='inferno', origin='lower', vmax=vmax)
ax1.set_title('(b) Intensity at back focal plane')
ax1.set_xlabel(r'$\nu_x$ (pixels $\propto x/\lambda f$)')
ax1.set_ylabel(r'$\nu_y$ (pixels $\propto y/\lambda f$)')

mid = N // 2
ax2.plot(I_focal[mid, :] / I_focal[mid, :].max())
ax2.set_xlabel(r'pixel index ($\propto \nu_x$)')
ax2.set_ylabel('intensity (norm.)')
ax2.set_title('(c) Cross-section through Fourier plane')
ax2.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()
Figure 1— A thin lens performs a spatial Fourier transform. (a) Test object: a double slit. (b) Intensity at the back focal plane \(\propto|\hat{t}(\nu_x,\nu_y)|^2\), computed as the squared magnitude of the 2D FFT. The \(\cos^2\) interference fringes from the slit separation appear inside a sinc² envelope from the finite slit width. (c) Horizontal cross-section through the Fourier plane.

Spatial Filtering and the 4f System

The lens-FT result leads immediately to a practical optical processor: the 4f system. Two lenses, each of focal length \(f\), are placed coaxially with their focal planes coinciding at the midpoint. The object sits one focal length in front of lens 1; the image forms one focal length behind lens 2. The system spans a total length of \(4f\).

The shared focal plane between the two lenses is the Fourier plane. Because lens 1 performs the FT there, the field at the Fourier plane is \(\propto\hat{t}(\nu_x,\nu_y)\). Lens 2 then performs an inverse FT back to the image plane. In the absence of any modification:

\[U_\text{image}(x,y) \propto \mathcal{F}^{-1}\{\hat{t}(\nu_x,\nu_y)\} = t(-x,-y)\]

The system produces an inverted (but otherwise perfect) image of the object.

Spatial filtering is performed by inserting a mask \(H(\nu_x,\nu_y)\) in the Fourier plane. The output becomes:

\[U_\text{out}(x,y) \propto \mathcal{F}^{-1}\{H(\nu_x,\nu_y)\cdot\hat{t}(\nu_x,\nu_y)\} = h(x,y)*t(-x,-y)\]

where \(h = \mathcal{F}^{-1}\{H\}\) is the impulse response of the filter. Common filters include:

Filter \(H(\nu_x,\nu_y)\) Effect
Low-pass \(1\) if \(\nu_r < \nu_c\), else \(0\) Blurring, noise suppression
High-pass \(0\) if \(\nu_r < \nu_c\), else \(1\) Edge enhancement
Phase-contrast \(e^{i\pi/2}\) at \(\nu_r \approx 0\) Phase-object contrast (Zernike)
Dark-field \(0\) at \(\nu_r = 0\), else \(1\) Block direct beam, reveal scattering

The last two rows foreshadow the contrast techniques covered in the microscopy lectures.

Code
N = 512
x4 = np.linspace(-1, 1, N)
X4, Y4 = np.meshgrid(x4, x4)
R4 = np.sqrt(X4**2 + Y4**2)

# Object: disk with superimposed grating
disk = (R4 < 0.35).astype(float)
grating = 0.5 * np.cos(2*np.pi*20*X4)
obj4 = disk * (0.5 + grating)

# Fourier transform
ft4 = np.fft.fftshift(np.fft.fft2(obj4))
fx4 = np.fft.fftshift(np.fft.fftfreq(N))
FX4, FY4 = np.meshgrid(fx4, fx4)
FR4 = np.sqrt(FX4**2 + FY4**2)

# Filters
nu_c = 0.03
mask_lp = (FR4 < nu_c).astype(float)
mask_hp = (FR4 >= nu_c).astype(float)

# Filtered images via inverse FFT
img_lp = np.real(np.fft.ifft2(np.fft.ifftshift(ft4 * mask_lp)))
img_hp = np.real(np.fft.ifft2(np.fft.ifftshift(ft4 * mask_hp)))

fig, axes = plt.subplots(2, 2, figsize=get_size(12, 10))

axes[0, 0].imshow(obj4, cmap='gray', origin='lower', extent=[-1, 1, -1, 1],
                   interpolation='none')
axes[0, 0].set_title('(a) Object')
axes[0, 0].set_xlabel('x')

axes[0, 1].imshow(np.log(np.abs(ft4) + 1), cmap='viridis', origin='lower')
axes[0, 1].set_title('(b) Fourier plane')
axes[0, 1].set_xlabel(r'$\nu_x$ (pixels)')
theta_c = np.linspace(0, 2*np.pi, 300)
axes[0, 1].plot(N/2 + nu_c*N*np.cos(theta_c), N/2 + nu_c*N*np.sin(theta_c),
             'r--', lw=1, label=fr'$\nu_c={nu_c}$')

axes[1, 0].imshow(img_lp, cmap='gray', origin='lower', extent=[-1, 1, -1, 1])
axes[1, 0].set_title('(c) Low-pass filtered')
axes[1, 0].set_xlabel('x')

axes[1, 1].imshow(img_hp, cmap='gray', origin='lower', extent=[-1, 1, -1, 1])
axes[1, 1].set_title('(d) High-pass filtered')
axes[1, 1].set_xlabel('x')

plt.tight_layout()
plt.show()
Figure 2— 4f spatial filtering demonstration. (a) Test object: a disk with a superimposed high-frequency grating. (b) Fourier plane spectrum; the dashed circle marks the low-pass cutoff \(\nu_c\). (c) Low-pass filtered image: the grating is removed, leaving a smooth disk. (d) High-pass filtered image: only the edges and fine texture survive.

The low-pass filter transmits only \(\nu_r < \nu_c\), smoothing the image by removing the high-frequency grating. The high-pass filter does the opposite: it blocks the DC and low-frequency components, leaving only sharp edges and fine texture. The disk boundary becomes a bright ring because it is where the high spatial frequencies are concentrated. This edge-enhancement is the basis of darkfield microscopy; the phase-contrast variant — shifting only the DC component by \(\pi/2\) — is the Zernike technique developed in the microscopy lectures.

Point Spread Function, Optical Transfer Function, and Resolution

The 4f filtering framework provides the natural language for characterising the imaging performance of any optical system.

Point Spread Function

The point spread function (PSF) \(h(x,y)\) is the image formed by the system of a single point source located at the origin of the object plane. In the Fourier framework it is the inverse Fourier transform of the system’s transfer function \(H(\nu_x,\nu_y)\):

\[h(x,y) = \mathcal{F}^{-1}\{H(\nu_x,\nu_y)\}\]

For a diffraction-limited system with a circular pupil of radius \(R\) (numerical aperture \(\mathrm{NA} = n\sin\theta_\mathrm{max}\)), the transfer function is a disk of radius \(\nu_\mathrm{max} = \mathrm{NA}/\lambda\) and the PSF is the Airy pattern:

\[h(r) \propto \left[\frac{2J_1(\pi D r/\lambda f)}{\pi D r/\lambda f}\right]^2\]

where \(D = 2R\) is the pupil diameter, \(f\) is the focal length, and \(r = \sqrt{x^2+y^2}\). The first zero of the Airy pattern falls at \(r_\mathrm{Airy} = 1.22\,\lambda f/D\), which is the Rayleigh resolution criterion: two point sources are just resolved when the peak of one coincides with the first zero of the other, giving a minimum resolvable distance

\[\delta r_\mathrm{Rayleigh} = \frac{0.61\,\lambda}{\mathrm{NA}}\]

The Abbe diffraction limit arrives at the same scale from a different argument — the finest grating whose first diffraction order still enters the objective has period \(d_\mathrm{min} = \lambda/2\,\mathrm{NA}\) — giving

\[\delta r_\mathrm{Abbe} = \frac{\lambda}{2\,\mathrm{NA}}\]

The two criteria agree to within a factor of \(\approx 1.2\) and both establish that no standard far-field optical system can resolve features finer than roughly \(\lambda / (2\,\mathrm{NA})\).

Image Formation as Convolution

Because the PSF is the impulse response of the imaging system, any linear, shift-invariant system maps an extended object \(f(x,y)\) to an image \(g(x,y)\) by convolution:

\[g(x,y) = h(x,y) * f(x,y) = \iint h(x-x',\, y-y')\,f(x',y')\,dx'\,dy'\]

The object is treated as a superposition of point sources; each contributes a shifted, weighted copy of the PSF, and the total image is their sum.

By the convolution theorem, the same operation is a pointwise product in the frequency domain:

\[\hat{G}(\nu_x,\nu_y) = H(\nu_x,\nu_y)\cdot\hat{F}(\nu_x,\nu_y)\]

The function \(H(\nu_x,\nu_y)\) here is the optical transfer function (OTF). Its magnitude \(|H|\) is the modulation transfer function (MTF): it equals 1 at low frequencies, rolls off, and reaches zero at the diffraction cut-off \(\nu_\mathrm{max} = D/(\lambda f)\). The system therefore acts as a low-pass filter – spatial frequencies beyond \(\nu_\mathrm{max}\) are completely suppressed and the corresponding fine detail is lost from the image.

Figure 3 makes this concrete by tracing each step in both domains side by side. The left column shows the spatial domain directly: object \(f\), PSF \(h\), and image \(g = f * h\). The right column shows the same steps in the frequency domain: spectrum \(|\hat{F}|\), MTF \(|H|\), and their pointwise product \(|\hat{F}| \cdot |H|\). The inverse transform of that product recovers the image. The key is panel (f): the sinc-like object spectrum is truncated wherever the MTF reaches zero (dotted lines at \(\pm\nu_\mathrm{max}\)). The spatial consequence of this truncation is visible in panel (e) – the sharp edges of the rectangular object are rounded in the image because the high-frequency components that encode those edges have been removed.

Code
N   = 2048
L   = 20.0
x   = np.linspace(-L/2, L/2, N)
dx  = x[1] - x[0]

# Object: centred rectangular bar of width W = 4 λf/D
W   = 4.0
obj = (np.abs(x) < W/2).astype(float)

# PSF: 1-D Airy profile, (2J₁(πx)/(πx))², first zero at x = 1.22
u   = np.pi * x
psf = (2 * j1(u) / u)**2
psf /= psf.sum() * dx             # area-normalise

# FFTs
nu     = np.fft.fftshift(np.fft.fftfreq(N, dx))
OBJ_FT = np.fft.fft(np.fft.ifftshift(obj))
PSF_FT = np.fft.fft(np.fft.ifftshift(psf)) * dx   # H(0) → 1
IMG_FT = OBJ_FT * PSF_FT

img = np.fft.fftshift(np.fft.ifft(IMG_FT)).real
img /= img.max()

A_obj = np.abs(np.fft.fftshift(OBJ_FT)) * dx;  A_obj /= A_obj.max()
A_psf = np.abs(np.fft.fftshift(PSF_FT));        A_psf /= A_psf.max()
A_img = A_obj * A_psf                            # product; max ≈ 1 at ν = 0

fig, axes = plt.subplots(3, 2, figsize=get_size(11, 14))
xl_sp = (-7, 7)
xl_fr = (-2, 2)

# (a) Object
ax = axes[0, 0]
ax.plot(x, obj, 'C0', lw=1.5)
ax.set_xlim(*xl_sp); ax.set_ylim(-0.15, 1.35)
ax.set_title(r'(a) Object $f(x)$')
ax.set_xlabel(r'$x\;[\lambda f/D]$'); ax.set_ylabel('amplitude')

# (b) Object spectrum
ax = axes[0, 1]
ax.plot(nu, A_obj, 'C0', lw=1.5)
ax.axvline(-1, color='k', ls=':', lw=0.7); ax.axvline(+1, color='k', ls=':', lw=0.7)
ax.set_xlim(*xl_fr); ax.set_ylim(-0.05, 1.15)
ax.set_title(r'(b) Object spectrum $|\hat{F}(\nu)|$')
ax.set_xlabel(r'$\nu\;[D/\lambda f]$'); ax.set_ylabel('norm. amplitude')

# (c) PSF
ax = axes[1, 0]
ax.plot(x, psf / psf.max(), 'C1', lw=1.5)
ax.axvline(-1.22, color='gray', ls=':', lw=0.7)
ax.axvline(+1.22, color='gray', ls=':', lw=0.7)
ax.text(1.35, 0.12, r'$1.22$', fontsize=7, color='gray')
ax.set_xlim(*xl_sp); ax.set_ylim(-0.15, 1.35)
ax.set_title(r'(c) PSF $h(x)$')
ax.set_xlabel(r'$x\;[\lambda f/D]$'); ax.set_ylabel('amplitude')

# (d) MTF
ax = axes[1, 1]
ax.plot(nu, A_psf, 'C1', lw=1.5)
ax.fill_between(nu, 0, A_psf, where=np.abs(nu) <= 1, alpha=0.15, color='C1')
ax.axvline(-1, color='k', ls=':', lw=0.7); ax.axvline(+1, color='k', ls=':', lw=0.7)
ax.text(1.04, 0.52, r'$\nu_\mathrm{max}$', fontsize=7)
ax.set_xlim(*xl_fr); ax.set_ylim(-0.05, 1.15)
ax.set_title(r'(d) MTF $|H(\nu)|$ = FT of PSF')
ax.set_xlabel(r'$\nu\;[D/\lambda f]$'); ax.set_ylabel('norm. amplitude')

# (e) Image
ax = axes[2, 1]
ax.plot(x, obj, 'C0', lw=1.0, ls='--', alpha=0.35, label='object $f$')
ax.plot(x, img, 'C2', lw=1.5, label=r'image $g = \mathcal{F}^{-1}\{\hat{F}H\}$')
ax.set_xlim(*xl_sp); ax.set_ylim(-0.15, 1.35)
ax.set_title(r'(f) Image $g(x)$ = IFFT of (e)')
ax.set_xlabel(r'$x\;[\lambda f/D]$'); ax.set_ylabel('amplitude')
#ax.legend(fontsize=7, loc='upper right')

# (f) Product
ax = axes[2, 0]
ax.plot(nu, A_obj, 'C0', lw=1.0, alpha=0.35, label=r'$|\hat{F}(\nu)|$')
ax.plot(nu, A_psf, 'C1', lw=1.0, alpha=0.35, label=r'$|H(\nu)|$')
ax.plot(nu, A_img, 'C2', lw=1.5,              label=r'$|\hat{F}|\cdot|H|$')
ax.axvline(-1, color='k', ls=':', lw=0.7); ax.axvline(+1, color='k', ls=':', lw=0.7)
ax.set_xlim(*xl_fr); ax.set_ylim(-0.05, 1.15)
ax.set_title(r'(e) Product $|\hat{F}(\nu)|\cdot|H(\nu)|$')
ax.set_xlabel(r'$\nu\;[D/\lambda f]$'); ax.set_ylabel('norm. amplitude')
#ax.legend(fontsize=7)

for ax in axes.flat:
    ax.grid(True, alpha=0.2)

plt.tight_layout()
plt.show()
Figure 3— Image formation as convolution, shown in two equivalent representations. Left column (spatial domain): (a) rectangular-bar object \(f(x)\), (c) PSF \(h(x)\) (1-D Airy profile, first zero at \(1.22\,\lambda f/D\)), (e) image \(g(x) = \mathcal{F}^{-1}\{\hat{F}\cdot H\}\) with the original object shown dashed for comparison – the sharp edges are rounded because their high-frequency content is removed. Right column (frequency domain): (b) object spectrum \(|\hat{F}(\nu)|\) (sinc-like, zeros every \(0.25\,D/\lambda f\)), (d) MTF \(|H(\nu)|\) with shaded passband ending at the diffraction cut-off \(\nu_\mathrm{max} = D/(\lambda f)\) (dotted), (f) the product \(|\hat{F}|\cdot|H|\) = image spectrum; components beyond \(\nu_\mathrm{max}\) are suppressed to zero.

Coherent vs. Incoherent Imaging

The convolution rule above comes in two distinct forms depending on whether the illumination is coherent (laser, single spatial mode) or incoherent (LED, thermal source, fluorescence).

Coherent imaging — the complex amplitude is the relevant quantity. The image amplitude is the convolution of the object amplitude with the coherent PSF:

\[U_\mathrm{image}(x,y) = h(x,y) * U_\mathrm{object}(x,y)\]

The system’s transfer function acts directly on complex amplitudes, and the OTF is the pupil function itself (top-hat up to \(\nu_\mathrm{max}\), zero beyond). Phase of the object is preserved and contributes to image contrast.

Incoherent imaging — intensities add (no phase relationship between source points). The image intensity is the convolution of the object intensity with the incoherent PSF:

\[I_\mathrm{image}(x,y) = |h(x,y)|^2 * I_\mathrm{object}(x,y)\]

The incoherent OTF is the autocorrelation of the pupil function, which extends to twice the coherent cut-off (\(2\nu_\mathrm{max}\)) but with reduced contrast at high frequencies. Despite the wider bandwidth, incoherent systems do not always produce sharper images than coherent systems — the MTF rolloff and the absence of phase contrast mean the two regimes are suited to different tasks.

Property Coherent Incoherent
Superposition Amplitudes Intensities
PSF \(h(x,y)\) (complex) \(|h(x,y)|^2\) (real, positive)
OTF Pupil function Autocorrelation of pupil
Bandwidth \(\nu_\mathrm{max}\) \(2\nu_\mathrm{max}\)
Phase sensitivity Yes No
Typical source Laser, SLM LED, fluorescence, white light

Fluorescence microscopy is inherently incoherent (each fluorophore emits independently), which is one reason it achieves clean, artefact-free images. Coherent systems such as holographic or interferometric microscopes recover phase and thus reveal refractive-index variations invisible to incoherent methods. The superresolution techniques discussed in later lectures (STED, STORM, SIM) each exploit specific aspects of this coherent/incoherent distinction.