Undo np.fft.fft2 to get the original image

孤街醉人 提交于 2021-02-05 06:25:06

问题


I've just started to learn about images frecuency domain.

I have this function:

def fourier_transform(img):
    f = np.fft.fft2(img)
    fshift = np.fft.fftshift(f)
    magnitude_spectrum = 20*np.log(np.abs(fshift))

    return magnitude_spectrum

And I want to implement this function:

def inverse_fourier_transform(magnitude_spectrum):

    return img

But I don't know how.

My idea is to use magnitude_spectrum to get the original img.

How can I do it?


回答1:


You are loosing phases here: np.abs(fshift).

np.abs takes only real part of your data. You could separate the amplitudes and phases by:

abs = fshift.real
ph = fshift.imag

In theory, you could work on abs and join them later together with phases and reverse FFT by np.fft.ifft2.

EDIT: You could try this approach:

import numpy as np
import matplotlib.pyplot as plt

# single chanel image
img = np.random.random((100, 100))
img = plt.imread(r'path/to/color/img.jpg')[:,:,0]

# should be only width and height
print(img.shape)

# do the 2D fourier transform
fft_img = np.fft.fft2(img)

# shift FFT to the center
fft_img_shift = np.fft.fftshift(fft_img)

# extract real and phases
real = fft_img_shift.real
phases = fft_img_shift.imag

# modify real part, put your modification here
real_mod = real/3

# create an empty complex array with the shape of the input image
fft_img_shift_mod = np.empty(real.shape, dtype=complex)

# insert real and phases to the new file
fft_img_shift_mod.real = real_mod
fft_img_shift_mod.imag = phases

# reverse shift
fft_img_mod = np.fft.ifftshift(fft_img_shift_mod)

# reverse the 2D fourier transform
img_mod = np.fft.ifft2(fft_img_mod)

# using np.abs gives the scalar value of the complex number
# with img_mod.real gives only real part. Not sure which is proper
img_mod = np.abs(img_mod)

# show differences
plt.subplot(121)
plt.imshow(img, cmap='gray')
plt.subplot(122)
plt.imshow(img_mod, cmap='gray')
plt.show()



回答2:


You cannot recover the exact original image without the phase information, so you cannot only use the magnitude of the fft2. To use the fft2 to recover the image, you just need to call numpy.fft.ifft2. See the code below:

import numpy as np
from numpy.fft import fft2, ifft2, fftshift, ifftshift

#do the 2D fourier transform
fft_img = fftshift(fft2(img))

# reverse the 2D fourier transform
freq_filt_img = ifft2(ifftshift(fft_img))

freq_filt_img = np.abs(freq_filt_img)
freq_filt_img = freq_filt_img.astype(np.uint8)

Note that calling fftshift and ifftshift is not necessary if you just want to recover the original image directly, but I added them in case there is some plotting to be done in the middle or some other operation that requires the centering of the zero frequency.

The result of calling numpy.abs() or freq_filt_img.real (assuming positive values for each pixel) to recover the image should be the same because the imaginary part of the ifft2 should be really small. Of course, the complexity of numpy.abs() is O(n) while freq_filt_img.real is O(1)



来源:https://stackoverflow.com/questions/59179262/undo-np-fft-fft2-to-get-the-original-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!