信号生成及DFT的python实现方式


Posted in Python onFebruary 25, 2020

DFT

DFT(Discrete Fourier Transform),离散傅里叶变化,可以将离散信号变换到频域,它的公式非常简单:

信号生成及DFT的python实现方式

信号生成及DFT的python实现方式离散频率下标为k时的频率大小

信号生成及DFT的python实现方式 离散时域信号序列

信号生成及DFT的python实现方式 信号序列的长度,也就是采样的个数

如果你刚接触DFT,并且之前没有信号处理的相关经验,那么第一次看到这个公式,你可能有一些疑惑,为什么这个公式就能进行时域与频域之间的转换呢?

这里,我不打算去解释它,因为我水平有限,说的不清楚。相反,在这里我想介绍,作为一个程序员,如何如实现DFT

从矩阵的角度看DFT

DFT的公式,虽然简单,但是理解起来比较麻烦,我发现如果用矩阵相乘的角度来理解上面的公式,就会非常简单,直接上矩阵:

信号生成及DFT的python实现方式

OK,通过上面的表示,我们很容易将DFT理解成为一种矩阵相乘的操作,这对于我们编码是很容易的。

Talk is cheap, show me the code

根据上面的理解,我们只需要构建出S SS矩阵,然后做矩阵相乘,就等得到DFT的结果

在这之前,我们先介绍如何生成正弦信号,以及如何用scipy中的fft模块进行DFT操作,以验证我们的结果是否正确

正弦信号

信号生成及DFT的python实现方式

A: 幅度

f: 信号频率

n: 时间下标

T: 采样间隔, 等于 1/fs,fs为采样频率

ϕ \phiϕ: 相位

下面介绍如何生成正弦信号

import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline
def generate_sinusoid(N, A, f0, fs, phi):
 '''
 N(int) : number of samples
 A(float) : amplitude
 f0(float): frequency in Hz
 fs(float): sample rate
 phi(float): initial phase
 
 return 
 x (numpy array): sinusoid signal which lenght is M
 '''
 
 T = 1/fs
 n = np.arange(N) # [0,1,..., N-1]
 x = A * np.cos( 2*f0*np.pi*n*T + phi )
 
 return x

N = 511
A = 0.8
f0 = 440
fs = 44100
phi = 0

x = generate_sinusoid(N, A, f0, fs, phi)

plt.plot(x)
plt.show()

信号生成及DFT的python实现方式

# 另一种生成正弦信号的方法,生成时长为t的序列
def generate_sinusoid_2(t, A, f0, fs, phi):
 '''
 t (float) : 生成序列的时长
 A (float) : amplitude
 f0 (float) : frequency
 fs (float) : sample rate
 phi(float) : initial phase
 
 returns
 x (numpy array): sinusoid signal sequence
 '''
 
 T = 1.0/fs
 N = t / T
 
 return generate_sinusoid(N, A, f0, fs, phi)

A = 1.0
f0 = 440
fs = 44100
phi = 0
t = 0.02

x = generate_sinusoid_2(t, A, f0, fs, phi)

n = np.arange(0, 0.02, 1/fs)
plt.plot(n, x)

信号生成及DFT的python实现方式

Scipy FFT

介绍如何Scipy的FFT模块计算DFT

注意,理论上输入信号的长度必须是信号生成及DFT的python实现方式才能做FFT,而scipy中FFT却没有这样的限制

这是因为当长度不等于信号生成及DFT的python实现方式时,scipy fft默认做DFT

from scipy.fftpack import fft

# generate sinusoid
N = 511
A = 0.8
f0 = 440
fs = 44100
phi = 1.0
x = generate_sinusoid(N, A, f0, fs, phi)

# fft is
X = fft(x)
mX = np.abs(X) # magnitude
pX = np.angle(X) # phase

# plot the magnitude and phase
plt.subplot(2,1,1)
plt.plot(mX)

plt.subplot(2,1,2)
plt.plot(pX)
plt.show()

信号生成及DFT的python实现方式

自己实现DFT

自己实现DFT的关键就是构造出S,有两种方式:

信号生成及DFT的python实现方式

def generate_complex_sinusoid(k, N):
 '''
 k (int): frequency index
 N (int): length of complex sinusoid in samples
 
 returns
 c_sin (numpy array): the generated complex sinusoid (length N)
 '''
 
 n = np.arange(N)
 
 c_sin = np.exp(1j * 2 * np.pi * k * n / N)
 
 return np.conjugate(c_sin)

def generate_complex_sinusoid_matrix(N):
 '''
 N (int): length of complex sinusoid in samples
 
 returns
 c_sin_matrix (numpy array): the generated complex sinusoid (length N)
 '''
 
 n = np.arange(N)
 n = np.expand_dims(n, axis=1)  # 扩充维度,将1D向量,转为2D矩阵,方便后面的矩阵相乘
 
 k = n
 
 m = n.T * k / N     # [N,1] * [1, N] = [N,N]
 
 S = np.exp(1j * 2 * np.pi * m)  # 计算矩阵 S
 
 return np.conjugate(S)
# 生成信号,用于测试
N = 511
A = 0.8
f0 = 440
fs = 44100
phi = 1.0
x = generate_sinusoid(N, A, f0, fs, phi)

# 第一种方式计算DFT
X_1 = np.array([])
for k in range(N):
 s = generate_complex_sinusoid(k, N)
 X_1 = np.append(X_1, np.sum(x * s))
 
mX = np.abs(X_1)
pX = np.angle(X_1)

# plot the magnitude and phase
plt.subplot(2,1,1)
plt.plot(mX)

plt.subplot(2,1,2)
plt.plot(pX)
plt.show()

# 结果和scipy的结果基本相同

信号生成及DFT的python实现方式

# 第二种方法计算DFT
S = generate_complex_sinusoid_matrix(N)
X_2 = np.dot(S, x)

mX = np.abs(X_2)
pX = np.angle(X_2)

# plot the magnitude and phase
plt.subplot(2,1,1)
plt.plot(mX)

plt.subplot(2,1,2)
plt.plot(pX)
plt.show()

信号生成及DFT的python实现方式

总结

回顾了DFT的计算公式,并尝试用矩阵相乘的角度来理解DFT

介绍了两种生成正弦信号的方法

实现了两种DFT的计算方法

完整代码在这里

以上这篇信号生成及DFT的python实现方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python 基础学习第二弹 类属性和实例属性
Aug 27 Python
多线程爬虫批量下载pcgame图片url 保存为xml的实现代码
Jan 17 Python
python网络编程学习笔记(六):Web客户端访问
Jun 09 Python
Python实现遍历windows所有窗口并输出窗口标题的方法
Mar 13 Python
Linux下用Python脚本监控目录变化代码分享
May 21 Python
Python的Django框架中URLconf相关的一些技巧整理
Jul 18 Python
配置 Pycharm 默认 Test runner 的图文教程
Nov 30 Python
selenium处理元素定位点击无效问题
Jun 12 Python
PYQT5 vscode联合操作qtdesigner的方法
Mar 24 Python
python解包概念及实例
Feb 17 Python
PyTorch dropout设置训练和测试模式的实现
May 27 Python
python分分钟绘制精美地图海报
Feb 15 Python
Pycharm远程连接服务器并实现代码同步上传更新功能
Feb 25 #Python
python生成任意频率正弦波方式
Feb 25 #Python
python numpy库linspace相同间隔采样的实现
Feb 25 #Python
Pandas时间序列:时期(period)及其算术运算详解
Feb 25 #Python
基于pygame实现童年掌机打砖块游戏
Feb 25 #Python
python GUI库图形界面开发之PyQt5拖放控件实例详解
Feb 25 #Python
python GUI库图形界面开发之PyQt5美化窗体与控件(异形窗体)实例
Feb 25 #Python
You might like
PHP错误抑制符(@)导致引用传参失败Bug的分析
2011/05/02 PHP
使用JQuery进行跨域请求
2010/01/25 Javascript
JQuery.closest(),parent(),parents()寻找父结点
2012/02/17 Javascript
在JavaScript里嵌入大量字符串常量的实现方法
2013/07/07 Javascript
jquery实现图片渐变切换兼容ie6/Chrome/Firefox
2013/08/02 Javascript
判断输入是否为空,获得输入类型的JS代码
2013/10/30 Javascript
html的DOM中document对象images集合用法实例
2015/01/21 Javascript
js控制文本框只输入数字和小数点的方法
2015/03/10 Javascript
NodeJs读取JSON文件格式化时的注意事项
2016/09/25 NodeJs
最常见和最有用的字符串相关的方法详解
2017/02/06 Javascript
利用Angular.js编写公共提示模块的方法教程
2017/05/28 Javascript
Node.js中流(stream)的使用方法示例
2017/07/16 Javascript
详解Webpack loader 之 file-loader
2018/11/07 Javascript
vue请求本地自己编写的json文件的方法
2019/04/25 Javascript
基于jQuery实现可编辑的表格
2019/12/11 jQuery
Python中的闭包详细介绍和实例
2014/11/21 Python
Python使用BeautifulSoup库解析HTML基本使用教程
2016/03/31 Python
pandas修改DataFrame列名的方法
2018/04/08 Python
django 在原有表格添加或删除字段的实例
2018/05/27 Python
Django跨域请求CSRF的方法示例
2018/11/11 Python
基于Python在MacOS上安装robotframework-ride
2018/12/28 Python
python pandas库的安装和创建
2019/01/10 Python
HTML5几个设计和修改的页面范例分享
2015/09/29 HTML / CSS
Html5让容器充满屏幕高度或自适应剩余高度的布局实现
2020/05/14 HTML / CSS
设计师家具购买和委托在线市场:Viyet
2016/11/16 全球购物
Currentbody法国:健康与美容高科技产品
2020/08/16 全球购物
红旗方阵解说词
2014/02/12 职场文书
党的群众路线学习材料
2014/05/16 职场文书
开展创先争优活动总结
2014/08/28 职场文书
七一建党节演讲稿
2014/09/11 职场文书
教师三严三实学习心得体会
2014/10/11 职场文书
加薪通知
2015/04/25 职场文书
红领巾广播站广播稿
2015/08/19 职场文书
2016年国庆节新闻稿范文
2015/11/25 职场文书
MySQL提取JSON字段数据实现查询
2022/04/22 MySQL
Redis基本数据类型List常用操作命令
2022/06/01 Redis