fft实验与理解

参考:
1- fft相位谱

实验
信号的表达式:f = sin(2*pi*5*t)+5*sin(2*pi*10*t)+3*cos(2*pi*22*t)
目的:学会使用fft函数分析信号

实验过程

  1. 设置采样频率、计算信号长度
    设置采样频率为200点,采样区间为[0,1]直接使用采样周期作为步长分割区间,因此得到的信号长度于采样频率相等为200点

由于信号的最大周期为0.2s,[0,1]区间包含了5个周期,共采200点,即每个周期内采样40点,频率倍数为8倍,能满足奈奎斯特采样定律大于2.56倍的要求

  1. 计算幅频图的参数

纵坐标为幅值
fft变换后的y数组中的值其实就是傅立叶系数ak,因此幅值就是|ak|,ak为复数(实数是虚部为0的复数),对复数求模就是复数的实部平方+虚部平方,再开更号,实数的取绝对值运算就是其特例。因此使用abs()函数就能求得幅值~。取值在左右两端对称,因此只要取一半的数据绘图即可

横坐标为频率
频率与采集的信号长度有关,由于傅立叶变换在具有对称性,因此只要取一半的信号长度作为横坐标即可
- 得到信号长度,将其转化为数组k
- 取数组的一半作为横坐标

有了横纵坐标就可以愉快的画图了_

更新: 上述为幅频图,每个成分的频率知道了,还需要知道相位,即t=0时刻的值,相位可以通过公式arctan(-real/imag) 得出

2017-1-5更新: fft_bug?
fft的问题,中间部分不为零?
array([ 2.3, 3.4, 2.2, 0. , 0. , 0. , 0. , 0. , 0. , 0. ])
ipdb> np.fft.fft(zw)
array([ 7.90000000+0.j , 5.73049517-4.09079419j,
1.57082039-4.52671971j, -0.53049517-1.9404646j ,
0.22917961+0.09385448j, 1.10000000+0.j ,
0.22917961-0.09385448j, -0.53049517+1.9404646j ,
1.57082039+4.52671971j, 5.73049517+4.09079419j])
ipdb> np.fft.fft(zw[3:-1])
array([ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j])
ipdb> np.fft.fft(zw)
array([ 7.90000000+0.j , 5.73049517-4.09079419j,
1.57082039-4.52671971j, -0.53049517-1.9404646j ,
0.22917961+0.09385448j, 1.10000000+0.j ,
0.22917961-0.09385448j, -0.53049517+1.9404646j ,
1.57082039+4.52671971j, 5.73049517+4.09079419j])

实验结果(幅频图+相频图)

figure_1.png
# numpy知识点
# numpy中取得复数的实部和虚部
# 快速过滤: arr[abs(arr)<0.0001]=0-1j 

import matplotlib.pyplot as plt
import numpy as np

Fs = 200.0  # sampling rate
Ts = 1.0/Fs # sampling interval
ff = 5      # frequency of the signal

# t = np.linspace(0,1,Fs) # time vectori #使用linspace时幅频图出现小的波动
t = np.arange(0,1, Ts)

#frequency ff=5
# y = np.sin(2*np.pi*ff*t)+5*np.sin(2*np.pi*2*ff*t)+3*np.cos(2*np.pi*22*t)
# 加入相位
y = np.sin(2*np.pi*ff*t+ np.pi/6)+5*np.sin(2*np.pi*2*ff*t)+3*np.cos(2*np.pi*22*t)

#set frequency
n = len(y) # length of the signal
k = np.arange(n)
frq = k[range(n//2)] # one side frequency range

# Y = np.fft.fft(y) # 不做normaliztion幅值将放大为采样点数的1/2倍
Y = np.fft.fft(y)/(n/2.0) # fft computing and normalization
Y = Y[range(n//2)]

amplitude=abs(Y) # 获得幅值
threshold = 0.005 # 过滤极小值点的阈值

# 得到有用数据的索引
'''
x_vline=[]
for i, data in enumerate(amplitude):
    if data>0.0001:
        x_vline.append(i)
'''
# 使用列表推导式代替上面几行
x_vline=[i for (i, data) in enumerate(amplitude) if data > threshold]
y_amp=amplitude[x_vline]
# Y.real 得到实部,一个array; Y.imag 得到虚部,一个array
y_pha=np.arctan(-Y[x_vline].real/Y[x_vline].imag) # 获得相位
# 过滤相位中的极小值点
y_pha[abs(y_pha)<threshold]=0

# 绘图
fig=plt.figure()
ax1=fig.add_subplot(311)
ax2=fig.add_subplot(312)
ax3=fig.add_subplot(313)
fig.subplots_adjust(hspace=0.4) # 设置子图的间距

x_lim=(0,100)       # 横轴的范围即为频率范围
ax2.set_xlim(x_lim) # 设置横轴的范围
ax3.set_xlim(x_lim)
ax1.plot(t,y)
ax2.plot(x_vline, y_amp, 'ro') # 幅频图
ax2.vlines(x_vline, [0], y_amp)
ax3.plot(x_vline, y_pha, 'ro') # 相频图
ax3.vlines(x_vline, [0], y_pha)
ax1.set_xlabel('t')
ax1.set_ylabel('|Amplitude|')
ax2.set_xlabel('Frequence')
ax2.set_ylabel('|Amplitude|')
ax3.set_xlabel('Frequence')
ax3.set_ylabel('Phase')
plt.show()

# ax1.set_xlabel('Time')
# ax1.set_ylabel('Amplitude')
# fig, ax = plt.subplots(2, 1)
# ax[0].set_xlabel('Time')
# ax[0].set_ylabel('Amplitude')
# ax[0].plot(t,y)
# ax[1].set_xlabel('Freq (Hz)')
# ax[1].set_ylabel('|Y(freq)|')
# ax[1].plot(frq, amplitude, 'r') # plotting the spectrum
# ax[1].acorr(amplitude)
# ax[2].plot(frq, phase, 'r')

实验结果(幅频图)

幅频图

从图中可以得到基波 sin(2*pi*5*t) 与 另外两谐波的频率幅值,与信号函数的组成一致

注意点

  • 经过傅立叶变换后的值为复数,需要取绝对值,将它投影到实数轴上才能表示信号的幅值,直接使用复数做图,python会丢弃虚部,只将实数部分进行绘图
  • 采样区间的长度影响频率的表示,将采样区间的长度设置为1,变换后的频率表示为信号频率,如果长度为2,3...则频率会扩大相应的倍数
  • 采样频率影响傅立叶变化的能够表示的频率上限值

源程序(python)

import matplotlib.pyplot as plt
import numpy as np

Fs = 200.0  # sampling rate
Ts = 1.0/Fs # sampling interval
ff = 5   # frequency of the signal

t = np.arange(0,1,Ts) # time vector

#frequency ff=5
y = np.sin(2*np.pi*ff*t)+5*np.sin(2*np.pi*2*ff*t)+3*np.cos(2*np.pi*22*t)

#set frequency
n = len(y) # length of the signal
k = np.arange(n)
frq = k[range(n//2)] # one side frequency range

Y = np.fft.fft(y)/(n/2.0) # fft computing and normalization
# 为什么要做normalization?
Y = Y[range(n//2)]

fig, ax = plt.subplots(2, 1)
ax[0].plot(t,y)
ax[0].set_xlabel('Time')
ax[0].set_ylabel('Amplitude')
ax[1].plot(frq,abs(Y), 'r') # plotting the spectrum
ax[1].set_xlabel('Freq (Hz)')
ax[1].set_ylabel('|Y(freq)|')

plt.show()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容

  • 一、傅立叶变换的由来 关于傅立叶变换,无论是书本还是在网上可以很容易找到关于傅立叶变换的描述,但是大都是些故弄玄虚...
    constant007阅读 4,355评论 1 10
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,800评论 6 13
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • 曾经因为一句话,我相信了一个人,因为忘不掉,我花足够的时间让她去忘记,因为一句暖心的话让我觉得她是爱我的,但到最后...
    雪天漫步阅读 215评论 0 0
  • 失利,挫折,不好的事情。解决的办法永远在脑子里酝酿,而不实践出来,难道这样的我太该神经。
    这就是现实阅读 116评论 0 0