基于Python实现DIT-FFT算法

目录
  • 自己写函数实现FFT
  • 使用python的第三方库进行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算法的资料请关注我们其它相关文章!

(0)

相关推荐

  • Python实现快速傅里叶变换的方法(FFT)

    本文介绍了Python实现快速傅里叶变换的方法(FFT),分享给大家,具体如下: 这里做一下记录,关于FFT就不做介绍了,直接贴上代码,有详细注释的了: import numpy as np from scipy.fftpack import fft,ifft import matplotlib.pyplot as plt import seaborn #采样点选择1400个,因为设置的信号频率分量最高为600赫兹,根据采样定理知采样频率要大于信号频率2倍,所以这里设置采样频率为1400赫兹(即

  • Python FFT合成波形的实例

    使用Python numpy模块带的FFT函数合成矩形波和方波,增加对离散傅里叶变换的理解. 导入模块 import numpy as np import matplotlib.pyplot as plt 分别是产生一个周期的方波和三角波程序 # 产生size点取样的三角波,其周期为1 def triangle_wave(size): x = np.arange(0, 1, 1.0/size) y = np.where(x<0.5, x, 0) y = np.where(x>=0.5, 1-x

  • FFT快速傅里叶变换的python实现过程解析

    FFT是DFT的高效算法,能够将时域信号转化到频域上,下面记录下一段用python实现的FFT代码. # encoding=utf-8 import numpy as np import pylab as pl # 导入和matplotlib同时安装的作图库pylab sampling_rate = 8000 # 采样频率8000Hz fft_size = 512 # 采样点512,就是说以8000Hz的速度采512个点,我们获得的数据只有这512个点的对应时刻和此时的信号值. t = np.l

  • python傅里叶变换FFT绘制频谱图

    本文实例为大家分享了python傅里叶变换FFT绘制频谱图的具体代码,供大家参考,具体内容如下 频谱图的横轴表示的是 频率, 纵轴表示的是振幅 #coding=gbk import numpy as np import pandas as pd import matplotlib.pyplot as plt #依据快速傅里叶算法得到信号的频域 def test_fft(): sampling_rate = 8000 #采样率 fft_size = 8000 #FFT长度 t = np.arang

  • Python利用FFT进行简单滤波的实现

    1.流程 大体流程如下,无论图像.声音.ADC数据都是如下流程: (1)将原信号进行FFT; (2)将进行FFT得到的数据去掉需要滤波的频率: (3)进行FFT逆变换得到信号数据: 2.算法仿真 2.1 生成数据: #采样点选择1400个,因为设置的信号频率分量最高为600Hz,根据采样定理知采样频率要大于信号频率2倍,所以这里设置采样频率为1400Hz(即一秒内有1400个采样点) x=np.linspace(0,1,1400) #设置需要采样的信号,频率分量有180,390和600 y=2*

  • 基于python实现KNN分类算法

    kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性.该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别. kNN方法在类别决策时,只与极少量的相邻样本有关.由于kNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,kNN方法较其他方法更为适合. 通俗简单的说,就是将这个样本进行分类,怎么分类,就是用该样本的

  • 基于Python实现DIT-FFT算法

    目录 自己写函数实现FFT 使用python的第三方库进行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'] = Fal

  • 基于Python实现迪杰斯特拉和弗洛伊德算法

    图搜索之基于Python的迪杰斯特拉算法和弗洛伊德算法,供大家参考,具体内容如下 Djstela算法 #encoding=UTF-8 MAX=9 ''' Created on 2016年9月28日 @author: sx ''' b=999 G=[[0,1,5,b,b,b,b,b,b],\ [1,0,3,7,5,b,b,b,b],\ [5,3,0,b,1,7,b,b,b],\ [b,7,b,0,2,b,3,b,b],\ [b,5,1,2,0,3,6,9,b],\ [b,b,7,b,3,0,b,5

  • Python基于sklearn库的分类算法简单应用示例

    本文实例讲述了Python基于sklearn库的分类算法简单应用.分享给大家供大家参考,具体如下: scikit-learn已经包含在Anaconda中.也可以在官方下载源码包进行安装.本文代码里封装了如下机器学习算法,我们修改数据加载函数,即可一键测试: # coding=gbk ''' Created on 2016年6月4日 @author: bryan ''' import time from sklearn import metrics import pickle as pickle

  • 基于python实现雪花算法过程详解

    这篇文章主要介绍了基于python实现雪花算法过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Snowflake是Twitter提出来的一个算法,其目的是生成一个64bit的整数: 1bit:一般是符号位,不做处理 41bit:用来记录时间戳,这里可以记录69年,如果设置好起始时间比如今年是2018年,那么可以用到2089年,到时候怎么办?要是这个系统能用69年,我相信这个系统早都重构了好多次了. 10bit:10bit用来记录机器ID

  • 基于 Python 实践感知器分类算法

    Perceptron是用于二进制分类任务的线性机器学习算法.它可以被认为是人工神经网络的第一种和最简单的类型之一.绝对不是"深度"学习,而是重要的组成部分.与逻辑回归相似,它可以快速学习两类分类任务在特征空间中的线性分离,尽管与逻辑回归不同,它使用随机梯度下降优化算法学习并且不预测校准概率. 在本教程中,您将发现Perceptron分类机器学习算法.完成本教程后,您将知道: Perceptron分类器是一种线性算法,可以应用于二进制分类任务. 如何使用带有Scikit-Learn的Pe

  • Python OpenCV基于霍夫圈变换算法检测图像中的圆形

    目录 第一章:霍夫变换检测圆 ① 实例演示1 ② 实例演示2 ③ 霍夫变换函数解析 第二章:Python + opencv 完整检测代码 ① 源代码 ② 运行效果图 第一章:霍夫变换检测圆 ① 实例演示1 这个是设定半径范围 0-50 后的效果. ② 实例演示2 这个是设定半径范围 50-70 后的效果,因为原图稍微大一点,半径也大了一些. ③ 霍夫变换函数解析 cv.HoughCircles() 方法 参数分别为:image.method.dp.minDist.param1.param2.mi

  • 基于Python代码实现Apriori 关联规则算法

    目录 一.关联规则概述 二.应用场景举例 1.股票涨跌预测 2.视频.音乐.图书等推荐 3.打车路线预测(考虑时空) 4.风控策略自动化挖掘 三.3个最重要的概念 1.支持度 2.置信度 3.提升度 4. 频繁项集 四.Python算法介绍 五.挖掘实例 一.关联规则概述 1993年,Agrawal等人在首先提出关联规则概念,迄今已经差不多30年了,在各种算法层出不穷的今天,这算得上是老古董了,比很多人的年纪还大,往往是数据挖掘的入门算法,但深入研究的不多,尤其在风控领域,有着极其重要的应用潜力

  • 基于Python实现Hash算法

    目录 1 前言 2 一般hash算法 2.1 算法逻辑 2.2 代码实现 2.3 总结 3 一致性hash算法 3.1 算法逻辑 3.2 代码实现 3.3 总结 1 前言 Simhash的算法简单的来说就是,从海量文本中快速搜索和已知simhash相差小于k位的simhash集合,这里每个文本都可以用一个simhash值来代表,一个simhash有64bit,相似的文本,64bit也相似,论文中k的经验值为3.该方法的缺点如优点一样明显,主要有两点,对于短文本,k值很敏感:另一个是由于算法是以空

  • Python实现基于标记的分水岭分割算法

    目录 1. 原理 2.代码实现 2.1 利用OpenCV和c++实现分水岭算法 2.2 Python实现分水岭分割(1) 2.3 Python实现分水岭分割(2) 分水岭技术是一种众所周知的分割算法,特别适用于提取图片中的相邻或重叠对象.使用分水岭方法时,我们必须从用户定义的标记开始.这些标记可以使用点击手动定义,也可以使用阈值或形态学处理方法定义. 分水岭技术将输入图像中的像素视为基于这些标记的局部极小值(称为地形)——该方法从标记向外“淹没”山谷,直到各种标记的山谷相遇.为了产生准确的分水岭

随机推荐