jjzjj

理解DFT(离散傅里叶变换)

live_for_myself 2023-10-31 原文

文章目录

DFT做什么?

  • 给出每个分量的频率, 幅值和相位

  • 信号可以看成由三角函数叠加而成, 而DFT就可以得到每个成分的幅值, 相位, 频率

DFT怎么做到这个的呢?

  • 假设我对一个余弦信号在两个周期内采样了40次

假设是cos wt, 那么w=2Π/T, t对应的是第n个点的时间, 那么40个点对应2T, t=(n/40)*2T, 化简后就是下面的式子

但是我现在问计算机一个问题, 这个信号在40个点震动了几个周期它, 它必须通过代数求解

  • 首先选择40个基信号, 40就是信号长度

比如下面的, 一开始是40个点0个周期, 第二个是1个周期, 然后一直到39个, 后面39和1重合不是说它们一样, 而是一个间隔就已经包含一个周期了, 信号采不到

  • 然后我们就可以把原信号和上面的40个信号进行相关程度的比较, 使用相关函数, 越大相关程度越高如下图:

详细查看配对过程

第一个就是原信号, 第二个就是第8个信号, 下图有些错误, 因为0是第一个, 当然了这里第一个计算机是不知道函数的, 只是知道有这么多点, 然后就是计算相关性, 把逐次比较的结果记到X这个序列里面

通过我们逐个的计算得到和40s内振动两个周期及40s内振动38个周期的相关性最大, 其他的基信号比较结果是0

这个时候就可以把X数组画出来了

把得到X的公式明确一下

  • 把40 换成N, 代表这个对比的采样信号可以不只是40个点, 把原来的函数写成x[n]

DFT的公式

欧拉公式展开后如图:

  • 前一项是一样的, 后面的是什么呢?

是为了保留相位信息

  • 假如现在原信号向左移, 如下:

  • 然后再进行一次相关性计算的话会得到下面的值, 最近的地方不是20而是10了

  • 这样其实会和原信号的一半混淆, 损失了相位

如何解决相位问题

  • 和正弦基向量去比较

  • 经过比较可以得到X[2]和X[38]的值应该是相反的, 下图不太对, X[38]是负的

  • 这时候可以合并上之前的结果

现在看看这个复数代表啥了呢?

  • 它的模代表的是20, 相位是 π / 3 \pi / 3 π/3 , 就可以重建出原信号

具体重建过程

  • 首先需要给定采样频率

举个例子, 假如说采样频率为100hz, 采样了40个点, 40个点中采样到的信号有两个周期, 那么被采样信号的频率就是5Hz。

具体来说, 40个点的持续时间是40*1/100 = 0.4s, 所以信号的每个周期就是0.2s, 1/0.2 = 5

再一般化一下, 我们知道X[k]记录的是信号和第K个基信号的相关程度,假如对应的k值比较高, 即包含的第k个频率的基信号要更多。那么 这第K个的频率应该怎么算呢? , 参见下图:

  • 给定采样频率 f s f_s fs N N N 个点的持续时间是 N ∗ 1 f s N*\frac{1}{f_s} Nfs1 , 假如在这个时间内有k个周期, 那么每个周期的时间就是 N ∗ 1 f s ∗ k N*\frac{1}{f_s*k} Nfsk1 , 倒数就是第k个基波信号的频率

  • 此时对于X[K] 代表的频率也十分清楚了:

举前面的例子

例1

  • 假设采样率是4k Hz, N是40, X[2]就代表 2*4K/40 = 200 Hz, 之前相关程度最大的是X[2] 和X[38], X[38]对应的是 38*100Hz, 当然后者根据采样定理是需要舍弃的, 因为采样定理规定, 只有采样频率大于等于原信号的一半频率时, 才能保证不发生频谱的混叠, 所以其实在查看X[k]时, 我们只需要关注它的一半就好了

  • 采样频率是原信号的两倍也可以理解成对于原来信号的一个周期至少需要采样两次, 假如是40个点那么存在20个周期恰好满足一个周期采样两次, 再后面就不可以了

例2

  • 现在的信号是多个信号聚再一块, 假如采样了100个点, 共1s, 也就是采样频率是100Hz, 可以把原来信号改写为离散的形式, t的地方就对应 n / 100 n/100 n/100 :

  • 经过DFT后变为如下所示, 下面标错了, 应该是98, 96, 95:

可以得到模值和相位, 模除去 N / 2 N/2 N/2 就是幅值

有关理解DFT(离散傅里叶变换)的更多相关文章

  1. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  2. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  3. ruby - 易于初学者理解的 Ruby 库 - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭3年前。Improvethisquestion我正处于学习Ruby的阶段,我想查看一些小型库的源代码以了解它们是如何构建的。我不知道什么是小型图书馆,但希望SO能推荐一些易于理解的图书馆来学习。因此,如果有人知道一两个非常小的库,这是新手Rubyists学习的好例子,请推荐!我想使用Manveru'sInnatelib,因为它试图保持在2000LOC以下,但我还不熟悉其中经常使用的Ruby速记。也许大约100-5

  4. ruby - 无法理解 `puts{}.class` 和 `puts({}.class)` 之间的区别 - 2

    由于匿名block和散列block看起来大致相同。我正在玩它。我做了一些严肃的观察,如下所示:{}.class#=>Hash好的,这很酷。空block被视为Hash。print{}.class#=>NilClassputs{}.class#=>NilClass为什么上面的代码和NilClass一样,下面的代码又显示了Hash?puts({}.class)#Hash#=>nilprint({}.class)#Hash=>nil谁能帮我理解上面发生了什么?我完全不同意@Lindydancer的观点你如何解释下面几行:print{}.class#NilClassprint[].class#A

  5. ruby - 如何理解 Ruby 中的发送者和接收者? - 2

    我很难理解Ruby中sender和receiver的实际含义。它们一般是什么意思?到目前为止,我只是将它们理解为方法调用和获取其返回值的调用。但是,我知道我的理解还远远不够。谁能给我一个Ruby中发送者和接收者的具体解释? 最佳答案 面向对象中的一个核心概念是消息传递和早期概念化,这在很大程度上借鉴了计算的Actor模型。艾伦·凯(AlanKay)创造了面向对象一词并发明了最早的OO语言之一SmallTalk,他拥有voicedregretatusingatermwhichputthefocusonobjectsinsteadofo

  6. ruby-on-rails - Rails - 理解 application.js 和 application.css - 2

    rails新手。只是想了解\assests目录中的这两个文件。例如,application.js文件有如下行://=requirejquery//=requirejquery_ujs//=require_tree.我理解require_tree。只是将所有JS文件添加到当前目录中。根据上下文,我可以看出requirejquery添加了jQuery库。但是它从哪里得到这些jQuery库呢?我没有在我的Assets文件夹中看到任何jquery.js文件——或者直接在我的整个应用程序中没有看到任何jquery.js文件?同样,我正在按照一些说明安装TwitterBootstrap(http:

  7. ruby - 你如何理解 Ruby 中的这个三元条件? - 2

    我在某些代码中遇到了三元组,但我无法理解条件:str.split(/',\s*'/).mapdo|match|match[0]==?,?match:"somestring"end.join我确实理解我是在某些点上拆分字符串并将总结果转换为数组,然后依次处理数组的每个元素。除此之外,我不知道发生了什么。 最佳答案 一种(稍微)不那么令人困惑的写法是:str.split(/',\s*'/).mapdo|match|ifmatch[0]==?,matchelse"somestring"endend.join我认为多行三元语句很糟糕,尤其是

  8. ruby - 您如何将 S3 理解为 Ruby 中的分层目录结构? - 2

    有没有人成功地将S3存储桶读取为子文件夹?文件夹1--子文件夹2----文件3----文件4--文件1--文件2文件夹2--子文件夹3--文件5--文件6我的任务是读取文件夹1。我希望看到子文件夹2、文件1和文件2,但看不到文件3或文件4。现在,因为我将存储桶键限制为prefix=>'folder1/',你仍然会得到file3和4,因为它们在技术上具有folder1前缀。似乎真正做到这一点的唯一方法是吸收folder1下的所有键,然后使用字符串搜索从结果数组中实际排除file3和file4。有没有人有过这方面的经验?我知道像Transmit和Cyber​​duck这样的FTP风格的S3

  9. 关于yolov5训练时参数workers和batch-size的理解 - 2

    关于yolov5训练时参数workers和batch-size的理解yolov5训练命令workers和batch-size参数的理解两个参数的调优总结yolov5训练命令python.\train.py--datamy.yaml--workers8--batch-size32--epochs100yolov5的训练很简单,下载好仓库,装好依赖后,只需自定义一下data目录中的yaml文件就可以了。这里我使用自定义的my.yaml文件,里面就是定义数据集位置和训练种类数和名字。workers和batch-size参数的理解一般训练主要需要调整的参数是这两个:workers指数据装载时cpu所使

  10. ruby - 无法理解 Grape API 路由参数 - 2

    我在理解GrapeAPI时遇到很多困难,特别是route_param以及它如何仅使用params。考虑这段代码:desc"Returnastatus."paramsdorequires:id,type:Integer,desc:"Statusid."endroute_param:iddogetdoStatus.find(param[:id])endend这个街区产生什么路线?我知道这是一个get请求,但为什么它被包裹在route_paramblock中?为什么它不能在paramsblock中? 最佳答案 你的block产生这条路线:

随机推荐