单变量离散傅里叶变换DFT原理及实现

本文深入解析了离散傅里叶变换(DFT)的基本原理及应用,涵盖单变量DFT公式、中心化处理、傅里叶谱计算、逆DFT及其实现代码。通过实例展示了如何将图像转换为频谱图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        一、单变量离散傅里叶变换

              离散傅里叶变换公式:

                                                   F(\mu )=\sum_{t=0}^{n}f(t)e^{-j2\pi \mu t/n}

              根据公式,单变量离散傅里叶变是换将一维数组变换为傅里叶频率。设定一个大小为N的数组,t为X轴上的变量,取值为[0,n-1],f(t)为t=x出的值,计算机处理时,t即为输入数组下标index,f(t)为index对应位置数组中的值。

              当μ=0时:

                                                   F(\mu )=\sum_{t=0}^{n}f(t)

             相当于整个输入数组直接求和。由于傅里叶变换计算涉及复数,可以将输入数组变换为复数形式,f(t)作为复数实部,虚部为0。根据欧拉公式:

                                                  e^{j\theta }=cos\theta +jsin\theta

            在进行实际使用时,可将傅里叶变换为如下形式:

                                                  F(\mu )=\sum_{t=0}^{n}f(t)[cos(2\pi \mu t/n)-jsin(2\pi \mu t/n)]

            由于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

        四、逆傅里叶变换

             

逆傅里叶变换公式:

                                                 F(\mu )=1/n\sum_{t=0}^{n}f(t)e^{-j2\pi \mu t/n}

            傅里叶变换本质上就是把数据从时域/空间域变换到频率域,而逆傅里叶变换就是把数据再从频率域变换回时域/空间域。

            逆傅里叶变换实现代码:

            

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();
}

            测试图像:

           频谱图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TheMatrixs

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值