实现一个函数 F=dft2D(f), 其中 f 是一个灰度源图像,F 是其对应的二维快速傅里叶变换 (FFT)图像. 具体实现要求按照课上的介绍通过两轮一维傅里叶变换实现。也就是首先计算 源图像每一行的一维傅里叶变换,然后对于得到的结果计算其每一列的一维傅里叶变换。
def dft2D(f):
h,w = f.shape
# 设置一个矩阵用来装变换后的矩阵, 从空间域到频率域的变换是傅里叶变换,而从频率域到空间域是傅里叶的反变换
F = np.zeros(f.shape, dtype=complex)
# 每行每列都进行快速傅里叶变换
for i in range(h):
F[i,:] = np.fft.fft(f[i,:])
for j in range(w):
F[:,j] = np.fft.fft(F[:,j])
return F
与库函数进行互相验证(需要电脑内有 PIL,numpy环境,注意图片的路径要按自身的路径编辑)
from PIL import Image
import numpy as np
img1 = Image.open("./img/lena_gray_512.tif")
img1 = np.array(img1)
# 验证和库函数的变换是否是结果一致的
testImg1 = dft2D(img1)
testImg2 = np.fft.fft2(img1)
print(testImg1 == testImg2)
结果如下:(可以看到与库函数完全对应上了数值)
实现一个函数 f=idft2D(F), 其中 F 是一个灰度图像的傅里叶变换,f 是其对应的二维快速傅 里叶逆变换 (IFFT)图像,也就是灰度源图像. 具体实现要求按照课上的介绍通过类似正向变 换的方式实现。
# 根据书187页(第3版图像处理)说的3个步骤写的
def idft2D(F):
h,w = F.shape
# 第一步:算输入的经过傅里叶变换后的复数矩阵的共轭
m = F.conjugate()
# 第二步:把共轭后的m当作正向傅里叶变换的输入进行计算
x = dft2D(m)
# 第三步:取x的共轭并除以宽高的乘积
res = x.conjugate() / (h*w)
return res
验证快速傅里叶变换的逆变换函数(注意:由于第一题已经引用了numpy ,PIL故此题不再单独引用,若是在同一个 jupyter 文件下,这样子是可行且常见的,下面代码中第二行的img1是第一题中的img1,建议使用 jupyter 编码,这样子就能引用上题的一些变量)
# 初始傅里叶变换矩阵
testImg3 = np.fft.fft2(img1)
# 与库函数对照测试
testImg4 = idft2D(testImg3)
testImg5 = np.fft.ifft2(testImg3)
print(testImg4 == testImg5)
结果如下:(当然有部分人可能会把自己写的函数生成的结果转成图片和库函数产生的结果转成图片后对比,这显然是非常困难的,因为图片的一些细微的差别还是比较难发现的,所以使用数值对比是较为直观的)
第二题不可通过类似第一题的方案,对每一行和每一列进行逆向的傅里叶变换,这样子不会得到想要的结果
对于给定的输入图像 rose512.tif, 首先将其灰度范围通过归一化调整到[0,1]. 将此归一化的 图像记为 f. 首先调用问题 1 下实现的函数 dft2D 计算其傅里叶变换,记为 F。然后调用问题 2 下的函数 idft2D 计算 F 的傅里叶逆变换,记为 g. 计算并显示误差图像 d = f-g.
import numpy as np
import cv2
import matplotlib.pyplot as plt
#读图
img2 = cv2.imread('./img/rose512.tif',cv2.IMREAD_GRAYSCALE)
plt.subplot(2,2,1)
plt.title("input image")
plt.imshow(img2,cmap='gray')
plt.axis('off')
#归一化
f = (img2 - np.min(img2)) / (np.max(img2) - np.min(img2))
# print(f)
#傅里叶变换
F = dft2D(img2)
#傅里叶逆变换
g = idft2D(F)
g = abs(g)
d = f - g
# 还原到255的范围
d = ((d - np.min(d))/(np.max(d)-np.min(d)))*255
#展示图像
plt.subplot(2,2,2)
plt.title("output image")
plt.imshow(d,cmap='gray')
plt.axis('off')
plt.show()
结果:
我们的目标是复现下图中的结果。首先合成矩形物体图像,建议图像尺寸为 512×512,矩 形位于图像中心,建议尺寸为 60 像素长,10 像素宽,灰度假设已归一化设为 1. 对于输入 图像 f 计算其中心化二维傅里叶变换 F。然后计算对应的谱图像 S=log(1+abs(F)). 显示该谱 图像。
# 让归一化后的图像返回去0-255的范围
def backTo255(img):
img = ((img - np.min(img))/(np.max(img)-np.min(img)))*255
return img
# 中心化
def centra(f):
for i in range(f.shape[0]):
for j in range(f.shape[1]):
f[i][j] = f[i][j] * pow(-1, i * j)
return f
以上是待使用的函数
# 生成图片
img = np.zeros([512,512])
i = 252
while i<= 262:
img[227:287,i] = 1.0
i += 1
# 展示原始图片
plt.imshow(img)
plt.axis('off')
plt.show()
#傅里叶变换
img4 = dft2D(img)
#复数取绝对值
img4_abs = abs(img4)
# 展示傅里叶
plt.imshow(img4_abs)
plt.axis('off')
plt.show()
#中心化傅里叶变换
img4 = centra(img)
img4_cen = dft2D(img4)
#复数取绝对值
img4_abs = abs(img4_cen)
# 展示中心傅里叶
plt.imshow(img4_abs)
plt.axis('off')
plt.show()
##实现对数变换的谱图像
# 按公式操作
S = np.log(1+abs(img4_cen))
img4 = backTo255(S)
plt.imshow(img4)
plt.axis('off')
plt.show()
结果:(只展示了部分(第3和第4个))