问题是:平均作为低通滤波器有什么问题?
细节: 我想对信号进行低通滤波以对其进行下采样。限制是:我没有可用的 RAM,并且我在流式传输中工作,因此我不能使用加权窗口进行过滤。因此,我必须对最后 X 个样本进行平均,或者像这样的经典过滤器:
signal_t+1 = signal_t * (1-factor) + new_measurement * factor
带有适合采样的值的因子。更重要的是,我知道在略高于下采样频率的频率附近有信号。
使用平均值还是使用上述一阶滤波器更好?
更多细节和测试: 我使用真实样本,并不复杂。采样频率 = 200 Hz,下采样后的频率 = 4Hz。
让我们比较一个截止频率为 1Hz 以限制混叠的一阶滤波器和两个平均滤波器。第一个平均滤波器是 50 个样本的平均值,从 200Hz 降采样到 4Hz。第二个平均滤波器是 66 个样本的平均值,以获得与 1 阶滤波器一样多的抑制。
我认为过滤器“66 个样本的平均值”是最好的:50 个样本的平均过滤器的拒绝率高于 1 阶过滤器,我真的需要限制混叠。但是 66 样本滤波器的截止频率大于 1 阶滤波器,并且在 2Hz 之后的抑制至少相等。更重要的是,66 个样本的滤波器削减了 3Hz 左右的频率,我知道在 3Hz 上会有信号,这会使我的信号在 4Hz 下采样后变得嘈杂——我使用的是真实样本,而不是复杂的。
然后,我会选择 66 样本平均滤波器。
上面的逻辑有问题吗? 你有什么建议吗?
这是代码:
import numpy as np
import matplotlib.pyplot as plt
nfft = 8192
fsampl = 200
dtsampl = 1 / 200
fcutoff = 1
dtcutoff = 1 / (2 * np.pi * fcutoff)
faverage1 = 4
faverage2 = 3
print("generate signal")
raw_signal = np.zeros(nfft)
raw_signal[int(nfft/2)]=1
print("filter signal")
filtered_signal = 0.*np.copy(raw_signal)
for i in range(1, np.size(raw_signal)):
filtered_signal[i] = filtered_signal[i-1]+ (raw_signal[i-1]-filtered_signal[i-1]) * dtsampl / dtcutoff
averaged_signal_1 = np.copy( raw_signal )
num_average = fsampl / faverage1
for i in range(1, np.size(raw_signal)):
averaged_signal_1[i] = np.average( raw_signal[int( max( 0, i - num_average ) ):i] )
averaged_signal_2 = np.copy( raw_signal )
num_average = fsampl / faverage2
for i in range(1, np.size(raw_signal)):
averaged_signal_2[i] = np.average( raw_signal[int( max( 0, i - num_average ) ):i] )
print("get FFT")
raw_signal_fft = np.fft.rfft(raw_signal)
filtered_signal_fft = np.fft.rfft(filtered_signal)
averaged_signal1_fft = np.fft.rfft( averaged_signal_1)
averaged_signal2_fft = np.fft.rfft( averaged_signal_2)
raw_signal_fftlog = 20*np.log10(np.abs(raw_signal_fft))
filtered_signal_fftlog = 20*np.log10(np.abs(filtered_signal_fft))
averaged_signal1_fftlog = 20*np.log10(np.abs(averaged_signal1_fft))
averaged_signal2_fftlog = 20*np.log10(np.abs(averaged_signal2_fft))
print("plot")
freq_axe= np.linspace( 0, fsampl / 2, int( nfft / 2 ) + 1 )
plt.plot(freq_axe, raw_signal_fftlog, '-')
plt.plot(freq_axe, filtered_signal_fftlog, 'r-')
plt.plot(freq_axe, averaged_signal1_fftlog, '-')
plt.plot(freq_axe, averaged_signal2_fftlog, '-')
plt.plot([0.02, 100], [-3, -3], 'k:')
plt.legend(['raw signal (dirac)', '1-order 1Hz filter', 'average on 50', 'average on 66'], loc="upper right")
plt.ylabel('amplitude (dB)')
plt.xlabel('frequencies (Hz)')
plt.xlim([0,8])
plt.ylim([-30,2])
plt.show()