二维傅里叶变换伪影——我做错了什么?

3

目前我正在尝试理解二维傅里叶变换。我想将一个图像进行傅里叶变换,然后返回仅包含幅度谱的结果,就像这个网站上的话题所示:

https://dsp.stackexchange.com/questions/16995/image-reconstructionphase-vs-magnitude

但是,使用Spyder IDE时,我的图像(使用上面链接中的相同图像)会出现一些奇怪的伪影,如下所示:

原始图像:

original image

幅度谱:

Magnitude spectrum

我使用的代码是Python中使用Numpy(np)、OpenCV和Matplotlib:

import numpy as np
import cv2
from matplotlib import pyplot as plt
from os import listdir
from os.path import isfile, join


image1 = cv2.imread("Images/test2.png", 0)
fourier = np.fft.fft2(image1)
magnitude = abs(fourier)
inverse = np.fft.ifftshift(np.fft.ifft2(magnitude))
plt.subplot(), plt.imshow(np.uint8(inverse), cmap='gray')
plt.title(''), plt.xticks([]), plt.yticks([])
plt.show()

我做错了什么?
更新:添加了导入

1
给定的代码无法运行,因为缺少导入、引用本地数据等。请更新代码,以便我们能够重现您的问题。 - Jonas Adler
抱歉!您好。我已更新了导入内容。它正在引用本地数据,但原始图像(图像链接)是我用来创建幅度谱的图像。 - Vindicare
那看起来像是由于大数值的包装而引起的瑕疵。为什么要转换为 uint8 - MB-F
@kazemakase 我这样做是因为傅里叶变换返回一个复数,为了将图像重构回来,我需要将其转换为原始格式(即uint8)。 - Vindicare
你有检查过inverse的值是否适合8字节整数吗?(我敢打赌它们不适合。)试着让自己的生活更轻松,转换为np.float64类型。同时考虑一下你是否真的想要丢弃虚部。 - MB-F
我也尝试过将其转换为np.float,但是结果返回的是一张黑色图像和一个白点,就像使用np.abs时一样。 - Vindicare
2个回答

3
您的图表中间出现了奇怪的东西,这是由于大数值被包裹(转换为uint8后取模)。如果不进行类型转换,您只会看到一个白点。通常情况下(针对自然图像),DFT在原点处具有非常高的幅度,在高频率上呈指数级递减。
最好的显示DFT的方法是对幅度应用对数变换:
inverse = np.fft.ifftshift(np.fft.ifft2(magnitude))
inverse = np.log(np.abs(inverse))
plt.subplot(), plt.imshow(inverse, cmap='gray')

3
您可以尝试将 np.uint8 更改为 np.abs。由于您希望在255以上进行截断而不是取模,因此应该像这样做:
inverse = np.fft.ifftshift(np.fft.ifft2(magnitude))
inv = np.abs(inverse)
inv[inv > 255] = 255
plt.subplot(), plt.imshow(inv, cmap='gray')

谢谢你的帮助,但是如果我改成np.abs,我只会得到一张黑色图像,中间有一个白点。我已经在使用rgbgray图像(cv2.imread(0)的第二个参数)。 - Vindicare
更正了我的答案。uint8不会截断超过255的值,而是作为模数。np.uint8(257)会得到1 - Aguy
它运行了!太棒了,非常感谢你的帮助。我没有想到这一点,但这很有道理,谢谢! - Vindicare

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接