环境:Python3.8 和 OpenCV
内容:一维离散傅里叶变换和二维离散傅里叶变换
傅里叶变换和傅里叶反变换:
一维傅里叶变换后,除去初始点,其余各点满足:
(1)实部的点对称
(2)虚部的点反对称
(3)幅值(模长)的点对称
因此,可以得到F(u) 和 F(M - u) 两点共轭。
一维离散傅里叶变换:
实现方式1:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
# 绘制方波信号
M = 100 # 信号长度
fx = np.zeros(M) #
fx[30: 70] = 1 # 方波信号
# 傅里叶变换
x = np.arange(0, M)
Fu = np.zeros(M, np.complex128)
for u in range(M):
Re = np.sum(fx * np.cos(-2 * np.pi * u * x / M))
Im = np.sum(fx * np.sin(-2 * np.pi * u * x / M))
Fu[u] = Re + 1j * Im
# 傅里叶反变换
u = np.arange(0, M)
Fx = np.zeros(M, np.complex128)
for x in range(M):
Re = np.sum(Fu * np.cos(2 * np.pi * u * x / M))
Im = np.sum(Fu * np.sin(2 * np.pi * u * x / M))
Fx[x] = Re + 1j * Im
# 解决中文乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 绘制结果
plt.plot(fx, 'r-', label='原始信号')
plt.plot(np.real(Fu), 'b-', label='傅里叶变换实部')
plt.plot(np.real(Fx), 'k-', label='反傅里叶变换实部')
plt.legend()
plt.xlim([0, 100])
plt.show()
实现方式2:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
# 绘制方波信号
M = 100 # 信号长度
fx = np.zeros(M) #
fx[30: 70] = 1 # 方波信号
# 傅里叶变换
x = np.arange(0, M)
Fu = np.zeros(M, np.complex128)
for u in range(M):
Fu[u] = np.sum(fx * np.exp(-2j * np.pi * u * x / M))
# 傅里叶反变换
u = np.arange(0, M)
Fx = np.zeros(M, np.complex128)
for x in range(M):
Fx[x] = np.sum(Fu * np.exp(2j * np.pi * u * x / M))
# 解决中文乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 绘制结果
plt.plot(fx, 'r-', label='原始信号')
plt.plot(np.real(Fu), 'b-', label='傅里叶变换实部')
plt.plot(np.real(Fx), 'k-', label='反傅里叶变换实部')
plt.legend()
plt.xlim([0, 100])
plt.show()
二维离散傅里叶变换:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
# 读取灰度图片
img_lenna = cv.imread('lenna.png', 0)
# 二维离散傅里叶变换
img_fft = np.fft.fft2(img_lenna)
# 傅里叶变换的平移
img_ffts = np.fft.fftshift(img_fft)
# 获取变换后的振幅谱和相位谱
Amp = np.abs(img_ffts)
Ang = np.angle(img_ffts)
# 显示振幅谱和相位谱
plt.figure()
plt.subplot(121)
plt.imshow(np.log(Amp + 1), cmap='jet')
plt.subplot(122)
plt.imshow(Ang, cmap='jet')
plt.show()
# 恢复成原图像
img_lenna_re1 = np.abs(np.fft.ifft2(img_fft))
img_lenna_re2 = np.abs(np.fft.ifft2(img_ffts))
# 显示恢复结果
plt.figure()
plt.subplot(121)
plt.imshow(img_lenna_re1, cmap='gray')
plt.subplot(122)
plt.imshow(img_lenna_re2, cmap='gray')
plt.show()
基于傅里叶变换的图像融合 :
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
# 封装图片显示函数
def image_show(image):
if image.ndim == 2:
plt.imshow(image, cmap='gray')
else:
image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
plt.imshow(image)
plt.show()
if __name__ == '__main__':
# 读取图像
img_desk = cv.imread('desk.png', 0)
img_lenna = cv.imread('lenna.png', 0)
# 图像裁剪
img_desk_crap = img_desk[:500, :500]
# 二维离散傅里叶变换
desk_fft = np.fft.fft2(img_desk_crap)
lenna_fft = np.fft.fft2(img_lenna)
# 获取幅值谱和相位谱
Desk_Amp, Desk_Ang = np.abs(desk_fft), np.angle(desk_fft)
Lenna_Amp, Lenna_Ang = np.abs(lenna_fft), np.angle(lenna_fft)
# 图像融合
Fu_A = Desk_Amp * np.cos(Lenna_Ang) + Desk_Amp * np.sin(Lenna_Ang)
Fu_B = Lenna_Amp * np.cos(Desk_Ang) + Lenna_Amp * np.sin(Desk_Ang)
# 傅里叶反变换
img_desk_rec = np.fft.ifft2(Fu_A)
img_Lenna_rec = np.fft.ifft2(Fu_B)
# 显示结果
image_show(np.abs(img_desk_rec))
image_show(np.abs(img_Lenna_rec))