低通:平均滤波有什么问题?

信息处理 过滤器 低通滤波器 移动平均线 平均
2022-02-17 15:48:00

问题是:平均作为低通滤波器有什么问题?

细节: 我想对信号进行低通滤波以对其进行下采样。限制是:我没有可用的 RAM,并且我在流式传输中工作,因此我不能使用加权窗口进行过滤。因此,我必须对最后 X 个样本进行平均,或者像这样的经典过滤器:

signal_t+1 = signal_t * (1-factor) + new_measurement * factor

带有适合采样的值的因子。更重要的是,我知道在略高于下采样频率的频率附近有信号。

使用平均值还是使用上述一阶滤波器更好?

更多细节和测试: 我使用真实样本,并不复杂。采样频率 = 200 Hz,下采样后的频率 = 4Hz。

让我们比较一个截止频率为 1Hz 以限制混叠的一阶滤波器和两个平均滤波器。第一个平均滤波器是 50 个样本的平均值,从 200Hz 降采样到 4Hz。第二个平均滤波器是 66 个样本的平均值,以获得与 1 阶滤波器一样多的抑制。

4个过滤器的比较

我认为过滤器“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()
1个回答

问题是:当没有可用的 RAM 时,移动平均和一阶滤波器之间最好的是什么?

解决方案是:没有一个,除了特定需要:拒绝特定频率。否则,最好使用比一阶更高阶的过滤器。

  • 移动平均线:
    • 缺点:延迟和拒绝差。
    • 资产:几个特定频率的巨大拒绝
  • 一阶滤波器
    • 缺点:无论频率如何,拒绝都很差
    • 资产:没有延迟
  • 高阶滤波器。高阶滤波器包括:级联一阶滤波器(此处以 5 个级联一阶滤波器为例)、巴特沃斯滤波器等。
    • 资产:比一阶过滤器更好的拒绝,不需要太多的内存。小延迟。

结果视图: 在此处输入图像描述

感谢@user883521 和@Florent Ecochard 的帮助!

这是 5 阶过滤器的 Pyhton 代码(对于其他顺序,请参见下面的链接。对于其他过滤器,请参阅 signal.lfilter)

import numpy as np
import matplotlib.pyplot as plt

nfft = 8192
fsampl = 200
dtsampl = 1 / 200

fcutoff_1st_order = 1
dtcutoff_1storder = 1 / (2 * np.pi * fcutoff_1st_order)
fcutoff_5thorder =2.635
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_1storder
filtered_signal5= np.copy(raw_signal)
x = np.exp( -2 * np.pi * fcutoff_5thorder / fsampl )
for i in range(5, np.size(raw_signal)):
    filtered_signal5[i] = np.power( 1 - x, 5 ) * raw_signal[i - 1] \
                          + 5 * np.power( x, 1 ) * filtered_signal5[i - 1] + \
                          -10 * np.power( x, 2 ) * filtered_signal5[i - 2] + \
                          +10 * np.power( x, 3 ) * filtered_signal5[i - 3] + \
                          -5 * np.power( x, 4 ) * filtered_signal5[i - 4] + \
                          +np.power( x, 5 ) * filtered_signal5[i-5]
averaged_signal_66 = np.copy( raw_signal )
num_average = fsampl / faverage2
for i in range(1, np.size(raw_signal)):
    averaged_signal_66[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)
filtered_signal5_fft = np.fft.rfft(filtered_signal5)
averaged_signal66_fft = np.fft.rfft( averaged_signal_66 )
raw_signal_fftlog = 20*np.log10(np.abs(raw_signal_fft))
filtered_signal_fftlog = 20*np.log10(np.abs(filtered_signal_fft))
filtered_signal5_fftlog = 20*np.log10(np.abs(filtered_signal5_fft))
averaged_signal66_fftlog = 20 * np.log10( np.abs( averaged_signal66_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, '-')
plt.plot(freq_axe, filtered_signal5_fftlog, '-')
plt.plot( freq_axe, averaged_signal66_fftlog, '-' )
plt.plot([0.02, 100], [-3, -3], 'b--')
plt.plot([2, 2],[-50, 0],  'k:')
plt.plot([3, 3],[-50, 0],  'k--')
plt.legend(['raw signal (dirac)', '1-order 1Hz filter', '5-order 1Hz filter', 'mooving average 66 samples',
            '-3dB', 'aliasing freq', 'unwanted signals frequency'],  loc="upper right")
plt.ylabel('amplitude (dB)')
plt.xlabel('frequency (Hz)')
plt.xlim([0,8])
plt.ylim([-30,2])

plt.show()

有用的链接: http ://www.analog.com/media/en/technical-documentation/dsp-book/dsp_book_Ch14.pdf http://www.analog.com/media/en/technical-documentation/dsp-book/ dsp_book_Ch15.pdf http://www.analog.com/media/en/technical-documentation/dsp-book/dsp_book_Ch19.pdf