簡體   English   中英

如何在 python 中將頻域轉換為時域

[英]How to convert from frequency domain to time domain in python

我知道這是信號處理的基礎,但是,我不確定我的方法有什么問題。 我有一個信號表現為阻尼正弦信號,采樣頻率為 5076Hz,樣本數為 15,000。 我從以下網站找到了如何將信號從時域轉換為頻域並設法獲得 FFT 和頻率值。 代碼可以在下面的鏈接中找到:

使用信號處理技術進行機器學習

def get_fft_values(y_values, T_s, N, f_s):
    f_values = np.linspace(0.0, 1.0/(2.0*T), N//2)
    fft_values_ = np.fft.rfft(y_values)
    fft_values = 2.0/N * np.abs(fft_values_[0:N//2])
    return f_values, fft_values

我設法獲得了頻率和 FFT 值。 但是,我需要實現濾波器來去除信號中的一些噪聲,因此,我創建了以下函數來實現濾波器部分:

def butter_bandpass(lowcut, highcut, fs, order):
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    b, a = butter(order, [low, high], btype='bandpass', output='ba')
    return b, a

def butter_bandpass_filter(data, lowcut, highcut, fs, order):
    b, a = butter_bandpass(lowcut, highcut, fs, order=order)
    y = filtfilt(b=b, a=a, x=data)
    # y = lfilter(b=b, a=a, x=data)
    return y

我知道我需要執行以下步驟:

  • 轉換為頻域
  • 應用帶通濾波器以消除您不關心的頻率
  • 通過傅里葉逆變換轉換回時域

因此,我創建了以下逆變換 function,但是,我無法恢復濾波后的信號,並且幅度與原始信號幾乎不匹配。 (對於我的情況,我需要重新采樣)

def get_ifft_values(fft_values, T, N, f_s):
    # Time axis:
    N = 9903
    S_T = 1 / S_F
    t_n = S_T * N  # seconds of sampling
    # Obtaining data in order to plot the graph:
    x_time = np.linspace(0, t_n, N)
    ifft_val = np.fft.irfft(fft_values, n=N)
    y_s, x_time = scipy.signal.resample(x=ifft_val, num=N, t=x_time)
    return x_time, y_s

我在這里做錯了什么?

編輯1:

基於@Han-Kwang Nienhuys 的回答。 我編輯了上面的代碼並將其應用於以下方法:

##### Converting the signal into fft:
f_val, fft_val = get_fft_values(y_values=y, T=S_T, N=N, f_s=S_F)
# Applying bandpass filter:
fft_filt_val = butter_bandpass_filter(data=fft_val, lowcut=50, highcut=600, fs=S_F, order=2)
# Applying the inverse transform of the frequency domain:
x_time, y = get_ifft_values(fft_values=fft_filt_val, T=S_T, N=N, f_s=S_F)

以下是信號的結果:

  • 原始信號的 FFT:

原始信號的 FFT

  • 原始信號的濾波 FFT:

從 FFT 值過濾 FFT

  • 從濾波 FFT 轉換的信號:

從濾波 FFT 轉換的信號

  • 不應用帶通濾波器:

不應用帶通濾波器

有幾個問題:

  • 您正在使用np.fft.fft ,它是一個復值離散傅立葉變換,包含的頻率高達 Nyqvist 頻率的兩倍。 高於 Nyqvist 頻率的頻率可以等效地解釋為負頻率。 您確實在使用頻率切片[:N//2] ,但是如果您希望逆變換起作用,您還需要處理頻譜的另一半。
  • 不要取 FFT 數據的絕對值。 濾波器必須對復值系數進行操作。
  • 如果您使用scipy.signal.filtfilt : function 對時域數據進行操作,而不是對頻域數據進行操作。

對於實值輸入數據,使用實值 FFT 要容易得多,它的行為更像您的預期:

n = len(y)
yf = np.fft.rfft(y)
fstep = f_sampling / n
freqs = np.arange(len(yf)) * fstep

要轉換回來,請使用np.fft.irfft

暫無
暫無

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

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