Reputation: 31
I'm trying to design a Gaussian notch filter in Python to remove periodic noise.I tried implementing the following formula:
And here is the code:
import numpy as np
def gaussian_bandpass_filter(image):
image_array = np.array(image)
#Fourier Transform
fourier_transform = np.fft.fftshift(np.fft.fft2(image_array))
#Size of Image
m = np.shape(fourier_transform)[0]
n = np.shape(fourier_transform)[1]
u = np.arange(m)
v = np.arange(n)
# Find the center
u0 = int(m/2)
v0 = int(n/2)
# Bandwidth
D0 = 10
gaussian_filter = np.zeros(np.shape(fourier_transform))
for x in u:
for y in v:
D1 = math.sqrt((x-m/2-u0)**2 + (y-n/2-v0)**2)
D2 = math.sqrt((x-m/2+u0)**2 + (y-n/2+v0)**2)
gaussian_filter[x][y] = 1 - math.exp(-0.5 * D1*D2/(D0**2))
#Apply the filter
fourier_transform = fourier_transform + gaussian_filter
image_array = np.fft.ifft2(np.fft.ifftshift(fourier_transform))
return image_array
this function is supposed to apply the Gaussian notch filter to an image and return the filtered image but it doesn't seem to work. I don't know where I went wrong with this (maybe I didn't understand the formula correctly?) so if anyone could help me I would really appreciate it.
Edit:
As an example, here is a noisy image. Using the existing gaussian_filter function in scipy.ndimage library, I get this, which is acceptable. But my function returns this. (I'm using PIL.Image.fromarray function to convert array to image)
Upvotes: 3
Views: 1961
Reputation: 23129
Note that frequency response of a Gaussian Band-Reject Filter (notch) function is defined as:
where D0 is the cutoff frequency and W is the bandwidth of the filter. Implementing the same with the function gaussian_bandstop_filter()
(it seems there is some issue with the frequency response formula you used) and using vectorization instead of loop for faster performance,
from skimage.io import imread
import numpy as np
import matplotlib.pylab as plt
def gaussian_bandstop_filter(image):
#Fourier Transform
image_freq = np.fft.fftshift(np.fft.fft2(image))
#Size of Image
m, n = np.shape(image_freq)
# Find the center
u0, v0 = int(n/2), int(m/2)
u, v = np.meshgrid(range(n), range(m))
D0, W = 4, 10 # cutoff and bandwidth for the BRF
D = np.sqrt((u-u0)**2+(v-v0)**2)
gaussian_filter = np.exp(-((D**2-D0**2)/(D*W))**2)
#Apply the filter
fourier_transform = image_freq * gaussian_filter
rec_image = np.fft.ifft2(np.fft.ifftshift(fourier_transform))
return rec_image, image_freq, gaussian_filter
def plot_spectrum(F, ax, method=None, cmap='coolwarm'):
F_disp = (20*np.log10(0.01 + np.abs(F))).astype(int) if method == 'log' else np.minimum(np.abs(F).astype(int)+100, 255)
ax.imshow(F_disp, cmap=cmap, aspect='auto')
im = imread('images/USc6e.png', as_gray=True)
im = im / im.max() # normalize
im_rec, F, G = gaussian_bandstop_filter(im)
im_rec = im_rec.real
# plot images
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(12,10))
axes = axes.ravel()
plt.gray()
axes[0].imshow(im), axes[0].axis('off')
axes[0].set_title('image with periodic noise', size=15)
plot_spectrum(F.real, axes[1]), axes[1].set_title('noisy image spectrum', size=15)
axes[2].imshow(im_rec/im_rec.max()), axes[2].axis('off')
axes[2].set_title('image with band-reject filter', size=15)
axes[3].imshow(G), axes[3].set_title('band reject filter spectrum', size=15)
plt.tight_layout()
plt.show()
The next figure shows the result obtained, along with the frequency spectrum of the noisy image and the BRF:
You may need to fine-tune the parameters D0 and W (see the frequency spectrum of the noisy image).
Upvotes: 0