没有合适的资源?快使用搜索试试~ 我知道了~
信号处理-python科学计算
1星 需积分: 5 99 下载量 154 浏览量
2015-01-23
15:04:50
上传
评论 2
收藏 1.09MB PDF 举报
温馨提示
试读
14页
用python进行数字信号处理的模拟、仿真及计算,特别是FFT计算,演绎时域到频域的转换,得到频谱。
资源推荐
资源详情
资源评论
14-6-19 频域信号处理 — 用Python做科学计算
sebug.net/paper/books/scipydoc/frequency_process.html 1/14
18 频域信号处理
用FFT(快速傅立叶变换)能将时域的数字信号转换为频域信号。转换为频域信号之后我们可
以很方便地分析出信号的频率成分,在频域上进行处理,最终还可以将处理完毕的频域信
号通过IFFT(逆变换)转换为时域信号,实现许多在时域无法完成的信号处理算法。本章通
过几个实例,简单地介绍有关频域信号处理的一些基本知识。
18.1 观察信号的频谱
将时域信号通过FFT转换为频域信号之后,将其各个频率分量的幅值绘制成图,可以很直观
地观察信号的频谱。下面的程序完成这一任务:
# -*- coding: utf-8 -*-
import numpy as np
import pylab as pl
sampling_rate = 8000
fft_size = 512
t = np.arange(0, 1.0, 1.0/sampling_rate)
x = np.sin(2*np.pi*156.25*t) + 2*np.sin(2*np.pi*234.375*t)
xs = x[:fft_size]
xf = np.fft.rfft(xs)/fft_size
freqs = np.linspace(0, sampling_rate/2, fft_size/2+1)
xfp = 20*np.log10(np.clip(np.abs(xf), 1e-20, 1e100))
pl.figure(figsize=(8,4))
pl.subplot(211)
pl.plot(t[:fft_size], xs)
pl.xlabel(u"时间(秒)")
pl.title(u"156.25Hz和234.375Hz的波形和频谱")
pl.subplot(212)
pl.plot(freqs, xfp)
pl.xlabel(u"频率(Hz)")
pl.subplots_adjust(hspace=0.4)
pl.show()
下面逐行对这个程序进行解释:
首先定义了两个常数:sampling_rate, fft_size,分别表示数字信号的取样频率和FFT的
长度。
然后调用np.arange产生1秒钟的取样时间,t中的每个数值直接表示取样点的时间,因此其
间隔为取样周期1/sampline_rate:
t = np.arange(0, 1.0, 1.0/sampling_rate)
用取样时间数组t可以很方便地调用函数计算出波形数据,这里计算的是两个正弦波的叠
加,一个频率是156.25Hz,一个是234.375Hz:
x = np.sin(2*np.pi*156.25*t) + 2*np.sin(2*np.pi*234.375*t)
为什么选择这两个奇怪的频率呢?因为这两个频率的正弦波在512个取样点中正好有整数个
周期。满足这个条件波形的FFT结果能够精确地反映其频谱。
14-6-19 频域信号处理 — 用Python做科学计算
sebug.net/paper/books/scipydoc/frequency_process.html 2/14
N点FFT能精确计算的频率
假设取样频率为fs, 取波形中的N个数据进行FFT变换。那么这N点数据包含整数个周期的
波形时,FFT所计算的结果是精确的。于是能精确计算的波形的周期是: n*fs/N。对于
8kHz取样,512点FFT来说,8000/512.0 = 15.625Hz,前面的156.25Hz和234.375Hz正好
是其10倍和15倍。
下面从波形数据x中截取fft_size个点进行fft计算。np.fft库中提供了一个rfft函数,它
方便我们对实数信号进行FFT计算。根据FFT计算公式,为了正确显示波形能量,还需要将
rfft函数的结果除以fft_size:
xs = x[:fft_size]
xf = np.fft.rfft(xs)/fft_size
rfft函数的返回值是N/2+1个复数,分别表示从0(Hz)到sampling_rate/2(Hz)的N/2+1点频
率的成分。于是可以通过下面的np.linspace计算出返回值中每个下标对应的真正的频率:
freqs = np.linspace(0, sampling_rate/2, fft_size/2+1)
最后我们计算每个频率分量的幅值,并通过 20*np.log10() 将其转换为以db单位的值。为
了防止0幅值的成分造成log10无法计算,我们调用np.clip对xf的幅值进行上下限处理:
xfp = 20*np.log10(np.clip(np.abs(xf), 1e-20, 1e100))
剩下的程序就是将时域波形和频域波形绘制出来,这里就不再详细叙述了。此程序的输出
为:
图1 8. 1 使用FFT计算正弦波的频谱
如果你放大其频谱中的两个峰值的部分的话,可以看到其值分别为:
>>> xfp[10]
-6.0205999132796251
>>> xfp[15]
-9.6432746655328714e-16
14-6-19 频域信号处理 — 用Python做科学计算
sebug.net/paper/books/scipydoc/frequency_process.html 3/14
即156.25Hz的成分为-6dB, 而234.375Hz的成分为0dB,与波形的计算公式中的各个分量的
能量(振幅值/2)符合。
如果我们波形不能在fft_size个取样中形成整数个周期的话会怎样呢?
将波形计算公式修改为:
x = np.sin(2*np.pi*200*t) + 2*np.sin(2*np.pi*300*t)
得到的结果如下:
图1 8. 2 非完整周期的正弦波经过FFT变换之后出现频谱泄漏
这次得到的频谱不再是两个完美的峰值,而是两个峰值频率周围的频率都有能量。这显然
和两个正弦波的叠加波形的频谱有区别。本来应该属于200Hz和300Hz的能量分散到了周围
的频率中,这个现象被称为频谱泄漏。出现频谱泄漏的原因在于fft_size个取样点无法放
下整数个200Hz和300Hz的波形。
频谱泄漏的解释
我们只能在有限的时间段中对信号进行测量,无法知道在测量范围之外的信号是怎样
的。因此只能对测量范围之外的信号进行假设。而傅立叶变换的假设很简单:测量范围
之外的信号是所测量到的信号的重复。
现在考虑512点FFT,从信号中取出的512个数据就是FFT的测量范围,它计算的是这512个
数据一直重复的波形的频谱。显然如果512个数据包含整数个周期的话,那么得到的结果
就是原始信号的频谱,而如果不是整数周期的话,得到的频谱就是如下波形的频谱,这
里假设对50Hz的正弦波进行512点FFT:
>>> t = np.arange(0, 1.0, 1.0/8000)
>>> x = np.sin(2*np.pi*50*t)[:512]
>>> pl.plot(np.hstack([x,x,x]))
>>> pl.show()
剩余13页未读,继续阅读
资源评论
- han_shan_zi2021-06-04内容太少,不全面
csdnwujunlin
- 粉丝: 1
- 资源: 6
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- tcp/ip 实验,临时上传
- 艾默生PAC System3i PLC系列与其它设备TCP/IP通讯教程(不用其它网关,直接通讯,实用)
- 电力场景遥感数电杆塔检测数据集VOC+YOLO格式400张1类别.7z
- 九宫格数独游戏入门初级高级骨灰级完美.docx
- 网件 WG111 V3 网卡Windows10 /11 64位驱动
- 母亲节快乐的python编程代码四组.txt
- 母亲节快乐的python编程代码四组.zip
- 九宫格数独游戏入门初级高级骨灰级完美.zip
- 电力场景安全帽检测数据集VOC+YOLO格式295张2类别.7z
- MISC图片隐写MISC图片隐写MISC图片隐写MISC图片隐写MISC图片隐写.txt
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功