从零开始学习FFT(快速傅里叶变换) 这也是我学习dft算法的心得,谢谢各位

本文主要是介绍从零开始学习FFT(快速傅里叶变换) 这也是我学习dft算法的心得,谢谢各位,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 本文是从最基础的知识开始讲解,力求用最通俗易懂的文字将问题将的通俗易懂,大神勿喷,多多指教啊,虽然说是从零学习FFT,但是基本的数学知识还是要有的,sincos,等。

       FFT(快速傅里叶变换)其本质就是DFT,只不过可以快速的计算出DFT结果,要弄懂FFT,必须先弄懂DFTDFT(DiscreteFourier Transform) 离散傅里叶变换的缩写,咱们先来详细讨论DFT,因为DFT懂了之后,FFT就容易的多了

DFT(FFT)的作用:可以将信号从时域变换到频域,而且时域和频域都是离散的,通俗的说,可以求出一个信号由哪些正弦波叠加而成,求出的结果就是这些正弦波的幅度和相位,我们音乐播放器上面显示的就是音乐fft之后不同频率正弦波的幅度,就像下面这张图片:

里面的柱状高度就是正弦波的幅度

     那么为什么可以求出正弦波的幅度呢,这里就要说一下信号的相关性了,我们也可以利用信号的相关性检测信号波中是否含有某个频率的信号波:把一个待检测信号波乘以另一个信号波,个新的信号波,再把这个新的信号波所有的点进行相加,从相加的结果就可以判断出这两个信号的相似程度,比如下图:

 

        上图中a,b图是待检测信号,cd3个周期的正弦信号,很显然a图含有正弦波,e=a*c,将e图的各点相加,很显然值是正的,这就说明a图含频率为3的正弦波,f=b*d,显然将f图中各点相加结果约等于0了,说明b图不含有周期为3的正弦波,这就是dft的原理,也就是离散傅里叶变换的原理,其实就是这么简单,只不过dft将待检测信号和很多不同频率的正弦波和余弦波相乘,也就是进行了信号相关性检测,从而可以计算出信号中含有的正弦波的幅度,若含有此频率的正弦波,那么幅值不为0,若不含有此正弦波,那么幅值为0,那么幅值是如何计算出来的呢,幅值就是上面e图和f图各点之和(若是连续信号的话就是两信号乘积求积分了,。。额,不说积分,抽象了)

下面来看个具体的例子:


上面图一即为待检测信号,也就是将进行DFT变换的信号,将它分成16个离散的点,图2是一个频率为1的正弦波,也分成16个点,将对应的点相乘,得到图3,再将图3的各个点的幅值相加,结果为10.06,也就是说图1中的图像含有图2的正弦波,此时用到的dft点数就为16,10/(N/2)=10/8=1.25,含有的频率为1的正弦波的幅度就是1.25,以此类推,若要求是否含有频率为2的正弦波,将图1和频率为2的正弦波相乘再求和,。。。。

至于为什么要除以N/2,数字信号处理里面有讲,我就不多说了

     接下来就是dft的实现了:                   

    DFT的公式:

   

   其中X(k)表示DFT变换后的数据,x(n)为采样的模拟信号,公式中的x(n)可以为复信号,实际当中x(n)都是实信号,即虚部为0,此时公式可以展开为:

     从这个公式可以看出,变换后的数据就是原信号对cos和sin的相关操作,即进行相乘求和(连续信号即为积分),为什么我要将n\N写在2k*pi后面呢?因为我觉得在对cos和sin进行相关操作时,k代表和频率为多少的正弦相关,而n和N则是在一个正弦周期内采样N个点,采样间隔为2*pi\N,,n用来步进,一次步进2*pi\N,最后进行累加求和,就得出了X(k),《实用数字信号处理》这本书的DFT章节详细的解释了此公式,并且还进行了举例,看了以后明白了不少,另外,DFT之后的数据是对称的,具体原因还是在那本书上面有,在FFT的章节。比如做8DFT,采样信号为x(n),DFT之后的数据为X(k),那么X(0)为直流信号,X(1), X(2), X(3), X(5), X(6), X(7),关于X(4)对称,X(1)=X(7), X(2)=X(6),X(3)=X(5),如下图,是对1+sin(2*PI)进行DFT变换,具体的幅值先不关心,只要知道它是对称的就行了。

接下来就是对公式写程序了,先将公式展开:

在计算机中可以这样展开:

里面有个j,不用管它,我们用两个数组,一个保存sin相关,一个保存cos相关,由于cos为实部,sin为虚部,可以定义以下两个数组:

float real[N];//用来保存cos相关。

float imag[N];//用来保存sin相关。

可以得到如下程序:

[cpp]  view plain copy
  1. for(k=0;k<N;k++)  
  2. {  
  3.   for(n=0;n<N;n++)  
  4.   {  
  5.     real[k] = real[k] + x[n] * cos(2*PI*k*n/N) ;  
  6.     imag[k] = imag[k] – x[n] * sin(2*PI*k*n/N);  
  7.   }  
  8. }  

Real就是cos相关的幅值,imag就是sin相关的幅值

最后将sincos合成一个sin

就完了。。。

这篇关于从零开始学习FFT(快速傅里叶变换) 这也是我学习dft算法的心得,谢谢各位的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/427226

相关文章

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

shell脚本快速检查192.168.1网段ip是否在用的方法

《shell脚本快速检查192.168.1网段ip是否在用的方法》该Shell脚本通过并发ping命令检查192.168.1网段中哪些IP地址正在使用,脚本定义了网络段、超时时间和并行扫描数量,并使用... 目录脚本:检查 192.168.1 网段 IP 是否在用脚本说明使用方法示例输出优化建议总结检查 1

Rust中的Option枚举快速入门教程

《Rust中的Option枚举快速入门教程》Rust中的Option枚举用于表示可能不存在的值,提供了多种方法来处理这些值,避免了空指针异常,文章介绍了Option的定义、常见方法、使用场景以及注意事... 目录引言Option介绍Option的常见方法Option使用场景场景一:函数返回可能不存在的值场景

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个