傅里叶变换--快速傅里叶变换实现

快速傅里叶变换学习(超详细,附代码实现) 在学习快速傅里叶变换之前,我们首先需要了解傅里叶变换。傅里叶变换,是将信号从时域的表现形式换成频域上的表现形式。如下面的正弦波: 阅读详情

图像处理中, 为了方便处理,便于抽取特征,数据压缩等目的,常常要将图像进行变换。
一般有如下变换方法

  1. 傅立叶变换Fourier Transform
  2. 离散余弦变换Discrete Cosine Transform
  3. 沃尔希-哈德玛变换Walsh-Hadamard Transform
  4. 斜变换Slant Transform
  5. 哈尔变换Haar Transform
  6. 离散K-L变换Discrete Karhunen-Leave Transform
  7. 奇异值分解SVD变换Singular-Value Decomposition
  8. 离散小波变换Discrete Wavelet Transform

这篇文章介绍一下傅里叶变换

0.1. 定义

0.1.1. 连续

积分形式
如果一个函数的绝对值的积分存在,即
∫ − ∞ ∞ ∣ h ( t ) ∣ d t &lt; ∞ \int_{-\infty} ^\infty |h(t)|dt&lt;\infty ∫−∞∞​∣h(t)∣dt<∞
并且函数是连续的或者只有有限个不连续点,则对于 x 的任何值, 函数的傅里叶变换存在

  • 一维傅里叶变换
    H ( f ) = ∫ − ∞ ∞ h ( t ) e − j 2 π f t d t H(f)=\int_{-\infty} ^\infty h(t)e^{-j2\pi ft}dt H(f)=∫−∞∞​h(t)e−j2πftdt
  • 一维傅里叶逆变换
    H ( f ) = ∫ − ∞ ∞ h ( t ) e j 2 π f t d t H(f)=\int_{-\infty} ^\infty h(t)e^{j2\pi ft}dt H(f)=∫−∞∞​h(t)ej2πftdt
    同理多重积分

0.1.2. 离散

实际应用中,多用离散傅里叶变换 DFT.

  • 一维傅里叶变换
    F ( u ) = ∑ x = 0 N − 1 f ( x ) e − 2 π j N u x F(u)=\sum_{x=0} ^{N-1} f(x)e^{\frac{-2\pi j}{N} ux} F(u)=x=0∑N−1​f(x)eN−2πj​ux
  • 一维傅里叶逆变换
    f ( x ) = 1 N ∑ u = 0 N − 1 F ( u ) e 2 π j N u x f(x)=\frac{1}{N}\sum_{u=0} ^{N-1} F(u)e^{\frac{2\pi j}{N} ux} f(x)=N1​u=0∑N−1​F(u)eN2πj​ux
    需要注意的是, 逆变换乘以 1 N \frac{1}{N} N1​ 是为了归一化,这个系数可以随意改变, 即可以正变换乘以 1 N \frac{1}{N} N1​, 逆变换就不乘,或者两者都乘以 1 N \frac{1}{\sqrt{N}} N ​1​等系数。
  • 二维傅里叶变换
    F ( u , v ) = 1 N ∑ x = 0 N − 1 ∑ y = 0 N − 1 f ( x , y ) e − 2 π j N ( u x + v y ) 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)=N1​x=0∑N−1​y=0∑N−1​f(x,y)eN−2πj​(ux+vy)
  • 二维傅里叶逆变换

f ( x , y ) = 1 N ∑ u = 0 N − 1 ∑ v = 0 N − 1 F ( u , v ) e 2 π j N ( u x + v y ) 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)=N1​u=0∑N−1​v=0∑N−1​F(u,v)eN2πj​(ux+vy)

幅度
∣ F ( u , v ) ∣ = r e a l ( F ) 2 + i m a g ( F ) 2 |F(u,v)| = \sqrt{real(F)^2+imag(F)^2} ∣F(u,v)∣=real(F)2+imag(F)2 ​
相位
a r c t a n i m a g ( F ) r e a l ( F ) arctan{\frac{imag(F)}{real(F)}} arctanreal(F)imag(F)​
对于图像的幅度谱显示,由于 |F(u,v)| 变换范围太大,一般显示 D = l o g ( ∣ F ( u , v ) + 1 ) D= log(|F(u,v)+1) D=log(∣F(u,v)+1)

用 <=> 表示傅里叶变换对
f ( x ) &lt; = &gt; F ( u ) f ( x , y ) &lt; = &gt; F ( u , v ) f(x)&lt;=&gt;F(u)\\ f(x,y)&lt;=&gt;F(u,v) f(x)<=>F(u)f(x,y)<=>F(u,v)

f,g,h 对应的傅里叶变换 F,G,H

F ∗ F^* F∗ 表示 F F F 的共轭

0.2. 性质

0.2.1. 分离性

F ( x , v ) = ∑ y = 0 N − 1 f ( x , y ) e − 2 π j N v y F ( u , v ) = 1 N ∑ x = 0 N − 1 F ( x , v ) e − 2 π j N u x \begin{aligned} &amp;F(x,v)=\sum_{y=0} ^{N-1} f(x,y)e^{\frac{-2\pi j}{N} vy}\\ &amp;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−1​f(x,y)eN−2πj​vyF(u,v)=N1​x=0∑N−1​F(x,v)eN−2πj​ux​
进行多维变换时,可以依次对每一维进行变换。 下面在代码中就是这样实现的。

0.2.2. 位移定理

f ( x , y ) e 2 π j N ( u 0 x + v 0 y ) &lt; = &gt; F ( u − u 0 , v − v 0 ) f(x,y)e^{\frac{2\pi j}{N}(u_0x+v_0y)} &lt;=&gt;F(u-u_0,v-v_0) f(x,y)eN2πj​(u0​x+v0​y)<=>F(u−u0​,v−v0​)
f ( x − x 0 , y − y 0 ) &lt; = &gt; F ( u , v ) e − 2 π j N ( u x 0 + v y 0 ) f(x-x_0,y-y_0)&lt;=&gt;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 , θ ) &lt; = &gt; F ( ω , ϕ ) f(r,\theta)&lt;=&gt;F(\omega,\phi) f(r,θ)<=>F(ω,ϕ)
then f ( r , θ + t ) &lt; = &gt; F ( ω , ϕ + t ) f(r,\theta+t)&lt;=&gt;F(\omega,\phi+t) f(r,θ+t)<=>F(ω,ϕ+t)

0.2.6. 加法定理

F o u r i e r [ f + g ] = F o u r i e r [ f ] + F o u r i e r [ g ] Fourier[f+g]=Fourier[f]+Fourier[g] Fourier[f+g]=Fourier[f]+Fourier[g]
2.
a f ( x , y ) &lt; = &gt; a F [ u , v ] af(x,y)&lt;=&gt;aF[u,v] af(x,y)<=>aF[u,v]

0.2.7. 平均值

1 N 2 ∑ x = 0 N − 1 ∑ y = 0 N − 1 f ( x , y ) = 1 N F ( 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) N21​x=0∑N−1​y=0∑N−1​f(x,y)=N1​F(0,0)

0.2.8. 相似性定理

尺度变换
f ( a x , b y ) &lt; = &gt; F ( u a , v b ) a b f(ax,by)&lt;=&gt;\frac{F(\frac{u}{a},\frac{v}{b})}{ab} f(ax,by)<=>abF(au​,bv​)​

0.2.9. 卷积定理

卷积定义
1d
f ∗ g = 1 M ∑ m = 0 M − 1 f ( m ) g ( x − m ) f*g = \frac{1}{M}\sum_{m=0}^{M-1}f(m)g(x-m) f∗g=M1​m=0∑M−1​f(m)g(x−m)
2d
f ( x , y ) ∗ g ( x , y ) = 1 M N ∑ m = 0 M − 1 ∑ n = 0 N − 1 f ( 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)=MN1​m=0∑M−1​n=0∑N−1​f(m,n)g(x−m,y−n)

卷积定理
f ( x , y ) ∗ g ( x , y ) &lt; = &gt; F ( u , v ) G ( u , v ) f(x,y)*g(x,y) &lt;=&gt; F(u,v)G(u,v) f(x,y)∗g(x,y)<=>F(u,v)G(u,v)
f ( x , y ) g ( x , y ) &lt; = &gt; F ( u , v ) ∗ G ( u , v ) f(x,y)g(x,y)&lt;=&gt;F(u,v)*G(u,v) f(x,y)g(x,y)<=>F(u,v)∗G(u,v)

离散卷积
用
∑ i = 0 N − 1 x ( i T ) h [ ( k − i ) T ] &lt; = &gt; X ( n N T ) H ( n N T ) \sum_{i=0}^{N-1}x(iT)h[(k-i)T] &lt;=&gt; X(\frac{n}{NT})H(\frac{n}{NT}) i=0∑N−1​x(iT)h[(k−i)T]<=>X(NTn​)H(NTn​)
即两个周期为 N 的抽样函数, 他们的卷积的离散傅里叶变换等于他们的离散傅里叶变换的卷积

卷积的应用:
去除噪声, 特征增强
两个不同周期的信号卷积需要周期扩展的原因:如果直接进行傅里叶变换和乘积,会产生折叠误差(卷绕)。

0.2.10. 相关定理

下面用$ \infty$ 表示相关。
相关函数描述了两个信号之间的相似性,其相关性大小有相关系数衡量

  • 相关函数的定义
    离散
    f ( x , y ) ∞ g ( x , y ) = 1 M N ∑ m = 0 M − 1 ∑ n = 0 N − 1 f ∗ ( 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)=MN1​m=0∑M−1​n=0∑N−1​f∗(m,n)g(x+m,y+n)
    连续
    z ( t ) = ∫ − ∞ ∞ x ∗ ( τ ) h ( t + τ ) d τ z(t) = \int_{-\infty}^{\infty}x^*(\tau) h(t+\tau)d\tau z(t)=∫−∞∞​x∗(τ)h(t+τ)dτ
  • 定理
    f ( x , y ) ∞ g ( x , y ) &lt; = &gt; F ∗ ( u , v ) G ( u , v ) f(x,y)\quad \infty \quad g(x,y)&lt;=&gt;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 ) ∣ 2 d t E = \int_{-\infty}^{\infty}|f(t)|^2dt E=∫−∞∞​∣f(t)∣2dt

其变换函数与原函数有相同的能量
∫ − ∞ ∞ ∣ f ( t ) ∣ 2 d t = ∫ − ∞ ∞ ∣ F ( u ) ∣ 2 d t \int_{-\infty}^{\infty}|f(t)|^2dt = \int_{-\infty}^{\infty}|F(u)|^2dt ∫−∞∞​∣f(t)∣2dt=∫−∞∞​∣F(u)∣2dt

0.3. 快速傅里叶变换

由上面离散傅里叶变换的性质易知,直接计算 1维 dft 的时间复杂度维 O ( N 2 ) O(N^2) O(N2)。

利用到单位根的对称性,快速傅里叶变换可以达到 O ( n l o g n ) O(nlogn) O(nlogn)的时间复杂度。

0.3.1. 复数中的单位根

我们知道, 在复平面,复数 c o s θ + i   s i n θ cos\theta +i\ sin\theta cosθ+i sinθk可以表示成 e i θ e^{i\theta} eiθ, 可以对应一个向量。 θ \theta θ即为幅角。
在单位圆中 ,单位圆被分成 2 π θ \frac{2\pi}{\theta} θ2π​ 份, 由单位圆的对称性
e i θ = e i ( θ + 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 个向量分别为 ω n 2 , ω n 3 , … , ω n n \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) $。
单位根的性质

  1. 这个可以用 e 表示出来证明
    ω 2 n 2 k = ω n k \omega_{2n}^{2k}=\omega_{n}^{k} ω2n2k​=ωnk​
  2. 可以写成三角函数证明
    ω n k + n 2 = − ω n k \omega_{n}^{k+\frac{n}{2}}=-\omega_{n}^{k} ωnk+2n​​=−ωnk​

容易看出 $w_{n}{n}=w_{n}{0}=1 $。

对于$ w_{n}^{k}$ , 它事实上就是 e 2 π i n k e^{\frac{2\pi i}{n}k} en2πi​k 。

0.3.2. 快速傅里叶变换的计算

下面的推导假设 n = 2 k n=2^k n=2k,以及代码实现 FFT 部分也是 如此。

利用上面的对称性,
将傅里叶计算进行奇偶分组
F ( u ) = ∑ i = 0 n − 1 ω n i u a i = ∑ i = 0 n 2 − 1 ω n 2 i u a 2 i + ∑ i = 0 n 2 − 1 ω n ( 2 i + 1 ) u a 2 i + 1 = ∑ i = 0 n 2 − 1 ω n 2 i u a 2 i + ω n u ∑ i = 0 n 2 − 1 ω n 2 i u a 2 i + 1 = F e v e n ( u ) + ω n u F o d d ( u ) \begin{aligned} F(u)&amp;=\sum_{i=0}^{n-1}\omega_n ^{iu} a^i\\ &amp;= \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}\\ &amp;=\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}\\ &amp; = F_{even}(u)+\omega_n^u F_{odd}(u) \end{aligned} F(u)​=i=0∑n−1​ωniu​ai=i=0∑2n​−1​ωn2iu​a2i+i=0∑2n​−1​ωn(2i+1)u​a2i+1=i=0∑2n​−1​ω2n​iu​a2i+ωnu​i=0∑2n​−1​ω2n​iu​a2i+1=Feven​(u)+ωnu​Fodd​(u)​
F e v e n F_{even} Feven​表示将 输入的次序中偶数点进行 Fourier 变换, F o d d F_{odd} Fodd​ 同理,这样就形成递推公式。
现在还没有减少计算量,下面通过将分别计算的 奇项,偶项利用起来,只计算 前 n 2 − 1 \frac{n}{2}-1 2n​−1项,后面的一半可以利用此结果马上算出来。每一次可以减少一半的计算量。

对于 n 2 ≤ i + n 2 ≤ n − 1 \frac{n}{2}\leq i+\frac{n}{2}\leq n-1 2n​≤i+2n​≤n−1
F ( ω n i + n 2 ) = F e v e n ( ω n 2 i + n ) + ω n i + n 2 ⋅ F o d d ( ω n 2 i + n ) = F e v e n ( ω n 2 i + n 2 ) + ω n 2 i + n 2 ⋅ F o d d ( ω n 2 i + n 2 ) = F e v e n ( ω n 2 i ) − ω n 2 i ⋅ F o d d ( ω n 2 i ) \begin{aligned} F(\omega_{n}^{i+\frac{n}{2}})&amp;=F_{even}(\omega_{n}^{2i+n})+\omega_{n}^{i+\frac{n}{2}}\cdot F_{odd}(\omega_{n}^{2i+n})\\ &amp;=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}})\\ &amp; =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​(ω2n​i+2n​​)+ω2n​i+2n​​⋅Fodd​(ω2n​i+2n​​)=Feven​(ω2n​i​)−ω2n​i​⋅Fodd​(ω2n​i​)​
现在很清楚了,在每次计算 a[0…n-1] 的傅里叶变换F[0…n-1],分别计算出奇 odd[0…n/2-1],偶even[0…n/2-1](可以递归地进行),
那么傅里叶变换为:
F [ i ] = { e v e n [ i ] + ω i ⋅ o d d [ i ] , i &lt; n 2 e v e n [ i ] − ω i ⋅ o d d [ i ] , e l s e F[i] = \begin{cases} even[i]+ \omega^i \cdot odd[i], \quad i&lt;\frac{n}{2}\\ even[i]- \omega^i \cdot odd[i], \quad else \end{cases} F[i]={even[i]+ωi⋅odd[i],i<2n​even[i]−ωi⋅odd[i],else​

0.4. 代码

下面是 python 实现
一维用 FFT 实现, 不过 只实现了 2 的幂。/ 对于非 2 的幂,用 FFT 实现有点困难,还需要插值,所以我 用 O ( n 2 ) O(n^2) O(n2) 直接实现。

二维的 DFT利用 分离性,直接调用 一维 FFT。
GitHub

import numpy as np


def _fft(a, invert=False):
    N = len(a)
    if N == 1:
        return [a[0]]
    elif N & (N - 1) == 0:  # O(nlogn),  2^k
        even = _fft(a[::2], invert)
        odd = _fft(a[1::2], invert)
        i = 2j if invert else -2j
        factor = np.exp(i * np.pi * np.arange(N // 2) / N)
        prod = factor * odd
        return np.concatenate([even + prod, even - prod])
    else:  # O(n^2)
        w = np.arange(N)
        i = 2j if invert else -2j
        m = w.reshape((N, 1)) * w
        W = 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) / n


def 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. 参考

图像处理中, 为了方便处理,便于抽取特征,数据压缩等目的,常常要将图像进行变换。
一般有如下变换方法

  1. 傅立叶变换Fourier Transform
  2. 离散余弦变换Discrete Cosine Transform
  3. 沃尔希-哈德玛变换Walsh-Hadamard Transform
  4. 斜变换Slant Transform
  5. 哈尔变换Haar Transform
  6. 离散K-L变换Discrete Karhunen-Leave Transform
  7. 奇异值分解SVD变换Singular-Value Decomposition
  8. 离散小波变换Discrete Wavelet Transform

这篇文章介绍一下傅里叶变换

0.1. 定义

0.1.1. 连续

积分形式
如果一个函数的绝对值的积分存在,即
∫ − ∞ ∞ ∣ h ( t ) ∣ d t &lt; ∞ \int_{-\infty} ^\infty |h(t)|dt&lt;\infty ∫−∞∞​∣h(t)∣dt<∞
并且函数是连续的或者只有有限个不连续点,则对于 x 的任何值, 函数的傅里叶变换存在

  • 一维傅里叶变换
    H ( f ) = ∫ − ∞ ∞ h ( t ) e − j 2 π f t d t H(f)=\int_{-\infty} ^\infty h(t)e^{-j2\pi ft}dt H(f)=∫−∞∞​h(t)e−j2πftdt
  • 一维傅里叶逆变换
    H ( f ) = ∫ − ∞ ∞ h ( t ) e j 2 π f t d t H(f)=\int_{-\infty} ^\infty h(t)e^{j2\pi ft}dt H(f)=∫−∞∞​h(t)ej2πftdt
    同理多重积分

0.1.2. 离散

实际应用中,多用离散傅里叶变换 DFT.

  • 一维傅里叶变换
    F ( u ) = ∑ x = 0 N − 1 f ( x ) e − 2 π j N u x F(u)=\sum_{x=0} ^{N-1} f(x)e^{\frac{-2\pi j}{N} ux} F(u)=x=0∑N−1​f(x)eN−2πj​ux
  • 一维傅里叶逆变换
    f ( x ) = 1 N ∑ u = 0 N − 1 F ( u ) e 2 π j N u x f(x)=\frac{1}{N}\sum_{u=0} ^{N-1} F(u)e^{\frac{2\pi j}{N} ux} f(x)=N1​u=0∑N−1​F(u)eN2πj​ux
    需要注意的是, 逆变换乘以 1 N \frac{1}{N} N1​ 是为了归一化,这个系数可以随意改变, 即可以正变换乘以 1 N \frac{1}{N} N1​, 逆变换就不乘,或者两者都乘以 1 N \frac{1}{\sqrt{N}} N ​1​等系数。
  • 二维傅里叶变换
    F ( u , v ) = 1 N ∑ x = 0 N − 1 ∑ y = 0 N − 1 f ( x , y ) e − 2 π j N ( u x + v y ) 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)=N1​x=0∑N−1​y=0∑N−1​f(x,y)eN−2πj​(ux+vy)
  • 二维傅里叶逆变换

f ( x , y ) = 1 N ∑ u = 0 N − 1 ∑ v = 0 N − 1 F ( u , v ) e 2 π j N ( u x + v y ) 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)=N1​u=0∑N−1​v=0∑N−1​F(u,v)eN2πj​(ux+vy)

幅度
∣ F ( u , v ) ∣ = r e a l ( F ) 2 + i m a g ( F ) 2 |F(u,v)| = \sqrt{real(F)^2+imag(F)^2} ∣F(u,v)∣=real(F)2+imag(F)2 ​
相位
a r c t a n i m a g ( F ) r e a l ( F ) arctan{\frac{imag(F)}{real(F)}} arctanreal(F)imag(F)​
对于图像的幅度谱显示,由于 |F(u,v)| 变换范围太大,一般显示 D = l o g ( ∣ F ( u , v ) + 1 ) D= log(|F(u,v)+1) D=log(∣F(u,v)+1)

用 <=> 表示傅里叶变换对
f ( x ) &lt; = &gt; F ( u ) f ( x , y ) &lt; = &gt; F ( u , v ) f(x)&lt;=&gt;F(u)\\ f(x,y)&lt;=&gt;F(u,v) f(x)<=>F(u)f(x,y)<=>F(u,v)

f,g,h 对应的傅里叶变换 F,G,H

F ∗ F^* F∗ 表示 F F F 的共轭

0.2. 性质

0.2.1. 分离性

F ( x , v ) = ∑ y = 0 N − 1 f ( x , y ) e − 2 π j N v y F ( u , v ) = 1 N ∑ x = 0 N − 1 F ( x , v ) e − 2 π j N u x \begin{aligned} &amp;F(x,v)=\sum_{y=0} ^{N-1} f(x,y)e^{\frac{-2\pi j}{N} vy}\\ &amp;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−1​f(x,y)eN−2πj​vyF(u,v)=N1​x=0∑N−1​F(x,v)eN−2πj​ux​
进行多维变换时,可以依次对每一维进行变换。 下面在代码中就是这样实现的。

0.2.2. 位移定理

f ( x , y ) e 2 π j N ( u 0 x + v 0 y ) &lt; = &gt; F ( u − u 0 , v − v 0 ) f(x,y)e^{\frac{2\pi j}{N}(u_0x+v_0y)} &lt;=&gt;F(u-u_0,v-v_0) f(x,y)eN2πj​(u0​x+v0​y)<=>F(u−u0​,v−v0​)
f ( x − x 0 , y − y 0 ) &lt; = &gt; F ( u , v ) e − 2 π j N ( u x 0 + v y 0 ) f(x-x_0,y-y_0)&lt;=&gt;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 , θ ) &lt; = &gt; F ( ω , ϕ ) f(r,\theta)&lt;=&gt;F(\omega,\phi) f(r,θ)<=>F(ω,ϕ)
then f ( r , θ + t ) &lt; = &gt; F ( ω , ϕ + t ) f(r,\theta+t)&lt;=&gt;F(\omega,\phi+t) f(r,θ+t)<=>F(ω,ϕ+t)

0.2.6. 加法定理

F o u r i e r [ f + g ] = F o u r i e r [ f ] + F o u r i e r [ g ] Fourier[f+g]=Fourier[f]+Fourier[g] Fourier[f+g]=Fourier[f]+Fourier[g]
2.
a f ( x , y ) &lt; = &gt; a F [ u , v ] af(x,y)&lt;=&gt;aF[u,v] af(x,y)<=>aF[u,v]

0.2.7. 平均值

1 N 2 ∑ x = 0 N − 1 ∑ y = 0 N − 1 f ( x , y ) = 1 N F ( 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) N21​x=0∑N−1​y=0∑N−1​f(x,y)=N1​F(0,0)

0.2.8. 相似性定理

尺度变换
f ( a x , b y ) &lt; = &gt; F ( u a , v b ) a b f(ax,by)&lt;=&gt;\frac{F(\frac{u}{a},\frac{v}{b})}{ab} f(ax,by)<=>abF(au​,bv​)​

0.2.9. 卷积定理

卷积定义
1d
f ∗ g = 1 M ∑ m = 0 M − 1 f ( m ) g ( x − m ) f*g = \frac{1}{M}\sum_{m=0}^{M-1}f(m)g(x-m) f∗g=M1​m=0∑M−1​f(m)g(x−m)
2d
f ( x , y ) ∗ g ( x , y ) = 1 M N ∑ m = 0 M − 1 ∑ n = 0 N − 1 f ( 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)=MN1​m=0∑M−1​n=0∑N−1​f(m,n)g(x−m,y−n)

卷积定理
f ( x , y ) ∗ g ( x , y ) &lt; = &gt; F ( u , v ) G ( u , v ) f(x,y)*g(x,y) &lt;=&gt; F(u,v)G(u,v) f(x,y)∗g(x,y)<=>F(u,v)G(u,v)
f ( x , y ) g ( x , y ) &lt; = &gt; F ( u , v ) ∗ G ( u , v ) f(x,y)g(x,y)&lt;=&gt;F(u,v)*G(u,v) f(x,y)g(x,y)<=>F(u,v)∗G(u,v)

离散卷积
用
∑ i = 0 N − 1 x ( i T ) h [ ( k − i ) T ] &lt; = &gt; X ( n N T ) H ( n N T ) \sum_{i=0}^{N-1}x(iT)h[(k-i)T] &lt;=&gt; X(\frac{n}{NT})H(\frac{n}{NT}) i=0∑N−1​x(iT)h[(k−i)T]<=>X(NTn​)H(NTn​)
即两个周期为 N 的抽样函数, 他们的卷积的离散傅里叶变换等于他们的离散傅里叶变换的卷积

卷积的应用:
去除噪声, 特征增强
两个不同周期的信号卷积需要周期扩展的原因:如果直接进行傅里叶变换和乘积,会产生折叠误差(卷绕)。

0.2.10. 相关定理

下面用$ \infty$ 表示相关。
相关函数描述了两个信号之间的相似性,其相关性大小有相关系数衡量

  • 相关函数的定义
    离散
    f ( x , y ) ∞ g ( x , y ) = 1 M N ∑ m = 0 M − 1 ∑ n = 0 N − 1 f ∗ ( 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)=MN1​m=0∑M−1​n=0∑N−1​f∗(m,n)g(x+m,y+n)
    连续
    z ( t ) = ∫ − ∞ ∞ x ∗ ( τ ) h ( t + τ ) d τ z(t) = \int_{-\infty}^{\infty}x^*(\tau) h(t+\tau)d\tau z(t)=∫−∞∞​x∗(τ)h(t+τ)dτ
  • 定理
    f ( x , y ) ∞ g ( x , y ) &lt; = &gt; F ∗ ( u , v ) G ( u , v ) f(x,y)\quad \infty \quad g(x,y)&lt;=&gt;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 ) ∣ 2 d t E = \int_{-\infty}^{\infty}|f(t)|^2dt E=∫−∞∞​∣f(t)∣2dt

其变换函数与原函数有相同的能量
∫ − ∞ ∞ ∣ f ( t ) ∣ 2 d t = ∫ − ∞ ∞ ∣ F ( u ) ∣ 2 d t \int_{-\infty}^{\infty}|f(t)|^2dt = \int_{-\infty}^{\infty}|F(u)|^2dt ∫−∞∞​∣f(t)∣2dt=∫−∞∞​∣F(u)∣2dt

0.3. 快速傅里叶变换

由上面离散傅里叶变换的性质易知,直接计算 1维 dft 的时间复杂度维 O ( N 2 ) O(N^2) O(N2)。

利用到单位根的对称性,快速傅里叶变换可以达到 O ( n l o g n ) O(nlogn) O(nlogn)的时间复杂度。

0.3.1. 复数中的单位根

我们知道, 在复平面,复数 c o s θ + i   s i n θ cos\theta +i\ sin\theta cosθ+i sinθk可以表示成 e i θ e^{i\theta} eiθ, 可以对应一个向量。 θ \theta θ即为幅角。
在单位圆中 ,单位圆被分成 2 π θ \frac{2\pi}{\theta} θ2π​ 份, 由单位圆的对称性
e i θ = e i ( θ + 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 个向量分别为 ω n 2 , ω n 3 , … , ω n n \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) $。
单位根的性质

  1. 这个可以用 e 表示出来证明
    ω 2 n 2 k = ω n k \omega_{2n}^{2k}=\omega_{n}^{k} ω2n2k​=ωnk​
  2. 可以写成三角函数证明
    ω n k + n 2 = − ω n k \omega_{n}^{k+\frac{n}{2}}=-\omega_{n}^{k} ωnk+2n​​=−ωnk​

容易看出 $w_{n}{n}=w_{n}{0}=1 $。

对于$ w_{n}^{k}$ , 它事实上就是 e 2 π i n k e^{\frac{2\pi i}{n}k} en2πi​k 。

0.3.2. 快速傅里叶变换的计算

下面的推导假设 n = 2 k n=2^k n=2k,以及代码实现 FFT 部分也是 如此。

利用上面的对称性,
将傅里叶计算进行奇偶分组
F ( u ) = ∑ i = 0 n − 1 ω n i u a i = ∑ i = 0 n 2 − 1 ω n 2 i u a 2 i + ∑ i = 0 n 2 − 1 ω n ( 2 i + 1 ) u a 2 i + 1 = ∑ i = 0 n 2 − 1 ω n 2 i u a 2 i + ω n u ∑ i = 0 n 2 − 1 ω n 2 i u a 2 i + 1 = F e v e n ( u ) + ω n u F o d d ( u ) \begin{aligned} F(u)&amp;=\sum_{i=0}^{n-1}\omega_n ^{iu} a^i\\ &amp;= \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}\\ &amp;=\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}\\ &amp; = F_{even}(u)+\omega_n^u F_{odd}(u) \end{aligned} F(u)​=i=0∑n−1​ωniu​ai=i=0∑2n​−1​ωn2iu​a2i+i=0∑2n​−1​ωn(2i+1)u​a2i+1=i=0∑2n​−1​ω2n​iu​a2i+ωnu​i=0∑2n​−1​ω2n​iu​a2i+1=Feven​(u)+ωnu​Fodd​(u)​
F e v e n F_{even} Feven​表示将 输入的次序中偶数点进行 Fourier 变换, F o d d F_{odd} Fodd​ 同理,这样就形成递推公式。
现在还没有减少计算量,下面通过将分别计算的 奇项,偶项利用起来,只计算 前 n 2 − 1 \frac{n}{2}-1 2n​−1项,后面的一半可以利用此结果马上算出来。每一次可以减少一半的计算量。

对于 n 2 ≤ i + n 2 ≤ n − 1 \frac{n}{2}\leq i+\frac{n}{2}\leq n-1 2n​≤i+2n​≤n−1
F ( ω n i + n 2 ) = F e v e n ( ω n 2 i + n ) + ω n i + n 2 ⋅ F o d d ( ω n 2 i + n ) = F e v e n ( ω n 2 i + n 2 ) + ω n 2 i + n 2 ⋅ F o d d ( ω n 2 i + n 2 ) = F e v e n ( ω n 2 i ) − ω n 2 i ⋅ F o d d ( ω n 2 i ) \begin{aligned} F(\omega_{n}^{i+\frac{n}{2}})&amp;=F_{even}(\omega_{n}^{2i+n})+\omega_{n}^{i+\frac{n}{2}}\cdot F_{odd}(\omega_{n}^{2i+n})\\ &amp;=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}})\\ &amp; =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​(ω2n​i+2n​​)+ω2n​i+2n​​⋅Fodd​(ω2n​i+2n​​)=Feven​(ω2n​i​)−ω2n​i​⋅Fodd​(ω2n​i​)​
现在很清楚了,在每次计算 a[0…n-1] 的傅里叶变换F[0…n-1],分别计算出奇 odd[0…n/2-1],偶even[0…n/2-1](可以递归地进行),
那么傅里叶变换为:
F [ i ] = { e v e n [ i ] + ω i ⋅ o d d [ i ] , i &lt; n 2 e v e n [ i ] − ω i ⋅ o d d [ i ] , e l s e F[i] = \begin{cases} even[i]+ \omega^i \cdot odd[i], \quad i&lt;\frac{n}{2}\\ even[i]- \omega^i \cdot odd[i], \quad else \end{cases} F[i]={even[i]+ωi⋅odd[i],i<2n​even[i]−ωi⋅odd[i],else​

0.4. 代码

下面是 python 实现
一维用 FFT 实现, 不过 只实现了 2 的幂。/ 对于非 2 的幂,用 FFT 实现有点困难,还需要插值,所以我 用 O ( n 2 ) O(n^2) O(n2) 直接实现。

二维的 DFT利用 分离性,直接调用 一维 FFT。
GitHub

import numpy as np


def _fft(a, invert=False):
    N = len(a)
    if N == 1:
        return [a[0]]
    elif N & (N - 1) == 0:  # O(nlogn),  2^k
        even = _fft(a[::2], invert)
        odd = _fft(a[1::2], invert)
        i = 2j if invert else -2j
        factor = np.exp(i * np.pi * np.arange(N // 2) / N)
        prod = factor * odd
        return np.concatenate([even + prod, even - prod])
    else:  # O(n^2)
        w = np.arange(N)
        i = 2j if invert else -2j
        m = w.reshape((N, 1)) * w
        W = 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) / n


def 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. 参考

十分简明易懂的FFT(快速傅里叶变换) FFT有什么用 快速傅里叶变换 (fast Fourier transform),即利用计算机计算离散傅里叶变换(DFT)的高效、快速计算方法的统称,简称FFT。快速傅里叶变换是1965年由J.W.库利和T.W.图基提出的。采用这种算法能使计算机计算离散傅里叶变换所需要的乘法次数大为减少,特别是被变换的抽样点数N越多,FFT算法计算量的节省就越显著。 FFT(Fast Fouri... 阅读详情

相关推荐

快速傅里叶变换及其实现

一、基本原理 长度为N的有限长离散序列的傅里叶变换的定义为:                                                  (1) 逆变换:                                                 (2) 其中,(3)   用矩阵来表达傅里叶变换为:            (4) 逆变换:

scuhank的专栏 1658

十一、图像傅里叶变换

目录 一、傅里叶变换 二、Numpy实现傅里叶变换 1、实现傅里叶变换 代码 2、实现傅里叶的逆变换 代码 三、OpenCV 实现傅里叶变换 1、实现傅里叶变换 代码 2、实现傅里叶逆变换 代码 四、高通滤波和低通滤波 1、高通滤波和低通滤波概述 2、Numpy 实现高通滤波 3、OpenCV 实现低通滤波 一、傅里叶变换 原理可以参考:傅里叶分析之掐死教程(完整...

嘻哈吼嘿呵的博客 468

C++实现二维快速傅里叶变换(FFT)

上一篇文章里,我根据DFT公式用C++实现了二维离散傅里叶变换。但跑一张300*300的图片都要好几分钟,速度实在太慢了。我研究了下快速傅里叶变换,在网上找了一些资料,然后用C++实现了二维快速傅里叶变换,速度超级快,512*512的图片在0.1秒内就能处理完。 我们知道一维离散傅里叶变换公式如下 其中。 用矩阵表示即为: ...

海盗Isaac 1万+

超详细易懂FFT(快速傅里叶变换)及代码实现

前言 昨天学了一晚上,终于搞懂了FFT。希望能写一篇清楚易懂的题解分享给大家,也进一步加深自己的理解。 FFT算是数论中比较重要的东西,听起来就很高深的亚子。但其实学会了(哪怕并不能完全理解),会实现代码,并知道怎么灵活运用 (背板子) 就行。接下来进入正题。 定义 FFT(Fast Fourier Transformation),中文名快速傅里叶变换,是离散傅氏变换的快速算法,它是根据离散傅氏变...

Flag_z的博客 25万+

快速傅里叶变换及Python代码实现

我想认真写好快速傅里叶变换(Fast Fourier Transform,FFT),所以这篇文章会由浅到细,由窄到宽的讲解,但是傅里叶变换对于寻常人并不是很容易理解的,所以对于基础不牢的人我会通过前言普及一下相关知识。我们复习一下三角函数的标准式:A代表振幅,函数周期是2πw,频率是周期的倒数w2π,θ是函数初相位,k在信号处理中称为直流分量。这个信号在频域就是一条竖线。我们再来假设有一个比较复杂的时域函数y=f(t),根据傅里叶的理论,任何一个周期函数可以被分解为一系列振幅A,频率ω或初相位。

m0_72557783的博客 3169

数字信号处理——Python实现快速傅里叶变换FFT

1、FFT背景 快速傅里叶变换(FFT)是离散傅里叶变换(DFT)的快速算法,它是根据离散傅里叶的奇、偶、虚、实等特性,在DFT的基础上进行改进获得的。它对傅里叶变换的理论没有新的发现,但它的出现让离散傅里叶变换在计算机系统中得到了广泛的应用。 设x(n)为N项的复数序列,对其进行DFT,任一X(m)的计算都需要N次复数乘法和N-1次复数加法,因此要求出N项复序列的X(m),大约需要N2N^2N2次运算。当N逐渐增大时,运算量将呈指数式增长,这在实际应用中是一场灾难。而在FFT中,利用WNW_NWN​的周期

我本傲骄的博客 4940

(数学建模)傅里叶变换-第一节——定义和简单例子(Python实现)

一、引入 生活当中,我们常常需要把杂乱的信息分解开进行研究。比如我们看到的光是无色的,但是当其透过三棱镜时,会发生色散,这样不同颜色的光就被我们分离出来了,我们就可以对光进行研究了。光是一种电磁波,同样地,声波、收音机的波也可以进行类似的处理,将不同的频段分离出来,就可以进行降噪。 二、概念 f(t)是t的周期函数,如果t满足狄里赫莱条件:在一个以2T为周期内f(X)连续或只有有限个第一类间断点,...

numb_ac的博客 3427

快速傅立叶的两种实现方法,c#

两种傅立叶的实现方法,第一种感觉上比较快和matlab的fft所得结果一样,第二种比较慢.用c#写的,当然你可以改成其他语言,比较简单,需要自己写个主函数调用,输入是两个数组(实部与需部),如果只是自然数,需部就需要全部输入0;

快速傅里叶变换及python代码实现

文章来源:https://www.cnblogs.com/LXP-Never/p/11558302.html 快速傅里叶变换及python代码实现 目录 一、前言  傅里叶变换相关函数  基于傅里叶变换的频域滤波  离散傅里叶变换(DFT)二、短时傅里叶变换stft三、frequency bin参考 一、前言   我想认真写好快速傅里叶变换(Fast Fourier Transform,FFT),所以这篇文章会由浅到细,由窄到宽的讲解,但是傅里叶变换对于寻常人并不是很容易理解的,所以对于基

学无止境,居安思危 6329

MATLAB App Designer 实现多窗口交互与数据传递实战

本文详细介绍了如何使用MATLAB App Designer实现多窗口交互与数据传递的实战技巧。从基础的多窗口应用设计到高级的动态窗口创建,涵盖了窗口调用控制、数据传递方法、状态管理及用户体验优化等核心内容,帮助开发者高效构建复杂的MATLAB GUI应用。

milk5的博客 664

避开SM30维护视图的坑:自动更新字段+日志记录的5个关键配置步骤

本文深入解析了SAP ABAP开发中SM30维护视图的深度定制,聚焦于实现自动更新字段与日志记录功能。文章详细阐述了从SE54配置起点到核心编码的5个关键步骤,重点讲解了如何利用事件驱动模型(如05创建事件和01保存前事件)安全操作动态数据结构,并提供了避免常见陷阱的实用技巧,帮助开发者构建稳定可靠的自动化维护机制。

plant的博客 622

傅里叶变换通俗解释及快速傅里叶变换的python实现

  通俗理解傅里叶变换,先看这篇文章傅里叶变换的通俗理解!   接下来便是使用python进行傅里叶FFT-频谱分析: 一、一些关键概念的引入 1、离散傅里叶变换(DFT) 离散傅里叶变换(discrete Fourier transform) 傅里叶分析方法是信号分析的最基本方法,傅里叶变换是傅里叶分析的核心,通过它把信号从时间域变换到频率域,进而研究信号的频谱结构和变化规...

weixin_30945039的博客 4876

CentOS 7 安装 Python 3.10

我这里已经软链接了,正常未链接之前是python->python2.7而不是python3.10。python2.7默认安装是在 /usr/bin目录中,切换到/usr/bin/更改yum配置,因为其要用到python2才能执行,否则会导致yum不能正常使用。2. 安装 Python 3.10 必需的 openssl >= 1.1.1。默认的centos7是没有安装pip,先添加epel扩展源。/usr/bin/python 修改为如下。添加软链接,将原来的链接备份。添加python3的软链接。

bensonyang888的博客 2905

快速傅里叶变换及java实现

傅里叶变换是一种线性的积分变换。它的理论依据是:任何连续周期信号都可以由一组适当的正弦曲线组合而成,即使用简单的正弦、余弦函数(如sinx,Acos(ωx+θ)),可以拟合复杂函数。

mvksfg的博客 1万+

知识推理——TransE(知识表示、知识嵌入)

知识图谱嵌入/表示方法 TransE

missyoudaisy的博客 1831

【中科院一区Top-源码复现】Day-ahead photovoltaic power forecastingwith multi-source temporal-featureconvoluti

【中科院一区Top-源码复现】Day-ahead photovoltaic power forecastingwith multi-source temporal-featureconvoluti

739

Java中实现快速傅里叶变换FFT

Java中实现快速傅里叶变换FFT一.概述1.傅里叶变换(FT)2.离散傅里叶变换(DFT)3.快速傅里叶变换(FFT)1)单位根2)快速傅里叶变换的思想3)蝶形图4)快速傅里叶变换的逆变换(IFFT)二.代码实现1.复数的实现1)复数的表示2)复数的运算3)复数数组2.单位根的实现1)单位根的计算2)获取单位根时的处理3.快速傅里叶变换的实现1)索引插值2)数据奇偶分组3)确定循环次数4)核心计...

LeeDuoZuiShuai的博客 5638

Ardupilot飞控姿态角与姿态角速度控制过程分析(超长篇)

目录 目录 摘要 1.代码控制过程分析 摘要 本节主要记录自己学习ardupilot飞控代码的姿态角速度的控制过程 1.代码控制过程分析 可以看出:AC_AttitudeControl *attitude_control; //指针对象 virtual void rate_controller_run() = 0;是AC_AttitudeContro...

陌城烟雨 1万+

快速傅里叶变换 java_二维快速傅里叶变换的java实现

图像处理与模式识别课作业,没学过信号与系统(哭晕)。恶补了两天冈萨里斯的书,写一下实现原理及过程看了网络上很多版本的概念讲解,道理我都懂,但是在将算法迁移到傅里叶变换的实现上时,出现了一些问题。接下来我会简要介绍快速傅里叶变换是如何加速的,着重写如何将加速算法应用到傅里叶变换上。二维快速傅里叶变换原理介绍1.1普通的二维傅里叶变换​二维傅里叶变换的公式如下:\[F(u, v) = \sum^{M-...

weixin_30074929的博客 658

基于YOLOv8的水果新鲜程度检测系统设计与实现

数据采集与预处理模块:负责收集水果图像数据并进行标注和增强深度学习模型:基于YOLOv8的目标检测模型新鲜度评估模块:根据检测结果评估水果新鲜程度用户界面:提供友好的交互界面系统集成:将各模块整合为完整系统水果新鲜程度检测需要包含多种水果在不同新鲜度状态下的图像数据集。:包含5种常见水果(苹果、香蕉、橙子、葡萄、草莓)在不同新鲜度下的图像包含约8,000张图像,分为新鲜和腐烂两类AgriVision:大型农业图像数据集,包含水果检测和分类任务Fruit-360:包含120种水果的高质量图像。

YOLO 444

Python爬虫实战:基于Scrapy与Playwright的搜狐新闻高效爬取

在当今信息爆炸的时代,网络爬虫技术已成为数据获取和分析的重要工具。作为国内领先的新闻门户网站,搜狐新闻包含了大量有价值的新闻数据,这些数据对于舆情分析、市场研究等领域具有重要意义。本文将详细介绍如何使用Python最新的爬虫技术栈(Scrapy框架结合Playwright浏览器自动化工具)来高效爬取搜狐新闻数据。pythontitle = scrapy.Field() # 新闻标题url = scrapy.Field() # 新闻链接。

2201_76125261的博客 1552

快速傅里叶变换(FFT)c语言实现

  快速傅里叶变换(FFT)c语言实现:(参考:FFT多种编程语言实现)。 #include <stdio.h> #include <math.h> #include <stdlib.h> #define PI 3.14159265358979 typedef struct Complex { double real; double image; } CPLX; void _fft(CPLX buf[], CPLX out[], int n, int st

Marc Pony 9328

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

快速傅里叶变换——FFT C语言实现

FFT原理及C语言实现

l13527971021的博客 3980

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

快速傅里叶变换 python_快速傅里叶变换及python代码实现

一、前言我想认真写好快速傅里叶变换(Fast Fourier Transform,FFT),所以这篇文章会由浅到细,由窄到宽的讲解,但是傅里叶变换对于寻常人并不是很容易理解的,所以对于基础不牢的人我会通过前言普及一下相关知识。我们复习一下三角函数的标准式:$$y=A\cos (\omega x+\theta )+k$$$A$代表振幅,函数周期是$\frac{2\pi}{w}$,频率是周期的倒数$\...

weixin_39851008的博客 989

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Java编程实现快速傅里叶变换FFT

快速傅里叶变换的时间复杂度分析1 快速傅里叶变换FFT1.1 理论分析1.1.1 离散傅里叶变换1.1.2 快速傅里叶变换1.2 编程实现1.2.1 算法思想1.2.2 实验结果 1 快速傅里叶变换FFT 1.1 理论分析 1.1.1 离散傅里叶变换 有限长序列x(n)的N点DFT为 考虑为x(n)复数序列的一般情况,对某一个k值,直接按照式(1)计算X(k)的1个值需要N次复数乘法和(N-1)次复数加法。因此,计算X(k)的所有N个值,共需N^2次复数乘法和N(N-1)次复数加法。当N>>1

美女的博客 3005

快速傅里叶变换简明教程与实现

目录 开场白 基础数学 1.复数运算 2.欧拉公式 基础信号论 奈奎斯特采样定理 从解方程到傅里叶变换 1.何方神圣 2.分量求解:从方程开始 3.得到DFT(可读) 快速傅里叶变换的原理 1.旋转因子 2.DFT到FFT 3.纸上谈兵 4.FFT伪代码 5.倒位序 开场白 最近研究数字滤波器的时候接触到了离散傅里叶变换(DFT),它的实现非常简单但是使用非常不便...

庸手著文章 4993
上一篇: WSL 中的 VIM 与 Windwos 剪切板通信
mbinary
博客等级 码龄9年 39粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值