信号生成及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中time模块与datetime模块在使用中的不同之处
Nov 24 Python
python实现list元素按关键字相加减的方法示例
Jun 09 Python
用tensorflow实现弹性网络回归算法
Jan 09 Python
python编写暴力破解zip文档程序的实例讲解
Apr 24 Python
使用python绘制3维正态分布图的方法
Dec 29 Python
Python中dict和set的用法讲解
Mar 28 Python
为什么你还不懂得怎么使用Python协程
May 13 Python
Python中的 is 和 == 以及字符串驻留机制详解
Jun 28 Python
Python+pyplot绘制带文本标注的柱状图方法
Jul 08 Python
django的403/404/500错误自定义页面的配置方式
May 21 Python
pytorch实现手写数字图片识别
May 20 Python
Python Pygame实战之塔防游戏的实现
Mar 17 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
ThinkPHP3.1数据CURD操作快速入门
2014/06/19 PHP
destoon二次开发模板及调用语法汇总
2014/06/21 PHP
Yii中CGridView关联表搜索排序方法实例详解
2014/12/03 PHP
深入探究PHP的多进程编程方法
2015/08/18 PHP
PHP各种常见经典算法总结【排序、查找、翻转等】
2019/08/05 PHP
一个简单的瀑布流效果(主体形式自写)
2013/05/27 Javascript
js函数排序的实例代码
2013/07/01 Javascript
js调用打印机打印网页字体总是缩小一号的解决方法
2014/01/24 Javascript
node.js中的fs.createWriteStream方法使用说明
2014/12/17 Javascript
Javascript URI 解析介绍
2015/03/15 Javascript
浅谈JavaScript正则表达式分组匹配
2015/04/10 Javascript
js实现简单秒表走动的时钟特效
2020/03/25 Javascript
微信小程序 Record API详解及实例代码
2016/09/30 Javascript
JavaScript交换两个变量值的七种解决方案
2016/12/01 Javascript
原生js轮播(仿慕课网)
2017/02/15 Javascript
详解Vue.js搭建路由报错 router.map is not a function
2017/06/27 Javascript
vue一步步实现alert功能
2017/07/05 Javascript
微信小程序利用canvas 绘制幸运大转盘功能
2018/07/06 Javascript
JavaScript面向对象程序设计创建对象的方法分析
2018/08/13 Javascript
js 实现在2d平面上画8的方法
2018/10/10 Javascript
在js代码拼接dom对象到页面上的模板总结
2018/10/21 Javascript
node.JS路径解析之PATH模块使用方法详解
2020/02/06 Javascript
Pycharm简单使用教程(入门小结)
2019/07/04 Python
django页面跳转问题及注意事项
2019/07/18 Python
pytorch自定义初始化权重的方法
2019/08/17 Python
使用python批量转换文件编码为UTF-8的实现
2020/04/03 Python
pycharm开发一个简单界面和通用mvc模板(操作方法图解)
2020/05/27 Python
python re模块常见用法例举
2021/03/01 Python
利用HTML5中Geolocation获取地理位置调用Google Map API在Google Map上定位
2013/01/23 HTML / CSS
求职者应聘的自我评价
2013/10/16 职场文书
入党积极分子批评与自我批评思想汇报
2014/09/14 职场文书
公司前台接待岗位职责
2015/04/03 职场文书
2015年国庆节标语大全
2015/07/30 职场文书
班委竞选稿范文
2015/11/21 职场文书
详解CSS不受控制的position fixed
2021/05/25 HTML / CSS
使用python绘制分组对比柱状图
2022/04/21 Python