单变量离散傅里叶变换DFT原理及实现
? ? ? ? 一、單變量離散傅里葉變換
? ? ? ? ? ? ??離散傅里葉變換公式:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ??根據公式,單變量離散傅里葉變是換將一維數組變換為傅里葉頻率。設定一個大小為N的數組,t為X軸上的變量,取值為[0,n-1],f(t)為t=x出的值,計算機處理時,t即為輸入數組下標index,f(t)為index對應位置數組中的值。
? ? ? ? ? ? ? 當μ=0時:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ?相當于整個輸入數組直接求和。由于傅里葉變換計算涉及復數,可以將輸入數組變換為復數形式,f(t)作為復數實部,虛部為0。根據歐拉公式:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ??在進行實際使用時,可將傅里葉變換為如下形式:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ??由于j為虛數,在實際計算過程中j=√-1是沒有代入的,只需要計算復數的實部和虛數實部即可。
? ? ? ? ? ??傅里葉變換核心代碼:
? ? ? ? ? ?
public Complex[] dft(Complex[] C) {int n = C.length;if (n == 1) {return C;}Complex[] result = new Complex[n];for (int i = 0; i < n; i++) {result[i] = new Complex(0, 0);for (int j = 0; j < n; j++) {double p = -2 * i * j * Math.PI / n;Complex m = new Complex(Math.cos(p), Math.sin(p));result[i] = result[i].add(C[j].multiply(m));}}return result;}? ? ? ? ? ??代碼中,i相當于公式中的μ,j相當于t。
? ? ? ??二、中心化
? ? ? ? ? ? ??為了便于分析和操作需要將輸入數組進行中心化,中心化公式:f’(t) = f(t)*(-1)t,即根據數組下標奇偶數,將下標為奇數的數乘以-1,把整個數組分為以0為中心的數組序列。
? ? ? ? ? ? ?中心化代碼:
? ? ? ? ? ? ?
public Complex[] dftShift(Complex[] C) {int n = C.length;Complex[] result = new Complex[n];for(int i = 0; i < n; i++) {Complex m = new Complex(Math.pow(-1, i),0);result[i] = C[i].multiply(m);}return result;}? ? ? ??三、傅里葉譜
? ? ? ? ? ? ? ?傅里葉譜,即傅里葉變換后的頻譜圖,頻譜計算也就是計算復數模長。
? ? ? ? ? ? ?? 復數模長計算公式:|C|=a2+b2
? ? ? ? 四、逆傅里葉變換
? ? ? ? ? ? ?
逆傅里葉變換公式:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ??傅里葉變換本質上就是把數據從時域/空間域變換到頻率域,而逆傅里葉變換就是把數據再從頻率域變換回時域/空間域。
? ? ? ? ? ??逆傅里葉變換實現代碼:
? ? ? ? ? ??
public Complex[] iDFT(Complex[] C) {int n = C.length;if (n == 1) {return C;}Complex[] result = new Complex[n];for (int i = 0; i < n; i++) {result[i] = new Complex(0, 0);for (int j = 0; j < n; j++) {double p = 2 * i * j * Math.PI / n;Complex m = new Complex(Math.cos(p), Math.sin(p));result[i] = result[i].add(C[j].multiply(m));}result[i] = new Complex(result[i].getRealPart() / n, result[i].getImaginePart() / n);}return result;}? ? ? 五、離散傅里葉變換實現代碼
public class DFT {/*** 計算離散傅里葉變換* * @param x* @return*/public Complex[] dft(Complex[] C) {int n = C.length;if (n == 1) {return C;}Complex[] result = new Complex[n];for (int i = 0; i < n; i++) {result[i] = new Complex(0, 0);for (int j = 0; j < n; j++) {double p = -2 * i * j * Math.PI / n;Complex m = new Complex(Math.cos(p), Math.sin(p));result[i] = result[i].add(C[j].multiply(m));}}return result;}/*** 逆離散傅里葉變換* * @param C* @return*/public Complex[] iDFT(Complex[] C) {int n = C.length;if (n == 1) {return C;}Complex[] result = new Complex[n];for (int i = 0; i < n; i++) {result[i] = new Complex(0, 0);for (int j = 0; j < n; j++) {double p = 2 * i * j * Math.PI / n;Complex m = new Complex(Math.cos(p), Math.sin(p));result[i] = result[i].add(C[j].multiply(m));}result[i] = new Complex(result[i].getRealPart() / n, result[i].getImaginePart() / n);}return result;}//中心化public Complex[] dftShift(Complex[] C) {int n = C.length;Complex[] result = new Complex[n];for(int i = 0; i < n; i++) {Complex m = new Complex(Math.pow(-1, i),0);result[i] = C[i].multiply(m);}return result;} }? ? ? ? ? ? 測試代碼:
public static void main(String[] args) throws Exception{File in = new File("E:\\桌面\\1.jpg");File out = new File("E:\\桌面\\4.txt");BufferedImage image = ImageIO.read(in);int width = image.getWidth();int height = image.getHeight();int length = width * height;Complex[] C = new Complex[length]; //將二維圖片轉為一維數組for(int i = 0; i < width; i++) {for(int j = 0; j < height; j++) {int rgb = image.getRGB(i, j);int index = i * height + j;C[index] = new Complex(rgb & 0xff, 0);}}C = new DFT().dftShift(C);//中心化Complex[] result = new DFT().dft(C);Writer writer = new FileWriter(out);for(int i = 0; i < length; i++) {writer.write(Double.toString(result[i].absValue()));//計算頻譜writer.write("\r\n");}writer.close(); }? ? ? ? ? ??測試圖像:
? ? ? ? ? ?頻譜圖:
總結
以上是生活随笔為你收集整理的单变量离散傅里叶变换DFT原理及实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 傅里叶变换基本概念及复数类实现
- 下一篇: 图像马赛克原理及实现