信号生成及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函数嵌套实例
Sep 23 Python
python中ConfigParse模块的用法
Sep 29 Python
Python中的两个内置模块介绍
Apr 05 Python
Python 递归函数详解及实例
Dec 27 Python
Python实现二维数组按照某行或列排序的方法【numpy lexsort】
Sep 22 Python
pandas DataFrame实现几列数据合并成为新的一列方法
Jun 08 Python
Python实现针对json中某个关键字段进行排序操作示例
Dec 25 Python
Python常见数据结构之栈与队列用法示例
Jan 14 Python
PyTorch的Debug指南
May 07 Python
Pytest中conftest.py的用法
Jun 27 Python
Python List remove()实例用法详解
Aug 02 Python
Django + Taro 前后端分离项目实现企业微信登录功能
Apr 07 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
77A一级收信机修理记
2021/03/02 无线电
PHP中copy on write写时复制机制介绍
2014/05/13 PHP
ThinkPHP的MVC开发机制实例解析
2014/08/23 PHP
PHP解压ZIP文件到指定文件夹的方法
2016/11/17 PHP
yii2中关于加密解密的那些事儿
2018/06/12 PHP
thinkPHP3.2使用RBAC实现权限管理的实现
2019/08/27 PHP
php使用redis的几种常见操作方式和用法示例
2020/02/20 PHP
PHP中类与对象功能、用法实例解读
2020/03/27 PHP
PHP高并发和大流量解决方案整理
2021/03/09 PHP
利用javascript移动div层-javascript 拖动层
2009/03/22 Javascript
jquery动画4.升级版遮罩效果的图片走廊--带自动运行效果
2012/08/24 Javascript
jquery中EasyUI使用技巧小结
2015/02/10 Javascript
JS实现带圆弧背景渐变效果的导航菜单代码
2015/10/13 Javascript
基于js文件加载优化(详解)
2018/01/03 Javascript
JS实现运动缓冲效果的封装函数示例
2018/02/18 Javascript
D3.js实现拓扑图的示例代码
2018/06/30 Javascript
在vue中安装使用vux的教程详解
2018/09/16 Javascript
vue中如何去掉空格的方法实现
2018/11/09 Javascript
BootStrap modal实现拖拽功能
2018/12/01 Javascript
jQuery添加新内容的四个常用方法分析【append,prepend,after,before】
2019/03/19 jQuery
微信小程序开发之获取用户手机号码(php接口解密)
2020/05/17 Javascript
python中dir函数用法分析
2015/04/17 Python
菜鸟使用python实现正则检测密码合法性
2016/01/05 Python
python标记语句块使用方法总结
2019/08/05 Python
python的sys.path模块路径添加方式
2020/03/09 Python
使用python检查yaml配置文件是否符合要求
2020/04/09 Python
美国高档帽子网上商店:Hats.com
2018/08/09 全球购物
挂牌仪式主持词
2014/03/20 职场文书
协议书样本
2014/04/23 职场文书
弄虚作假心得体会
2014/09/10 职场文书
公积金贷款承诺书
2015/04/30 职场文书
沂蒙六姐妹观后感
2015/06/08 职场文书
go语言中GOPATH GOROOT的作用和设置方式
2021/05/05 Golang
Python序列化与反序列化相关知识总结
2021/06/08 Python
MySQL批量更新不同表中的数据
2022/05/11 MySQL
postgresql如何找到表中重复数据的行并删除
2023/05/08 MySQL