信号处理 - 为什么在我的截止频率下信号没有被完全过滤掉?
Signal processing - Why a signal is not completely filtered out at my cutoff frequency?
我需要过滤一个信号。我想将频率保持在 0 到 51Hz 之间。以下是我正在使用的代码,其中一部分来自这两个问题(Python: Designing a time-series filter after Fourier analysis, Creating lowpass filter in SciPy - understanding methods and units):
def butter_lowpass(cutoff, fs, order=5):
nyq = 0.5 * fs
normal_cutoff = cutoff / nyq
b, a = butter(order, normal_cutoff, btype='low', analog=False)
return b, a
def butter_lowpass_filter(data, cutoff, fs, order=5):
b, a = butter_lowpass(cutoff, fs, order=order)
y = lfilter(b, a, data)
return y
# y is the original signal
# getting the unbiased signal
y = list(np.array(y)-sts.mean(y))
# saving the original signal
y_before = y
# x is the time vector
# for the spectrum of the original signal
yps_before = np.abs(np.fft.fft(y_before))**2
yfreqs_before = np.fft.fftfreq(6000, d = 0.001)
y_idx_before = np.argsort(yfreqs_before)
#Filtering
order = 8
fs = 1000.0
cutoff = 50.0
y = butter_lowpass_filter(y, cutoff, fs, order)
# for the spectrum of the filtered signal
yps = np.abs(np.fft.fft(y))**2
yfreqs = np.fft.fftfreq(6000, d = 0.001)
y_idx = np.argsort(yfreqs)
fig = plt.figure(figsize=(14,10))
fig.suptitle(file_name, fontsize=20)
plt.plot(yfreqs_before[y_idx_before], yps_before[y_idx_before], 'k-', label='original spectrum',linewidth=0.5)
plt.plot(yfreqs[y_idx], yps[y_idx], 'r-', linewidth=2, label='filtered spectrum')
plt.xlabel('Frequency [Hz]')
plt.yscale('log')
plt.grid()
plt.legend()
plt.show()
此代码的结果是经过过滤的信号,但是,这是频谱比较:
如您所见,频谱在 100Hz 之后看起来不错,但是,在 50Hz 和大约 100Hz 之间仍然存在一个分量。因此,我尝试使用更高阶 (20) 的滤波器,但作为输出,我得到了一个非常奇怪的频谱:
所以,我知道过滤器不可能也永远不会完美,但对我来说,这似乎有点过分了。根据我的经验,我总是能够在我的截止频率下获得非常好的滤波信号。有什么建议吗?
截止频率通常是传递函数下降 -6dB 的地方。
增加阶数会使过滤器更陡峭,但也会根据过滤器类型添加伪影。通常,你有更大的相位问题(数值问题,相位变化与阶数成正比,波纹......)。
在这里,我不知道,它似乎很好地遵循了原始曲线,直到截止。
话虽如此,20 阶滤波器也非常陡峭,并且由于系数中的数字较小,会出现数值问题。通常的技巧是级联 2 阶滤波器并使全局滤波器遵循相同的曲线(您可以查看 Linkwitz-Riley 滤波器)。请注意,这些过滤器是 LTI,因此您不能即时修改参数(这不是 LTI)。
我需要过滤一个信号。我想将频率保持在 0 到 51Hz 之间。以下是我正在使用的代码,其中一部分来自这两个问题(Python: Designing a time-series filter after Fourier analysis, Creating lowpass filter in SciPy - understanding methods and units):
def butter_lowpass(cutoff, fs, order=5):
nyq = 0.5 * fs
normal_cutoff = cutoff / nyq
b, a = butter(order, normal_cutoff, btype='low', analog=False)
return b, a
def butter_lowpass_filter(data, cutoff, fs, order=5):
b, a = butter_lowpass(cutoff, fs, order=order)
y = lfilter(b, a, data)
return y
# y is the original signal
# getting the unbiased signal
y = list(np.array(y)-sts.mean(y))
# saving the original signal
y_before = y
# x is the time vector
# for the spectrum of the original signal
yps_before = np.abs(np.fft.fft(y_before))**2
yfreqs_before = np.fft.fftfreq(6000, d = 0.001)
y_idx_before = np.argsort(yfreqs_before)
#Filtering
order = 8
fs = 1000.0
cutoff = 50.0
y = butter_lowpass_filter(y, cutoff, fs, order)
# for the spectrum of the filtered signal
yps = np.abs(np.fft.fft(y))**2
yfreqs = np.fft.fftfreq(6000, d = 0.001)
y_idx = np.argsort(yfreqs)
fig = plt.figure(figsize=(14,10))
fig.suptitle(file_name, fontsize=20)
plt.plot(yfreqs_before[y_idx_before], yps_before[y_idx_before], 'k-', label='original spectrum',linewidth=0.5)
plt.plot(yfreqs[y_idx], yps[y_idx], 'r-', linewidth=2, label='filtered spectrum')
plt.xlabel('Frequency [Hz]')
plt.yscale('log')
plt.grid()
plt.legend()
plt.show()
此代码的结果是经过过滤的信号,但是,这是频谱比较:
如您所见,频谱在 100Hz 之后看起来不错,但是,在 50Hz 和大约 100Hz 之间仍然存在一个分量。因此,我尝试使用更高阶 (20) 的滤波器,但作为输出,我得到了一个非常奇怪的频谱:
所以,我知道过滤器不可能也永远不会完美,但对我来说,这似乎有点过分了。根据我的经验,我总是能够在我的截止频率下获得非常好的滤波信号。有什么建议吗?
截止频率通常是传递函数下降 -6dB 的地方。
增加阶数会使过滤器更陡峭,但也会根据过滤器类型添加伪影。通常,你有更大的相位问题(数值问题,相位变化与阶数成正比,波纹......)。
在这里,我不知道,它似乎很好地遵循了原始曲线,直到截止。
话虽如此,20 阶滤波器也非常陡峭,并且由于系数中的数字较小,会出现数值问题。通常的技巧是级联 2 阶滤波器并使全局滤波器遵循相同的曲线(您可以查看 Linkwitz-Riley 滤波器)。请注意,这些过滤器是 LTI,因此您不能即时修改参数(这不是 LTI)。