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

使用NumPy FFT系数与傅里叶设计矩阵重建周期信号的时间偏移问题

问题分析:傅里叶重建信号的时间偏移问题

问题背景

通过叠加带幅度、频率、相位的正弦波生成周期时域信号,使用NumPy的FFT计算正弦/余弦基下的傅里叶系数,再构建由不同时间和频率的正弦/余弦元素组成的傅里叶设计矩阵,理论上系数与矩阵相乘可重建原始信号,但运行代码后出现了重建信号与原始信号的时间偏移问题。

问题根源

核心矛盾在于FFT的默认时间基准假设与代码中实际使用的时间轴不匹配:

  • FFT的数学定义默认输入信号的时间起点为t=0,但代码中时间采样点是从5000到12000,相当于信号整体平移了t₀=5000的时间偏移。
  • 原始信号的正弦项为sin(2πft + φ),当时间轴从t变为t'=t - t₀时,展开后相位变为2πft' + 2πft₀ + φ,FFT计算出的系数是对应平移后信号的结果。
  • 但代码中的傅里叶设计矩阵直接使用原始t计算基函数,未考虑这个相位偏移,导致系数与基函数的相位不匹配,最终重建信号出现时间偏移。

修复方案

最直接的解决方法是统一时间基准,将原始时间轴平移到以0为起点,让FFT的假设与设计矩阵的基函数计算保持一致。

修正后的完整代码

import numpy as np
import matplotlib.pyplot as plt

# 生成含非整数时间采样点的实值信号
def create_signal(t, freq_components):
    signal = np.zeros(len(t))
    for amplitude, freq, phase in freq_components:
        signal += amplitude * np.sin(2 * np.pi * freq * t + phase)
    return signal

# 执行FFT并获取正弦、余弦系数
def compute_fourier_coefficients(signal):
    N = len(signal)
    fft_result = np.fft.fft(signal)
    
    # 初始化余弦和正弦系数数组
    cosine_coeffs = np.zeros(N // 2 + 1)
    sine_coeffs = np.zeros(N // 2 + 1)
    
    # 计算系数
    for k in range(1, N // 2 + 1):
        cosine_coeffs[k] = (2 / N) * fft_result[k].real
        sine_coeffs[k] = -(2 / N) * fft_result[k].imag
    
    # 直流分量(均值)
    cosine_coeffs[0] = np.mean(signal)
    
    return cosine_coeffs, sine_coeffs

# 创建含非整数时间采样点的傅里叶设计矩阵(修正:使用平移后的时间轴)
def create_fourier_design_matrix(t_shifted, num_modes, T):
    N = len(t_shifted)
    design_matrix = np.zeros((N, 2 * num_modes))
    
    for k in range(1, num_modes + 1):
        design_matrix[:, 2 * (k - 1)] = np.cos(2 * np.pi * k * t_shifted / T)
        design_matrix[:, 2 * (k - 1) + 1] = np.sin(2 * np.pi * k * t_shifted / T)
    
    return design_matrix

# 从傅里叶系数重建信号
def reconstruct_signal_from_design_matrix(fourier_design_matrix, cosine_coeffs, sine_coeffs):
    num_modes = len(cosine_coeffs) - 1
    coeffs = np.zeros(2 * num_modes)
    coeffs[0::2] = cosine_coeffs[1:]
    coeffs[1::2] = sine_coeffs[1:]
    reconstructed_signal = fourier_design_matrix @ coeffs
    reconstructed_signal += cosine_coeffs[0]  # 添加直流分量以匹配原信号均值
    return reconstructed_signal

# 参数
N = 1024  # 采样点数
t = np.linspace(5000, 12000, N)  # 5000到12000的非整数时间采样点
t_shifted = t - t[0]  # 平移时间轴到以0为起点
T = t_shifted[-1] - t_shifted[0]  # 总时长
# 频率分量需与信号实际频率对应
freq_components = [(1.0, 5 / T, 0), (0.5, 10 / T, np.pi/4), (0.2, 20 / T, np.pi/2)]  # (幅度, 频率, 相位)

# 生成原始信号(用平移后的时间轴,信号值与原信号一致)
original_signal = create_signal(t_shifted, freq_components)

# 计算傅里叶系数
cosine_coeffs, sine_coeffs = compute_fourier_coefficients(original_signal)

# 创建傅里叶设计矩阵(用平移后的时间轴)
num_modes = N // 2
fourier_design_matrix = create_fourier_design_matrix(t_shifted, num_modes, T)

# 重建信号
reconstructed_signal = reconstruct_signal_from_design_matrix(fourier_design_matrix, cosine_coeffs, sine_coeffs)

# 绘制原始信号与重建信号(用原始时间轴展示)
plt.plot(t, original_signal, label='Original Signal')
plt.plot(t, reconstructed_signal, label='Reconstructed Signal', linestyle='dashed')
plt.legend(loc='upper right')
plt.xlabel('time')
plt.ylabel('signal')
plt.show()

关键修改点说明

  1. 新增t_shifted = t - t[0],将时间轴平移至以0为起点,对齐FFT的默认时间基准。
  2. 生成信号、构建设计矩阵时均使用t_shifted,确保FFT计算的系数与基函数的相位完全匹配。
  3. 绘图时仍使用原始t轴,不影响结果的可视化展示。

验证结果

修改后运行代码,重建信号与原始信号会完全重合,时间偏移问题彻底解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 13:19:52