傅里叶变换应用 (01/2):频域和相位

news2025/1/15 13:13:55

一、说明

        我努力理解傅里叶变换,直到我将这个概念映射到现实世界的直觉上。这是一系列技术性越来越强的解释中的第一篇文章。我希望直觉也能帮助你!

二、傅里叶变换中频域简介

        声音是一种机械波,是空气中的振动或其他介质。音符对应于波的频率。高频波对应于高音符(高压和低压之间的变化较快),低频波对应于低音符(高压和低压之间的较慢变化)。

        这些波随着时间的推移在空间中传播。当波到达麦克风时,它会摆动一种称为振膜的结构。隔膜的运动产生电流,这使我们能够记录加压和减压的速率。

图 1:对于纯音,压力随时间变化绘制一个简单的正弦曲线。对于复杂音调,即纯音调的混合,压力随时间变化绘制正弦波的总和。

        如果我们考虑一个静止的麦克风,当波通过它时,记录的压力变化是时间的函数。时间域中的这种表示与我们的直觉非常吻合:随着时间的推移,压力会以与频率相对应的速度周期性地增加和减少。更复杂的音调是多个频率的总和组合(图 1)。

        信号在时域中的这种表示是密集的:对于大多数域,它不为零。但我们知道,我们可以更简洁地谈论音乐基调,而不是描述每个时间点的压力。相反,我们可以简单地命名一个音符,或者等效地以赫兹 (Hz) 表示频率:每秒的周期数。

        在频域中,x轴表示频率,y轴是信号中的频率量。对于图1中描述的简单音调,频域中的这种描述是稀疏的:对于大多数域,它为零

傅里叶变换是一种数学运算,它将我们在时域或空间域中的信号映射到频域中的函数。

        傅里叶变换正是我们想要的!它采用我们在图1中绘制的密集时间信号,并给出图2在频域中的稀疏描述。从图中看,每个分量频率都很明显。

图 2:对于  1 中的相同三个信号,离散傅里叶变换的正频率项的幅度。x 轴值对应于窗口时间段内的周期数。

        如果我们将图1中信号的时间持续时间视为一秒,则图2中的x轴值对应于赫兹。傅里叶变换为第一个图恢复 5Hz,为第二个图恢复 25Hz,为第三个复音恢复组合。对于所有其他频率值,傅里叶变换的值约为零。目前,我们只考虑量级,我们将在以后的帖子中探索更多!

图 3:使用  Tone Gen 应用程序播放 440Hz 音调时使用 我的存储库源进行音频绘图!

        我发现在实时音频数据上试验傅里叶变换最有价值!我把一个小的Python存储库放在一起,试验傅里叶变换的结果,应用于从计算机麦克风记录的短片段。

查看来源!尝试乐器和环境声音。

三、傅里叶变换---了解相位角

        在上一节中,可视化专门讨论了傅里叶变换的大小。在这里,我们将扩展缺失的部分:相位!在上节中,我展示了如何使用傅里叶变换的幅度来估计信号的频率分量。然而,仅凭频率,我们无法完美地重建信号;我们需要相位!

图 2-1:三个相同的正弦波相位偏移。图片由作者提供。

        如果我们查看纯音音频文件,但将信号从左向右移动怎么办?

        在我们前面的音频示例中,这带来了挑战。左侧的所有三个信号(图1)具有相同的频率。高压和低压之间的振荡速率是相同的。唯一的区别是起始位置,从左到右移动。

        我们可以将其表示为“相移”。三个信号是相同的频率,只是在振荡的起始位置偏移。查看三个生成方程,分别 — 0.5 * cos(5x)、05 * cos(5x + 1) 和 0.5 * cos(5x + 2) — 此偏移量表示为余弦表达式中的求和值,即 0、1 和 2。

图 2-2:使用傅里叶变换的 np.angle 恢复的近似相位。图片由作者提供。

        该相位信息也用傅里叶变换表示,可以使用numpy“角度”函数恢复。如果我们查看与具有最大幅度的频率相同的指数处的相位值,我们可以确定与该频率分量相关的相位偏移。在这里(图 2),傅里叶变换从上面的方程中恢复 0、1 和 2!

四、傅里叶变换,应用(3):复杂数据中的幅度和相位编码

        我们已经建立了常识性的理解,即傅里叶变换的幅度和相位值可以告诉我们信号的复合频率。现在,我们将进站了解 np.abs 和 np.angle 函数如何在引擎盖下工作。为此,我们还将介绍复数的工作定义!

4.1 复数基础知识

        在本系列的后面,我们将在处理复数时获得更多技术性。不过,就目前而言,我们只需要将复数识别为两部分的复合:分量和虚分量。

        我们很快就会回到复数的一些神奇性质(并介绍一位名叫欧拉的特别嘉宾),但为了达到量级和相位,我们可以将复数视为简单的二维值。每个复数都是一对实值和一个虚值。像任何二维一样,我们可以绘制这些复杂的对。按照惯例,我们通常将实部放在 x 轴上,将虚部放在 y 轴上。

图 1:可视化幅度和相位。图片由作者提供。

        我们复数的虚部是 i 的倍数(或 j,取决于你问谁):(-1)。在左边,我可视化了复数 1+1j。实值为 1,虚值为 1 的复数。同样,实部分量在 x 轴上,虚部分量在 y 轴上。正如预期的那样,这使我们直接处于第一象限。

        现在,我们不需要太担心为什么 y 轴表示为 j 的系数。 只要你接受我们可以将这个虚值视为第二维度,几何直觉就会起作用。我们会回来的,我保证!

傅里叶变换返回的值很复杂。在这些复数值上调用 np.abs 会给我们每个复值的大小。对这些复数值调用 np.angle 会给出每个复数值的相位角。通过这种方式,幅度和相位被编码在傅里叶变换的复数值中。

4.2 重新实现 np.abs

        复数的大小只是到原点的欧几里得距离 (0+0j):平方和的平方根。如上图所示,对于 1+1j,这是 (1² + 1²)≈1.41(想想勾股定理!下面,我包含了任意复数的逻辑:

def abs(complex_number: complex) -> float:  # pylint: disable=redefined-builtin
    """
    Get the magnitude (abs) of complex number.
    Args:
        complex_number: Complex number.
    Returns:
        Magnitude.
    """

    real_component = complex_number.real
    imaginary_component = complex_number.imag

    # calculate distance to origin
    sum_of_squares = (real_component ** 2) + (imaginary_component ** 2)
    sqrt_of_sum_of_squares = sum_of_squares ** (1 / 2)

    return sqrt_of_sum_of_squares


assert abs(1 + 1j) == np.abs(1 + 1j)
assert abs(2 * (1 - 1j)) == np.abs(2 * (1 - 1j))
assert abs(3 * (-1 + 1j)) == np.abs(3 * (-1 + 1j))
assert abs(4 * (-1 - 1j)) == np.abs(4 * (-1 - 1j))

4.3 重新实现 np.angle

        复数的相位是标准角(从右顺时针方向)。如上图所示,对于 1+1j,这是 arctan2(1, 1)≈0.79 弧度。检查度数(0.79弧度 * 180° / π弧度≈ 45°),该值正确反映了上图的角度。如果 arctan 使您的血压飙升,请花一分钟时间查看允许我们恢复这个角度的逆三角恒等式!

下面,我包含了任意复数的逻辑:

def angle(complex_number: complex) -> float:
    """
    Get phase (angle) of complex number.
    Args:
        complex_number: Complex number.
    Returns:
        Phase angle.
    """

    real_component = complex_number.real
    imaginary_component = complex_number.imag

    return np.arctan2(imaginary_component, real_component)


assert angle(1 + 1j) == np.angle(1 + 1j)
assert angle(2 * (1 - 1j)) == np.angle(2 * (1 - 1j))
assert angle(3 * (-1 + 1j)) == np.angle(3 * (-1 + 1j))
assert angle(4 * (-1 - 1j)) == np.angle(4 * (-1 - 1j))

        伟大!盘点一下,我们现在对傅里叶变换的大小和相位的含义有了很好的直观把握。我们对复数有一个基本的处理方法,以及从中恢复幅度和相位信息的方式。

        接下来,我们将研究傅里叶逆变换(IFFT),并展示我们可以使用迄今为止开发的工具包完成什么!

        如果代码或文本对您有价值,请为文章鼓掌!感谢您的阅读!

五、傅里叶变换应用 :让 FFT 发挥作用

现在,我们拥有了演示FFT的一些实际用例所需的所有工具!

5.1 介绍金融交易

        到目前为止,我们已经将傅里叶变换视为数学黑盒运算。同样,我们现在将介绍傅里叶变换,而不剖析实现细节。傅里叶逆变换(IFFT)让我们反转FFT!

傅里叶逆变换是一种数学运算,它将频域中的函数映射到时域或空间域中的函数信号。

arr = np.random.normal(loc=0, scale=10, size=20)
np.allclose(np.fft.ifft(np.fft.fft(arr)), arr)
# >>> True

IFFT(FFT(x)) ≈ x,反性质成立!

至关重要的是,这种逆运算允许我们在频域和时空/空间域之间跳转,以最方便的方式操作我们的数据。

5.2 傅里叶变换的应用

让我们开始玩弄傅里叶变换的实际应用吧!

5.2.1 滤波和去噪

FFT为我们提供了宝贵的“去噪”技术,以抑制或消除数据中的伪影。首先,让我们考虑一个近似静止的信号,它受到一些低功耗白噪声的影响。为了进行演示,我们可以使用与之前相同的纯音信号(图 1,“无噪声信号”)。此外,让我们在该信号中添加一些高斯噪声(图 1,“噪声信号”)。

就像我们之前所做的那样,我们可以使用傅里叶变换来查看频率分量(图 1,“无噪声 FFT”和“噪声 FFT”)。

图 1:简单的去噪,用于消除纯音信号中的低功耗噪声。图片由作者提供。

超级有趣!在FFT中,我们可以看到我选择添加的噪声的一些属性。我添加的高斯噪声是零平均加性“白”噪声:它在整个频率上的强度大致相等。

尽管噪声在时域中看起来非常可怕,但在频域中很容易分离出来。查看傅里叶变换的幅度值,我们可以将振幅可视化为频率的函数。在这个简单的情况下,我们可以很容易地完美地恢复我们的无噪音信号!由于信号和噪声之间有清晰的分离,我们可以设置一个硬阈值并降低(即设置为零)低幅度分量。将值保持在阈值以上(图 1,绿色的“噪声 FFT”)并将值放在阈值之前(图 1,红色的“噪声 FFT”),我们可以得到一个很好的无噪声信号重建(图 1,“去噪信号”)!

我们通常不会那么幸运。现实世界的噪音可能更令人讨厌!在许多情况下,噪声可能比我们的信号大。不过,我们还可以使用许多其他方法!

为了介绍一种常见的滤波方法,让我们看一下带通滤光片。带通滤波器由两个阈值组成:(1)去除低于某个阈值的频率的滤波器,允许更高的频率通过(即“高通”)和(2)去除高于某个阈值的频率的滤波器,允许较低频率通过(即“低通”)。这两个滤波器组合在一起,只允许低频截止和高频截止之间的频率“带”通过。

让我们在信号中添加一些高频分量。在实践中,这些可能是我们环境中不需要的音损(例如,在我们的声音示例中,环境中不受控制的音频源)。

图 2:简单的去噪,可去除纯音信号中的高频伪影。图片由作者提供。

现在,我们不是在最小幅度上设置硬阈值,而是将通带之外的频率的分量设置为零(图 2,“噪声 FFT”)。再一次,我们从噪音中恢复信号!

5.2.2 特征提取

我们还可以使用傅里叶变换来提取数据的特征。如果你以前遇到过小波卷积的想法,就会有很深的数学联系!如果您对深入探讨卷积定理的文章的评论感兴趣,请告诉我!

不过,现在,我们可以通过可视化不同的频率分量来专注于一个简单的示例。当我们在这里时,让我们尝试傅里叶变换的 2D 推广!

我们建立的所有直觉仍然适用!靠近原点的值将对应于低频,远离原点的值将对应于高频。和以前一样,np.abs将恢复幅度,np.angle将恢复相位。

如果我们只想检查图像中的边缘,我们可以查看高频值,将原点附近的傅里叶变换分量的振幅设置为零(图 4)。

图 4:轻松去除低频图像分量,可视化高频。按作者绘制。照片CC0由摄影师Lav Varshney拍摄。

我们还可以通过将远离原点的值设置为零来查看缓慢变化的低频分量!

图 5:轻松去除高频图像分量,可视化低频。按作者绘制。照片CC0由摄影师Lav Varshney拍摄。

我们可以使用这些技巧来提取各种有趣的统计属性。相同的方法也适用于一维时间或空间数据,使我们能够将缓慢移动的低频趋势与时间序列数据的突然突然变化(例如,股票价值或整体市场分析)分开。

5.3 其他应用

还有无数其他用途,但如果您有兴趣进一步阅读,这里有一些会想到:

  • 有损图像压缩(如JPEG)通常使用对引擎盖下的频域的变换,
  • 物理系统建模(如热力学!撇开,3blue1brown绝对是一个灵感),
  • 对齐和注册方法,使照片(或时间序列数据!
  • 估计和预测周期性生物现象(例如,呼吸频率、心率),以及
  • 无线电数据分析和处理。

我们已经对傅里叶变换有了足够的了解,这是危险的!我们已经设法充分发展了我们的直觉,可以解决现实世界的问题。如果您想解释其他傅立叶概念,请发表评论。感谢您的阅读!

接下来,我们将介绍常见操作的傅里叶“备忘单”及其在工具包中的位置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1016591.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode75】第五十七题 电话号码的字母组合

目录 题目: 示例: 分析: 代码: 题目: 示例: 分析: 给我们按下的按键,让我们返回对应按键可能产生的所有可能。 这是一道很经典的递归题,我们首先先拿一个数组把每个…

day45:C++ day5,运算符重载剩余部分、静态成员、继承

#include <iostream> #include <cstring> #define pi 3.14 using namespace std;class Shape { protected:double round;double area; public://无参构造Shape():round(40),area(100){cout<<"Shape::无参构造函数&#xff0c;默认周长为40&#xff0c;面…

C语言入门Day_21 函数的使用

目录 前言&#xff1a; 1.变量作用域 2.代码执行顺序 3.易错点 4.思维导图 前言&#xff1a; 我们是先定义函数&#xff0c;再调用函数。完成了函数的定义以后&#xff0c;我们就可以开始调用函数了&#xff0c;让我们来回顾一下&#xff1a; 调用函数分为两部分&#…

1131. 绝对值表达式的最大值

1131. 绝对值表达式的最大值 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;求方向一次遍历两度统计 参考代码&#xff1a;求方向一次遍历两度统计 原题链接&#xff1a; 1131. 绝对值表达式的最大值 https://leetcode.cn/problems/maximum-of-absolute-val…

网络安全深入学习第二课——热门框架漏洞(RCE—Thinkphp5.0.23 代码执行)

文章目录 一、什么是框架&#xff1f;二、导致框架漏洞原因二、使用步骤三、ThinkPHP介绍四、Thinkphp框架特征五、Thinkphp5.0.23 远程代码执行1、漏洞影响范围2、漏洞成因 六、POC数据包Windows下的Linux下的 七、漏洞手工复现1、先Burp抓包&#xff0c;把抓到的请求包发送到…

【AI语言大模型】文心一言功能使用介绍

一、前言 文心一言是一个知识增强的大语言模型,基于飞桨深度学习平台和文心知识增强大模型,持续从海量数据和大规模知识中融合学习具备知识增强、检索增强和对话增强的技术特色。 最近收到百度旗下产品【文心一言】的产品,抱着试一试的心态体验了一下,整体感觉:还行! 二…

自动化测试API【软件测试】

自动化测试 selenium 1. 为什么使用selenium&#xff1f; 开源免费支持多浏览器支持多系统支持多语言编程提供了丰富的web自动化测试API 2. API 查找页面元素 find Element() find Elements() 元素定位的方式 xpath selector 通常情况下&#xff0c;不需要手动来编写xpath…

Learn Prompt-经验法则

还记得我们在“基础用法”当中提到的三个经验法则吗&#xff1f; 尝试提示的多种表述以获得最佳结果使用清晰简短的提示&#xff0c;避免不必要的词语减少不精确的描述 现在经过了几页的学习&#xff0c;我认为是时候引入一些新的原则了。 3. 一个话题对应一个chat​ ChatG…

Kafka开篇

前言 从本篇开始对个人Kafka学习做一个总结, 目标有这么几个。 从概念架构角度, 对消息中间件形成概要认知;从使用角度, 掌握其常见用法;从性能角度, 探究其高性能实现机制; 消息中间件的用途 从消息生产和消费的角度, 平衡消费者和消费者的速率差。基于该点可以做到削峰填…

白炽灯对新生儿视力有影响吗?推荐专业的儿童台灯

大家都知道婴儿还在成长发育的重要阶段&#xff0c;身体各方面都是比较脆弱的&#xff0c;对外界事务的感知也很敏感&#xff0c;一点点的刺激都会影响的婴儿。而白炽灯是否适合婴儿使用这个问题&#xff0c;我的建议是尽量不要用白炽灯。 因为白炽灯光线不是很柔和&#xff0c…

周易算卦流程c++实现

代码 #include<iostream> using namespace std; #include<vector> #include<cstdlib> #include<ctime> #include<Windows.h>int huaYiXiangLiang(int all, int& left) {Sleep(3000);srand(time(0));left rand() % all 1;while (true) {if…

许可分析 license分析 第十二章

许可分析是指对软件许可证进行详细的分析和评估&#xff0c;以了解组织内部对软件许可的需求和使用情况。通过许可分析&#xff0c;可以帮助组织更好地管理和优化软件许可证的使用。以下是一些可能的许可分析方法和步骤&#xff1a; 软件许可证的分配和使用权限&#xff1a;制定…

01Spring的Ioc思想和依赖注入手段(DI)

传统方式创建对象的缺陷 连接MySQL实现登录功能 控制层UserController public class UserController {//多态,半面向接口编程private UserService userService new UserServiceImpl();public void login(){String username "admin";String password "1234…

基于 Zookeeper 实现分布式锁

文章目录 前言声明前置知识分布式锁设计原则Zookeeper 分布式锁实现Curator框架实现分布式锁总结 前言 在分布式系统中&#xff0c;确保数据的一致性和避免冲突是一个核心问题&#xff0c;通常我们通过分布式锁来解决&#xff0c;分布式锁本质是一种同步机制&#xff0c;用于控…

【AI】机器学习——支持向量机(线性模型)

支持向量机是一种二分类算法&#xff0c;通过在高维空间中构建超平面实现对样本的分类 文章目录 5.1 SVM概述5.1.1 分类 5.2 线性可分SVM5.2.1 线性可分SVM基本思想5.2.2 策略函数间隔几何间隔硬间隔最大化 5.2.3 原始算法支持向量 5.2.4 对偶形式算法1. 构造并求解对偶问题2. …

【小沐学CAD】嵌入式UI开发工具:GL Studio

文章目录 1、简介2、软件功能3、应用行业3.1 航空3.2 汽车3.3 防御3.4 工业3.5 电力与能源3.6 医疗3.7 空间3.8 科技 结语 1、简介 https://disti.com/gl-studio/ DiSTI 是 HMI 软件、虚拟驾驶舱、仪表、信息娱乐、集群显示器和嵌入式 UI 解决方案的领先提供商。 而它的GL Stu…

kubernetes部署(kubeadmin)

文章目录 1.环境准备2. 安装dokcer3.部署cri-docker4.各个节点安装kubeadm等5.整合kubelet和cri-dockerd配置cri-dockerd配置kubelet 6.初始化集群 1.环境准备 环境和软件版本 OS : ubuntu 20.04 container runtime: docker CE 20.10.22 kubernetes 1.24.17 CRI&#xff1a;cr…

atoi函数

介绍&#xff1a; 头文件: <stdlib.h> 此函数的功能是将数字字符的字符串转化为字面上的整型返回。 例如&#xff1a; char arr1[] "-12"; char arr2[] "12"; char arr3[] " -12"; char arr4[] "-12a";使用atoi 我们…

Postman的高级用法一:重新认识postman核心模块

本请求示例来自于免费天气API&#xff1a; 实况天气接口API开发指南 未来一天天气预报api - 天气API 关于Postman的核心模块 全局变量请求接口请求体预处理脚本 类似beforeTest&#xff0c;在发起请求前的预执行逻辑&#xff0c;通常是生成一些动态变量值 测试用例模块 测试者…

RK3399平台开发系列讲解(入门篇)VIM的基础命令

🚀返回专栏总目录 文章目录 一、Vim 命令速查二、其他命令三、Vim模式沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 本篇将介绍Vim相关命令。 一、Vim 命令速查 简单说明一下,这张图上展示了一个键盘。图中的“•”表示,单个字母不是完整的命令,必须再有进一步…