按照某度的解释,傅立叶变换,是表示能将满足一定条件的某个函数表示成三角函数(正弦和/或余弦函数)或者它们的积分的线性组合。在不同的研究领域,傅立叶变换具有多种不同的变体形式,如连续傅立叶变换和离散傅立叶变换。最初傅立叶分析是作为热过程的解析分析的工具被提出的。其公式是一个连续积分函数:
公式描述:公式中F(ω)为f(t)的像函数,f(t)为F(ω)的像原函数。
原理解析
抛开复杂的公式推导简单来说,傅立叶变换的实际意义就是对一个指定的信号曲线,可以使用傅立叶变换的方法对其进行分解重组,其目的就是将复杂问题简单化处理,再将处理后的结果综合起来考虑。
具体操作就是将一个信号曲线分解成若干个正弦曲线,这些正弦的频率代表了原信号曲线的频率变化情况,总的来说就是对原来信号曲线上的不同频率的信号进行分门别类,同一频率下的信号被分到了一个正弦曲线上,这样就有了若干个不同频率的正弦曲线了,而这些正弦曲线中,有些是我们需要的信息,而有些是不需要的信息。
相对原始的信号,分解后的若干正弦曲线的信号是非常容易处理的,比如我们需要去除指定频段的信号,在原信号曲线上是比较难实现的,但是在分解后的若干正弦曲线中就变得非常容易,我们要做的只需要对这些正弦曲线按照频率大小进行排序,然后删除掉不需要的频段曲线即可,当然,操作完之后要记得将分解处理完后剩下的正弦曲线信号合并成原始的信号,这种操作被称为傅立叶逆变换或者逆傅立叶变换。
以语音信号为例,一般我们接触到的信号是一幅基于时间序列的音频声波图,也称为时域图。声音是介质振动在听觉系统中产生的反应。声音总可以被分解为不同频率不同强度正弦波的叠加(傅里叶变换)。声音有两个基本的物理属性:频率与振幅。声音的振幅就是音量,频率的高低就是指音调,频率用赫兹(Hz)作单位。人耳只能听到20Hz到20khz范围的声音。
音频图上波峰的高低象征着声音的振幅大小,从物理角度解释,振幅就是声带偏离原来位置的大小,声带偏离原来的位置越大,则声音越大,波峰越高的地方意味着音频的振幅越高,也就是音量越大。而频率就是声带在单位时间内振动的次数,在音频图上可以看作是一个周期,频率越高,就意味着声带振动的次数越多,也就是音调越高。
直接时域上的音频图进行处理比较麻烦,所以一般会先将时域图按照不同的频率振幅分解成若干个音频和振幅不同的音频信号图。再将这些不同的信号图按照不同的振幅映射到一个平面图上,就是我们所说的频域图。
傅立叶变换对于信号的处理主要作用是将信号从时域图像转换到频域图像,其完整步骤如下:傅立叶变换(时域图→频域图)→频域图排序→去除指定频率的信号→频域图顺序还原→逆傅立叶变换(频域图→时域图)→时域图取模还原。
那么我们如此大费周章的去除信号中指定频段的信号目的是什么呢?当然是基于实际问题的处理,最常见的就是信号去噪,一般来说。信号中都会存在一些干扰的噪声信号,不利于信号的处理,而这些噪声信号的频段往往都是固定的,只要我们对信号进行傅立叶变换的操作,就很容易去除掉这些干扰的噪声信号了。
举个例子,我们在户外街道上录制一段语音,这段语音的信号中,实际是上包含了我们正常发出的声音和街道背景的噪声信号的。这个时候我们如果想要让录制的语音变得清晰一些,就需要对这段语音进行傅立叶变换的操作,目的就是去除噪声干扰。当然处理语音信号噪声的方法有很多,而傅里叶变换是必将经典的一种方法。
大多数情况下,噪声属于高频信号,去除掉噪声的音频图和原始音频图相比,差异不大,整体来看,由于有一部分的高频信号被去除了,去噪后的信号图比原图会更平滑一些。
说完傅立叶变换在信号领域的应用,接下来说说傅立叶变换在图像视觉领域的应用。我们一般所说的信号是一个一维数据,数据前后是由顺序的,而图像是一个二维(灰度图)或三维(RGB图)的数据(在代码实现中,会统一转成二维灰度图),但是无论数据是多少个维度,他们的处理步骤都是一样的,只不过具体操作细节有所变换而已,但是要明白,不管是一维数据也好,还是二维三维数据也罢,它们之间其实都是可以互相转换的。
那么傅立叶变换在图像视觉领域的具体实现方法是怎么样的呢?实际上只需要把在一维信号中处理流程的时域信号换成空域信号即可,其他步骤不做任何变化。其实也很好理解,一维信号数据是具有先后时序的,而二维或者三维数据之间的关系就不像一维信号那么,只是基于时序的关系了,它们之间的关系是基于空间的关系。
代码演示
接下来,我们就傅立叶变换在图像领域的应用进行代码实际操作演示,我们先通过傅立叶变换对图像进行去噪操作的演示,也就是去掉一部分高频信号的操作,由于是去高频信号,留低频信号,这个操作也被称为低通滤波。
下面以成都深度智谷科技的教学机构“深度人工智能学院”的教学练习题为例演示傅立叶变换的结果,在opencv中以离散傅立叶变换(DFT)来实现图像低通滤波操作:
import numpy
import cv2
import matplotlib.pyplot as plt
DFT:离散傅里叶变换'
# 2.OpenCV中的 DFT(Discrete Fourier Transform) 离散傅里叶变换
img = cv2.imread(".images/1.jpg")
# 0.转化为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
rows, cols = gray.shape
# 1.DFT离散傅里叶变换:空域--〉频域
dft = cv2.dft(src=numpy.float32(gray), flags=cv2.DFT_COMPLEX_OUTPUT) # src为灰度图,并且是numpy.float32类型
print(dft.shape)#两个通道
# 2.中心化:将低频移动到图像中心
fftshift = numpy.fft.fftshift(dft)
# 获取振幅谱(展示图片用): numpy.log()是为了将值限制在[0, 255]
magnitude_spectrum = numpy.log(cv2.magnitude(fftshift[:, :, 0], fftshift[:, :, 1]))
# 3.滤波操作之低通滤波(去高频,保低频)
mask = numpy.zeros((rows, cols,2), dtype=numpy.uint8)
mask[(rows / 2 - 30): (rows / 2 + 30), (cols / 2 - 30): (cols / 2 + 30)] = 1
fftshift = fftshift * mask
# 4.去中心化:将低频和高频的位置还原
ifftshift = numpy.fft.ifftshift(fftshift)
# 5.逆傅里叶变换:频域--〉空域
idft = cv2.idft(ifftshift)
# 6.二维向量取模(幅值)
img_back = cv2.magnitude(idft[:, :, 0], idft[:, :, 1])
# 结合matplotlib展示多张图片
plt.figure(figsize=(10, 10))
plt.subplot(221), plt.imshow(gray, cmap="gray"), plt.title("Input Gray Image")
plt.xticks([]), plt.yticks([])
plt.subplot(222), plt.imshow(magnitude_spectrum, cmap="gray"), plt.title("Magnitude Spectrum")
plt.xticks([]), plt.yticks([])
plt.subplot(223), plt.imshow(img_back, cmap="gray"), plt.title("Image after LPF")
plt.xticks([]), plt.yticks([])
plt.subplot(224), plt.imshow(img_back), plt.title("Result in JET") # 默认cmap='jet'
plt.xticks([]), plt.yticks([])
plt.show()
代码展现效果:
通过上面案例,我们直观地感受到了傅立叶变换在图像去噪方面的实际效果,去掉了高频信号后,无论是灰度图,还是默认色彩图,图像的轮廓都会被软化,界限变得模糊,这是由于图像的噪声以及边缘部位往往梯度变化较大,而梯度较大的地方属于高频信号,所以在去噪的同时会软化图像边缘。
接下来我们进行一个反向操作,也就是图像高通滤波操作,即去低频信号,留高频信号,看看处理后的图像最终有什么变化。我们这次以numpy中的快速傅立叶变换为例来实现图像高通滤波操作:
import numpy
import cv2
import matplotlib.pyplot as plt
img = cv2.imread(".images/1.jpg")
# 0.转化为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
rows, cols = gray.shape
print(gray.shape)
# 1.FFT快速傅里叶变换:空域--〉频域
fft = numpy.fft.fft2(gray) # 傅里叶变换,参数为灰度图
print(fft.shape)
# 2.中心化:将低频信号移动到图像中心
fftshift = numpy.fft.fftshift(fft)
print(numpy.min(numpy.abs(fftshift)))#绝对最低频率信号
print(numpy.max(fftshift),numpy.min(fftshift))#最高频率信号,最低频率信号
# 获取振幅谱(展示图片用): numpy.log()是为了将值压缩在[0, 255]附近
magnitude_spectrum = numpy.log(numpy.abs(fftshift))
print(numpy.max(magnitude_spectrum),numpy.min(magnitude_spectrum))
# 3.滤波操作之高通滤波(去低频,保高频)
fftshift[rows / 2 - 50:rows / 2 + 50, cols / 2 - 50: cols / 2 + 50] = 0
# print(fftshift.shape)
# 4.去中心化:将剩余的低频和高频的位置还原
ifftshift = numpy.fft.ifftshift(fftshift)
# 5.逆傅里叶变换:频域--〉空域
ifft = numpy.fft.ifft2(ifftshift)
# print(ifft)
# 6.二维向量取模(幅值)
img_back = numpy.abs(ifft)
#结合matplotlib展示多张图片
plt.figure(figsize=(10, 10))
plt.subplot(221), plt.imshow(gray, cmap="gray"), plt.title("Input Gray Image")
plt.xticks([]), plt.yticks([])
plt.subplot(222), plt.imshow(magnitude_spectrum, cmap="gray"), plt.title("Magnitude Spectrum")
plt.xticks([]), plt.yticks([])
plt.subplot(223), plt.imshow(img_back, cmap="gray"), plt.title("Image after HPF")
plt.xticks([]), plt.yticks([])
plt.subplot(224), plt.imshow(img_back), plt.title("Result in JET") # 默认cmap='jet'
plt.xticks([]), plt.yticks([])
plt.show()
代码展现效果:
图像高通滤波的效果和低通滤波效果刚好相反,从上面案例的结果来看,高通滤波的操作会使图像失去更多的背景细节部分,只保留了图像相应的轮廓界面。这是因为背景部分的图像梯度变化相对轮廓部分的梯度变化较小,图像梯度变化较小的这部分属于低频信号,去除掉这部分低频信号,会使得图像缺少过渡,边缘显得生硬,当去除过多的低频信号时,甚至会让图像变成一副边缘轮廓图。
既然我们能够通过傅立叶变换对图像进行高通滤波或低通滤波的操作,那么同样也能对图像进行指定任意频段的滤波操作,比如中通滤波就是保留图像中间指定频段的数据,去除高频数据和低频数据的操作,而阻滞滤波刚好是去除图像中间指定频段的数据,保留高频和低频数据。
后记:
关于普通傅立叶变换和离散傅立叶变换、快速傅立叶变换之间的概念关系如下:
DTFT是离散时间傅里叶变换,用来表达连续的信号的频谱。
DFT是离散傅里叶变换,针对的是离散的信号和频谱DFT是DTFT变化而来,其实就是将连续时间t变成了nT。为什么要这样做呢,因为计算机是在数字环境下工作的,它不可能看见或者处理现实中连续的信号,只能够进行离散计算,在真实性上尽可能地逼近连续信号。所以DFT是为了我们能够去用工具分析信号而创造出来的,通常我们直接用DTFT的机会很少。
FFT(Fast Fourier Transformation),即为快速傅氏变换,是离散傅氏变换的快速算法,
它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。
它对傅氏变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。在FFT中,利用WN的周期性和对称性,把一个N项序列(设N=2k,k为正整数),分为两个N/2项的子序列,每个N/2点DFT变换需要(N/2)2次运算,再用N次运算把两个N/2点的DFT变换组合成一个N点的DFT变换。这样变换以后,总的运算次数就变成N+2*(N/2)^2=N+N^2/2。FFT提高了运算速度,但是,也对参与运算的样本序列作出了限制,即要求样本数为2^N点。离散傅里叶变换DFT则无上述限制。
小结:FFT快,DFT灵活,各有优点,如果满足分析要求,两者准确度相同。
关注深度人工智能学院,我们长期致力于人工智能职业教育培训领域的发展,“传播AI教育,培养AI人才” 是我们的长期愿景。
文末附上一张傅立叶变换的动态图,理论上任何图形都能被分解成若干个正弦波,也就可以被若干个圆组合的运动轨迹拟合:
关注微信公众号:深度人工智能学院,获取更多人工智能方面的知识!
官方公众号 官方微信号