我正在使用Python通过傅里叶变换过滤信号。
原始信号是由一些仪器产生的,这些仪器应该包含基于周期的波动信号。示例如下所示:
我的目标是提取每个周期的每个平台作为一个单独的样本。在基于FFT的方法中,我尝试先得到一条更平滑的曲线,然后使用微分法得到突变点(最大/最小微分值)。基于起始点和结束点(如下图所示),我可以识别包含几个数据点的每个样本
然而,这种方法遇到了问题,因为原始信号还包含一些非感测信号,这些信号不有用,但导致FFT滤波的结果更差。
下面是我使用的部分数据和整个时间序列的代码和结果。在子图2中我们可以看到,由于最终噪声的影响,滤波后的信号不能反映原始信号周期的实际变化。
import pandas as pd
import numpy as np
from scipy import fftpack
from scipy.signal import find_peaks, general_gaussian, fftconvolve
test = pd.read_csv("https://raw.githubusercontent.com/envhyf/Notebook/master/example_raw_signal.csv")
def fft_filter(sig):
time_step = 1
period = len(sig)
time_vec = np.arange(0, period,time_step)
# reference: https://scipy-lectures.org/intro/scipy/auto_examples/plot_fftpack.html
sig_fft = fftpack.fft(sig)
power = np.abs(sig_fft)**2
sample_freq = fftpack.fftfreq(sig.size, d=time_step)
pos_mask = np.where(sample_freq > 0)
freqs = sample_freq[pos_mask]
peak_freq = freqs[power[pos_mask].argmax()]
high_freq_fft = sig_fft.copy()
high_freq_fft[np.abs(sample_freq) > peak_freq] = 0
filtered_sig = fftpack.ifft(high_freq_fft)
return filtered_sig
fig = plt.figure(figsize=(12, 6))
##########only extract part of the signal#######################
ax = plt.subplot(211)
sig = cutting_sig(test).F2.values[0:600]
sig_filtered = fft_filter(sig)
period = len(sig)
time_step = 1
time_vec = np.arange(0, period,time_step)
plt.plot(time_vec, sig, label='Original signal')
plt.plot(time_vec,sig_filtered , linewidth=2, label='Filtered signal')
deriv = np.diff(sig_filtered)
pos_peaks, pos_details = find_peaks(deriv)
neg_peaks, neg_details = find_peaks(-deriv)
plt.scatter(time_vec[pos_peaks], sig_filtered[pos_peaks],color = 'r')
plt.scatter(time_vec[neg_peaks], sig_filtered[neg_peaks],color = 'k')
plt.title('Part of the data')
plt.xlabel('Time [s]')
plt.legend(loc='best')
#######################################################################
ax = plt.subplot(212)
sig = cutting_sig(test).F2.values#[0:600]
sig_filtered = fft_filter(sig)
period = len(sig)
time_step = 1
time_vec = np.arange(0, period,time_step)
plt.plot(time_vec, sig, label='Original signal')
plt.plot(time_vec,sig_filtered , linewidth=2, label='Filtered signal')
deriv = np.diff(sig_filtered)
pos_peaks, pos_details = find_peaks(deriv)
neg_peaks, neg_details = find_peaks(-deriv)
plt.scatter(time_vec[pos_peaks], sig_filtered[pos_peaks],color = 'r')
plt.scatter(time_vec[neg_peaks], sig_filtered[neg_peaks],color = 'k')
plt.title('Whole series')
plt.legend()
plt.tight_layout()
plt.show()
所以,我的问题是如何预先去除这些噪声,然后进行FFT滤波以达到我的目标?我想不出摆脱那些坏数据点的方法。如有任何建议或意见,将不胜感激。