Image Processing with Python — Application of Fourier Transformation

How to make use of the Fourier Transformation to remove image elements

Tonichi Edeza
Towards Data Science

--

Fourier Transformations (Image by Author)

One of the more advanced topics in image processing has to do with the concept of Fourier Transformation. Put very briefly, some images contain systematic noise that users may want to remove. If such noise is regular enough, employing Fourier Transformation adjustments may aid in image processing. In this article we shall see exactly how to do this.

Let us begin.

As always, start by importing the required Python libraries.

import numpy as np
import matplotlib.pyplot as plt
from skimage.io import imread, imshow
from skimage.color import rgb2hsv, rgb2gray, rgb2yuv
from skimage import color, exposure, transform
from skimage.exposure import equalize_hist

First let us load the image we will use for this article.

dark_image = imread('against_the_light.png')
Image with Dark Horizontal Lines

The image we will be using is the one above. It as image of a street taken when the sun was facing directly at the camera. For this simple exercise we shall try to find a way to eliminate (or least drastically reduce) the powerlines in the back.

As a start, let us convert our image into greyscale.

dark_image_grey = rgb2gray(dark_image)
plt.figure(num=None, figsize=(8, 6), dpi=80)
plt.imshow(dark_image_grey, cmap='gray');
Greyscale Image

Excellent, from here we can now easily use the fft function found in Skimage.

dark_image_grey_fourier = np.fft.fftshift(np.fft.fft2(dark_image_grey))
plt.figure(num=None, figsize=(8, 6), dpi=80)
plt.imshow(np.log(abs(dark_image_grey_fourier)), cmap='gray');
Fourier Transformation of the Image

In the image we can see two very clear distortions. The white vertical and horizontal lines refer to the sharp horizontal and vertical elements of the image. Let us see what happens if we mask one of them.

def fourier_masker_ver(image, i):
f_size = 15
dark_image_grey_fourier =
np.fft.fftshift(np.fft.fft2(rgb2gray(image)))
dark_image_grey_fourier[:225, 235:240] = i
dark_image_grey_fourier[-225:,235:240] = i
fig, ax = plt.subplots(1,3,figsize=(15,15))
ax[0].imshow(np.log(abs(dark_image_grey_fourier)), cmap='gray')
ax[0].set_title('Masked Fourier', fontsize = f_size)
ax[1].imshow(rgb2gray(image), cmap = 'gray')
ax[1].set_title('Greyscale Image', fontsize = f_size);
ax[2].imshow(abs(np.fft.ifft2(dark_image_grey_fourier)),
cmap='gray')
ax[2].set_title('Transformed Greyscale Image',
fontsize = f_size);

fourier_masker(dark_image, 1)
Fourier Transform Vertical Masked Image

We can see that the horizontal power cables have significantly reduced in size. As an interesting experiment, let us see what would happen if we masked the horizontal line instead.

def fourier_masker_hor(image, i):
f_size = 15
dark_image_grey_fourier =
np.fft.fftshift(np.fft.fft2(rgb2gray(image)))
dark_image_grey_fourier[235:240, :230] = i
dark_image_grey_fourier[235:240,-230:] = i
fig, ax = plt.subplots(1,3,figsize=(15,15))
ax[0].imshow(np.log(abs(dark_image_grey_fourier)), cmap='gray')
ax[0].set_title('Masked Fourier', fontsize = f_size)
ax[1].imshow(rgb2gray(image), cmap = 'gray')
ax[1].set_title('Greyscale Image', fontsize = f_size);
ax[2].imshow(abs(np.fft.ifft2(dark_image_grey_fourier)),
cmap='gray')
ax[2].set_title('Transformed Greyscale Image',
fontsize = f_size);
fourier_masker_hor(dark_image, 1)
Fourier Transform Horizontal Masked Image

We can see that all the vertical aspects of the image have been smudged. This is highly noticeable in the electric poles. Though helpful in some settings, this is clearly not helpful in this here.

Though we will stick to masking the Fourier Transformation’s vertical line (again remember that when converted back into the original image this smudges the horizontal lines), let us experiment with different degrees of masking.

def fourier_iterator(image, value_list):
for i in value_list:
fourier_masker_ver(image, i)

fourier_iterator(dark_image, [0.001, 1, 100])
Iterations of Masking Values

We can see that decreasing the value has almost no effect on the original image, however increasing the value seems to darken original image. As there is practically no difference between the smaller value and 1, let us stick to 1 for simplicity.

Finally, let us enact Fourier Transformation adjustment while retaining the colors of the original image.

def fourier_transform_rgb(image):
f_size = 25
transformed_channels = []
for i in range(3):
rgb_fft = np.fft.fftshift(np.fft.fft2((image[:, :, i])))
rgb_fft[:225, 235:237] = 1
rgb_fft[-225:,235:237] = 1
transformed_channels.append(abs(np.fft.ifft2(rgb_fft)))

final_image = np.dstack([transformed_channels[0].astype(int),
transformed_channels[1].astype(int),
transformed_channels[2].astype(int)])

fig, ax = plt.subplots(1, 2, figsize=(17,12))
ax[0].imshow(image)
ax[0].set_title('Original Image', fontsize = f_size)
ax[0].set_axis_off()

ax[1].imshow(final_image)
ax[1].set_title('Transformed Image', fontsize = f_size)
ax[1].set_axis_off()

fig.tight_layout()
Fourier Transformed Colored Image

We can see that the horizontal power cables have been greatly reduced while the rest of the image remains mostly intact. This showcases how we can make subtle changes to an image via Fourier Transformation.

In Summary

Fourier Transformation is a powerful tool that can be quite useful for data scientists working with images. In future articles we shall go over how to apply the technique in much more impactful ways. For now, I hope you were able to get a basic grasp of the subject.

--

--