快速傅里叶变换FFT和逆变换的python编程

news2024/11/19 21:27:24

0. 预备知识

快速傅里叶变换旨在解决离散傅里叶变换DFT计算量大效率低的问题。当我们想要抑制噪声提取出某段信号中的有效信息时,如系统模型辨识或者是使用高精度力传感器测量人体腕部寸关尺脉搏信号这类应用,应该如何设计采样流程?

  • 首先,应当考虑采样频率 f s f_s fs的问题,根据香农采样定理,采样频率应大于等于目标信号频率 f f f最高频段的2倍,工程中通常取2.56到4倍的频率。采样频率可以直接配置传感器的采样触发信号,对于采样频率固定的设备,如普通家用摄像头,则需要根据应用选择设备型号。采样频率最好是2的幂次。
  • 其次,采样时间的问题,在确定采样频率后等同于确定采样点数量 N N N。采样点数量越多,则FFT变换后生成的频谱的频段间隔越小,即分辨力越高。采样数据点数量最好是采样频率的倍数关系。

FFT应用时需要主意的点包括:

  • FFT输出的频谱是双边对称的,关于第 N / 2 N/2 N/2个数据点左右对称,每一个数据点是一个复数 a + b j a+b\mathbf{j} a+bj,这些数据点只有幅值和相位是具有实际意义的。
  • FFT输入 N N N个数据点,输出 N N N个频段的复数,可以通过这些复数计算出对应的相位和未归一化的幅值。对幅值部分进行归一化时需要主意的是,直流分量需要除以 N N N,剩余分量需要除以 N / 2 N/2 N/2
  • 由于FFT是双边对称的,因此频率和幅值部分应该取前半段,频段点为: f = ( n − 1 ) f s / N f=(n-1)f_s/N f=(n1)fs/N, 需要注意,因为FFT输出的结果是双边的,只有前半段的频谱是有意义的,因此这里 n n n的取值范围是 n = 1 ,   . . . ,   N / 2 n=1,~...,~N/2 n=1, ..., N/2

当我们理解fft的过程,就可以调整不同频段的幅值,重新组合出一个过滤后的信号。

1. 代码示例

1.1 代码

借用这位老哥的案例: https://blog.csdn.net/qq_27825451/article/details/88553441?spm=1001.2014.3001.5506 。
我们重新写一份FFT的代码,分析信号的频谱:

'''
Author: Dianye Huang
Date: 2023-01-14 10:26:47
LastEditors: Dianye Huang
LastEditTime: 2023-01-14 14:37:02
Description: 
'''

import numpy as np
from scipy.fftpack import fft, ifft
import matplotlib.pyplot as plt

class myFFT:
    def __init__(self):
        pass
    
    def get_spetrum(self, data, fs, flag_plt=False):
        N = len(data)
        fft_y = fft(data)        # get complex number
        abs_y = np.abs(fft_y)    # get magnitude
        ang_y = np.angle(fft_y)  # get phase
        nrm_y = abs_y/(N/2)      # get normailzed magnitude (A0/N, A1.../(N/2))
        nrm_y[0] = nrm_y[0]/2      
        nmh_y = nrm_y[:int(N/2)] # half normalized magnitude
        agh_y = ang_y[:int(N/2)] # half normalized angle
        spes  = np.arange(int(N/2))*fs/N  # specturm axis 
        
        if flag_plt:
            plt.figure()
            x = np.arange(N)
            plt.subplot(2,3,1)
            plt.plot(x/fs, data)
            plt.title('raw signal')
            plt.xlabel('Time (s)')
            
            plt.subplot(2,3,4)
            plt.plot(x[:50]/fs, data[:50])
            plt.title('partial raw signal')
            plt.xlabel('Time (s)')
            
            plt.subplot(2,3,2)
            plt.plot(x, abs_y)
            plt.title('magnitudes')
            plt.xlabel('Sample index')
            
            plt.subplot(2,3,5)
            plt.plot(x, ang_y)
            plt.title('angles')
            plt.xlabel('Sample index')
            
            plt.subplot(2,3,3)
            plt.plot(x, nrm_y)
            plt.title('nomalized magnitude')
            plt.xlabel('Sample index')
            
            plt.subplot(2,3,6)
            plt.plot(spes, nmh_y)
            plt.title('half nomalized magnitude')
            plt.xlabel('Frequency (Hz)')
            
            plt.show()
        
        return nmh_y, agh_y, spes

    def get_fft(self, data, fs):
        N = len(data)
        fft_y = fft(data)
        tmp_arr = np.arange(0, fs/2, fs/N)
        freq_y = np.hstack((tmp_arr, np.flip(tmp_arr, axis=0)))
        return fft_y, freq_y
    
    def create_demo_signal(self, N=2800, fs=1400):
        # create a signal along with sample rate
        t = np.arange(0, N/fs, 1/fs)
        y = 3 + 7*np.sin(2*np.pi*200*t) + 5*np.sin(2*np.pi*400*t) + 3*np.sin(2*np.pi*600*t)
        noise_arr = np.random.normal(0, 2, N)
        return t, y+noise_arr, fs
    
if __name__ == '__main__':
    mfft=myFFT()
    t, data, fs = mfft.create_demo_signal(N=4096, fs=2048)
    # mags, angs, spes = mfft.get_spetrum(data, fs, flag_plt=True) 
    fft_y, freq_y = mfft.get_fft(data, fs)
    fft_y[freq_y>450] = 0
    sig = ifft(fft_y)
    
    plt.figure()
    plt.plot(t[:50], data[:50])
    plt.plot(t[:50], sig[:50])
    plt.show()

1.2 总结

  • f f t fft fft i f f t ifft ifft的求解包在scipy.fftpack中
  • 复数的幅值和相位可以使用numpy包中的np.abs()和np.angle()函数

示例程序运行结果如下:

1.2.1 分析频谱,右下角为最终结果

if __name__ == '__main__':
    mfft=myFFT()
    t, data, fs = mfft.create_demo_signal(N=4096, fs=2048)
    mags, angs, spes = mfft.get_spetrum(data, fs, flag_plt=True) 

在这里插入图片描述

1.2.2 简单的滤波,除去大于450Hz的分量利用ifft重新组合信号的结果

if __name__ == '__main__':
    mfft=myFFT()
    t, data, fs = mfft.create_demo_signal(N=4096, fs=2048)
    
    fft_y, freq_y = mfft.get_fft(data, fs)
    fft_y[freq_y>450] = 0
    sig = ifft(fft_y)
    
    plt.figure()
    plt.plot(t[:50], data[:50])
    plt.plot(t[:50], sig[:50])
    plt.show()

在这里插入图片描述

以上,
Dianye
2023.01.14

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/163208.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《通讯录》思路及代码实现详解

目录 一、通讯录功能实现的详细描述 二、通讯录的代码及思路实现 2、1 定义联系人结构体 2、2 初始化就结构体与释放动态开辟空间的实现 2、3 菜单打印 2、4 添加联系人信息 2、5 删除联系人信息 2、6 查询联系人信息 2、7 修改联系人信息 2、8 打印所有联系人信息 2、9 排序整…

75. 序列模型的代码实现

1. 训练 在了解了上述统计工具后,让我们在实践中尝试一下! 首先,我们生成一些数据:(使用正弦函数和一些可加性噪声来生成序列数据, 时间步为 1,2,…,1000 。) %matplotlib inline import torch from torch import nn…

新手nvm npm 卸载不用依赖包,项识别为 cmdlet、函数、脚本文件,等命令集合

nvm安装包:Releases coreybutler/nvm-windows GitHub下载ta就不用单独下载node了注意:vnm安装位置尽量不要动C:\Users\Administrator\AppData\Roaming\nvm\settings.txt增加下面代码node_mirror: https://npm.taobao.org/mirrors/node/ npm_mirror: https://npm.t…

java+Springboot交通事故档案管理系统

系统分为用户和管理员两个角色 用户的主要功能有: 1.用户注册和登陆系统 2.用户查看警察相关信息 3.用户查看我的相关事故信息,可以对交通事故进行交通申诉 4.用户查看交通申诉审核信息 5.退出登陆 管理员的主要功能有: 1.管理员输入账户登陆…

Metasploit渗透框架介绍及永恒之蓝复现

Metasploit渗透框架介绍及永恒之蓝复现一、Metasploit渗透框架介绍1.1 名词解释1.2 MSF简介1.3 MSF框架结构1.4 MSF命令汇总1.4.1 常用命令1.4.2 基本命令1.4.3 Exploits模块1.4.4 漏洞名称规则1.5 MSF模块介绍1.5.1 auxiliary(辅助模块)1.5.2 exploits(漏洞利用模块)1.5.3 pay…

Open3D 泊松盘网格采样(Python版本)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 在图形的许多应用中,特别是在渲染中,从蓝色噪声分布生成样本是很重要的。然而,现有的有效技术不容易推广到二维以外。不过泊松盘采样是个例外,它允许在O(N)时间内生成泊松盘样本,而且该方法很容易在任意维度上…

分布式CAP和BASE理论学习笔记

参考至:https://blog.csdn.net/solihawk/article/details/124442443 1. CAP理论 CAP理论是计算机科学家Eric Brewer在2000年提出的理论猜想,在2002年被证明并成为分布式计算领域公认的定理,其理论的基本观念是,在分布式系统中不…

加密算法 AES和RSA

一,加密(一)加密基础?通过互联网发送数据,数据可能会被第三者恶意窃听,造成损失。因此需要给重要的数据进行加密,加密后的数据被称为“密文”。接收方通过解除加密或得原本的数据,把…

人工智能卷积算法

文章目录前言数字信号处理与卷积运算卷积公式与计算过程边缘卷积计算与0填充NumPy卷积函数二维矩阵卷积计算图像卷积应用实例总结前言 卷积运算实际上是一种常见的数学方法,与加法,乘法等运算类似,都是由两个输入的到一个输出。不同的是&…

迷宫问题---数据结构实践作业

迷宫问题—数据结构实践作业 ✅作者简介:大家好,我是新小白2022,让我们一起学习,共同进步吧🏆 📃个人主页:新小白2022的CSDN博客 🔥系列专栏:算法与数据结构 💖如果觉得博…

什么是HAL库和标准库,区别在哪里?

参考文章https://blog.csdn.net/u012846795/article/details/122227823 参考文章 https://zhuanlan.zhihu.com/p/581798453 STM32的三种开发方式 通常新手在入门STM32的时候,首先都要先选择一种要用的开发方式,不同的开发方式会导致你编程的架构是完全…

Java 面向对象程序设计 消息、继承与多态实验 课程设计研究报告

代码:Java计算机课程设计面向对象程序设计对战游戏SwingGUI界面-Java文档类资源-CSDN文库 一、课程设计内容 一个游戏中有多种角色(Character),例如:国王(King)、皇后(Queen)、骑士&#xff0…

【Linux多线程】

Linux多线程Linux线程概念什么是线程线程的优点线程的缺点线程异常线程用途Linux进程VS线程进程和线程进程的多个线程共享Linux线程控制POSIX线程库线程创建线程等待线程终止分离线程线程ID及进程地址空间布局Linux线程概念 什么是线程 在一个程序里的一个执行路线就叫做线程…

JavaScript 如何正确的分析报错信息

文章目录前言一、报错类型1.控制台报错2.终端报错二、错误追查总结前言 摸爬滚打了这么长时间…总结了一些排查错误的经验, 总的来说, 这是一篇JavaScript新手向文章. 里面会有些不那么系统性的, 呃, 知识? 一、报错类型 报错信息该怎么看, 怎么根据信息快速的追查错误. 1.…

瑞吉外卖项目

技术选型: 1、JAVA版本:JDK11 2、数据库:mysql5.7 Navicat 3、后端框架:SpringBoot SpringMVC MyBatisPlus 4、工具类:发邮件工具类、生成验证码工具类 5、项目优化:Nginx、Redis、读写分离 项目来…

2022. 12 青少年机器人技术等级考试理论综合试卷(五级)

2022.年12月青少年机器人技术等级考试理论综合试卷(五级) 分数: 100 题数: 30 一、 单选题(共 20 题, 共 80 分) 1.下列程序执行后,串口监视器显示的相应内容是? ( ) A.1 B.2 C.4 D.…

WPF绑定(Binding)下的数据验证IDataErrorInfo

绑定下的数据验证 WPF中Binding数据校验、并捕获异常信息的三种方式讲到了三种方式,其中使用ValidatinRule的方式比较推荐,但是如果一个类中有多个属性,要为每个属性都要声明一个ValidatinRule,这样做非常麻烦。可以让类继承自ID…

【High 翻天】Higer-order Networks with Battiston Federico (8)

目录传播与社会动力学(2)Opinion and cultural dynamicsVoter modelMajority modelsContinuous models of opinion dynamicsCultural dynamics传播与社会动力学(2) 在本节将讨论一些观点和文化动力学模型,它们基于物理…

【JavaSE】反射

一、概念反射是在运行期间,动态获取对象的属性和方法二、相关的类在Java的反射里主要有以下几个类:Class类,这是反射的起源,反射必须要先获取Class对象,其次是Field类,当我们需要通过反射获取私有字段时就需…

老杨说运维 | 2023,浅谈智能运维趋势(一)

(文末附视频回顾,一键直达精彩内容) 前言: 2022年,是经济被影响的一年,这一年无论是企业还是个人经济形势都呈下滑趋势,消费降级状态或许不会因为2022的结束而改观。 全球经济紧缩的状态下&am…