快速傅里叶变换(FFT)的简单应用——提取信号中的主频率
创作时间:
作者:
@小白创作中心
快速傅里叶变换(FFT)的简单应用——提取信号中的主频率
引用
CSDN
1.
https://blog.csdn.net/weixin_40146921/article/details/122006305
快速傅里叶变换(FFT)是信号处理领域的重要工具,能够帮助我们从复杂的信号中提取关键信息。本文将通过一个具体的Python示例,演示如何使用FFT从含噪信号中提取主频率。
概述
我们知道,现实生活中能接触到的信号大都可以展开成傅里叶级数的形式,即表现为无数个余弦波(谐波)的叠加。其中,有的谐波振幅比较大,在信号中占主导地位。利用快速傅里叶变换,我们可以很方便地提取出这些起主导作用的谐波的频率(即题中说的主频率),为进一步还原出这些主要信号做准备。
测试信号
首先,生成一个含有大量噪声的信号:
import numpy
t = numpy.arange(-10, 10, 1 / 1e4) # 时间序列
f1, f2 = 0.1, 2e2
noise = 10 * numpy.random.randn(len(t)) # 用于干扰的噪音信号,把10改成0就可以获得无噪声的原始信号
# 将频率为f1和f2的两个信号以及噪声信号相叠加,生成我们的测试信号
y = 1.3 * numpy.sin(2 * numpy.pi * f1 * t) + 2.5 * numpy.cos(2 * numpy.pi * f2 * t) + noise
import matplotlib.pyplot as plt
plt.figure()
plt.plot(t, y)
plt.xlabel("t")
plt.ylabel("y")
plt.show()
这个信号在时域上大概长这个鬼样子:
可见由于噪声很大,我们几乎看不出主要的信号长啥样。实际上,在没有噪声干扰的时候,它长这样:
利用FFT提取主频率
from scipy.fft import fft, fftfreq
def analyse_freq_and_amp(x: numpy.ndarray, y: numpy.ndarray):
"""
分析不同各频率谐波的幅值
:param x: (几乎)等间隔的升序序列
:param y:
:return: 频率序列,幅值序列
"""
n = len(x)
sample_freq = (n - 1) / (x[-1] - x[0]) # 信号的采样频率
freqs = fftfreq(n, 1. / sample_freq)[:n // 2]
amplitudes = 2. / n * numpy.abs(fft(y)[:n // 2])
return freqs, amplitudes
调用:
freqs, amps = analyse_freq_and_amp(t, y)
plt.figure()
plt.plot(freqs, amps)
plt.xlabel("Freq./Hz")
plt.ylabel("Amplitude")
plt.show()
在生成的如下所示的频域图上,我们可以看出,这个信号有两个频率的谐波具有很大的幅值:
放大可以看出,这两个频率一个在0.1左右,幅值约1.3;另一个在200左右,幅值约2.5,这正是我们测试信号的主频率和对应的振幅。
如果要还原出完整的信号,除了这两个主频外,我们还需要知道两个信号的初始相位。这一部分的内容将在后面的文章介绍。
完整代码
完整代码如下:
# -*- coding: utf-8 -*-
# @Time : 2021/12/17 14:56
# @Author : Z.J. Zhang
# @Email : zijingzhang@mail.ustc.edu.cn
# @File : ffttool.py
# @Software: PyCharm
import matplotlib.pyplot as plt
import numpy
from scipy.fft import fft, fftfreq
def analyse_freq_and_amp(x: numpy.ndarray, y: numpy.ndarray):
"""
分析不同各频率谐波的幅值
:param x: (几乎)等间隔的升序序列
:param y:
:return: 频率序列,幅值序列
"""
n = len(x)
sample_freq = (n - 1) / (x[-1] - x[0]) # 信号的采样频率
freqs = fftfreq(n, 1. / sample_freq)[:n // 2]
amplitudes = 2. / n * numpy.abs(fft(y)[:n // 2])
return freqs, amplitudes
if __name__ == "__main__":
t = numpy.arange(-10, 10, 1 / 1e4)
f1, f2 = .1, 2e2
noise = 10 * numpy.random.randn(len(t)) # 用于干扰的噪音信号
# 将频率为f1和f2的两个信号以及噪声信号相叠加,生成我们的测试信号
y = 1.3 * numpy.sin(2 * numpy.pi * f1 * t) + 2.5 * numpy.cos(2 * numpy.pi * f2 * t) + noise
freqs, amps = analyse_freq_and_amp(t, y)
plt.figure()
plt.plot(t, y)
plt.xlabel("t")
plt.ylabel("y")
plt.figure()
plt.plot(freqs, amps)
plt.xlabel("Freq./Hz")
plt.ylabel("Amplitude")
plt.show()
热门推荐
麦太育儿秘笈:如何减少孩子电子产品依赖
专家建议:科学引导孩子使用电子产品
海神缘上的告白:王冬儿恢复女儿身背后的禁忌与争议
从云水谣到厦门的路程:璺、琛岀、璺濈、琛岄、浣嗚、娌块
嘉兴至厦门自驾全攻略:沿途景点、路线规划与旅行贴士
茅台酒有保质期吗?详解茅台酒的保存与鉴赏
什么是美国的保守主义?不了解它就不了解美国——大选给了它解读
北极虾怎么做最好吃?原汁原味,最衬它的气质!
长兴八都岕:浙江湖州的银杏胜地
浙江长兴旅游攻略:8大景点详解,尽享“鱼米之乡”与“丝绸之府”的魅力
中国县市旅行第339篇——浙江省.长兴县
维生素C是如何通血管的,这7个方面太重要了
斗罗大陆2:近战击败震天吼攻略
维生素B3(烟酸):血脂天然调节剂
烟酸的作用与应用:调节血脂、支持能量代谢和维护神经系统健康
维生素B3(烟酸):血脂天然调节剂
小猴子荡秋千:一个故事的多重打开方式
春节自制健康饮品,全家人都爱喝!
春节必备神器:益生元高纤饮品&和胃整肠丸
壁挂炉出现e1是什么原因?检查这5处,就能轻松解决!
燃气灶不出气的处理方法
《斗罗大陆2:绝世唐门》最新剧情高潮解析:娜娜的秘密任务与霍雨浩的逆袭
厦门高崎国际机场完全指南:交通、设施与实用信息
粘合剂在汽车行业中的应用
食品安全化学物质应用对食品安全性的影响
硫酸有哪些用途 硫酸的化学性质
胃溃疡患者的福音:拉呋替丁胶囊详解
学会这几招,提高购票成功率
火车动车高铁候补票是什么?候补购票操作流程全攻略
为什么火车票一开售就显示没票了?购票攻略来了!