You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

手动实现逆FFT时误差沿x轴递增的原因及修正方法咨询

手动实现逆FFT时误差随x轴递增的原因与修正方法

问题描述

通过NumPy的FFT组件手动计算逆FFT,将重建信号与原始正弦信号对比时,误差(original - rebuilt)沿x轴逐渐增大;但使用内置函数ifft重建信号时无此现象,请问原因及修正方法?

用户提供的代码如下:

import numpy as np
from scipy import *
from matplotlib import pyplot as plt
tempdata = np.loadtxt("sinx_80.dat")


x_positions = tempdata[:, 0]
delta_x=x_positions[1] - x_positions[0]
roughness_data = tempdata[:, 1]


fft_1d = np.fft.fft(roughness_data)
num_x = len(fft_1d)

freq_x = np.fft.fftfreq(num_x, d=delta_x)
reconstructed_surface=np.zeros(num_x)
x_grid = (x_positions - x_positions[0])

for n in range(num_x):
    amplitude = np.abs(fft_1d[n]) / (num_x)
    phase = np.angle(fft_1d[n])
    reconstructed_surface += amplitude * np.cos(2 * np.pi * (freq_x[n] * x_grid) + phase)

difference = roughness_data - reconstructed_surface


max_error = np.max(np.abs(difference))
rms_error = np.sqrt(np.mean(difference**2))

print(f"Max Error: {max_error}")
print(f"RMS Error: {rms_error}")


plt.figure(figsize=(12, 8))
plt.subplot(3, 1, 1)
plt.plot(x_positions, roughness_data, label="Original Data", color="blue")
plt.title("Original Data")
plt.legend()
plt.grid()


plt.subplot(3, 1, 2)
plt.plot(x_positions, reconstructed_surface, label="Reconstructed Data", color="orange")
plt.title("Reconstructed Data")
plt.legend()
plt.grid()


plt.subplot(3, 1, 3)
plt.plot(x_positions, difference, label="Difference (Original - Reconstructed)", color="red")
plt.title("Difference")
plt.legend()
plt.grid()


plt.show()

误差表现:误差沿x轴逐渐递增(对应图示趋势)

原因分析

  • 频率相位符号错误:np.fft.fftfreq返回的频率包含正、负两类,逆FFT的余弦合成中,负频率项的相位符号需要反向。你当前对所有频率项统一使用+ phase,导致正负频率的相位无法正确抵消虚部,产生累积的相位偏移,最终表现为误差随x递增。
  • 振幅处理逻辑缺失:FFT中正负频率是共轭对,除直流分量(n=0)和Nyquist频率(n=num_x//2)外,每个正频率的振幅需要乘以2才能和对应的负频率共同还原原始信号的幅度,你当前的振幅计算没有做这个处理,会导致信号幅度偏差,但这不是误差递增的核心原因。

修正方法

核心修正点

  1. 区分正、负频率,负频率项使用- phase参与余弦合成;
  2. 对正频率(除直流和Nyquist频率)的振幅乘以2,合并共轭频率对的贡献。

修改后的代码

import numpy as np
from matplotlib import pyplot as plt  # 移除未使用的scipy导入

tempdata = np.loadtxt("sinx_80.dat")

x_positions = tempdata[:, 0]
delta_x = x_positions[1] - x_positions[0]
roughness_data = tempdata[:, 1]

fft_1d = np.fft.fft(roughness_data)
num_x = len(fft_1d)

freq_x = np.fft.fftfreq(num_x, d=delta_x)
reconstructed_surface = np.zeros(num_x)
x_grid = x_positions - x_positions[0]

for n in range(num_x):
    amplitude = np.abs(fft_1d[n]) / num_x
    phase = np.angle(fft_1d[n])
    # 区分正负频率调整相位符号
    if freq_x[n] < 0:
        reconstructed_surface += amplitude * np.cos(2 * np.pi * freq_x[n] * x_grid - phase)
    else:
        # 正频率中,除直流和Nyquist频率外,振幅乘以2
        if n != 0 and n != num_x // 2:
            amplitude *= 2
        reconstructed_surface += amplitude * np.cos(2 * np.pi * freq_x[n] * x_grid + phase)

difference = roughness_data - reconstructed_surface

max_error = np.max(np.abs(difference))
rms_error = np.sqrt(np.mean(difference**2))

print(f"Max Error: {max_error}")
print(f"RMS Error: {rms_error}")

plt.figure(figsize=(12, 8))
plt.subplot(3, 1, 1)
plt.plot(x_positions, roughness_data, label="Original Data", color="blue")
plt.title("Original Data")
plt.legend()
plt.grid()

plt.subplot(3, 1, 2)
plt.plot(x_positions, reconstructed_surface, label="Reconstructed Data", color="orange")
plt.title("Reconstructed Data")
plt.legend()
plt.grid()

plt.subplot(3, 1, 3)
plt.plot(x_positions, difference, label="Difference (Original - Reconstructed)", color="red")
plt.title("Difference")
plt.legend()
plt.grid()

plt.show()

原理说明

FFT结果中,正频率fft_1d[n]和负频率fft_1d[num_x-n]是共轭对称的,手动合成时需要将这一对的贡献合并:A*cos(ωt+φ) + A*cos(-ωt+φ) = 2A*cos(ωt)cos(φ),才能还原原始实信号。如果不对负频率相位取反,会变成A*cos(ωt+φ) + A*cos(-ωt-φ) = 2A*cos(ωt+φ),引入额外的相位偏移,随x增大累积形成递增误差。

内容的提问来源于stack exchange,提问作者user22248229

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 23:29:51