Optical Fourier Transforms (of letters)

In Optics f2f we frequently use the example of letters to illustrate Fraunhofer diffraction (Chapter 6), convolution (Chapter 10 and Appendix B), spatial filtering (Chapter 10) and the properties of Fourier transforms in general (Chapters 6, 10 and Appendix B). Below, we share a python code, based on eqns (6.35) and (9.9) in Optics f2f, that calculates the intensity patterns associated with the optical Fourier transforms of letters.

The code works by printing a letter as an image, e.g. an E

letter_e

then digitising this image as an array, calculating the Fourier transform, and finally plotting the modulus squared as a colormap.

letter_e_ft

The code (last updated 2019-02-14 [1]) evaluates eqns (6.35) and (9.9) in Optics f2f for cases where the input aperture function has the shape of a letter.

from numpy import frombuffer, uint8, mean, shape, zeros, log, flipud, meshgrid
from numpy.fft import fft2, fftshift, ifftshift
from matplotlib import figure, cm
from matplotlib.pyplot import close, show, figure, pcolormesh
 
close("all")
fig = figure(1,facecolor='white')
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8]) #add axis for letter
ax.axison = False
ax.text(-0.5,-1.0, 'Z', fontsize=460,family='sans-serif') #print letter
ax.set_xlim(-1.0,1.0)
ax.set_ylim(-1.0,1.0)
 
fig.canvas.draw() #extract data from figure
data = frombuffer(fig.canvas.tostring_rgb(), dtype=uint8)
data = data.reshape(fig.canvas.get_width_height()[::-1] + (3,))
bw=mean(data,-1)/255.0
 
bw-=1.0 #invert
[xpix, ypix]=shape(bw)
mul=4 # add zeros to increase resolution
num_x=mul*xpix
num_y=mul*ypix
 
H=zeros((num_x,num_y))
H[int((num_x-xpix)/2):int((num_x+xpix)/2),int((num_y-ypix)/2):int((num_y+ypix)/2)]+=bw
 
F=flipud(fftshift(fft2(H))) #perform Fourier transform and centre
Fr=F.real
Fi=F.imag
F2=Fr*Fr+Fi*Fi #calculate modulus squared
Fs=F2[int((num_x-xpix/2)/2):int((num_x+xpix/2)/2),int((num_y-ypix/2)/2):int((num_y+ypix/2)/2)]
 
fig = figure(2,facecolor='white')
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.axison = False
p=ax.pcolormesh(log(Fs),cmap=cm.afmhot) # plot log(intensity) pattern
p.set_clim(12,20) #choose limits to highlight desired region
show()

[1] Note, code works using python 2 and 3. Cut and paste text into jupyter notebook. Last tested using jupyter with python 3.7.1 numpy 1.15.4 and matplotlib 3.0.2 .

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s