文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Python中利用FFT(快速傅里叶变换)进行频谱分析

2023-09-09 21:34

关注

本文将从实例的角度出发讲解fft函数的基本使用,不包含复杂的理论推导。

要对一个信号进行频谱分析,首先需要知道几个基本条件。

  1. 采样频率fs
  2. 信号长度N(信号的点数)

采样频率fs:根据采样定理可知,采样频率应当大于等于被测信号里最高频率的2倍,才能保证不失真,但是实际情况下,我们可能并不知道最高频率是多少,所以这个就是根据一定的经验或者搜索得到的,比如本次所使用到的ECG(心电)信号,最高频率一般不高于100Hz,于是我们设置采样频率为500(原本200Hz就够了,但是实际工程一般会将标准放大3~5倍,以便留有一定的裕量)。

信号长度N:这个一般很容易获得,因为我们经过采样得到的信号都是离散信号,如果是一维的,只需要使用len函数就可以直接获得信号的点数。

在Python的第三方库文件中,numpy和scipy都有fft的函数,本文使用scipy中的fft函数。

from scipy.fftpack import fft

打开fft函数的源文件,可以看到如下内容:

def fft(x, n=None, axis=-1, overwrite_x=False):    """    Return discrete Fourier transform of real or complex sequence.    The returned complex array contains ``y(0), y(1),..., y(n-1)``, where    ``y(j) = (x * exp(-2*pi*sqrt(-1)*j*np.arange(n)/n)).sum()``.    Parameters    ----------    x : array_like        Array to Fourier transform.    n : int, optional        Length of the Fourier transform. If ``n < x.shape[axis]``, `x` is        truncated. If ``n > x.shape[axis]``, `x` is zero-padded. The        default results in ``n = x.shape[axis]``.

阅读一下可以得到输入参数的信息:

x:待进行FFT的信号序列。

n:可选,傅里叶变换的点数,如果n的长度小于序列x长度,则x将会被截断(truncated),如果n大于序列长度,则序列将会补零,默认是两者相等。

于是,我们开始对fft函数根据自己的需要进行函数封装编写:

def FFT(Fs, data):    """    对输入信号进行FFT    :param Fs:  采样频率    :param data:待FFT的序列    :return:    """    L = len(data)  # 信号长度    N = np.power(2, np.ceil(np.log2(L)))  # 下一个最近二次幂,也即N个点的FFT    result = np.abs(fft(x=data, n=int(N))) / L * 2  # N点FFT    axisFreq = np.arange(int(N / 2)) * Fs / N  # 频率坐标    result = result[range(int(N / 2))]  # 因为图形对称,所以取一半    return axisFreq, result

代码解读:

L是输入序列的长度,很容易理解并获得。

N为大于序列长度的第一个2的幂次数,比如3之后第一个2的幂次数为2^2=4,5之后的第一个2的幂次数为2^3=8,因为FFT变换一般选择2的幂次进行,但是计算机计算的话,我们也可以不必如此费事,反正不是我们自己手算。

傅里叶变换的核心代码在第三行,abs是取模运算,因为FFT返回的数据是复数,为了便于绘图,需要求模进行,至于为什么后面又除以L又乘以2,是为了保证变换前后的幅值和变换前一致,比如2sin(2\pi t)的信号,如果不进行这一步的话,得到的FFT结果在频率为1的那个“柱子”幅度就不是2,而是一个很大的数,会发生变化,至于为什么,这里理论不去深究。

第四行代码时获取绘图所用的频率x轴,Fs/N是频率分辨率,乘以N个点就可以获得一个序列,这个序列就是每个频率分布点的x轴坐标点,N/2是为了截取一半,我们知道FFT绘制出来的图形是左右对称的,因此这里只取前一半,下面一行代码也是一样,取前一半。

举例说明:通过手动设计被测信号和采样频率等条件,掌握对库函数fft的使用和理解,以便迁移到实际工程中。下面这个例子中,我们设计了一个信号频率为390和2000Hz的正弦叠加信号,该信号的样子如图1所示,对其进行FFT之后如图2所示。

import numpy as npfrom scipy.fftpack import fftimport matplotlib.pyplot as pltdef FFT(Fs, data):    """    对输入信号进行FFT    :param Fs:  采样频率    :param data:待FFT的序列    :return:    """    L = len(data)  # 信号长度    N = np.power(2, np.ceil(np.log2(L)))  # 下一个最近二次幂,也即N个点的FFT    result = np.abs(fft(x=data, n=int(N))) / L * 2  # N点FFT    axisFreq = np.arange(int(N / 2)) * Fs / N  # 频率坐标    result = result[range(int(N / 2))]  # 因为图形对称,所以取一半    return axisFreq, resultif __name__ == '__main__':    Fs = 10000  # 采样频率    f1 = 390  # 信号频率1    f2 = 2000  # 信号频率2    t = np.linspace(0, 1, Fs)  # 生成 1s 的时间序列    # 给定信号    y = 2 * np.sin(2 * np.pi * f1 * t) + 5 * np.sin(2 * np.pi * f2 * t)    # 第一步,对没有添加噪声的信号进行FFT,验证分析是否正确    x, result = FFT(Fs, y)    # 绘图    fig1 = plt.figure(figsize=(16, 9))    plt.title('original data')    plt.plot(t, y)    plt.xlabel('time/s')    plt.ylabel('Amplitude')    plt.grid()    fig2 = plt.figure(figsize=(16, 9))    plt.title('FFT')    plt.plot(x, result)    plt.xlabel('Frequency/Hz')    plt.ylabel('Amplitude')    plt.grid()    plt.show()

输出结果如下:

图1. 原始信号
图2. 对信号进行FFT

结果分析:从FFT的结果我们可以看到,在频率为390到2000Hz的地方有两个凸起的“高峰”,说明原信号在此处的频率占据比重较大,而且FFT的结果也满足原信号的幅值大小,即390Hz信号的幅度为2,2000Hz的信号幅度为5。


如果我们对信号进行加噪,可以查看FFT分析结果。

噪声信号选择随机信号,注意,点数要和被分析的信号的点数保持一致。

# 0-1 之间的随机噪声乘以10倍,也即0-10之间的噪声noise1 = 10*np.random.random(10000)  
图3. 没有加入噪声的FFT频谱
图4.加入噪声之后的FFT频谱

 从图中可以看到的是,加入的噪声信号有直流成分(0Hz),其他横坐标上密密麻麻分布的是一些零碎的频率信号。

参考文章:

Python 中 FFT 快速傅里叶分析 - 知乎

来源地址:https://blog.csdn.net/weixin_43589323/article/details/127562996

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯