计算物理专题:傅里叶变换与快速傅里叶变换

news2024/9/25 21:23:13

计算物理专题:傅里叶变换与快速傅里叶变换

  • 傅里叶变换提供一个全新的角度去观察和描述问题,如在量子力学中,动量与坐标表象之间的变换就是傅里叶变换。傅里叶变换同意可以用在数据处理等领域。
  • 1965年,Cooley 和 Tukey 提出了快速傅里叶算法,将计算一个N点变换的工作量由N^2 降低至 N log_2N

傅里叶变换(FT)

  • 一个波形的傅里叶变换就是把这个波形分解成多个不同频率的正弦波之和。设h(t) 是一个给定的波形,其傅里叶积分为 : H(f) = \int_{-\infty}^{+\infty} h(t) exp(-i 2\pi f t)dt 
  • 傅里叶变换的逆变换 h(t) = \int_{-\infty}^{+\infty} H(f) exp(i2\pi f t)df
  • 傅里叶变换例题:

\begin{matrix} h(t)=\left\{\begin{matrix} A &(|t|\leq T_0) \\ 0 &(|t|>T_0) \end{matrix}\right.\\ \\ H(f)=\int_{-T_0}^{T_0}Ae^{-i2\pi ft}dt\\ =\frac{A}{\pi T_0}sin(2\pi fT_0) \end{matrix}(1)

\begin{matrix} h(t)=Acos(2\pi f_0 t)\\ H(f)=\frac{A}{2}(\delta(f-f_0)+\delta(f+f_0)) \end{matrix}(2)

离散傅里叶变换(DFT)

  • discrete_fourier_transform
  • 在计算机上做傅里叶变换必须对傅里叶变换做离散化处理。离散傅里叶变换一般视作抽样后的波形的连续傅里叶变换
  • 设函数 f(x) 在区间 0<= x <= 2\pi 上N个等分点 2\pi l/N 处的值已知,用已知周期为2\pi 的函数exp(ikx)的线性组合做 f(x) 在此区间上的三角插值函数,f(x) = \sum_{k=0}^{N-1} F_k exp(ikx)
    • 并且 f(2\pi l/N) = \sum_{k=0}^{N-1} F_k exp(i2\pi kl/N),F_k 一般为一个复数
  • 离散傅里叶变换一般具有两个性质

\begin{matrix} \sum_{k=0}^{N-1}e^{ik2\pi/N}e^{-ik2\pi/N}=N \\ \sum_{k=0}^{N-1}e^{ijk2\pi/N}e^{-ilk2\pi/N}=0(l\neq j) \end{matrix}

  • 离散傅里叶变换有公式如下:

F_k=\frac{1}{N}\sum_{l=0}^{N-1}f(2l\pi/N)e^{-ikl2\pi/N}

离散傅里叶变换的Python 实现

import numpy as np

def DFT(x,threshold=False):
    N = len(x)

    FKR = np.zeros(N)
    FKI = np.zeros(N)
    
    for k in range(N):
        Fk_r,Fk_i = 0.0,0.0
        for l in range(N):
            angle = 2 * np.pi * k * l / N
            Fk_r += x[l] * np.cos(angle)
            Fk_i -= x[l] * np.sin(angle)
    
        FKR[k] = Fk_r
        FKI[k] = Fk_i

    if threshold:
        for i in range(N):
            if abs(FKR[i])<threshold:
                FKR[i] = 0.0
            FKR[i] = round(FKR[i],5)
            if abs(FKI[i])<threshold:
                FKI[i] = 0.0
            FKI[i] = round(FKI[i],5)

    return FKR,FKI

#testing
threshold = 1e-5

# sin(x) example:
N = 10
X = [np.sin(i*2*np.pi/N) for i in range(N)]
FKR,FKI = DFT(X,threshold = 1e-5)

#standard output
for i in range(len(FKR)):
    print(f"FK[{i}] = {FKR[i]} + {FKI[i]}j")

快速傅里叶变换(FFT)

  • 注意到F_k表达式中exp(-ikl2\pi /N)的周期性,就会发先这N个F_k 中N^2个不同的项中只有N个是不同的,即:1,exp[-i2\pi/N],exp[-i4\pi/N]......
  • 快速傅里叶算法将各项先按 exp[-ik2\pi/N]归类与合并同类项,从而将操作数从N^2 减少到 Nlog_2 N 

  • 设 N = 2^k(pos int) ,令 W = exp(-i2\pi/N) ,则W^N = 1,若记:f_l = f(2\pi l/N)/N
  • 则离散傅里叶变换的两个性质可以改写为:  

F_j = \sum_{l=0}^{N-1}f_lW^{jl}(j=0,1,...,N-1) 

\begin{matrix} F_{2j_1}=\sum_{l=0}^{N/2-1}(f_l+f_{l+N/2})(W^2)^{j_1l}\\ F_{2j_1+1}=\sum_{l=0}^{N/2-1}(f_l-f_{l+N/2})W^l(W^2)^{j_1l} \end{matrix}

快速傅里叶变换的Python实现

import numpy as np

def FFT(x):
    N = len(x)
    assert (N&(N-1))==0,f"{N} is not a power of 2"

    if N <= 1:
        return x
    
    even = FFT(x[0::2])
    odd  = FFT(x[1::2])

    T = [np.exp(-2j * np.pi * k/N) * odd[k] for k in range(N//2)]

    return [even[k] + T[k] for k in range(N//2)] + [even[k] - T[k] for k in range(N//2)]

# example
Num = 16
x = [np.sin(j*2*np.pi/Num) for j in range(Num)]
result = FFT(x)

FKR = [np.real(c) for c in result]
FKI = [np.imag(c) for c in result]

快速傅里叶变换的C语言实现

#include <stdio.h>
#include <math.h>

#define PI 3.14159265358979

struct Complex 
{
    double real;
    double imag;
};

void FFT(struct Complex x[], int N)
{
    if (N <= 1)
        return ;

    struct Complex even[N/2], odd[N/2];
    for (int i = 0; i < N/2; i++) 
	{
        even[i] = x[2*i];
        odd[i] = x[2*i + 1];
    }

    FFT(even,N/2);
    FFT(odd, N/2);

    for (int k = 0; k < N/2; k++) 
	{
        double angle = -2 * PI * k / N;        
        x[k].real = even[k].real + cos(angle) * odd[k].real + sin(angle) * odd[k].imag;
        x[k].imag = even[k].imag + cos(angle) * odd[k].imag - sin(angle) * odd[k].real;
        x[k + N/2].real = even[k].real - cos(angle) * odd[k].real + sin(angle) * odd[k].imag;
        x[k + N/2].imag = even[k].imag - cos(angle) * odd[k].imag - sin(angle) * odd[k].real;

    }
}

int main()
{
    int N = 8;
    struct Complex x[N] = {{1,0}, {0,0}, {1,0},{0,0}, {1,0}, {0,0}, {1,0}, {0,0}};
    FFT(x,N);
    
    printf("FFT result:\n");
    for (int i = 0; i < N; i++) 
	{
        printf("FK[%d] = %.2f + %.2f i\n",i,x[i].real,x[i].imag);
	}
}
  • 在编程中最复杂的就是处理复数的问题,一般使用新的struct 或者只能开动脑筋了用多个列表代替了,那样肯定会更加复杂和头晕。

傅里叶变换的应用举例

振荡频率的处理

import numpy as np
import matplotlib.pyplot as plt

Fs = 1000   #采样率
T = 1 / Fs  #采样间隔
L = 1000    #数据长度

A1 = 1
A2 = 2
A3 = 40

f1 = 50
f2 = 120
f3 = 400

t = np.arange(0,L)*T  # 时间序列
data = A1 * np.sin(2*np.pi * f1 *t) +\
       A2 * np.sin(2*np.pi * f2 *t) +\
       A3 * np.sin(2*np.pi * f3 *t)

#FFT变换
fft_result = np.fft.fft(data)
#频率轴
frequencies = np.fft.fftfreq(len(data),T)

N = len(frequencies)
N = N //2
frequencies = frequencies[:N]
fft_result = fft_result[:N]
Norm = np.linalg.norm(np.abs(fft_result))
fft_result = np.abs(fft_result)/Norm

plt.plot(frequencies,fft_result)
plt.xlabel("Frequency(Hz)")
plt.ylabel("Amplitude(normalized)")
plt.pause(0.01)


Nmax = 3
max_indices = np.argsort(fft_result)[::-1][:Nmax]
# 对应的频率和幅度比例
main_frequencies = frequencies[max_indices]
main_amplitudes = fft_result[max_indices]
main_amplitudes = [i/min(main_amplitudes) for i in main_amplitudes]
print("主要频率:", main_frequencies)
print("对应幅度比例:", main_amplitudes)

 

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

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

相关文章

redis之主从复制、哨兵、集群

文章目录 一、redis的高可用1.1 redis高可用的概念1.2 Redis的高可用技术 二、redis 主从复制2.1主从复制的原理2.2搭建Redis 主从复制 三、Redis 哨兵模式3.1搭建Redis 哨兵模式3.2启动哨兵模式3.3查看哨兵信息3.4故障模拟 四、Redis 群集模式4.1搭建Redis 群集模式 一、redis…

数据结构--串的定义和基本操作

数据结构–串的定义和基本操作 注:数据结构三要素――逻辑结构、数据的运算、存储结构&#xff08;物理结构) 存储结构不同&#xff0c;运算的实现方式不同 \color{pink}存储结构不同&#xff0c;运算的实现方式不同 存储结构不同&#xff0c;运算的实现方式不同 串的定义 串 …

用Java制作简单的记事本

目录 前言 主界面设计 功能实现 打开 另存为 保存 查找 替换 成员变量 其他方法 警告弹窗 不移动光标更新文本框内容 源代码 总结 转载请注明出处&#xff0c;尊重作者劳动成果。 前言 考完试想写敲一下代码就写了一下这个程序&#xff0c;整个也是写了怎么久…

JavaEE语法第二章之多线程(初级一)

一、认识线程 1.1线程的概念 一个线程就是一个 "执行流"。每个线程之间都可以按照顺序执行自己的代码. 多个线程之间 "同时"执行着多份代码。 一家公司要去银行办理业务&#xff0c;既要进行财务转账&#xff0c;又要进行福利发放&#xff0c;还得进行缴…

Docker常见问题集合

一、Docker安装 1、yum 安装 1&#xff09;更新yum包到最新 yum update2&#xff09;安装软件需要的软件&#xff0c;yum-util&#xff08;提供 yum-config-manager 功能&#xff09;&#xff0c;device-mapper-persistent-data、lvm2&#xff08;devicemapper 驱动依赖&…

mmdetection踩坑记录

1.mmcv-full和mmdetection的版本匹配问题 Readme里应该会给可复现的版本&#xff0c;一定要按照readme里的&#xff0c;这里是一些版本对应关系&#xff0c;像我的mmdet是2.3.0&#xff0c;我就只能装1.0.5的mmcv-full 表格来源&#xff1a;https://blog.csdn.net/qq_55957975/…

高频-测试岗面试题,软件测试面试常问面试题(付答案)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 测试流程&#xf…

【Zynq】Xilinx SDK设置编码方式

举例&#xff1a;将Xilinx SDK设置为UTF-8编码 工具栏->Window->Preferences

基于Tensorflow和Keras实现卷积神经网络CNN并进行猫狗识别

文章目录 一、环境配置1、安装Anaconda2、配置TensorFlow、Keras 二、猫狗数据集分类建模3.1 猫狗图像预处理3.2 猫狗分类的实例——基准模型3.1 构建神经网络3.2 配置优化器3.3 图片格式转化3.4 训练模型3.5 保存模型3.6 可视化 三、数据增强四、dropout 层五、参考资料 一、环…

Openresty原理概念篇(十五)Lua 规则和 NGINX 配置文件产生冲突怎么办?

一 Lua 规则和 NGINX 配置文件产生冲突怎么办? ① OpenResty 的名字和语言 说明&#xff1a; 了解openresty的发展史 ② 配置文件的规则优先级 1) 如何各司其职2) 都能满足功能,该如何取舍 理解&#xff1a; 1) rewrite ... break 到POST_WRITE阶段2) 而rewrite_by_lua*…

JAVA的DIFF算法

首先看一下我的文件结构 1.EnumType 类 public enum EnumType {ADD("ADD"),MODIFIED("MODIFIED"), DELETED("DELETED");//创建私有变量private String type;EnumType(String type) {this.type type;} }2.OperationType类 public class Operati…

vue封装svg组件来修改svg图片颜色

文章目录 1、引入依赖2、根目录的vue.config.js配置3、在组件文件夹(compontents)中创建svgIcon.vue4、在src目录下创建icons文件5、处理svg格式的图片6、在main.js文件中引入icons文件中的index.js文件7、使用8、效果图1、项目成功运行后的样子2、直接在html上添加样式&#x…

DEBUG系列三:使用 F9 和 watch point

首先是我随便找了个报错。 报销消息号信息&#xff1a; No pricing procedure could be determined Message No. V1212 1&#xff09;首先可以直接SE91 来追溯这个消息号哪儿报出来的 可以看到下面两个地方可能会报这个消息&#xff0c;可以直接在这两个地方打断点&#xff0c;…

开发一个RISC-V上的操作系统(一)—— 环境搭建

在前面我们使用Verilog实现了一个简易的RISC-V处理器&#xff0c;并且能烧录到板子上跑一些简单C程序&#xff0c;传送门&#xff1a; RISC-V处理器的设计与实现&#xff08;一&#xff09;—— 基本指令集_risc_v处理器_Patarw_Li的博客-CSDN博客 RISC-V处理器的设计与实现&…

电子器件系列41:扁平高压电阻

这种电阻和其他的高压电阻不同&#xff0c;不是绕线电阻而是陶瓷电阻 找到一个大神&#xff0c;他的专栏也得很详细了&#xff0c;贴在这里 https://blog.csdn.net/wkezheng/category_12059870.html 阻容感基础03&#xff1a;电阻器分类&#xff08;1&#xff09;-片式电阻器…

如何快速判断是否在容器环境

在渗透测试过程中&#xff0c;我们的起始攻击点可能在一台虚拟机里或是一个Docker环境里&#xff0c;甚至可能是在K8s集群环境的一个pod里&#xff0c;我们应该如何快速判断当前是否在容器环境中运行呢&#xff1f; 当拿到shell权限&#xff0c;看到数字和字母随机生成的主机名…

软考A计划-系统集成项目管理工程师-项目范围管理(二)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…

HTML、Markdown、Word、Excel等格式的文档转换为PDF

工具&#xff1a;gotenberg&#xff0c;docker部署 github&#xff1a;https://github.com/gotenberg/gotenberg 文档&#xff1a;https://gotenberg.dev/docs/about https://gotenberg.dev/docs/modules/libreoffice docker运行&#xff1a; docker run -d --rm -p 3000:30…

kubernete部署prometheus监控sring-boot程序

目录 1、kubernete集群环境以及prometheus基础环境 2、kubernetes监控集群内部的spring-boot程序 2.1、application.yml系统配置&#xff0c;endpoints相关设置 2.2、引入监控的相关依赖文件 pom.xml &#xff0c;主要是spring-boot-starter-actuator和micrometer-registr…