FFT初步代码分析和逼近曲线
FFT:快速傅里叶变换
文章从两个方面来写,一个是FFT的基础知识,也就是将时域信号转换为频域信号,另一个是合成时域信号。
- 将时域信号转换为频域信号
代码来源于http://bigsec.net/b52/scipydoc/fft_study.html
FFT是将时域信号转换为频域信号,它是对一组数值进行运算,数组长度是2的整数次幂(64,128,256), 数值可以是实数也可以是复数,通常我们的时域信号都是实数,因此下面都以实数为例。我们可以把这一组实数想像成对某个连续信号按照一定取样周期进行取样而得来,如果对这组N个实数值进行FFT变换,将得到一个有N个复数的数组,我们称此复数数组为频域信号,此复数数组符合如下规律:
- 下标为0和N/2的两个复数的虚数部分为0,
- 下标为i和N-i的两个复数共轭,也就是其虚数部分数值相同、符号相反。
下面的例子演示了这一个规律,先以rand随机产生有8个元素的实数数组x,然后用fft对其运算之后,观察其结果为8个复数,并且满足上面两个条件:
import numpy as np
from numpy import * #随机产生8个数
x = np.random(8) #对这8个数进行傅里叶变换
xf = np.fft.fft(x)
# (3.988037788578344+0.0j)
# (-0.4137886303518952+0.4932605470110098j)
# (1.2456400001700039+0.14530526335520622j)
# (0.35597667913863856+0.3148093703101355j)
# (0.8683347993093808+0.0j)
# (0.35597667913863856-0.3148093703101355j)
# (1.2456400001700039-0.14530526335520622j)
# (-0.4137886303518952-0.4932605470110098j) #对xf进行逆傅里叶变换,逆变换之后,实数部分与原来的X相同
xff = np.fft.ifft(xf)
结果分析:下标为0的实数表示时域信号中直流成分是多少,下标为i的a+b * j表示时域信号中周期为N/i个取样值的正弦波和余弦波的成分的多少, 其中a表示cos波形的成分,b表示sin波形的成分。用全是1的数组来做实验。
x = np.ones(8)
#array([1., 1., 1., 1., 1., 1., 1., 1.])
np.fft.fft(x)
#[8.+0.j 0.-0.j 0.+0.j 0.+0.j 0.+0.j 0.-0.j 0.-0.j 0.+0.j]
取一个 周期为8个的取样的正弦波,观察FFT结果
x = np.arange(0, 2*np.pi, 2*np.pi/8)
#array([0. , 0.78539816, 1.57079633, 2.35619449, 3.14159265,
# 3.92699082, 4.71238898, 5.49778714])
y = np.sin(x)
np.fft.fft(y)
#array([ 1.22464680e-16+0.00000000e+00j, -4.36483172e-16-4.00000000e+00j,
# 1.22464680e-16-2.22044605e-16j, 1.91553812e-16-4.44089210e-16j,
# 1.22464680e-16+0.00000000e+00j, 1.91553812e-16+4.44089210e-16j,
# 1.22464680e-16+2.22044605e-16j, -4.36483172e-16+4.00000000e+00j])
用linspace创建取样点x,等分数据时步长只能使用整数
#若步长为8,则会7等分,因此设步长为9,将数据8等分,然后省去最后一个点。
x = np.linspace(0, 2*np.pi, 9, endpoint=False)
y = np.cos(x) np.fft.fft(np.cos(x))/len(x)
#([-8.63506797e-17+0.00000000e+00j, 5.00000000e-01-1.51531594e-16j,
# 3.77494957e-17-9.83914667e-19j, 6.16790569e-18+1.06831260e-17j,
# -3.77494957e-17-4.17485895e-17j, -3.77494957e-17+4.17485895e-17j,
# 6.16790569e-18-1.06831260e-17j, 3.77494957e-17+9.83914667e-19j,
# 5.00000000e-01+1.51531594e-16j])
#可看出实数的有效值是下标为1的数,5.00000000e-01-1.51531594e-16j,和余弦波之间的关系是0.5 * 2 = 1
再取不同的放大倍数作比较。
#将正弦的放大倍数设为2倍
np.fft.fft(2*np.sin(2*x))/len(x) #array([ 2.46716228e-16+0.00000000e+00j, 2.46716228e-17+1.97372982e-16j,
# -3.37020635e-16-1.00000000e+00j, 9.86864911e-17-8.54650083e-17j,
# 9.03044069e-17+0.00000000e+00j, 9.03044069e-17-0.00000000e+00j,
# 9.86864911e-17+8.54650083e-17j, -3.37020635e-16+1.00000000e+00j,
# 2.46716228e-17-1.97372982e-16j]) #可看出有效值在下标为2处,放大系数为2,由2*数值= 放大系数可知正弦对应的复数部分数值为-1. np.fft.fft(0.8*np.cos(2*x))/len(x) #array([-5.24271984e-17+0.00000000e+00j, -2.46716228e-17+9.08065713e-17j,
# 4.00000000e-01-1.76271580e-16j, 6.32210333e-17+2.67078151e-18j,
# 2.46716228e-17+5.34156302e-18j, 2.46716228e-17-5.34156302e-18j,
# 6.32210333e-17-2.67078151e-18j, 4.00000000e-01+1.76271580e-16j,
# -2.46716228e-17-9.08065713e-17j]) #可看出有效值在下标为2处,放大系数为0.8,由2*数值= 放大系数可知正弦对应的复数部分数值为0.4,即4.00000000e-01-1.76271580e-16j。
接下来考虑正弦波和余弦波叠之后,可产生同频率不同相位的各种余弦波。复数的模代表余弦波的振幅,幅角代表此频率余弦波的相位。
x = np.arange(0, 2*np.pi, 2*np.pi/128)
y = 0.3*np.cos(x) + 0.5*np.cos(2*x+np.pi/4) + 0.8*np.cos(3*x-np.pi/3)
yf = np.fft.fft(y)/len(y)
#前5个数值为有效值
yf[:4]
#计算数值对应的相位角
np.angle(yf[1]) #abs:返回绝对值,np.rad2deg:从弧度转为角度
np.abs(yf[1]), np.rad2deg(np.angle(yf[1]))
# (0.15000000000000002, -5.300924469105861e-15)
# 角度是0度,振幅是0.3
np.abs(yf[2]), np.rad2deg(np.angle(yf[2]))
#(0.2500000000000001, 45.000000000000014)
# 角度是45度,振幅是0.5
np.abs(yf[3]), np.rad2deg(np.angle(yf[3]))
#(0.4, -60.00000000000001)
# 角度是-60度,振幅是0.4
也就是说,进行傅里叶变换后,绝对值 * 2 对应振幅,np.rad2deg可求出对应的角度,即相位。
- 合成时域信号
使用正弦波和方波去逐步逼近曲线
import numpy as np
import pylab as pl # 取FFT计算的结果freqs中的前n项进行合成,返回合成结果,计算loops个周期的波形,返回合成波形
def fft_combine(freqs, n, loops=1):
length = len(freqs) * loops
data = np.zeros(length)
index = loops * np.arange(0, length, 1.0) / length * (2 * np.pi)
for k, p in enumerate(freqs[:n]):
if k != 0: p *= 2 # 除去直流成分之外,其余的系数都*2
data += np.real(p) * np.cos(k*index) # 余弦成分的系数为实数部
data -= np.imag(p) * np.sin(k*index) # 正弦成分的系数为负的虚数部
return index, data # 产生size点取样的三角波,其周期为1
#def triangle_wave(size):
# x = np.arange(0, 1, 1.0/size)
# y = np.where(x<0.5, x, 0)
# y = np.where(x>=0.5, 1-x, y)
# return x, y # 产生size点取样的方波,其周期为1
def square_wave(size):
x = np.arange(0, 1, 1.0/size)
y = np.where(x<0.5, 1.0, 0)
return x, y fft_size = 256 # 计算方波和其FFT
x, y = square_wave(fft_size)
fy = np.fft.fft(y) / fft_size # 绘制三角波的FFT的前20项的振幅,由于不含下标为偶数的值均为0, 因此取
# log之后无穷小,无法绘图,用np.clip函数设置数组值的上下限,保证绘图正确
pl.figure()
#np.clip(x,3,8):给数值设定范围,对于小于3的数,全部变成3,大于8的数全部变成8
pl.plot(np.clip(20*np.log10(np.abs(fy[:20])), -120, 120), "o")
pl.xlabel("frequency bin")
pl.ylabel("power(dB)")
pl.title("FFT result of triangle wave") # 绘制原始的三角波和用正弦波逐级合成的结果,使用取样点为x轴坐标
pl.figure()
pl.plot(y, label="original triangle", linewidth=2)
for i in [0,1,3,5,7,9]:
index, data = fft_combine(fy, i+1, 2) # 计算两个周期的合成波形
pl.plot(data, label = "N=%s" % i)
pl.legend()
pl.title("partial Fourier series of triangle wave")
pl.show()
用正弦波去逼近方波结果如下所示:
用正弦波去逼近三角波如下所示:
FFT初步代码分析和逼近曲线的更多相关文章
- 2018-2019-2 网络对抗技术 20165206 Exp4 恶意代码分析
- 2018-2019-2 网络对抗技术 20165206 Exp4 恶意代码分析 - 实验任务 1系统运行监控(2分) (1)使用如计划任务,每隔一分钟记录自己的电脑有哪些程序在联网,连接的外部IP ...
- 2018-2019-2 网络对抗技术 20165305 Exp4 恶意代码分析
Exp4 恶意代码分析 1.实践目标 1.1是监控你自己系统的运行状态,看有没有可疑的程序在运行. 1.2是分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或sysi ...
- Exp4 恶意代码分析 20154320 李超
恶意代码 概述 恶意代码是指故意编制或设置的.对网络或系统会产生威胁或潜在威胁的计算机代码.最常见的恶意代码有计算机病毒(简称病毒).特洛伊木马(简称木马).计算机蠕虫(简称蠕虫).后门.逻辑炸弹等. ...
- 20145317《网络对抗》Exp4 恶意代码分析
20145317<网络对抗>Exp4 恶意代码分析 一.基础问题回答 (1)总结一下监控一个系统通常需要监控什么.用什么来监控. 通常监控以下几项信息: 注册表信息的增删添改 系统上各类程 ...
- opencv —— approxPolyDP 生成逼近曲线
生成逼近曲线:approxPolyDP 函数 该函数采用 Douglas-Peucker 算法(也称迭代终点拟合算法).可以有效减少多边形曲线上点的数量,生成逼近曲线,简化后继操作. 经典的 Doug ...
- 病毒木马查杀实战第010篇:QQ盗号木马之十六进制代码分析
前言 按照我的个人习惯,在运用诸如IDA Pro与OllyDBG对病毒进行逆向分析之前,我都会利用一些自动化的工具,通过静态或动态的分析方法(参见<病毒木马查杀第008篇:熊猫烧香之病毒查杀总结 ...
- Android代码分析工具lint学习
1 lint简介 1.1 概述 lint是随Android SDK自带的一个静态代码分析工具.它用来对Android工程的源文件进行检查,找出在正确性.安全.性能.可使用性.可访问性及国际化等方面可能 ...
- pmd静态代码分析
在正式进入测试之前,进行一定的静态代码分析及code review对代码质量及系统提高是有帮助的,以上为数据证明 Pmd 它是一个基于静态规则集的Java源码分析器,它可以识别出潜在的如下问题:– 可 ...
- [Asp.net 5] DependencyInjection项目代码分析-目录
微软DI文章系列如下所示: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Autofac [ ...
随机推荐
- LUOGU P3387 【模板】缩点 (缩点+DAG dp)
解题思路 缩点后按拓扑排序跑一个dp. #include<iostream> #include<cstdio> #include<cstring> #include ...
- PAT甲级——A1078 Hashing
The task of this problem is simple: insert a sequence of distinct positive integers into a hash tabl ...
- Spring注解驱动(上)
记录常用的spring注解 1.@Configuration 和 @Bean spring中可以使用xml 的方式进行配置, 也可以使用 @ Configuration 来指定一个类为配置类, 并使用 ...
- 在scrapy中将数据保存到mongodb中
利用item pipeline可以实现将数据存入数据库的操作,可以创建一个关于数据库的item pipeline 需要在类属性中定义两个常量 DB_URL:数据库的URL地址 DB_NAME:数据库的 ...
- 解决element-ui表头错位的问题
经过测试得出: 使用element-ui的表格,并在table中设置固定height会出现表头错位的现象(不知道是什么bug) 解决方案: 将height改为max-height,设置固定高度为最大高 ...
- Spriongboot+quartz定时任务
y需求: 需要一个定时任务,比如 2019-5-10 10:00 执行一次期初库存推送的功能~ Spring自带的@Schedule() 的cron表达式不支持年份,所以考虑一下quartz定时任 ...
- html如何设置表格单元格内容垂直居中?
父元素设置为表格的单元格元素td,而在表格单元格中的元素设置vertical-align: middle; 对父容器(td)使用:display: table-cell 其内子元素使用:vertica ...
- PAT甲级——A1043 Is It a Binary Search Tree
A Binary Search Tree (BST) is recursively defined as a binary tree which has the following propertie ...
- 【DM642学习笔记十】DSP优化记录
1. 处理的数据先EDMA到片内,具有更高的效率! 以YUV2RGB为例: #pragma DATA_SECTION(onchipBuf0_y,".INTPROCBUFF"); # ...
- leetcode 699. Falling Squares 线段树的实现
线段树实现.很多细节值得品味 都在注释里面了 class SegTree: def __init__(self,N,query_fn,update_fn): self.tree=[0]*(2*N+2) ...