Matlab之快速傅里叶变换

一、快速傅里叶介绍

傅立叶原理表明:任何连续测量的时序或信号,都可以表示为不同频率的余弦(或正弦)波信号的无限叠加。FFT是离散傅立叶变换的快速算法,可以将一个信号变换到频域。那其在实际应用中,有哪些用途呢?

1.有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征(频率,幅值,初相位);

2.FFT可以将一个信号的频谱提取出来,进行频谱分析,为后续滤波准备;

3.通过对一个系统的输入信号和输出信号进行快速傅里叶变换后,两者进行对比,对系统可以有一个初步认识。

假设采样频率Fs,信号频率F,信号长度L,采样点数N。那么FFT之后结果就是一个为N点的复数。每一个点就对应着一个频率点。这个点的模值,就是该频率值下的幅度特性。

具体跟原始信号的幅度有什么关系呢?

1. 假设原始信号的峰值为A,那么FFT的结果的每个点(除了第一个点直流分量之外)的模值就是A的N/2倍,而第一个点就是直流分量(即0Hz),它的模值是直流分量的N倍;

2. 每个点的相位呢,就是在该频率下的信号的相位。第一个点表示直流分量,它的相位是该频率的初相位,matlab以cos为底的,若信号时正弦形式sin(t),则变成cos(t-pi/2)即可。

采样频率Fs,被N-1个点平均分成N等份,每个点的频率依次增加。为了方便进行FFT运算,通常N取大于信号长度L的2的整数次方。

例如某点n所表示的频率为:Fn=(n-1)*Fs/N。由上面的公式可以看出,Fn所能分辨到频率为为Fs/N。如果采样频率Fs为1024Hz,采样点数为1024点,则可以分辨到1Hz。

1024Hz的采样率采样1024点,刚好是1秒,也就是说,采样1秒时间的信号并做FFT,则结果可以分析到1Hz。如果采样2秒时间的信号,则N为2048,并做FFT,则结果可以分析到0.5Hz。

如果要提高频率分辨力,则必须增加采样点数,也即采样时间。频率分辨率和采样时间是倒数关系。

假设FFT之后某点n用复数a+bi表示,该复数的模就是An=sqrt(a*a+b*b),相位就是Pn=atan2(b,a)。根据以上的结果,就可以计算出n点(n≠1,且n<=N/2)对应的信号的表达式为:An/(N/2)*cos(2*pi*Fn*t+Pn),即2*An/N*cos(2*pi*Fn*t+Pn);对于n=1点的信号,是直流分量,幅度即为A1/N。

由于FFT结果的对称性,通常我们只使用前半部分的结果,即小于采样频率一半的结果。

二、例子

假设我们有一个信号,它含有5V的直流分量,频率为50Hz、相位为-30度、幅度为7V的交流信号以及一个频率为90Hz、相位为90度、幅度为3V的交流信号。数学表达式为:

x = 5 + 7*cos(2*pi*15*t - 30*pi/180) + 3*cos(2*pi*40*t - 90*pi/180)。

我们以128Hz的采样率对这个信号进行采样,总共采样256点。按照我们上面的分析,Fn=(n-1)*Fs/N,我们可以知道,每两个点之间的间距就是0.5Hz。我们的信号有3个频率:0Hz、15Hz、40Hz

出于编程方便,因为直流分量的幅值A1/N,其他点幅值为An/(N/2),故直流分量最后要除以2才是对的。

一般FFT所用数据点数N与原含有信号数据点数L相同,这样的频谱图具有较高的质量,可减小因补零或截断而产生的影响。

三、Matlab代码

Fs = 128;       % 采样频率

T = 1/Fs;       % 采样时间

L = 256;        % 信号长度

t = (0:L-1)*T; % 时间

x = 5 + 7*cos(2*pi*15*t - 30*pi/180) + 3*cos(2*pi*40*t - 90*pi/180);   %cos为底原始信号

y = x + randn(size(t));     %添加噪声

figure;

plot(t,y)

title(‘加噪声的信号‘)

xlabel(‘时间(s)‘)

N = 2^nextpow2(L); %采样点数,采样点数越大,分辨的频率越精确,N>=L,超出的部分信号补为0

Y = fft(y,N)/N*2;   %除以N乘以2才是真实幅值,N越大,幅值精度越高

f = Fs/N*(0:1:N-1); %频率

A = abs(Y);     %幅值

P = angle(Y);   %相值

figure;

subplot(211);plot(f(1:N/2),A(1:N/2));   %函数fft返回值的数据结构具有对称性,因此我们只取前一半

title(‘幅值频谱‘)

xlabel(‘频率(Hz)‘)

ylabel(‘幅值‘)

subplot(212);plot(f(1:N/2),P(1:N/2));

title(‘相位谱频‘)

xlabel(‘频率(Hz)‘)

ylabel(‘相位‘)

原始信号中x = 5 + 7*cos(2*pi*15*t - 30*pi/180) + 3*cos(2*pi*40*t - 90*pi/180);

可以看到,幅值频谱中15Hz(与数学表达式中的15Hz对应),幅值7.063(与7对应),相位频谱中初相位-0.5072(与-30*pi/180对应)

幅值频谱中40Hz(与数学表达式中的40Hz对应),幅值3.082(与3对应),相位频谱中初相位-1.57(与-90*pi/180对应)

下面验证Matlab中快速傅里叶变换是以cos为底的。

1.原始信号换为:x = 5 + 7*sin(2*pi*15*t - 30*pi/180) + 3*sin(2*pi*40*t - 90*pi/180);   %sin为底的原始信号

幅值频谱明显对应正确,只需验证相位频谱。由于sin(t + p1)=cos(t + p1 - pi/2),故

-30*pi/180 - pi/2 = -2.0944,这与相位频谱中-2.093对应

-90*pi/180 - pi/2 = -3.1416,这与相位频谱中-3.057对应

若想提高结果的精度,可以提高信号长度L和采样点数N。

2.原始信号若为x = 5 + 7*cos(2*pi*15*t - 30*pi/180) + 3*sin(2*pi*40*t - 90*pi/180);   %sin和cos为底的原始信号

同样验证正确。

时间: 2024-10-12 16:22:17

Matlab之快速傅里叶变换的相关文章

为什么要进行傅立叶变换?傅立叶变换究竟有何意义?如何用Matlab实现快速傅立叶变换

写在最前面:本文是我阅读了多篇相关文章后对它们进行分析重组整合而得,绝大部分内容非我所原创.在此向多位原创作者致敬!!! 一.傅立叶变换的由来 关于傅立叶变换,无论是书本还是在网上可以很容易找到关于傅立叶变换的描述,但是大都是些故弄玄虚的文章,太过抽象,尽是一些让人看了就望而生畏的公式的罗列,让人很难能够从感性上得到理解,最近,我偶尔从网上看到一个关于数字信号处理的电子书籍,是一个叫Steven W. Smith, Ph.D.外国人写的,写得非常浅显,里面有七章由浅入深地专门讲述关于离散信号的傅

一维快速傅里叶变换代码

上一篇随笔,简要写了一下FFT中数组重新排序的算法.现在把完整的FFT代码分享给大家(有比较详细的注释). /*2015年11月10日于河北工业大学*/ #include <complex>#include <iostream.h>#include <math.h>#include <stdlib.h>const int N=8;      //数组的长度const double PI=3.141592653589793; //圆周率const double

codeforces #250E The Child and Binary Tree 快速傅里叶变换

题目大意:给定一个集合S,对于i=1...m求有多少二叉树满足每个节点的权值都在集合S中且权值和为i 构造答案多项式F(x)和集合S的生成函数C(x),那么 根节点的左子树是一棵二叉树,右子树是一棵二叉树,本身的权值必须在集合S中,此外还有空树的情况 故有F(x)=F2(x)C(x)+1 解得F(x)=1±1?4C(x)√2C(x)=21±1?4C(x)√ 若等式下方取减号则分母不可逆,舍去 得到F(x)=21+1?4C(x)√ 有关多项式求逆和多项式开根的内容参见Picks的博客 CF上每个点

快速傅里叶变换(FFT)算法【详解】

快速傅里叶变换(Fast Fourier Transform)是信号处理与数据分析领域里最重要的算法之一.我打开一本老旧的算法书,欣赏了JW Cooley 和 John Tukey 在1965年的文章中,以看似简单的计算技巧来讲解这个东西. 本文的目标是,深入Cooley-Tukey  FFT 算法,解释作为其根源的“对称性”,并以一些直观的python代码将其理论转变为实际.我希望这次研究能对这个算法的背景原理有更全面的认识. FFT(快速傅里叶变换)本身就是离散傅里叶变换(Discrete

研究傅里叶变换的一本好书&lt;&lt;快速傅里叶变换及其C程序&gt;&gt;

快速傅里叶变换及其C程序 <快速傅里叶变换及其C程序>是中国科学技术大学出版社出版的.本书系统地介绍了傅里叶变换的理论和技术,内容包括傅里叶变换(FT)的定义.存在条件及其性质,离散傅里叶变换(DFT)的定义.性质及由离散引起的频谱混叠和渗漏,快速傅里叶变换(FFT)算法的基本原理和复序列基2算法及其实用程序,并以此为基础,给出了实序列DFT.正弦变换.余弦变换.傅里叶级数.谱函数近似.功率谱估计.卷积和相关等的快速算法和实用程序,给出了 2D—DFT的行列算法.二维实序列2D—DFT的行列算

[学习笔记] 多项式与快速傅里叶变换(FFT)基础

引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积(或者多项式乘法/高精度乘法), 而代码量却非常小. 博主一年半前曾经因COGS的一道叫做"神秘的常数 $\pi$"的题目而去学习过FFT, 但是基本就是照着板子打打完并不知道自己在写些什么鬼畜的东西OwO 不过...博主这几天突然照着算法导论自己看了一遍发现自己似乎突然意识到了什么OwO然后就打了一道板子题还1A了OwO再加上午考试差点AK

快速傅里叶变换(FFT)

快速傅里叶变换(FFT)算法[详解] 快速傅里叶变换(Fast Fourier Transform)是信号处理与数据分析领域里最重要的算法之一.我打开一本老旧的算法书,欣赏了JW Cooley 和 John Tukey 在1965年的文章中,以看似简单的计算技巧来讲解这个东西. 本文的目标是,深入Cooley-Tukey  FFT 算法,解释作为其根源的"对称性",并以一些直观的python代码将其理论转变为实际.我希望这次研究能对这个算法的背景原理有更全面的认识. FFT(快速傅里叶

FFT —— 快速傅里叶变换

问题: 已知A[], B[], 求C[],使: 定义C是A,B的卷积,例如多项式乘法等. 朴素做法是按照定义枚举i和j,但这样时间复杂度是O(n2). 能不能使时间复杂度降下来呢? 点值表示法: 我们把A,B,C看作表达式. 即: A(x)=a0 + a1* x + a2 * x2 +... 将A={(x1,A(x1)), (x2,A(x2)), (x3,A(x3))...}叫做A的点值表示法. 那么使用点值表示法做多项式乘法就很简单了:对应项相乘. 那么,如何将A和B转换成点值表示法,再将C转

快速傅里叶变换FFT

快速傅里叶变换FFT DFT是信号分析与处理中的一种重要变换.但直接计算DFT的计算量与变换区间长度N的平方成正比,当N较大时,计算量太大,直接用DFT算法进行谱分析和信号的实时处理是不切实际的. 1.直接计算DFT 长度为N的有限长序列x(n)的DFT为: 2.减少运算量的思路和方法 思路:N点DFT的复乘次数等于N2.把N点DFT分解为几个较短的DFT,可使乘法次数大大减少.另外,旋转因子WmN具有周期性和对称性. (考虑x(n)为复数序列的一般情况,对某一个k值,直接按上式计算X(k)值需