快速傅里叶变换和快速卷积算法

1. 快速傅里叶变换

有限长序列的傅里叶变换公式为
X ( k ) = D F T [ x ( n ) ] = ∑ n = 0 N − 1 x ( n ) W N k n , W N = e − j 2 π N   … … ( 1 ) X(k)=DFT[x(n)]=\sum\limits_{n=0}^{N-1}x(n)W_{N}^{kn},W_N=e^{-j\frac{2\pi}{N}}\,……(1) X(k)=DFT[x(n)]=n=0N1x(n)WNkn,WN=ejN2π1
将序列x(n)按奇偶分为两个系列
{ x 1 ( r ) = x ( 2 r ) x 2 ( r ) = x ( 2 r + 1 ) , r = 0 , 1 , . . . , N 2 − 1 \begin{cases}x_1(r)=x(2r)\\x_2(r)=x(2r+1)\end{cases},r=0,1,...,\frac{N}{2}-1 { x1(r)=x(2r)x2(r)=x(2r+1),r=0,1,...,2N1
于是
X ( k ) = ∑ r = 0 N / 2 − 1 x ( 2 r ) W N k 2 r + ∑ r = 0 N / 2 − 1 x ( 2 r + 1 ) W N k ( 2 r + 1 ) X(k)=\sum\limits_{r=0}^{N/2-1}x(2r)W_N^{k2r}+\sum\limits_{r=0}^{N/2-1}x(2r+1)W_N^{k(2r+1)} X(k)=r=0N/21x(2r)WNk2r+r=0N/21x(2r+1)WNk(2r+1) = ∑ r = 0 N / 2 − 1 x 1 ( r ) W N / 2 k r + W N k ∑ r = 0 N / 2 − 1 x 2 ( r ) W N / 2 k r   k = 0 , 1 , . . . , N − 1   … … ( 2 ) =\sum\limits_{r=0}^{N/2-1}x_1(r)W_{N/2}^{kr}+W_N^k\sum\limits_{r=0}^{N/2-1}x_2(r)W_{N/2}^{kr}\,k=0,1,...,N-1\,……(2) =r=0N/21x1(r)WN/2kr+WNkr=0N/21x2(r)WN/2krk=0,1,...,N12
设x1(n)和x2(n)的N/2点DFT分别为X1(k)和X2(k),带入(2)式中有
X ( k ) = X 1 ( k ) + W N k X 2 ( k ) , k = 0 , 1 , . . . , N 2 − 1   … … ( 3 ) X(k)=X_1(k)+W_N^kX_2(k),k=0,1,...,\frac{N}{2}-1\,……(3) X(k)=X1(k)+WNkX2(k),k=0,1,...,2N13
为得到另一半k值的表达式,将(2)式中的k用k+N/2代替,即
X ( k + N 2 ) = ∑ r = 0 N / 2 − 1 x 1 ( r ) W N / 2 ( k + N / 2 ) r + W N k + N / 2 ∑ r = 0 N / 2 − 1 x 2 ( r ) W N / 2 ( k + N / 2 ) r X(k+\frac{N}{2})=\sum\limits_{r=0}^{N/2-1}x_1(r)W_{N/2}^{(k+N/2)r}+W_N^{k+N/2}\sum\limits_{r=0}^{N/2-1}x_2(r)W_{N/2}^{(k+N/2)r} X(k+2N)=r=0N/21x1(r)WN/2(k+N/2)r+WNk+N/2r=0N/21x2(r)WN/2(k+N/2)r = ∑ r = 0 N / 2 − 1 x 1 ( r ) W N / 2 k r − W N k ∑ r = 0 N / 2 − 1 x 2 ( r ) W N / 2 k r =\sum\limits_{r=0}^{N/2-1}x_1(r)W_{N/2}^{kr}-W_N^k\sum\limits_{r=0}^{N/2-1}x_2(r)W_{N/2}^{kr} =r=0N/21x1(r)WN/2krWNkr=0N/21x2(r)WN/2kr

X ( k ) = X 1 ( k ) − W N k X 2 ( k ) , k = N 2 , N 2 + 1 , . . . , N − 1   … … ( 4 ) X(k)=X_1(k)-W_N^kX_2(k),k=\frac{N}{2},\frac{N}{2}+1,...,N-1\,……(4) X(k)=X1(k)WNkX2(k),k=2N,2N+1,...,N14
由(3)(4)两式可知,一个N点DFT可以分解为两个N/2点DFT计算,这两个N/2点DFT计算通过(3)(4)两式的运算组合成N点DFT。这种运算的信号流图如下,因为形似蝴蝶,故这种运算被称为蝶形运算。
在这里插入图片描述
N = 2 L N=2^L N=2L,则这个分解可以一只持续下去,直到分解得到的子序列式2点序列为止,易得,两点DFT表示为如下形式
{ X b ( 0 ) = x b ( 0 ) + W 2 0 x b ( 1 ) X b ( 1 ) = x b ( 0 ) − W 2 0 x b ( 1 ) \begin{cases}X_b(0)=x_b(0)+W_2^0x_b(1)\\X_b(1)=x_b(0)-W_2^0x_b(1)\end{cases} { Xb(0)=xb(0)+W20xb(1)Xb(1)=xb(0)W20xb(1)
与(3)(4)两式一致,故2点DFT也可化为蝶形运算,于是整个N点DFT可以分解为L级蝶形运算,这样就大大降低了DFT的运算量。
8点FFT信号流图

import numpy as np

def dft1d(x):
    N=len(x)
    x=np.mat(x)
    W=np.mat(range(N)).transpose()*np.mat(range(N))
    W=np.exp(-2j*np.pi/N*W)
    return x*W
    
def binaryInverse(n,L):
    b=bin(n)[2:].zfill(L)
    b=b[-1::-1]
    return int(b,2)
fftResort=np.frompyfunc(binaryInverse,2,1)

def fft1d(x,oversample=1):
    N0=len(x)
    N=2**(len(bin(N0-1)[2:]))*2**(oversample-1)
    L=len(bin(N0-1)[2:])+oversample-1
    x+=[0]*(N-N0)
    x=np.array(x,dtype=np.complex)
    x=x[np.int16(fftResort(range(N),L))]
    for n in range(L):
        for k in range(int(2**n)):
            W=np.exp(-2j*np.pi/2**(n+1)*k)
            x[k::int(2**(n+1))],x[k+int(2**n)::int(2**(n+1))]=\
            x[k::int(2**(n+1))]+W*x[k+int(2**n)::int(2**(n+1))],\
            x[k::int(2**(n+1))]-W*x[k+int(2**n)::int(2**(n+1))]
    return x 

2. 快速卷积算法

2.1 基本步骤

快速卷积运算步骤如下:

Created with Raphaël 2.2.0 设参加卷积运算序列x(n)长度为L,h(n)的长度为M x(n)和h(n)补零至长度N>=L+M-1 计算x(n)和h(n)的N点DFT 将DFT相乘,得到乘积Y(k)=X(k)H(k) 计算Y(k)的IDFT,得到y(n)=x(n)*h(n) 结束

2.2 运算量

若直接按照 y = ∑ n = 0 M − 1 h ( m ) x ( n − m ) y=\sum\limits_{n=0}^{M-1}h(m)x(n-m) y=n=0M1h(m)x(nm)计算卷积,则总的乘法次数为
m d = M L … … ( 5 ) m_d=ML……(5) md=ML5
快速卷积运算需要做3次FFT和N次复数乘法,计算量为
m f = N ( 3 2 l o g 2 N + 1 ) … … ( 6 ) m_f=N(\frac{3}{2}log_2N+1)……(6) mf=N(23log2N+1)6
比值为
K m = m d m f = M L N ( 3 2 l o g 2 N + 1 ) = M L ( M + L − 1 ) ( 3 2 l o g 2 ( M + L − 1 ) + 1 ) K_m=\frac{m_d}{m_f}=\frac{ML}{N(\frac{3}{2}log_2N+1)}=\frac{ML}{(M+L-1)(\frac{3}{2}log_2(M+L-1)+1)} Km=mfmd=N(23log2N+1)ML=(M+L1)(23log2(M+L1)+1)ML
L ≈ M L \approx M LM时,
K m ≈ L 3 l o g 2 L + 5 K_m\approx\frac{L}{3log_2L+5} Km3log2L+5L
比值随L增加而增大,说明序列越长,快速卷积方法效率越高。
但是当 L > > M L>>M L>>M
K m ≈ M 3 2 l o g 2 L + 1 K_m\approx\frac{M}{\frac{3}{2}log_2L+1} Km23log2L+1M
当L足够大时,快速卷积法反而比直接计算卷积效率低。

2.3 分段卷积

实际信号处理中,序列x(n)的长度大大超过h(n)是很普遍的,为了提高计算效率,应先将序列x(n)分段,使每段长度都与h(n)长度相当,再进行卷积,分段卷积后,还需将卷积结果拼合为长序列的卷积输出,根据分段方式的不同,合成算法也不一样,常用的有重叠相加法和重叠保留法。

2.3.1 重叠相加法

重叠相加法
将x(n)分为若干长度为L的子序列,其中每个子序列的表达式为
x i ( n ) = { x ( n + i L ) n = 0 , 1 , . . . , L − 1 0 其 它 … … ( 7 ) x_i(n)=\begin{cases}x(n+iL)&n=0,1,...,L-1\\0&其它\end{cases}……(7) xi(n)={ x(n+iL)0n=0,1,...,L17
y ( n ) = x ( n ) ∗ h ( n ) = [ ∑ i = 0 ∞ x i ( n − i L ) ] ∗ h ( n ) y(n)=x(n)*h(n)=[\sum\limits_{i=0}^{\infty}x_i(n-iL)]*h(n) y(n)=x(n)h(n)=[i=0xi(niL)]h(n) = ∑ i = 0 ∞ x i ( n − i L ) ∗ h ( n ) =\sum\limits_{i=0}^{\infty}x_i(n-iL)*h(n) =i=0xi(niL)h(n)
由于LSI系统的时不变特性,有
y i ( n − i L ) = x i ( n − i L ) ∗ h ( n ) y_i(n-iL)=x_i(n-iL)*h(n) yi(niL)=xi(niL)h(n)

y ( n ) = ∑ i = 0 ∞ y i ( n − i L ) y(n)=\sum\limits_{i=0}^{\infty}y_i(n-iL) y(n)=i=0yi(niL)
在按照(7)式将卷积结果叠加过程中,yi(n)的长度是L+M-1,而每一段的位移是iL,前一段yi-1(n)值的后M-1个样会与后一段yi(n)的前M-1个样值重叠,故这种算法称为重叠相加法。

2.3.2 重叠保留法

在这里插入图片描述在这里插入图片描述
将y(n)均匀分为长度为L没有重叠的子序列,即令
y i ( n ) = { y ( n + i L ) n = 0 , 1 , . . . L − 1 0 其 它 y_i(n)=\begin{cases}y(n+iL)&n=0,1,...L-1\\0&其它\end{cases} yi(n)={ y(n+iL)0n=0,1,...L1
由图可见,yi(n-iL)不仅与第i段输入xi(m-iL)有关,还与前一段的后M-1个值有关,故对x(n)分段时,每一段xi(n)要包含前一段的后M-1个值,分为长度为N=L+M-1相互之间有重叠的子序列xi(n),即
x i ( n ) = { x ( n + i L − M + 1 ) n = 0 , 1 , . . . , N − 1 0 其 它 … … ( 8 ) x_i(n)=\begin{cases}x(n+iL-M+1)&n=0,1,...,N-1\\0&其它\end{cases}……(8) xi(n)={ x(n+iLM+1)0n=0,1,...,N18
设xi(n)与h(n)的卷积结果为yi(n),有由于xi(n)前面增加了M-1个样值,yi(n)的起始样值与输出分段yi(n)的起始样值不一样,yi(n)应是yi(n)的第M-1号样值,故
y i ( n ) = y i ′ ( n + M − 1 ) , n = 0 , 1 , . . . , L − 1 y_i(n)=y_{i}^{'}(n+M-1),n=0,1,...,L-1 yi(n)=yi(n+M1),n=0,1,...,L1

猜你喜欢

转载自blog.csdn.net/qq_39573785/article/details/103845190