Fourier Transform of Images

[Activity 5]

Hello again! Today we’ll be using the Fourier Transform on some simple black and white images to get a little more understanding of how Fourier Transform works and how it is useful in image processing and image analysis. It’s been a hassle to keep switching from a Mac partition to a Windows partition, so I instead opted to use Matlab, which has Image Processing support for Mac. However, most of the code and functions used are similar to that in Scilab.

Fourier Theory states that any signal can be represented as a sum of sinusoid signals. For images, this is the sinusoidal variations in the brightness of an image. By getting the Fourier Transform of an image, we are able to know three things: The spatial frequency (how the brightness modulates over space), the magnitude (positive or negative), and the phase. The magnitude corresponds to its contrast (difference between the lightest and darkest parts of the image), and the phase corresponds to how the sinusoidal signal is shifted relative to its origin.

For the first part of our activity, we’ll be doing 4 basic steps:

  1. Import our image as a grayscale array
  2. Apply the Fourier Transform to the grayscale array of the image
  3. Shift our result from the Fourier Transform
  4. Apply Fourier Transform again to the result (basically Inverse Fourier Transform
circle.001
Figure 1. A Circle
Figure 2. The letter A
Figure 2. The letter A

For Figures 1 and 2, there are six images shown.

  1. The original image
  2. The Fourier Transform of the image
  3. The shifted Fourier Transform of the image
  4. The inverse Fourier Transform of (2)
  5. The real part of (2)
  6. The imaginary part of (2)

If you’d like to see the code, here is the one I made for the Letter A:

I = imread(‘A.bmp’);
Igray = mat2gray(I);
FIgray = fft2(Igray);
imshow(mat2gray(abs(FIgray)));
imwrite(mat2gray(abs(FIgray)), ‘FTofA.png’)
FI2gray = fftshift(abs(FIgray));
imshow(mat2gray(FI2gray));
imwrite(mat2gray(FI2gray), ‘FTShiftofA.png’)
FTFTgray = abs(fft2(FIgray));
imshow(FTFTgray);
imwrite(FTFTgray, ‘FTFTofA.png’)
R = real(FIgray);
imwrite(R, ‘RealofA.png’)
Im = imag(FIgray);
imwrite(Im, ‘ImagofA.png’)

(2) shows the Fourier Transform of the image. A Fourier Transform of an image encodes a whole range of sinusoids from zero (no modulation, i.e. the average brightness of the whole image) up to the ‘Nyquist frequency’, the highest spatial frequency possible for the digital image, which is related to the resolution of the image (size of pixels). The center of the image is known as the ‘DC term’ or the zero frequency, and as spatial frequency increases as you go farther from the center. The height of the peak of the frequency corresponds to the magnitude or the contrast of that signal. When performing a Fourier Transform, the result is always a scan of the negative and positive frequencies. Mathematics can show that the negative and positive scans are always mirror-images of each other. Hence in (2) of Figure 1 and 2, the left and right sides are mirror images of each other.

When applying Fourier Transforms to an image, the quadrants of the Fourier Transform is different from the original image. If we follow the quadrant division in the Cartesian coordinates: I and IV are switched, and II and III are switched. Hence, we need to apply a shift to the Fourier Transform in order to see it in the correct order.

Also, to convince ourselves that we are actually getting frequencies in our Fourier Transform, remember that sinusoidal signals are can be composed of real and imaginary frequencies. Hence, in our Fourier Transform, we expect also real and imaginary frequencies to be part of the scanned frequencies. (5) and (6) show us that indeed, we are able to get the real and imaginary parts of the sinusoidal frequencies.

Figure 3. A Sinusoid along the x-direction
Figure 3. A Sinusoid along the x-direction
Figure 4. A Double slit
Figure 4. A Double slit
Figure 5. A Square
Figure 5. A Square
Figure 6. A Circle with a Gaussian gradient
Figure 6. A Circle with a Gaussian gradient

For Figures 3 to 6, there are six images shown.

  1. The original image
  2. The Fourier Transform of the image
  3. The shifted Fourier Transform of the image
  4. The inverse Fourier Transform of (2)

As we can see, each image has a unique Fourier Transform.

Fourier Transforms become more useful when we study convolution. Convolution is the result of the ‘mixing’ of two signals. If we let h to be the convolution and f,to be functions:

h = f * g

In real-life applications, h can be the convolution of a signal f entering a measuring device or instrument with a transfer function g. As we know, we are not able to make devices that are able to record a signal perfectly, hence we expect that the convolution will not be exactly the same as the original signal. In cameras, the transfer function of the camera is dependent on the size of the lens. For a smaller lens, less light reflected from the object can enter the camera. Hence, the size of the lens must be big enough such that the convolution is as close as possible to the original image.

We can simulate this by treating Figure 1 as our aperture, and then varying the radius of the circle to see its effect on the convolution.

Figure 7. The Convolution of the 'VIP' text and the Circular aperture
Figure 7. The Convolution of the ‘VIP’ text and the Circular aperture

The VIP image on the far left is the original image f. The convolution of that image with a circular aperture is shown on the succeeding images. Starting from the second to the left to the final image on the right, the radius of the circle is as follows:

  1. Radius = 0.1
  2. Radius = 0.3
  3. Radius = 0.5
  4. Radius = 0.9

This confirms our suspicions that a larger radius results in a better image after the convolution. Hence in the camera industry, companies would want to be able to reproduce an image like that in the final convolution while still having a relatively smaller lens.

The code for convolution is here:

cir5 = mat2gray(double(imread(‘Circle128x128.bmp’)));
cir3 = mat2gray(double(imread(‘circle.bmp’)));
vip = mat2gray(double(imread(‘VIP.bmp’)));
cirshift = fftshift(cir3);
Fvip = fft2(vip);
A = cirshift.*(Fvip);
IA = fft2(A);
im = mat2gray(abs(IA));
imshow(im)
imwrite(im,’vipconvolution_0.9r.png’)

Finally, correlation, which is very similar to convolution, is used when we want to find the degree of similarity of between two functions, in this case, the Fourier Transforms of two images. By doing so, we can find the points where the two functions match. This is useful if you want to find something in an image. For example. If we have some text on one image and a sample of one of the letters in another image (with the exact same font and font size), we can use correlation to find where that letter is found on our text image.

Figure 8. The correlation of the text and our reference letter.
Figure 8. The correlation of the text and our reference letter.

In the correlation image (far right), the bright points show where the letter A is in the text. You can also extend this for other images and even for coloured images.

We can also apply template matching, which is to have a synthetic image of an edge or a shape that we want to find on our image, using correlation:

Figure 9. Correlation of the VIP image with different edges.
Figure 9. Correlation of the VIP image with different edges.

Due to the size of our images (128×128), the size of the edge (only 3×3) that we want to match is too small to see easily, but we have from left to right: a horizontal edge, vertical edge, spot. The images on the bottom row show slight blurriness where the horizontal or vertical edge template does not match the original image. On the final image we don’t see any change because all the points of our original image match the point template.

The code for correlation is here:

rain = fft2(mat2gray(double(imread(‘THERAIN.bmp’))));
A = fft2(mat2gray(double(imread(‘Atherain.bmp’))));
Arr = A.*conj(rain);
IArr = mat2gray(fftshift(fft2(Arr)));
imshow(IArr)
imwrite(IArr, ‘TheRain&Acorrelation.png’)

vip = fft2(mat2gray(double(imread(‘VIP.bmp’))));
pat1 = fft2(mat2gray(double(imread(‘pattern1.bmp’))));
PA1 = pat1.*conj(vip);
IPA1 = mat2gray(fftshift(fft2(PA1)));
imwrite(IPA1, ‘VIP&Pat1correlation.png’)
pat2 = fft2(mat2gray(double(imread(‘pattern2.bmp’))));
PA2 = pat2.*conj(vip);
IPA2 = mat2gray(fftshift(fft2(PA2)));
imwrite(IPA2, ‘VIP&Pat2correlation.png’)
pat3 = fft2(mat2gray(double(imread(‘pattern3.bmp’))));
PA3 = pat3.*conj(vip);
IPA3 = mat2gray(fftshift(fft2(PA3)));
imwrite(IPA3, ‘VIP&Pat3correlation.png’)

If you’d like to read a bit more on Fourier Transforms, this link is very helpful.

 

Activity: 10/10

Leave a comment