信号生成及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实例分享:快速查找出被挂马的文件
Jun 08 Python
Python高级应用实例对比:高效计算大文件中的最长行的长度
Jun 08 Python
Python性能提升之延迟初始化
Dec 04 Python
pip命令无法使用的解决方法
Jun 12 Python
Python小游戏之300行代码实现俄罗斯方块
Jan 04 Python
通过实例解析Python return运行原理
Mar 04 Python
Python3+selenium实现cookie免密登录的示例代码
Mar 18 Python
解决Jupyter Notebook开始菜单栏Anaconda下消失的问题
Apr 13 Python
Python稀疏矩阵及参数保存代码实现
Apr 18 Python
Python数据清洗工具之Numpy的基本操作
Apr 22 Python
PyTorch的Debug指南
May 07 Python
python实现简单的三子棋游戏
Apr 28 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
ThinkPHP应用模式扩展详解
2014/07/16 PHP
PHP图像处理类库MagickWand用法实例分析
2015/05/21 PHP
php删除二维数组中的重复值方法
2018/03/12 PHP
php引用和拷贝的区别知识点总结
2019/09/23 PHP
Yii框架getter与setter方法功能与用法分析
2019/10/22 PHP
jquery的ajax和getJson跨域获取json数据的实现方法
2014/02/04 Javascript
IE8中使用javascript动态加载CSS的解决方法
2014/06/17 Javascript
js+ajax实现获取文件大小的方法
2015/12/08 Javascript
JS显示日历和天气的方法
2016/03/01 Javascript
jQuery插件FusionCharts绘制2D双折线图效果示例【附demo源码】
2017/04/14 jQuery
ES6深入理解之“let”能替代”var“吗?
2017/06/28 Javascript
写一个移动端惯性滑动&回弹Vue导航栏组件 ly-tab
2018/03/06 Javascript
JavaScript获取用户所在城市及地理位置
2018/04/21 Javascript
vue实现百度搜索功能
2020/12/28 Javascript
[01:46]TI4西雅图DOTA2前线报道 中国选手抱团调时差
2014/07/08 DOTA
[02:09]抵达西雅图!中国军团加油!
2014/07/07 DOTA
Python网络爬虫项目:内容提取器的定义
2016/10/25 Python
详解python 字符串和日期之间转换 StringAndDate
2017/05/04 Python
分析python动态规划的递归、非递归实现
2018/03/04 Python
python 文件转成16进制数组的实例
2018/07/09 Python
windows下 兼容Python2和Python3的解决方法
2018/12/05 Python
PyCharm2018 安装及破解方法实现步骤
2019/09/09 Python
python+opencv3生成一个自定义纯色图教程
2020/02/19 Python
python GUI库图形界面开发之PyQt5时间控件QTimer详细使用方法与实例
2020/02/26 Python
django自带的权限管理Permission用法说明
2020/05/13 Python
PyTorch之nn.ReLU与F.ReLU的区别介绍
2020/06/27 Python
CSS3属性使网站设计增强同时不消弱可用性
2009/08/29 HTML / CSS
MAC彩妆英国官网:M·A·C UK
2018/05/30 全球购物
Priority Pass机场贵宾室会籍计划:全球超过1200间机场贵宾室
2018/08/26 全球购物
护理助产毕业生的求职信
2014/03/02 职场文书
志愿者活动总结报告
2014/06/27 职场文书
信访工作个人总结
2015/03/03 职场文书
培训计划通知
2015/07/15 职场文书
家长必看:义务教育,不得以面试 评测等名义选拔学生
2019/07/09 职场文书
管理者日常工作必备:22条企业管理流程模板!
2019/07/12 职场文书
nginx限制并发连接请求数的方法
2021/04/01 Servers