簡體   English   中英

Matlab 與 Python 中使用 FFT 的不同結果

[英]Different results using FFT in Matlab compared to Python

我有加速度計數據的時間序列,我想將其集成到速度和 position 時間序列中。 這是使用 FFT 完成的,但是 Matlab 和 Python 中的兩種方法給了我不同的結果。

Matlab 代碼:

nsamples = length(acc(:,1));
domega = 2*pi/(dt*nsamples);      
acchat = fft(acc);

% Make frequency array:
Omega = zeros(nsamples,1);

% Create Omega:
if even(nsamples)
   nh = nsamples/2;
   Omega(1:nh+1) = domega*(0:nh);
   Omega(nh+2:nsamples) = domega*(-nh+1:-1);
else
   nh = (nsamples-1)/2;
   Omega(1:nh+1) = domega*(0:nh); 
   Omega(nh+2:nsamples) = domega*(-nh:-1);
end

% High-pass filter:
n_low=floor(2*pi*f_low/domega);
acchat(1:n_low)=0;
acchat(nsamples-n_low+1:nsamples)=0;

% Multiply by omega^2:
acchat(2:nsamples) = -acchat(2:nsamples) ./ Omega(2:nsamples).^2;

% Inverse Fourier transform:
pos = real(ifft(acchat));

% --- End of function ---

Python 代碼:

import numpy as np


def acc2velpos(acc, dt):

    n = len(acc)

    freq = np.fft.fftfreq(n, d=dt)
    omegas = 2 * np.pi * freq
    omegas = omegas[1:]

    # Fast Fourier Transform of Acceleration
    accfft = np.array(np.fft.fft(acc, axis=0))

    # Integrating the Fast Fourier Transform
    velfft = -accfft[1:] / (omegas * 1j)
    posfft = accfft[1:] / ((omegas * 1j) ** 2)

    velfft = np.array([0] + list(velfft))
    posfft = np.array([0] + list(posfft))

    # Inverse Fast Fourier Transform back to time domain
    vel = np.real(np.fft.ifft(velfft, axis=0))
    pos = np.real(np.fft.ifft(posfft, axis=0))

    return vel, pos

這兩個代碼通常應該給出完全相同的結果,但是當我 plot 比較時,這就是我得到的

加速度到速度

在此處輸入圖像描述

加速到Position

在此處輸入圖像描述

知道為什么 Python 結果與 Position 中的 Matlab 結果不同嗎? 獲得與我使用這些實驗中的加速度測量值來識別駁船運動相同的結果對我來說至關重要。

我在 Python 中還有第二個版本,我嘗試在其中包含 Matlab 代碼中的過濾器。 這也給出了不同的結果,很像 Python 中沒有過濾器的結果。

def acc2vel2(acc, dt, flow):

    nsamples = len(acc)
    domega = (2*np.pi) / (dt*nsamples)
    acchat = np.fft.fft(acc)

    # Make Freq. Array
    Omega = np.zeros(nsamples)

    # Create Omega:
    if nsamples % 2 == 0:
        nh = int(nsamples/2)
        Omega[:nh] = domega * np.array(range(0, nh))
        Omega[nh:] = domega * np.array(range(-nh-1, -1))

    else:
        nh = int((nsamples - 1)/2)
        Omega[:nh] = domega * np.array(range(0, nh))
        Omega[nh:] = domega * np.array(range(-nh-2, -1))

    # High-pass filter
    n_low = int(np.floor((2*np.pi*flow)/domega))
    acchat[:n_low - 1] = 0
    acchat[nsamples - n_low:] = 0

    # Divide by omega
    acchat[1:] = -acchat[1:] / Omega[1:]

    # Inverse FFT
    vel = np.imag(np.fft.ifft(acchat))

return vel

這仍然與 Matlab 代碼有點不同。 建議?

看起來你在matlab代碼中有一個高通濾波器,而不是在python代碼中。 考慮到python和matlab位置結果之間的差異,這是有道理的。

您的python位置波似乎以低頻率上下振盪,表明頻域中的某些低頻分量未被濾除。 matlab代碼中的高通濾波器刪除了低頻分量。

在 Python 腳本中實現高通濾波器解決了這個問題:

def acc2velpos(acc, dt, f_low):

    n = len(acc)

    freq = np.fft.fftfreq(n, d=dt)
    domega = (2*np.pi)/(dt*(n + 1))
    omegas = 2 * np.pi * freq
    omegas = omegas[1:]

    # Fast Fourier Transform of Acceleration
    accfft = np.array(np.fft.fft(acc, axis=0))

    # High-pass filter
    n_low = int(np.floor((2*np.pi*f_low)/domega))
    accfft[:n_low - 1] = 0
    accfft[n - n_low:] = 0

    # Integrating the Fast Fourier Transform
    velfft = -accfft[1:] / (omegas * 1j)
    posfft = accfft[1:] / ((omegas * 1j) ** 2)

    velfft = np.array([0] + list(velfft))
    posfft = np.array([0] + list(posfft))

    # Inverse Fast Fourier Transform back to time domain
    vel = np.real(np.fft.ifft(velfft, axis=0))
    pos = np.real(np.fft.ifft(posfft, axis=0))

    return vel, pos

該答案作為對 Matlab 中使用 FFT 的不同結果與 Python中 CC BY-SA 3.0 下的 OP Kakemonster問題的編輯發布。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM