傅里叶变换--快速傅里叶变换实现
- 0.1. 定义
- 0.1.1. 连续
- 0.1.2. 离散
- 0.2. 性质
- 0.2.1. 分离性
- 0.2.2. 位移定理
- 0.2.3. 周期性
- 0.2.4. 共轭对称性
- 0.2.5. 旋转性
- 0.2.6. 加法定理
- 0.2.7. 平均值
- 0.2.8. 相似性定理
- 0.2.9. 卷积定理
- 0.2.10. 相关定理
- 0.2.11. Rayleigh 定理
- 0.3. 快速傅里叶变换
- 0.3.1. 复数中的单位根
- 0.3.2. 快速傅里叶变换的计算
- 0.4. 代码
- 0.5. 参考
图像处理中, 为了方便处理,便于抽取特征,数据压缩等目的,常常要将图像进行变换。
一般有如下变换方法
- 傅立叶变换Fourier Transform
- 离散余弦变换Discrete Cosine Transform
- 沃尔希-哈德玛变换Walsh-Hadamard Transform
- 斜变换Slant Transform
- 哈尔变换Haar Transform
- 离散K-L变换Discrete Karhunen-Leave Transform
- 奇异值分解SVD变换Singular-Value Decomposition
- 离散小波变换Discrete Wavelet Transform
这篇文章介绍一下傅里叶变换
0.1. 定义
0.1.1. 连续
积分形式
如果一个函数的绝对值的积分存在,即
∫−∞∞∣h(t)∣dt<∞\int_{-\infty} ^\infty |h(t)|dt<\infty ∫−∞∞∣h(t)∣dt<∞
并且函数是连续的或者只有有限个不连续点,则对于 x 的任何值, 函数的傅里叶变换存在
- 一维傅里叶变换
H(f)=∫−∞∞h(t)e−j2πftdtH(f)=\int_{-\infty} ^\infty h(t)e^{-j2\pi ft}dt H(f)=∫−∞∞h(t)e−j2πftdt - 一维傅里叶逆变换
H(f)=∫−∞∞h(t)ej2πftdtH(f)=\int_{-\infty} ^\infty h(t)e^{j2\pi ft}dt H(f)=∫−∞∞h(t)ej2πftdt
同理多重积分
0.1.2. 离散
实际应用中,多用离散傅里叶变换 DFT.
- 一维傅里叶变换
F(u)=∑x=0N−1f(x)e−2πjNuxF(u)=\sum_{x=0} ^{N-1} f(x)e^{\frac{-2\pi j}{N} ux} F(u)=x=0∑N−1f(x)eN−2πjux - 一维傅里叶逆变换
f(x)=1N∑u=0N−1F(u)e2πjNuxf(x)=\frac{1}{N}\sum_{u=0} ^{N-1} F(u)e^{\frac{2\pi j}{N} ux} f(x)=N1u=0∑N−1F(u)eN2πjux
需要注意的是, 逆变换乘以 1N\frac{1}{N}N1 是为了归一化,这个系数可以随意改变, 即可以正变换乘以 1N\frac{1}{N}N1, 逆变换就不乘,或者两者都乘以1N\frac{1}{\sqrt{N}}N1等系数。 - 二维傅里叶变换
F(u,v)=1N∑x=0N−1∑y=0N−1f(x,y)e−2πjN(ux+vy)F(u,v)=\frac{1}{N}\sum_{x=0}^{N-1}\sum_{y=0} ^{N-1} f(x,y)e^{\frac{-2\pi j}{N} (ux+vy)} F(u,v)=N1x=0∑N−1y=0∑N−1f(x,y)eN−2πj(ux+vy) - 二维傅里叶逆变换
f(x,y)=1N∑u=0N−1∑v=0N−1F(u,v)e2πjN(ux+vy)f(x,y)=\frac{1}{N}\sum_{u=0}^{N-1}\sum_{v=0} ^{N-1} F(u,v)e^{\frac{2\pi j}{N} (ux+vy)} f(x,y)=N1u=0∑N−1v=0∑N−1F(u,v)eN2πj(ux+vy)
幅度
∣F(u,v)∣=real(F)2+imag(F)2|F(u,v)| = \sqrt{real(F)^2+imag(F)^2} ∣F(u,v)∣=real(F)2+imag(F)2
相位
arctanimag(F)real(F)arctan{\frac{imag(F)}{real(F)}} arctanreal(F)imag(F)
对于图像的幅度谱显示,由于 |F(u,v)| 变换范围太大,一般显示 D=log(∣F(u,v)+1)D= log(|F(u,v)+1)D=log(∣F(u,v)+1)
用 <=>
表示傅里叶变换对
f(x)<=>F(u)f(x,y)<=>F(u,v)f(x)<=>F(u)\\ f(x,y)<=>F(u,v) f(x)<=>F(u)f(x,y)<=>F(u,v)
f,g,h 对应的傅里叶变换 F,G,H
F∗F^*F∗ 表示 FFF 的共轭
0.2. 性质
0.2.1. 分离性
F(x,v)=∑y=0N−1f(x,y)e−2πjNvyF(u,v)=1N∑x=0N−1F(x,v)e−2πjNux\begin{aligned} &F(x,v)=\sum_{y=0} ^{N-1} f(x,y)e^{\frac{-2\pi j}{N} vy}\\ &F(u,v)=\frac{1}{N}\sum_{x=0}^{N-1}F(x,v)e^{\frac{-2\pi j}{N}ux} \end{aligned} F(x,v)=y=0∑N−1f(x,y)eN−2πjvyF(u,v)=N1x=0∑N−1F(x,v)eN−2πjux
进行多维变换时,可以依次对每一维进行变换。 下面在代码中就是这样实现的。
0.2.2. 位移定理
f(x,y)e2πjN(u0x+v0y)<=>F(u−u0,v−v0)f(x,y)e^{\frac{2\pi j}{N}(u_0x+v_0y)} <=>F(u-u_0,v-v_0) f(x,y)eN2πj(u0x+v0y)<=>F(u−u0,v−v0)
f(x−x0,y−y0)<=>F(u,v)e−2πjN(ux0+vy0)f(x-x_0,y-y_0)<=>F(u,v)e^{\frac{-2\pi j}{N}(ux_0+vy_0)} f(x−x0,y−y0)<=>F(u,v)eN−2πj(ux0+vy0)
0.2.3. 周期性
F(u,v)=F(u+N,v+N)F(u,v) = F(u+N,v+N) F(u,v)=F(u+N,v+N)
0.2.4. 共轭对称性
F(u,v)=F∗(−u,−v)F(u,v) = F^*(-u,-v)F(u,v)=F∗(−u,−v)
a)偶分量函数在变换中产生偶分量函数;
b)奇分量函数在变换中产生奇分量函数;
c)奇分量函数在变换中引入系数-j;
d)偶分量函数在变换中不引入系数.
0.2.5. 旋转性
if f(r,θ)<=>F(ω,ϕ)f(r,\theta)<=>F(\omega,\phi) f(r,θ)<=>F(ω,ϕ)
then f(r,θ+t)<=>F(ω,ϕ+t)f(r,\theta+t)<=>F(\omega,\phi+t) f(r,θ+t)<=>F(ω,ϕ+t)
0.2.6. 加法定理
Fourier[f+g]=Fourier[f]+Fourier[g]Fourier[f+g]=Fourier[f]+Fourier[g] Fourier[f+g]=Fourier[f]+Fourier[g]
2.
af(x,y)<=>aF[u,v]af(x,y)<=>aF[u,v] af(x,y)<=>aF[u,v]
0.2.7. 平均值
1N2∑x=0N−1∑y=0N−1f(x,y)=1NF(0,0)\frac{1}{N^2}\sum_{x=0}^{N-1}\sum_{y=0} ^{N-1} f(x,y) = \frac{1}{N}F(0,0) N21x=0∑N−1y=0∑N−1f(x,y)=N1F(0,0)
0.2.8. 相似性定理
尺度变换
f(ax,by)<=>F(ua,vb)abf(ax,by)<=>\frac{F(\frac{u}{a},\frac{v}{b})}{ab} f(ax,by)<=>abF(au,bv)
0.2.9. 卷积定理
卷积定义
1d
f∗g=1M∑m=0M−1f(m)g(x−m)f*g = \frac{1}{M}\sum_{m=0}^{M-1}f(m)g(x-m) f∗g=M1m=0∑M−1f(m)g(x−m)
2d
f(x,y)∗g(x,y)=1MN∑m=0M−1∑n=0N−1f(m,n)g(x−m,y−n)f(x,y)*g(x,y) = \frac{1}{MN}\sum_{m=0}^{M-1}\sum_{n=0}^{N-1}f(m,n)g(x-m,y-n) f(x,y)∗g(x,y)=MN1m=0∑M−1n=0∑N−1f(m,n)g(x−m,y−n)
卷积定理
f(x,y)∗g(x,y)<=>F(u,v)G(u,v)f(x,y)*g(x,y) <=> F(u,v)G(u,v) f(x,y)∗g(x,y)<=>F(u,v)G(u,v)
f(x,y)g(x,y)<=>F(u,v)∗G(u,v)f(x,y)g(x,y)<=>F(u,v)*G(u,v) f(x,y)g(x,y)<=>F(u,v)∗G(u,v)
离散卷积
用
∑i=0N−1x(iT)h[(k−i)T]<=>X(nNT)H(nNT)\sum_{i=0}^{N-1}x(iT)h[(k-i)T] <=> X(\frac{n}{NT})H(\frac{n}{NT}) i=0∑N−1x(iT)h[(k−i)T]<=>X(NTn)H(NTn)
即两个周期为 N 的抽样函数, 他们的卷积的离散傅里叶变换等于他们的离散傅里叶变换的卷积
卷积的应用:
去除噪声, 特征增强
两个不同周期的信号卷积需要周期扩展的原因:如果直接进行傅里叶变换和乘积,会产生折叠误差(卷绕)。
0.2.10. 相关定理
下面用$ \infty$ 表示相关。
相关函数描述了两个信号之间的相似性,其相关性大小有相关系数衡量
- 相关函数的定义
离散
f(x,y)∞g(x,y)=1MN∑m=0M−1∑n=0N−1f∗(m,n)g(x+m,y+n)f(x,y)\quad \infty \quad g(x,y) = \frac{1}{MN}\sum_{m=0}^{M-1}\sum_{n=0}^{N-1}f^*(m,n)g(x+m,y+n) f(x,y)∞g(x,y)=MN1m=0∑M−1n=0∑N−1f∗(m,n)g(x+m,y+n)
连续
z(t)=∫−∞∞x∗(τ)h(t+τ)dτz(t) = \int_{-\infty}^{\infty}x^*(\tau) h(t+\tau)d\tauz(t)=∫−∞∞x∗(τ)h(t+τ)dτ - 定理
f(x,y)∞g(x,y)<=>F∗(u,v)G(u,v)f(x,y)\quad \infty \quad g(x,y)<=>F^*(u,v)G(u,v) f(x,y)∞g(x,y)<=>F∗(u,v)G(u,v)
0.2.11. Rayleigh 定理
能量变换
对于有限区间非零函数 f(t), 其能量为
E=∫−∞∞∣f(t)∣2dtE = \int_{-\infty}^{\infty}|f(t)|^2dt E=∫−∞∞∣f(t)∣2dt
其变换函数与原函数有相同的能量
∫−∞∞∣f(t)∣2dt=∫−∞∞∣F(u)∣2dt\int_{-\infty}^{\infty}|f(t)|^2dt = \int_{-\infty}^{\infty}|F(u)|^2dt ∫−∞∞∣f(t)∣2dt=∫−∞∞∣F(u)∣2dt
0.3. 快速傅里叶变换
由上面离散傅里叶变换的性质易知,直接计算 1维 dft 的时间复杂度维 O(N2)O(N^2)O(N2)。
利用到单位根的对称性,快速傅里叶变换可以达到 O(nlogn)O(nlogn)O(nlogn)的时间复杂度。
0.3.1. 复数中的单位根
我们知道, 在复平面,复数 cosθ+isinθcos\theta +i\ sin\thetacosθ+i sinθk可以表示成 eiθe^{i\theta}eiθ, 可以对应一个向量。θ\thetaθ即为幅角。
在单位圆中 ,单位圆被分成 2πθ\frac{2\pi}{\theta}θ2π 份, 由单位圆的对称性
eiθ=ei(θ+2π)e^{i\theta} = e^{i(\theta+2\pi)} eiθ=ei(θ+2π)
现在记 $ n =\frac{ 2\pi }{\theta}$ , 即被分成 n 份,幅度角为正且最小的向量称为 n 次单位向量, 记为ωn\omega _nωn,
其余的 n-1 个向量分别为 ωn2,ωn3,…,ωnn\omega_{n}^{2},\omega_{n}^{3},\ldots,\omega_{n}^{n}ωn2,ωn3,…,ωnn ,它们可以由复数之间的乘法得来 $w_{n}{k}=w_{n}{k-1}\cdot w_{n}^{1}\ (2 \leq k \leq n) $。
单位根的性质
- 这个可以用 e 表示出来证明
ω2n2k=ωnk\omega_{2n}^{2k}=\omega_{n}^{k} ω2n2k=ωnk - 可以写成三角函数证明
ωnk+n2=−ωnk\omega_{n}^{k+\frac{n}{2}}=-\omega_{n}^{k} ωnk+2n=−ωnk
容易看出 $w_{n}{n}=w_{n}{0}=1 $。
对于$ w_{n}^{k}$ , 它事实上就是 e2πinke^{\frac{2\pi i}{n}k}en2πik 。
0.3.2. 快速傅里叶变换的计算
下面的推导假设 n=2kn=2^kn=2k,以及代码实现 FFT 部分也是 如此。
利用上面的对称性,
将傅里叶计算进行奇偶分组
F(u)=∑i=0n−1ωniuai=∑i=0n2−1ωn2iua2i+∑i=0n2−1ωn(2i+1)ua2i+1=∑i=0n2−1ωn2iua2i+ωnu∑i=0n2−1ωn2iua2i+1=Feven(u)+ωnuFodd(u)\begin{aligned} F(u)&=\sum_{i=0}^{n-1}\omega_n ^{iu} a^i\\ &= \sum_{i=0}^{\frac{n}{2}-1}\omega_n ^{2iu} a^{2i}+\sum_{i=0}^{\frac{n}{2}-1}\omega_n ^{(2i+1)u} a^{2i+1}\\ &=\sum_{i=0}^{\frac{n}{2}-1}\omega_{\frac{n}{2}} ^{iu} a^{2i}+\omega_n^u\sum_{i=0}^{\frac{n}{2}-1}\omega_{\frac{n}{2}} ^{iu} a^{2i+1}\\ & = F_{even}(u)+\omega_n^u F_{odd}(u) \end{aligned} F(u)=i=0∑n−1ωniuai=i=0∑2n−1ωn2iua2i+i=0∑2n−1ωn(2i+1)ua2i+1=i=0∑2n−1ω2niua2i+ωnui=0∑2n−1ω2niua2i+1=Feven(u)+ωnuFodd(u)
FevenF_{even}Feven表示将 输入的次序中偶数点进行 Fourier 变换, FoddF_{odd}Fodd 同理,这样就形成递推公式。
现在还没有减少计算量,下面通过将分别计算的 奇项,偶项利用起来,只计算 前 n2−1\frac{n}{2}-12n−1项,后面的一半可以利用此结果马上算出来。每一次可以减少一半的计算量。
对于 n2≤i+n2≤n−1\frac{n}{2}\leq i+\frac{n}{2}\leq n-12n≤i+2n≤n−1
F(ωni+n2)=Feven(ωn2i+n)+ωni+n2⋅Fodd(ωn2i+n)=Feven(ωn2i+n2)+ωn2i+n2⋅Fodd(ωn2i+n2)=Feven(ωn2i)−ωn2i⋅Fodd(ωn2i)\begin{aligned} F(\omega_{n}^{i+\frac{n}{2}})&=F_{even}(\omega_{n}^{2i+n})+\omega_{n}^{i+\frac{n}{2}}\cdot F_{odd}(\omega_{n}^{2i+n})\\ &=F_{even}(\omega_{\frac{n}{2}}^{i+\frac{n}{2}})+\omega_{\frac{n}{2}}^{i+\frac{n}{2}}\cdot F_{odd}(\omega_{\frac{n}{2}}^{i+\frac{n}{2}})\\ & =F_{even}(\omega_{\frac{n}{2}}^{i})-\omega_{\frac{n}{2}}^{i}\cdot F_{odd}(\omega_{\frac{n}{2}}^{i}) \end{aligned} F(ωni+2n)=Feven(ωn2i+n)+ωni+2n⋅Fodd(ωn2i+n)=Feven(ω2ni+2n)+ω2ni+2n⋅Fodd(ω2ni+2n)=Feven(ω2ni)−ω2ni⋅Fodd(ω2ni)
现在很清楚了,在每次计算 a[0…n-1] 的傅里叶变换F[0…n-1],分别计算出奇 odd[0…n/2-1],偶even[0…n/2-1](可以递归地进行),
那么傅里叶变换为:
F[i]={even[i]+ωi⋅odd[i],i<n2even[i]−ωi⋅odd[i],elseF[i] = \begin{cases} even[i]+ \omega^i \cdot odd[i], \quad i<\frac{n}{2}\\ even[i]- \omega^i \cdot odd[i], \quad else \end{cases} F[i]={even[i]+ωi⋅odd[i],i<2neven[i]−ωi⋅odd[i],else
0.4. 代码
下面是 python 实现
一维用 FFT 实现, 不过 只实现了 2 的幂。/ 对于非 2 的幂,用 FFT 实现有点困难,还需要插值,所以我 用O(n2)O(n^2)O(n2) 直接实现。
二维的 DFT利用 分离性,直接调用 一维 FFT。
GitHub
import numpy as npdef _fft(a, invert=False):N = len(a)if N == 1:return [a[0]]elif N & (N - 1) == 0: # O(nlogn), 2^keven = _fft(a[::2], invert)odd = _fft(a[1::2], invert)i = 2j if invert else -2jfactor = np.exp(i * np.pi * np.arange(N // 2) / N)prod = factor * oddreturn np.concatenate([even + prod, even - prod])else: # O(n^2)w = np.arange(N)i = 2j if invert else -2jm = w.reshape((N, 1)) * wW = np.exp(m * i * np.pi / N)return np.concatenate(np.dot(W, a.reshape((N, 1)))) # important, cannot use *def fft(a):'''fourier[a]'''n = len(a)if n == 0:raise Exception("[Error]: Invalid length: 0")return _fft(a)def ifft(a):'''invert fourier[a]'''n = len(a)if n == 0:raise Exception("[Error]: Invalid length: 0")return _fft(a, True) / ndef fft2(arr):return np.apply_along_axis(fft, 0,np.apply_along_axis(fft, 1, np.asarray(arr)))def ifft2(arr):return np.apply_along_axis(ifft, 0,np.apply_along_axis(ifft, 1, np.asarray(arr)))def test(n=128):print('\nsequence length:', n)print('fft')li = np.random.random(n)print(np.allclose(fft(li), np.fft.fft(li)))print('ifft')li = np.random.random(n)print(np.allclose(ifft(li), np.fft.ifft(li)))print('fft2')li = np.random.random(n * n).reshape((n, n))print(np.allclose(fft2(li), np.fft.fft2(li)))print('ifft2')li = np.random.random(n * n).reshape((n, n))print(np.allclose(ifft2(li), np.fft.ifft2(li)))if __name__ == '__main__':for i in range(1, 3):test(i * 16)
0.5. 参考
- 万寿红老师课件
- 一小时学会快速傅里叶变换 Fast Fourier Transform
- 快速傅里叶变换(FFT)算法【详解】
- 0.1. 定义
- 0.1.1. 连续
- 0.1.2. 离散
- 0.2. 性质
- 0.2.1. 分离性
- 0.2.2. 位移定理
- 0.2.3. 周期性
- 0.2.4. 共轭对称性
- 0.2.5. 旋转性
- 0.2.6. 加法定理
- 0.2.7. 平均值
- 0.2.8. 相似性定理
- 0.2.9. 卷积定理
- 0.2.10. 相关定理
- 0.2.11. Rayleigh 定理
- 0.3. 快速傅里叶变换
- 0.3.1. 复数中的单位根
- 0.3.2. 快速傅里叶变换的计算
- 0.4. 代码
- 0.5. 参考
图像处理中, 为了方便处理,便于抽取特征,数据压缩等目的,常常要将图像进行变换。
一般有如下变换方法
- 傅立叶变换Fourier Transform
- 离散余弦变换Discrete Cosine Transform
- 沃尔希-哈德玛变换Walsh-Hadamard Transform
- 斜变换Slant Transform
- 哈尔变换Haar Transform
- 离散K-L变换Discrete Karhunen-Leave Transform
- 奇异值分解SVD变换Singular-Value Decomposition
- 离散小波变换Discrete Wavelet Transform
这篇文章介绍一下傅里叶变换
0.1. 定义
0.1.1. 连续
积分形式
如果一个函数的绝对值的积分存在,即
∫−∞∞∣h(t)∣dt<∞\int_{-\infty} ^\infty |h(t)|dt<\infty ∫−∞∞∣h(t)∣dt<∞
并且函数是连续的或者只有有限个不连续点,则对于 x 的任何值, 函数的傅里叶变换存在
- 一维傅里叶变换
H(f)=∫−∞∞h(t)e−j2πftdtH(f)=\int_{-\infty} ^\infty h(t)e^{-j2\pi ft}dt H(f)=∫−∞∞h(t)e−j2πftdt - 一维傅里叶逆变换
H(f)=∫−∞∞h(t)ej2πftdtH(f)=\int_{-\infty} ^\infty h(t)e^{j2\pi ft}dt H(f)=∫−∞∞h(t)ej2πftdt
同理多重积分
0.1.2. 离散
实际应用中,多用离散傅里叶变换 DFT.
- 一维傅里叶变换
F(u)=∑x=0N−1f(x)e−2πjNuxF(u)=\sum_{x=0} ^{N-1} f(x)e^{\frac{-2\pi j}{N} ux} F(u)=x=0∑N−1f(x)eN−2πjux - 一维傅里叶逆变换
f(x)=1N∑u=0N−1F(u)e2πjNuxf(x)=\frac{1}{N}\sum_{u=0} ^{N-1} F(u)e^{\frac{2\pi j}{N} ux} f(x)=N1u=0∑N−1F(u)eN2πjux
需要注意的是, 逆变换乘以 1N\frac{1}{N}N1 是为了归一化,这个系数可以随意改变, 即可以正变换乘以 1N\frac{1}{N}N1, 逆变换就不乘,或者两者都乘以1N\frac{1}{\sqrt{N}}N1等系数。 - 二维傅里叶变换
F(u,v)=1N∑x=0N−1∑y=0N−1f(x,y)e−2πjN(ux+vy)F(u,v)=\frac{1}{N}\sum_{x=0}^{N-1}\sum_{y=0} ^{N-1} f(x,y)e^{\frac{-2\pi j}{N} (ux+vy)} F(u,v)=N1x=0∑N−1y=0∑N−1f(x,y)eN−2πj(ux+vy) - 二维傅里叶逆变换
f(x,y)=1N∑u=0N−1∑v=0N−1F(u,v)e2πjN(ux+vy)f(x,y)=\frac{1}{N}\sum_{u=0}^{N-1}\sum_{v=0} ^{N-1} F(u,v)e^{\frac{2\pi j}{N} (ux+vy)} f(x,y)=N1u=0∑N−1v=0∑N−1F(u,v)eN2πj(ux+vy)
幅度
∣F(u,v)∣=real(F)2+imag(F)2|F(u,v)| = \sqrt{real(F)^2+imag(F)^2} ∣F(u,v)∣=real(F)2+imag(F)2
相位
arctanimag(F)real(F)arctan{\frac{imag(F)}{real(F)}} arctanreal(F)imag(F)
对于图像的幅度谱显示,由于 |F(u,v)| 变换范围太大,一般显示 D=log(∣F(u,v)+1)D= log(|F(u,v)+1)D=log(∣F(u,v)+1)
用 <=>
表示傅里叶变换对
f(x)<=>F(u)f(x,y)<=>F(u,v)f(x)<=>F(u)\\ f(x,y)<=>F(u,v) f(x)<=>F(u)f(x,y)<=>F(u,v)
f,g,h 对应的傅里叶变换 F,G,H
F∗F^*F∗ 表示 FFF 的共轭
0.2. 性质
0.2.1. 分离性
F(x,v)=∑y=0N−1f(x,y)e−2πjNvyF(u,v)=1N∑x=0N−1F(x,v)e−2πjNux\begin{aligned} &F(x,v)=\sum_{y=0} ^{N-1} f(x,y)e^{\frac{-2\pi j}{N} vy}\\ &F(u,v)=\frac{1}{N}\sum_{x=0}^{N-1}F(x,v)e^{\frac{-2\pi j}{N}ux} \end{aligned} F(x,v)=y=0∑N−1f(x,y)eN−2πjvyF(u,v)=N1x=0∑N−1F(x,v)eN−2πjux
进行多维变换时,可以依次对每一维进行变换。 下面在代码中就是这样实现的。
0.2.2. 位移定理
f(x,y)e2πjN(u0x+v0y)<=>F(u−u0,v−v0)f(x,y)e^{\frac{2\pi j}{N}(u_0x+v_0y)} <=>F(u-u_0,v-v_0) f(x,y)eN2πj(u0x+v0y)<=>F(u−u0,v−v0)
f(x−x0,y−y0)<=>F(u,v)e−2πjN(ux0+vy0)f(x-x_0,y-y_0)<=>F(u,v)e^{\frac{-2\pi j}{N}(ux_0+vy_0)} f(x−x0,y−y0)<=>F(u,v)eN−2πj(ux0+vy0)
0.2.3. 周期性
F(u,v)=F(u+N,v+N)F(u,v) = F(u+N,v+N) F(u,v)=F(u+N,v+N)
0.2.4. 共轭对称性
F(u,v)=F∗(−u,−v)F(u,v) = F^*(-u,-v)F(u,v)=F∗(−u,−v)
a)偶分量函数在变换中产生偶分量函数;
b)奇分量函数在变换中产生奇分量函数;
c)奇分量函数在变换中引入系数-j;
d)偶分量函数在变换中不引入系数.
0.2.5. 旋转性
if f(r,θ)<=>F(ω,ϕ)f(r,\theta)<=>F(\omega,\phi) f(r,θ)<=>F(ω,ϕ)
then f(r,θ+t)<=>F(ω,ϕ+t)f(r,\theta+t)<=>F(\omega,\phi+t) f(r,θ+t)<=>F(ω,ϕ+t)
0.2.6. 加法定理
Fourier[f+g]=Fourier[f]+Fourier[g]Fourier[f+g]=Fourier[f]+Fourier[g] Fourier[f+g]=Fourier[f]+Fourier[g]
2.
af(x,y)<=>aF[u,v]af(x,y)<=>aF[u,v] af(x,y)<=>aF[u,v]
0.2.7. 平均值
1N2∑x=0N−1∑y=0N−1f(x,y)=1NF(0,0)\frac{1}{N^2}\sum_{x=0}^{N-1}\sum_{y=0} ^{N-1} f(x,y) = \frac{1}{N}F(0,0) N21x=0∑N−1y=0∑N−1f(x,y)=N1F(0,0)
0.2.8. 相似性定理
尺度变换
f(ax,by)<=>F(ua,vb)abf(ax,by)<=>\frac{F(\frac{u}{a},\frac{v}{b})}{ab} f(ax,by)<=>abF(au,bv)
0.2.9. 卷积定理
卷积定义
1d
f∗g=1M∑m=0M−1f(m)g(x−m)f*g = \frac{1}{M}\sum_{m=0}^{M-1}f(m)g(x-m) f∗g=M1m=0∑M−1f(m)g(x−m)
2d
f(x,y)∗g(x,y)=1MN∑m=0M−1∑n=0N−1f(m,n)g(x−m,y−n)f(x,y)*g(x,y) = \frac{1}{MN}\sum_{m=0}^{M-1}\sum_{n=0}^{N-1}f(m,n)g(x-m,y-n) f(x,y)∗g(x,y)=MN1m=0∑M−1n=0∑N−1f(m,n)g(x−m,y−n)
卷积定理
f(x,y)∗g(x,y)<=>F(u,v)G(u,v)f(x,y)*g(x,y) <=> F(u,v)G(u,v) f(x,y)∗g(x,y)<=>F(u,v)G(u,v)
f(x,y)g(x,y)<=>F(u,v)∗G(u,v)f(x,y)g(x,y)<=>F(u,v)*G(u,v) f(x,y)g(x,y)<=>F(u,v)∗G(u,v)
离散卷积
用
∑i=0N−1x(iT)h[(k−i)T]<=>X(nNT)H(nNT)\sum_{i=0}^{N-1}x(iT)h[(k-i)T] <=> X(\frac{n}{NT})H(\frac{n}{NT}) i=0∑N−1x(iT)h[(k−i)T]<=>X(NTn)H(NTn)
即两个周期为 N 的抽样函数, 他们的卷积的离散傅里叶变换等于他们的离散傅里叶变换的卷积
卷积的应用:
去除噪声, 特征增强
两个不同周期的信号卷积需要周期扩展的原因:如果直接进行傅里叶变换和乘积,会产生折叠误差(卷绕)。
0.2.10. 相关定理
下面用$ \infty$ 表示相关。
相关函数描述了两个信号之间的相似性,其相关性大小有相关系数衡量
- 相关函数的定义
离散
f(x,y)∞g(x,y)=1MN∑m=0M−1∑n=0N−1f∗(m,n)g(x+m,y+n)f(x,y)\quad \infty \quad g(x,y) = \frac{1}{MN}\sum_{m=0}^{M-1}\sum_{n=0}^{N-1}f^*(m,n)g(x+m,y+n) f(x,y)∞g(x,y)=MN1m=0∑M−1n=0∑N−1f∗(m,n)g(x+m,y+n)
连续
z(t)=∫−∞∞x∗(τ)h(t+τ)dτz(t) = \int_{-\infty}^{\infty}x^*(\tau) h(t+\tau)d\tauz(t)=∫−∞∞x∗(τ)h(t+τ)dτ - 定理
f(x,y)∞g(x,y)<=>F∗(u,v)G(u,v)f(x,y)\quad \infty \quad g(x,y)<=>F^*(u,v)G(u,v) f(x,y)∞g(x,y)<=>F∗(u,v)G(u,v)
0.2.11. Rayleigh 定理
能量变换
对于有限区间非零函数 f(t), 其能量为
E=∫−∞∞∣f(t)∣2dtE = \int_{-\infty}^{\infty}|f(t)|^2dt E=∫−∞∞∣f(t)∣2dt
其变换函数与原函数有相同的能量
∫−∞∞∣f(t)∣2dt=∫−∞∞∣F(u)∣2dt\int_{-\infty}^{\infty}|f(t)|^2dt = \int_{-\infty}^{\infty}|F(u)|^2dt ∫−∞∞∣f(t)∣2dt=∫−∞∞∣F(u)∣2dt
0.3. 快速傅里叶变换
由上面离散傅里叶变换的性质易知,直接计算 1维 dft 的时间复杂度维 O(N2)O(N^2)O(N2)。
利用到单位根的对称性,快速傅里叶变换可以达到 O(nlogn)O(nlogn)O(nlogn)的时间复杂度。
0.3.1. 复数中的单位根
我们知道, 在复平面,复数 cosθ+isinθcos\theta +i\ sin\thetacosθ+i sinθk可以表示成 eiθe^{i\theta}eiθ, 可以对应一个向量。θ\thetaθ即为幅角。
在单位圆中 ,单位圆被分成 2πθ\frac{2\pi}{\theta}θ2π 份, 由单位圆的对称性
eiθ=ei(θ+2π)e^{i\theta} = e^{i(\theta+2\pi)} eiθ=ei(θ+2π)
现在记 $ n =\frac{ 2\pi }{\theta}$ , 即被分成 n 份,幅度角为正且最小的向量称为 n 次单位向量, 记为ωn\omega _nωn,
其余的 n-1 个向量分别为 ωn2,ωn3,…,ωnn\omega_{n}^{2},\omega_{n}^{3},\ldots,\omega_{n}^{n}ωn2,ωn3,…,ωnn ,它们可以由复数之间的乘法得来 $w_{n}{k}=w_{n}{k-1}\cdot w_{n}^{1}\ (2 \leq k \leq n) $。
单位根的性质
- 这个可以用 e 表示出来证明
ω2n2k=ωnk\omega_{2n}^{2k}=\omega_{n}^{k} ω2n2k=ωnk - 可以写成三角函数证明
ωnk+n2=−ωnk\omega_{n}^{k+\frac{n}{2}}=-\omega_{n}^{k} ωnk+2n=−ωnk
容易看出 $w_{n}{n}=w_{n}{0}=1 $。
对于$ w_{n}^{k}$ , 它事实上就是 e2πinke^{\frac{2\pi i}{n}k}en2πik 。
0.3.2. 快速傅里叶变换的计算
下面的推导假设 n=2kn=2^kn=2k,以及代码实现 FFT 部分也是 如此。
利用上面的对称性,
将傅里叶计算进行奇偶分组
F(u)=∑i=0n−1ωniuai=∑i=0n2−1ωn2iua2i+∑i=0n2−1ωn(2i+1)ua2i+1=∑i=0n2−1ωn2iua2i+ωnu∑i=0n2−1ωn2iua2i+1=Feven(u)+ωnuFodd(u)\begin{aligned} F(u)&=\sum_{i=0}^{n-1}\omega_n ^{iu} a^i\\ &= \sum_{i=0}^{\frac{n}{2}-1}\omega_n ^{2iu} a^{2i}+\sum_{i=0}^{\frac{n}{2}-1}\omega_n ^{(2i+1)u} a^{2i+1}\\ &=\sum_{i=0}^{\frac{n}{2}-1}\omega_{\frac{n}{2}} ^{iu} a^{2i}+\omega_n^u\sum_{i=0}^{\frac{n}{2}-1}\omega_{\frac{n}{2}} ^{iu} a^{2i+1}\\ & = F_{even}(u)+\omega_n^u F_{odd}(u) \end{aligned} F(u)=i=0∑n−1ωniuai=i=0∑2n−1ωn2iua2i+i=0∑2n−1ωn(2i+1)ua2i+1=i=0∑2n−1ω2niua2i+ωnui=0∑2n−1ω2niua2i+1=Feven(u)+ωnuFodd(u)
FevenF_{even}Feven表示将 输入的次序中偶数点进行 Fourier 变换, FoddF_{odd}Fodd 同理,这样就形成递推公式。
现在还没有减少计算量,下面通过将分别计算的 奇项,偶项利用起来,只计算 前 n2−1\frac{n}{2}-12n−1项,后面的一半可以利用此结果马上算出来。每一次可以减少一半的计算量。
对于 n2≤i+n2≤n−1\frac{n}{2}\leq i+\frac{n}{2}\leq n-12n≤i+2n≤n−1
F(ωni+n2)=Feven(ωn2i+n)+ωni+n2⋅Fodd(ωn2i+n)=Feven(ωn2i+n2)+ωn2i+n2⋅Fodd(ωn2i+n2)=Feven(ωn2i)−ωn2i⋅Fodd(ωn2i)\begin{aligned} F(\omega_{n}^{i+\frac{n}{2}})&=F_{even}(\omega_{n}^{2i+n})+\omega_{n}^{i+\frac{n}{2}}\cdot F_{odd}(\omega_{n}^{2i+n})\\ &=F_{even}(\omega_{\frac{n}{2}}^{i+\frac{n}{2}})+\omega_{\frac{n}{2}}^{i+\frac{n}{2}}\cdot F_{odd}(\omega_{\frac{n}{2}}^{i+\frac{n}{2}})\\ & =F_{even}(\omega_{\frac{n}{2}}^{i})-\omega_{\frac{n}{2}}^{i}\cdot F_{odd}(\omega_{\frac{n}{2}}^{i}) \end{aligned} F(ωni+2n)=Feven(ωn2i+n)+ωni+2n⋅Fodd(ωn2i+n)=Feven(ω2ni+2n)+ω2ni+2n⋅Fodd(ω2ni+2n)=Feven(ω2ni)−ω2ni⋅Fodd(ω2ni)
现在很清楚了,在每次计算 a[0…n-1] 的傅里叶变换F[0…n-1],分别计算出奇 odd[0…n/2-1],偶even[0…n/2-1](可以递归地进行),
那么傅里叶变换为:
F[i]={even[i]+ωi⋅odd[i],i<n2even[i]−ωi⋅odd[i],elseF[i] = \begin{cases} even[i]+ \omega^i \cdot odd[i], \quad i<\frac{n}{2}\\ even[i]- \omega^i \cdot odd[i], \quad else \end{cases} F[i]={even[i]+ωi⋅odd[i],i<2neven[i]−ωi⋅odd[i],else
0.4. 代码
下面是 python 实现
一维用 FFT 实现, 不过 只实现了 2 的幂。/ 对于非 2 的幂,用 FFT 实现有点困难,还需要插值,所以我 用O(n2)O(n^2)O(n2) 直接实现。
二维的 DFT利用 分离性,直接调用 一维 FFT。
GitHub
import numpy as npdef _fft(a, invert=False):N = len(a)if N == 1:return [a[0]]elif N & (N - 1) == 0: # O(nlogn), 2^keven = _fft(a[::2], invert)odd = _fft(a[1::2], invert)i = 2j if invert else -2jfactor = np.exp(i * np.pi * np.arange(N // 2) / N)prod = factor * oddreturn np.concatenate([even + prod, even - prod])else: # O(n^2)w = np.arange(N)i = 2j if invert else -2jm = w.reshape((N, 1)) * wW = np.exp(m * i * np.pi / N)return np.concatenate(np.dot(W, a.reshape((N, 1)))) # important, cannot use *def fft(a):'''fourier[a]'''n = len(a)if n == 0:raise Exception("[Error]: Invalid length: 0")return _fft(a)def ifft(a):'''invert fourier[a]'''n = len(a)if n == 0:raise Exception("[Error]: Invalid length: 0")return _fft(a, True) / ndef fft2(arr):return np.apply_along_axis(fft, 0,np.apply_along_axis(fft, 1, np.asarray(arr)))def ifft2(arr):return np.apply_along_axis(ifft, 0,np.apply_along_axis(ifft, 1, np.asarray(arr)))def test(n=128):print('\nsequence length:', n)print('fft')li = np.random.random(n)print(np.allclose(fft(li), np.fft.fft(li)))print('ifft')li = np.random.random(n)print(np.allclose(ifft(li), np.fft.ifft(li)))print('fft2')li = np.random.random(n * n).reshape((n, n))print(np.allclose(fft2(li), np.fft.fft2(li)))print('ifft2')li = np.random.random(n * n).reshape((n, n))print(np.allclose(ifft2(li), np.fft.ifft2(li)))if __name__ == '__main__':for i in range(1, 3):test(i * 16)
0.5. 参考
- 万寿红老师课件
- 一小时学会快速傅里叶变换 Fast Fourier Transform
- 快速傅里叶变换(FFT)算法【详解】
傅里叶变换--快速傅里叶变换实现相关推荐
- 快速傅里叶变换-快速傅里叶变换
快速傅里叶变换-正文 计算离散傅里叶变换的一种快速算法,简称FFT.快速傅里叶变换是1965年由J.W.库利和T.W.图基提出的.采用这种算法能使计算机计算离散傅里叶变换所需要的乘法次数大为减少,特别 ...
- 用matlab对excel数据傅里叶变换,快速傅里叶变换_用excel如何作快速傅里叶变换?...
用excel如何作快速傅里叶变换? 具体实例如下: 1.对于时间序列,可以展开成傅立叶级数,进行频谱分析.对于时间序列xt其傅立叶级数展开式为展开成傅立叶级数: 由图可见,图形完全对称,通常只取左半部 ...
- 【Python】可视化的离散傅里叶变换+快速傅里叶变换后时域信号的频域分析
前面的知识这里就不介绍了,下面是Python语言实现的离散傅里叶变换的处理: 时域信号的函数表达 要处理的时域信号: f(t)=sin(t)+2sin(3t)+2cos(2t)+4sin(15t)f( ...
- 在python实现快速傅里叶变换FFT与频域滤波
参考:https://baike.baidu.com/item/快速傅里叶变换/214957?fr=aladdin https://blog.csdn.net/u012531536/article/d ...
- python语音信号快速傅里叶变换
python语音信号快速傅里叶变换 文章目录 python语音信号快速傅里叶变换 快速傅里叶变换的理解 引入必要的库 快速傅里叶变换函数用法 快速傅里叶变换的理解 快速傅里叶变换 (fast Four ...
- c语言做快速傅里叶变换和快速逆傅里叶变换
C语言做快速傅里叶变换和快速逆傅里叶变换 快速傅里叶变换(FFT)和快速逆傅里叶变换(IFFT)要求做傅里叶变换的数据点数只能是2的整数次幂,比如2,4,8,16,32,64,128,256,512, ...
- 【FFT】快速傅里叶变换
开个新坑, 快速傅里叶变换在现在世界的各个领域都发挥重要作用. 包括音视频压缩.5G.WIFI.卷积.航空.雷达.核武等等 为什么使用快速傅里叶变换 快速傅里叶变换计算复杂度仅为O(nlogn) 而原 ...
- 图像傅里叶变换(快速傅里叶变换FFT)
学习DIP第7天,图像傅里叶变换 转载请标明出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对 ...
- 离散傅里叶变换 (DFT)、快速傅里叶变换 (FFT)
目录 离散傅里叶变换 (DFT) 离散傅里叶变换的基 离散傅里叶变换 快速傅里叶变换 (FFT) 卷积 线性时不变系统 傅里叶级数 参考文献 离散傅里叶变换 (DFT) 离散傅里叶变换的基 对于周期为 ...
最新文章
- 只需一行代码,你的纯文本秒变 Markdown
- DIY三通道程控直流电源
- Spark创建RDD的四种方式(一):从集合(内存)中创建 RDD代码示例
- hibernate 延迟加载的错误 failed to lazily initialize a collection of role
- springboot 详解 (四)redis filter
- linux c之命名管道简单使用
- word 2010中正文页码如何从第1页开始?
- 阿里云官方网站免费套餐怎么抢
- Python实现:某个用户登录后,查看自己拥有所有权限
- jsp连接Sql Server 2000数据库
- ajax上传文件报错500,JQuery的AJAX文件上传错误500
- 九、SpringBoot——默认错误页面错误页面定制
- DELL G3 3590 重装win10后,显卡不识别,喇叭x号没声解决办法
- 记录-QuartuesⅡ-Qsys自定义数码管IP过程以及遇到的源文件路径问题
- LVGL 7.8.1生成二维码例程
- 《Reasoning about Entailment with Neural Attention》阅读笔记
- 基于一道ctf 引发的 TP链分析
- 假设检验-方差齐性检验
- 通过股票代码识别所属板块(20190730)
- 微星GE62 NVIDIA960m 双系统ubuntu16.04 配置caffe-ssd