当前位置: 首页 > article >正文

傅里叶变换 二维离散傅里叶变换

1、介绍。

        DFT:(Discrete Fourier Transform)离散傅里叶变换是傅里叶变换在时域和频域上都呈离散的形式,将信号的时域采样变换为其DTFT的频域采样。在形式上,变换两端(时域和频域上)的序列是有限长的,而实际上这两组序列都应当被认为是离散周期信号的主值序列。即使对有限长的离散信号作DFT,也应当将其看作其周期延拓的变换。

1)、欧拉公式:

\LARGE \dpi{100} \LARGE e^{\theta i}=cos \theta +(sin \theta )i,其中i是虚数,即i的平方为-1。

2)、二维离散傅里叶变换DFT公式:

N是二维数组的行数,M是二维数组的列数。u和v是转换后二维数组的位置,F(u,v)是转换后数组中相应位置的值。x和y是原二维数组的位置,f(x,y)是原数组中相应的值。

\LARGE F(u,v)=\sum_{x=0}^{M-1}\sum_{y=0}^{N-1}f(x,y)e^{-2\pi (\frac{ux}{M}+\frac{vy}{N})i}

根据欧拉公式,也可以写成:

\LARGE F(u,v)=\sum_{x=0}^{M-1}\sum_{y=0}^{N-1}f(x,y)[cos(2\pi (\frac{ux}{M}+\frac{vy}{N})) -sin(2\pi (\frac{ux}{M}+\frac{vy}{N}))i ]

3)、二维离散傅里叶逆变换IDFT公式:

N是二维数组的行数,M是二维数组的列数。x和y是转换后二维数组的位置,f(x,y)是转换后数组中相应位置的值。u和v是原二维数组的位置,F(u,v)是原数组中相应的值。

\LARGE f(x,y)=\frac{1}{NM}\sum_{u=0}^{N-1}\sum_{v=0}^{N-1}F(u,v)e^{2\pi (\frac{ux}{M}+\frac{vy}{N})i}

根据欧拉公式,也可以写成:

\LARGE F(u,v)=\sum_{x=0}^{M-1}\sum_{y=0}^{N-1}f(x,y)[cos(2\pi (\frac{ux}{M}+\frac{vy}{N}))+sin(2\pi (\frac{ux}{M}+\frac{vy}{N}))i ]

2、生成随机的二维数组。

//f(x,y)=1+2x+8x^2+2y+3xy^2
private static double[][] getRandom2(int row, int column) {double[][] arrays = new double[row][column];for (int x = 0; x < row; x++) {for (int y = 0; y < column; y++) {double value = 1 + 2 * x + 8 * x * x + 2 * y + 3 * x * y * y;arrays[x][y] = value;}}return arrays;
}

3、复数类。参考文章高数 复数的四则运算

package com.zxj.reptile.utils.number;public class Complex {private double real;//实数private double image;//虚数public Complex() {real = 0;image = 0;}public Complex(double real, double image) {this.real = real;this.image = image;}//加:(a+bi)+(c+di)=(a+c)+(b+d)ipublic Complex add(Complex complex) {double real = complex.getReal();double image = complex.getImage();double newReal = this.real + real;double newImage = this.image + image;return new Complex(newReal, newImage);}//减:(a+bi)-(c+di)=(a-c)+(b-d)ipublic Complex sub(Complex complex) {double real = complex.getReal();double image = complex.getImage();double newReal = this.real - real;double newImage = this.image - image;return new Complex(newReal, newImage);}//乘:(a+bi)(c+di)=(ac-bd)+(bc+ad)ipublic Complex mul(Complex complex) {double real = complex.getReal();double image = complex.getImage();double newReal = this.real * real - this.image * image;double newImage = this.image * real + this.real * image;return new Complex(newReal, newImage);}//乘:a(c+di)=ac+adipublic Complex mul(double multiplier) {return mul(new Complex(multiplier, 0));}//除:(a+bi)/(c+di)=(ac+bd)/(c^2+d^2) +((bc-ad)/(c^2+d^2))ipublic Complex div(Complex complex) {double real = complex.getReal();double image = complex.getImage();double denominator = real * real + image * image;double newReal = (this.real * real + this.image * image) / denominator;double newImage = (this.image * real - this.real * image) / denominator;return new Complex(newReal, newImage);}//欧拉公式 e^(ix)=cosx+isinxpublic static Complex euler(double x) {double newReal = Math.cos(x);double newImage = Math.sin(x);return new Complex(newReal, newImage);}public double getReal() {return real;}public void setReal(double real) {this.real = real;}public double getImage() {return image;}public void setImage(double image) {this.image = image;}@Overridepublic String toString() {String str = "";if (real != 0) {str += real;} else {str += "0";}if (image < 0) {str += image + "i";} else if (image > 0) {str += "+" + image + "i";}return str;}
}

4、二维离散傅里叶变换DFT代码。

    public static Complex[][] getDft2(double[][] arrays) {int M = arrays.length;int N = arrays[0].length;Complex[][] complexArrays = new Complex[M][N];double flag = -2 * Math.PI;for (int u = 0; u < M; u++) {for (int v = 0; v < N; v++) {//x-->M和y-->N的累加Complex sum = new Complex();for (int x = 0; x < M; x++) {for (int y = 0; y < N; y++) {//e^(-(2 * PI * (ux / M + vy / N)i)double angle = flag * (u * x * 1.0 / M + v * y * 1.0 / N);Complex complex = Complex.euler(angle);//f(x) * e^(-(2 * PI * (ux / M + vy / N)i)complex = complex.mul(arrays[x][y]);sum = complex.add(sum);}}complexArrays[u][v] = sum;}}return complexArrays;}

5、二维离散傅里叶逆变换IDFT代码。

    public static double[][] getInverseDft2(Complex[][] complexArrays) {int M = complexArrays.length;int N = complexArrays[0].length;double[][] arrays = new double[M][N];double flag = 2 * Math.PI;for (int x = 0; x < M; x++) {for (int y = 0; y < N; y++) {//u-->M和v-->N的累加Complex sum = new Complex();for (int u = 0; u < M; u++) {for (int v = 0; v < N; v++) {//e^((2 * PI * (ux / M + vy / N)i)double angle = flag * (u * x * 1.0 / M + v * y * 1.0 / N);Complex complex = Complex.euler(angle);//f(x) * e^((2 * PI * (ux / M + vy / N)i)complex = complex.mul(complexArrays[u][v]);sum = complex.add(sum);}}//f(x) * e^((2 * PI * (ux / M + vy / N)i) / (M * N)sum = sum.mul(1 * 1.0 / (N * M));double realSum = sum.getReal();arrays[x][y] = Math.round(realSum * 100) / 100.0;}}return arrays;}

6、因为java的Arrays类没有提供二维数组是否相等的比较方法,所以自己写一个比较二维数组是否相等的方法。

public static boolean equals(double[][] a, double[][] b) {if (a == null || b == null || a.length != b.length) {return false;}for (int i = 0; i < a.length; i++) {if (!Arrays.equals(a[i], b[i])) {return false;}}return true;
}

7、流程。可以先将随机数组的大小设小点,然后将打印日志的代码开起来,这样子才会对流程有更多的了解。

    public static void main(String[] args) {System.out.println("------开始------");long time = System.currentTimeMillis();// testDft();//一维离散傅里叶变换testDft2(10, 10);//二维离散傅里叶变换System.out.println("花费时间 :" + (System.currentTimeMillis() - time));System.out.println("------结束------");}private static void testDft2(int row, int column) {System.out.println(String.format("二维数组共有%d行%d列", row, column));//System.out.println("原数据: ");double[][] arrays = getRandom2(row, column);for (int x = 0; x < row; x++) {for (int y = 0; y < column; y++) {//System.out.print(arrays[x][y] + " ");}//System.out.println();}//System.out.println("离散傅里叶变换DFT: ");Complex[][] dtfArrays = FourierUtils.getDft2(arrays);for (int x = 0; x < row; x++) {for (int y = 0; y < column; y++) {//System.out.print(dtfArrays[x][y] + " ");}//System.out.println();}//System.out.println("逆离散傅里叶变换IDFT: ");double[][] inverseDtfArrays = FourierUtils.getInverseDft2(dtfArrays);for (int x = 0; x < row; x++) {for (int y = 0; y < column; y++) {//System.out.print(inverseDtfArrays[x][y] + " ");}//System.out.println();}System.out.print("二维离散傅里叶变换和逆离散傅里叶变换");if (ArrayUtils.equals(arrays, inverseDtfArrays)) {System.out.println("成功");} else {System.out.println("失败");}}

8、结果。可以将生成随机二维数组的大小进行改变,也可以对生成随机数据的函数进行改变。会发现原数组和经过离散傅里叶变换DFT及逆离散傅里叶变换IDFT之后的数组是一模一样的,就可以验证出算法和公式是对的。我将打印的日志和结果截图一并给出来。

9、结论。

      二维离散傅里叶因为涉及到4个嵌套循环,时间复杂度十分的大,所以在实际应用场景上得不到使用,现在的照片小的差不多也要500*500的大小,但是二维离散傅里叶处理大小60*60的时候,就已经显得十分的吃力了。

http://www.lryc.cn/news/2413944.html

相关文章:

  • Nature Microbiology | 可感染阿斯加德古菌的六种深海沉积物中的病毒基因组
  • 3DMAX程序贴图之3D木材贴图使用教程
  • java与javascript
  • 模糊神经网络系统1
  • MOS基础知识
  • 笔记本电脑如何开启wifi热点共享
  • BeanUtils.populate方法使用
  • 最大相关 - 最小冗余(mRMR)特征选择
  • 深度时空网络、记忆网络与特征表达学习在 CTR 预估中的应用
  • C#实现在RichTextBox控件中显示RTF格式的文件(附完整源码)
  • Linux网络编程-wireshark和tcpdump抓包(数据过滤和分析)
  • 知识图谱概念与知识图谱构建流程(KGC)总览
  • Java中StringBuilder的清空方法比较
  • 数据库SQL优化大总结1之- 百万级数据库优化方案
  • 9个Mac软件下载站,天下没有难找的软件。
  • CA证书服务器搭建及证书申请
  • DEDE5.7 模板文件不存在,无法解析文档个中解决方法
  • 【前端素材】推荐优质后台管理系统Acara平台模板(附源码)
  • IIS无法启动:发生意外错误0x8ffe2740的原因
  • 控制理论中常见名词中英文对照
  • 使用DM368的GPIO控制NANDFLASH的WP
  • Java图形化界面编程超详细知识点(7)——进度条
  • 雅虎YUI 3.7.1发布
  • FastDFS,Redis,Solr,ActiveMQ核心技术整合二(1)
  • CTF training WriteUp
  • 【转】花开正当时,十四款120/128GB SSD横向评测
  • widgets
  • win7开机出现修复计算机,win7开机提示系统自动修复无法正常进入的原因分析及解决...
  • 空间转换与动画
  • cf聊天室,cf聊天室下载