python傅里叶变换 信号处理 序列_Python 中 FFT 快速傅里叶分析

行文思路:

  • 采样频率和采样定理
  • 生成信号并做FFT 变换
  • 频率分辨率和显示分辨率
  • FFT 归一化操作
  • 对噪声信号进行FFT
  • 导入自定义模块
  • 总结

一,相关定理介绍

1,采样频率

采样频率,也称为采样速度或者采样率,定义了每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。采样频率的倒数是采样周期或者叫作采样时间,它是采样之间的时间间隔。通俗的讲采样频率是指计算机每秒钟采集多少个信号样本。

2,采样定理

所谓采样定理 ,又称香农采样定理,奈奎斯特采样定理,是信息论,特别是通讯与信号处理学科中的一个重要基本结论。采样定理指出,如果信号是带限的,并且采样频率高于信号带宽的两倍,那么,原来的连续信号可以从采样样本中完全重建出来。

定理的具体表述为:在进行模拟/数字信号的转换过程中,当采样频率fs大于信号中最高频率fmax的2倍时,即 fs>2*fmax

Note:采样之后的数字信号完整地保留了原始信号中的信息,一般实际应用中保证采样频率为信号最高频率的2.56~4倍;采样定理又称奈奎斯特定理。

二,FFT 变换

numpy中有一个fft的库,scipy中也有一个fftpack的库,各自都有fft函数,两者的用法基本是一致的。下面内容是利用 scipy 库中的FFT 对信号进行快速傅里叶变化。

1,生成信号做FFT

import 

2,插值补零

进行FFT 运算,实际就一个关键的函数fft(),在进行变换之前先做小的处理。求出信号长度的下一个最近二次幂。类似于MATLAB 中的Nextpower2(), 为了更加精确快速的进行傅里叶变换。

L = len (data) # 信号长度
N =np.power(2,np.ceil(np.log2(L))) # 下一个最近二次幂

求 2 的下一个整数次幂,有更简单快速的方法。这里采用最为易懂的方式实现的。

3,fft() 参数说明

下面为fft()函数的参数说明。比较重要的是关注下输入参数的类型为数组,其中第二个参数n 指的是做FFT 的点数,如果n 小于信号的长度,输入无效。当n大于信号长度时,超出的部分补零。

Note: 补零并没有提高信号实际的频率分辨率(df=Fs/N),只是提高了显示分辨了(df=Fs/L)。要想提高实际分辨率可行的办法是:

  1. 相同时间下提高采样率
  2. 相同采样率下增长采样时间。

23140d22fbd323bac128ce646409c132.png

下面为完整的FFT 函数。

def FFT (Fs,data):
    L = len (data)                          # 信号长度
    N =np.power(2,np.ceil(np.log2(L)))      # 下一个最近二次幂
    FFT_y = (fft(y,N))/L*2                  # N点FFT,但除以实际信号长度 L
    Fre = np.arange(int(N/2))*Fs/N          # 频率坐标
    FFT_y = FFT_y[range(int(N/2))]          # 取一半
    return Fre, FFT_y

4,归一化操作

通常有N个点做FFT就有 N 个复数点与之对应,此时幅值是对复数取绝对值运算。除第一个点之外,实际的幅值是信号的实际长度L,再乘以2。所以一般对信号先做FFT 再取绝对值然后除以L乘以2。

Note: 第一个频率点我信号中的直流分量,对于交流信号来讲直流分量为0,FFT变换后第一个频点为0。

下面以一个例子说明归一化操作。

例如 A1 = 3, A2 =2, A3=5

y=3+2*np.sin(2*np.pi*f1*t)+5*np.sin(2*np.pi*f2*t).

例子中信号的长度为10e3个点。

归一化后图形如下,可以看到第一个峰值为原来的 L 倍

第二个峰为原来的 N/2

第三个峰为原来的N/2

第一个峰为直流分量,其余的峰为信号中包含的频率。

c22b4f3534de26a2ef5689eb38a548c1.png

对信号归一化并乘以2 之后为:

9f1adc66cb0710157473bebd76d6c4d1.png

信号中加入随机噪声

noise1 = np.random.random(10e3) 
# 0-1 之间的随机噪声
noise2 = np.random.normal(1,10,10e3)
#产生的是一个10e3的高斯噪声点数组集合(均值为:1,标准差:10)

当加入 0-1 之间的随机噪声时,可以看到频率0点的数值变大,说明噪声部分相当于直流分量。在加入高斯噪声后,其发现其均值可以理解为直流分量,改变均值的时候频率点0 发生相应变化。标准差表示了噪声之间的离散程度。

5344834467f99812a36f43f0356ccc55.png
加入 0-1 之间随机噪声 频谱

06bbe1059f1a91864b2297f488644717.png
加入 高斯噪声 均值为1,标准差为10 频谱

三,导入自定义模块

1,执行文件和包含模块的文件夹同一个目录下

b56f2237be9e3423e2f0719b4ea04e16.png

FFT 模块文件夹中包含:

f68a72b987389e34aeb9c7a301624b59.png

运行主函数 main.py,将定义的函数写在 __init__.py 中。

通过导入自定义函数:

import 

2, 导入的模块不在统一目录下

即执行文件在 main文件夹,模块文件在FFT文件夹,FFT 和 main 的父文件夹为 Python。

a393a8591798a8b8036821d5c85c3ca2.png

这时候需要通过导入sys 模块设定导入模块的路径

import 

这里导入路径写到模块的父文件夹即可。

总结:

FFT 变化是信号从时域变化到频域的桥梁,是信号处理的基本方法。本文讲述了利用Python SciPy 库中的fft() 函数进行傅里叶变化,其关键是注意信号输入的类型为np.array 数组类型,以及FFT 变化后归一化和取半操作,得到信号真实的幅度值。 注意如果FFT点数和实际信号长度不一样,则归一化时除以信号的实际长度而不是 FFT的点数。

完整代码:

import numpy as np
from scipy.fftpack import fft
import matplotlib.pyplot as plt
Fs =10e3      # 采样频率
f1 =390       # 信号频率1
f2 = 2e3      # 信号频率2
t=np.linspace(0,1,Fs)   # 生成 1s 的实践序列   
noise1 = np.random.random(10e3)      # 0-1 之间的随机噪声
noise2 = np.random.normal(1,10,10e3)
#产生的是一个10e3的高斯噪声点数组集合(均值为:1,标准差:10)
y=2*np.sin(2*np.pi*f1*t)+5*np.sin(2*np.pi*f2*t)+noise2

def FFT (Fs,data):
    L = len (data)                        # 信号长度
    N =np.power(2,np.ceil(np.log2(L)))    # 下一个最近二次幂
    FFT_y1 = np.abs(fft(data,N))/L*2      # N点FFT 变化,但处于信号长度
    Fre = np.arange(int(N/2))*Fs/N        # 频率坐标
    FFT_y1 = FFT_y1[range(int(N/2))]      # 取一半
    return Fre, FFT_y1

Fre, FFT_y1 = FFT(Fs,y)
plt.figure
plt.plot(Fre,FFT_y1)
plt.grid()
plt.show()
导入模块参考​blog.csdn.net
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值