信号生成及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 相关文章推荐
Windows下安装python2和python3多版本教程
Mar 30 Python
Python简单实现两个任意字符串乘积的方法示例
Apr 12 Python
Python openpyxl 遍历所有sheet 查找特定字符串的方法
Dec 10 Python
不归路系列:Python入门之旅-一定要注意缩进!!!(推荐)
Apr 16 Python
python动态进度条的实现代码
Jul 03 Python
Python使用sklearn库实现的各种分类算法简单应用小结
Jul 04 Python
python的debug实用工具 pdb详解
Jul 12 Python
TensorFlow 读取CSV数据的实例
Feb 05 Python
解决Python 异常TypeError: cannot concatenate 'str' and 'int' objects
Apr 08 Python
python实现AdaBoost算法的示例
Oct 03 Python
Python极值整数的边界探讨分析
Sep 15 Python
Python Flask实现进度条
May 11 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结束标签的使用细节探讨及联想
2013/03/04 PHP
php读取和保存base64编码的图片内容
2017/04/22 PHP
PHP基于array_unique实现二维数组去重
2020/07/14 PHP
经典的解除许多网站无法复制文字的绝招
2006/12/31 Javascript
JS与框架页的操作代码
2010/01/17 Javascript
JS判断是否长按某一键的方法
2016/03/02 Javascript
jQuery Mobile动态刷新页面样式的实现方法
2016/05/28 Javascript
jquery easyUI中ajax异步校验用户名
2016/08/19 Javascript
AngularJS中如何使用echart插件示例详解
2016/10/26 Javascript
微信小程序 弹框和模态框实现代码
2017/03/10 Javascript
详解webpack模块化管理和打包工具
2018/04/21 Javascript
详解vue 数组和对象渲染问题
2018/09/21 Javascript
详解VUE中的插值( Interpolation)语法
2020/10/18 Javascript
原生js实现自定义难度的扫雷游戏
2021/01/22 Javascript
Python 时间操作例子和时间格式化参数小结
2014/04/24 Python
跟老齐学Python之关于循环的小伎俩
2014/10/02 Python
python 实现一个贴吧图片爬虫的示例
2017/10/12 Python
python 简单搭建阻塞式单进程,多进程,多线程服务的实例
2017/11/01 Python
Pycharm设置去除显示的波浪线方法
2018/10/28 Python
Python产生Gnuplot绘图数据的方法
2018/11/09 Python
python实现统计文本中单词出现的频率详解
2019/05/20 Python
利用Python实现自动扫雷小脚本
2020/12/17 Python
基于HTML5 WebGL的3D机房的示例
2018/03/16 HTML / CSS
英国、欧洲和全球租车服务:Avis英国
2016/08/29 全球购物
门卫工作岗位职责
2013/12/17 职场文书
肯尼迪就职演说稿
2013/12/31 职场文书
职业规划书如何设计?
2014/01/09 职场文书
校三好学生主要事迹
2014/01/11 职场文书
大学生学习面向未来的赶考思想汇报
2014/09/12 职场文书
群众路线教育实践活动自我剖析思想汇报
2014/10/04 职场文书
有限公司股东合作协议书
2014/10/29 职场文书
英语版自我评价,35句话轻松搞定
2019/10/08 职场文书
正确的理解和使用Django信号(Signals)
2021/04/14 Python
JavaScript offset实现鼠标坐标获取和窗口内模块拖动
2021/05/30 Javascript
总结Python连接CS2000的详细步骤
2021/06/23 Python
python中__slots__节约内存的具体做法
2021/07/04 Python