基于Python实现DIT-FFT算法

 更新时间:2022年10月20日 14:48:02   作者:weixin_51613747  
FFT(Fast Fourier Transformation)是离散傅氏变换(DFT)的快速算法。即为快速傅氏变换。本文将用Python语言实现DIT-FFT算法,感兴趣的可以了解一下

自己写函数实现FFT

使用递归方法

from math import log, ceil, cos, sin, pi
import matplotlib.pyplot as plt
import numpy as np
 
 
# 这两行代码解决 plt 中文显示的问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
 
 
def fft(x, N=None):
    # DIT-FFT 函数说明
    # x: 时域序列
    # N: N点DFT, 理论上N=2**M
    # 返回值为序列x的DFT
    if N is None:
        N = len(x)
    elif N < len(x):
        N = len(x)
    
    if N == 2:
        return [x[0]+x[1], x[0]-x[1]]
    
    # 补0使得N=2**M
    M = ceil(log(N, 2))
    N = 2**M
    x = x + [0] * (N-len(x))
    
    # 递归地计算偶数项和奇数项的DFT
    X1 = fft(x[0::2])
    X2 = fft(x[1::2])
    X = [0] * N
    for i in range(N//2):
        # 蝶形计算
        tmp = (cos(2*pi/N*i)-1j*sin(2*pi/N*i))*X2[i]
        X[i] = X1[i] + tmp
        X[i+N//2] = X1[i] - tmp
    
    return X
 
 
if __name__ == '__main__':
    x = [1]*10
    y = fft(x, 1024)
    # print(y)
    z = [abs(i) for i in y]
    # print(z)
    plt.plot(np.arange(len(z))*2/len(z), z, label='10点矩形窗函数的FFT')
    plt.title("幅度谱")
    plt.xlabel(r'单位:$\pi$')
    plt.ylabel(r'$|H(j\omega)|$')
    plt.grid(linestyle="-.")
    plt.legend()
    plt.show()

使用循环,流式计算(极大地节省了内存)

from math import log, ceil, cos, sin, pi
import matplotlib.pyplot as plt
import numpy as np
 
 
# 这两行代码解决 plt 中文显示的问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
 
 
def fft(x, N=None):
    # DIT-FFT 函数说明
    # x: 时域序列
    # N: N点DFT, 理论上N=2**M
    # 返回值为序列x的DFT
    """
    采用流式计算方法,只用了一个N(N=2**M)点的数组内存
    """
    if N is None:
        N = len(x)
    elif N < len(x):
        N = len(x)
    
    # 补0使得:N=2**M
    M = ceil(log(N, 2))
    N = 2**M
    x = x + [0] * (N-len(x))
    
    fm = "{:0"+f"{M}"+"b}"
    X = [0] * N
    for i in range(N//2):
        index1 = eval('0b'+fm.format(i*2)[::-1])
        index2 = eval('0b'+fm.format(i*2+1)[::-1])
        X[2*i] = x[index1] + x[index2]
        X[2*i+1] = x[index1] - x[index2]
    
    for i in range(1, M):
        # 第i步表示将2**i点DFT合成2**(i+1)点的DFT
        # 蝶形宽度width
        width = 2**i
        
        """
        将X(k)序列进行分组,每组2**(i+1)个点,
        便于将每组中两组2**i点DFT合成一组2**(i+1)点的DFT
        """
        # num=2*width=2**(i+1), 表示每组点数
        num = 2*width
        # 组数groups
        groups = N//num
        
        for j in range(groups):
            # 对每组将2**i点DFT合成2**(i+1)=num点的DFT
            for k in range(num//2):
                # 旋转因子
                W = cos(2*pi/num*k) - 1j * sin(2*pi/num*k)
                # 第j组第k个
                index = j*num + k
                tmp = W * X[index+width]    # 每个蝶形一次复数乘法
                X[index], X[index+width] = X[index]+tmp, X[index]-tmp
                
    return X
    
 
if __name__ == '__main__':
    x = [1]*10
    y = fft(x, 1024)
    # print(y)
    z = [abs(i) for i in y]
    # print(z)
    plt.plot(np.arange(len(z))*2/len(z), z, label='10点矩形窗函数的FFT')
    plt.title("幅度谱")
    plt.xlabel(r'单位:$\pi$')
    plt.ylabel(r'$|H(j\omega)|$')
    plt.grid(linestyle="-.")
    plt.legend()
    plt.show()

运行结果:

# 说明:建议使用第二种方法实现FFT。第一种递归的方法在递归调用时也需要一定的成本,且使用的内存较大;而第二种方法只使用了一个N(N=2**M)点的数组进行计算,内存可重用。

使用python的第三方库进行FFT

import numpy as np
from numpy.fft import fft, ifft
# from scipy.fftpack import fft, ifft
import matplotlib.pyplot as plt
 
 
# 这两行代码解决 plt 中文显示的问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
 
 
if __name__ == '__main__':
    x = 2*np.sin(np.pi/2*np.arange(100))+np.sin(np.pi/5*np.arange(100))
    z = [abs(i) for i in fft(x, 2048)]
    # print(z)
    L = len(z)
    plt.plot((np.arange(L)*2/L)[:L//2], z[:L//2], label='两个不同频率正弦信号相加的DFT')
    plt.title("幅度谱")
    plt.xlabel('$\pi$')
    plt.ylabel('$|H(j\omega)|$')
    plt.grid(linestyle="-.")
    plt.legend()
    plt.show()
    
    print('max(abs(ifft(fft(x))-x)) = ', end='')
    print(max(abs(ifft(fft(x))-x)))

运行结果:

max(abs(ifft(fft(x))-x)) = 9.01467522361575e-16

以上就是基于Python实现DIT-FFT算法的详细内容,更多关于Python DIT-FFT算法的资料请关注脚本之家其它相关文章!

相关文章

  • Python+Matplotlib绘制发散条形图的示例代码

    Python+Matplotlib绘制发散条形图的示例代码

    发散条形图(Diverging Bar)是一种用于显示数据分布的图表,可以帮助我们比较不同类别或分组的数据的差异和相对性,本文介绍了Matplotlib绘制发散条形图的函数源码,需要的可以参考一下
    2023-06-06
  • Python中urlencode()函数构建URL查询字符串的利器学习

    Python中urlencode()函数构建URL查询字符串的利器学习

    这篇文章主要为大家介绍了Python中urlencode()函数构建URL查询字符串的利器学习,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • python可视化爬虫界面之天气查询

    python可视化爬虫界面之天气查询

    这篇文章主要介绍了python可视化爬虫界面之天气查询的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • TensorFlow中关于tf.app.flags命令行参数解析模块

    TensorFlow中关于tf.app.flags命令行参数解析模块

    这篇文章主要介绍了TensorFlow中关于tf.app.flags命令行参数解析模块,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • 线程和进程的区别及Python代码实例

    线程和进程的区别及Python代码实例

    这篇文章主要介绍了线程和进程的区别及Python代码实例,本文给出了一个python的脚本让一个进程中运行两个线程,需要的朋友可以参考下
    2015-02-02
  • Python使用turtule画五角星的方法

    Python使用turtule画五角星的方法

    这篇文章主要介绍了Python使用turtule画五角星的方法,运行该程序可以看到箭头间歇移动绘制五角星的效果,涉及Python使用turtle及time模块绘制图形的相关技巧,需要的朋友可以参考下
    2015-07-07
  • 使用Python脚本备份华为交换机的配置信息

    使用Python脚本备份华为交换机的配置信息

    在现代网络管理中,备份交换机的配置信息是一项至关重要的任务,备份可以确保在交换机发生故障或配置错误时,能够迅速恢复到之前的工作状态,本文将详细介绍如何使用Python脚本备份华为交换机的配置信息,需要的朋友可以参考下
    2024-06-06
  • Python利用arcpy模块实现栅格的创建与拼接

    Python利用arcpy模块实现栅格的创建与拼接

    这篇文章主要为大家详细介绍了如何基于Python语言arcpy模块,实现栅格影像图层建立与多幅遥感影像数据批量拼接(Mosaic)的操作,感兴趣的可以了解一下
    2023-02-02
  • Python opencv图像基本操作学习之灰度图转换

    Python opencv图像基本操作学习之灰度图转换

    使用opencv将图片转为灰度图主要有两种方法,第一种是将彩色图转为灰度图,第二种是在使用OpenCV读取图片的时候直接读取为灰度图,今天通过实例代码讲解Python opencv图像基本操作学习之灰度图转换,感兴趣的朋友一起看看吧
    2023-02-02
  • Python 支持向量机分类器的实现

    Python 支持向量机分类器的实现

    这篇文章主要介绍了Python 支持向量机分类器的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01

最新评论