Python 高通滤波器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39032325/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python High Pass Filter
提问by ChrisG
I implemented an high pass filter in python using this code:
我使用以下代码在 python 中实现了一个高通滤波器:
from scipy.signal import butter, filtfilt
import numpy as np
def butter_highpass(cutoff, fs, order=5):
nyq = 0.5 * fs
normal_cutoff = cutoff / nyq
b, a = butter(order, normal_cutoff, btype='high', analog=False)
return b, a
def butter_highpass_filter(data, cutoff, fs, order=5):
b, a = butter_highpass(cutoff, fs, order=order)
y = filtfilt(b, a, data)
return y
rawdata = np.loadtxt('sampleSignal.txt', skiprows=0)
signal = rawdata
fs = 100000.0
cutoff = 100
order = 6
conditioned_signal = butter_highpass_filter(signal, cutoff, fs, order)
I am applying this filter on a 100 kHz voltage signal and it works fine for cutoff frequencies >= 60 Hz. But it doesn't work below. I would like to cut off all the frequencies below 10 Hz. Any hints where my mistake is? What I observed is the lower the order of the filter the lower the cutoff frequency could be.
我将此滤波器应用于 100 kHz 电压信号,它适用于 >= 60 Hz 的截止频率。但它在下面不起作用。我想切断所有低于 10 Hz 的频率。任何提示我的错误在哪里?我观察到的是滤波器的阶数越低,截止频率就越低。
回答by Konstantin Purtov
I hope this can help you:
我希望这可以帮助你:
import numpy as np
import pandas as pd
from scipy import signal
import matplotlib.pyplot as plt
def sine_generator(fs, sinefreq, duration):
T = duration
nsamples = fs * T
w = 2. * np.pi * sinefreq
t_sine = np.linspace(0, T, nsamples, endpoint=False)
y_sine = np.sin(w * t_sine)
result = pd.DataFrame({
'data' : y_sine} ,index=t_sine)
return result
def butter_highpass(cutoff, fs, order=5):
nyq = 0.5 * fs
normal_cutoff = cutoff / nyq
b, a = signal.butter(order, normal_cutoff, btype='high', analog=False)
return b, a
def butter_highpass_filter(data, cutoff, fs, order=5):
b, a = butter_highpass(cutoff, fs, order=order)
y = signal.filtfilt(b, a, data)
return y
fps = 30
sine_fq = 10 #Hz
duration = 10 #seconds
sine_5Hz = sine_generator(fps,sine_fq,duration)
sine_fq = 1 #Hz
duration = 10 #seconds
sine_1Hz = sine_generator(fps,sine_fq,duration)
sine = sine_5Hz + sine_1Hz
filtered_sine = butter_highpass_filter(sine.data,10,fps)
plt.figure(figsize=(20,10))
plt.subplot(211)
plt.plot(range(len(sine)),sine)
plt.title('generated signal')
plt.subplot(212)
plt.plot(range(len(filtered_sine)),filtered_sine)
plt.title('filtered signal')
plt.show()
回答by Sriharsha Madala
Since my reputation is low I am unable to comment on your question - "What is the relationship between cutoff and filter order?" This is not an answer to your original question.
由于我的声誉很低,我无法对您的问题发表评论 - “截止和过滤顺序之间有什么关系?” 这不是对您原始问题的回答。
For an FIR filter, for a given cutoff frequency, the slope of the impulse response plot (|H(f)| vs f) is steeper for a higher order filter. So, to achieve higher attenuation for the undesired frequency range, you increase the filter order. But what happens when the filter order is so high that the impulse response is an ideal box function? You will see an inter-symbol interference (ISI in digital communications) like effect. The intensity of this effect increases when the ratio of cutoff frequency to the sampling frequency gets smaller (think of the relation between the width of box function in frequency domain and the width of the main lobe of the sinc function).
对于 FIR 滤波器,对于给定的截止频率,脉冲响应图的斜率(|H(f)| vs f)对于高阶滤波器更陡峭。因此,要在不需要的频率范围内实现更高的衰减,您可以增加滤波器阶数。但是当滤波器阶数如此之高以至于脉冲响应是理想的盒函数时会发生什么?您将看到符号间干扰(数字通信中的 ISI)效果。当截止频率与采样频率之比变小时,这种效应的强度会增加(想想频域中盒函数的宽度与正弦函数的主瓣宽度之间的关系)。
I first observed this when I tried to implement a very narrow band low-pass IIR filter on a TI DSP microcontroller. The TI library, implemented the filter as a cascaded bi-quad structure to handle the well known truncation effects. This still did not solve the problem because the problem is not due to truncation alone. The way I solved this problem was to use an anti-aliasing filter followed by down-sampling the input signal, followed my desired low-pass IIR filter.
当我尝试在 TI DSP 微控制器上实现一个非常窄带的低通 IIR 滤波器时,我第一次观察到了这一点。TI 库将滤波器实现为级联双二阶结构,以处理众所周知的截断效应。这仍然没有解决问题,因为问题不仅仅是由于截断造成的。我解决这个问题的方法是使用抗混叠滤波器,然后对输入信号进行下采样,然后使用我想要的低通 IIR 滤波器。
I understand that you are implementing a HPF, which is an LPF translated in frequency domain. Hope this answers some of your questions. Let me know if down-sampling works for you.
我知道您正在实施 HPF,它是在频域中转换的 LPF。希望这能回答您的一些问题。让我知道下采样是否适合您。
回答by Cloud Cho
I add function to verify above Konstantin Purtov's code, so you could see relationship between order and cut off frequency. The code is mostly from Warren Weckesser.
我在Konstantin Purtov的代码上面添加了验证函数,所以你可以看到顺序和截止频率之间的关系。代码主要来自Warren Weckesser。
import scipy
import sys
from scipy import signal
from scipy import pi
from scipy.io.wavfile import write
import matplotlib.pyplot as plt
import numpy as np
from scipy.signal import butter, lfilter, freqz
# ----- ----- ----- -----
def butter_highpass(cutoff, fs, order=5):
nyq = 0.5 * fs
normal_cutoff = cutoff / nyq
b, a = signal.butter(order, normal_cutoff, btype='high', analog=False)
return b, a
def butter_highpass_filter(data, cutoff, fs, order=5):
b, a = butter_highpass(cutoff, fs, order=order)
y = signal.filtfilt(b, a, data)
return y
# ----- -----
# (1)
def foo(sel):
if (sel == 1):
# Filter requirements.
order = 6
fs = 300.0 # sample rate, Hz
cutoff = 10 # desired cutoff frequency of the filter, Hz
# Get the filter coefficients so we can check its frequency response.
b, a = butter_highpass(cutoff, fs, order)
# Plot the frequency response.
w, h = freqz(b, a, worN=8000)
plt.subplot(2, 1, 1)
plt.plot(0.5 * fs * w / np.pi, np.abs(h), 'b')
plt.plot(cutoff, 0.5 * np.sqrt(2), 'ko')
plt.axvline(cutoff, color='k')
plt.xlim(0, 0.5 * fs)
plt.title("High Filter Frequency Response")
plt.xlabel('Frequency [Hz]')
plt.grid()
# Demonstrate the use of the filter.
# First make some data to be filtered.
T = 0.5 # seconds
n = int(T * fs) # total number of samples
t = np.linspace(0, T, n, endpoint=False)
# "Noisy" data. We want to recover the 20 Hz signal from this.
data = np.sin(1.2 * 2 * np.pi * t) + 1.5 * np.cos(5 * 2 * np.pi * t) + 0.5 * np.sin(20.0 * 2 * np.pi * t)
# Filter the data, and plot both the original and filtered signals.
y = butter_highpass_filter(data, cutoff, fs, order)
plt.subplot(2, 1, 2)
plt.plot(t, data, 'b-', label='data')
plt.plot(t, y, 'g-', linewidth=2, label='filtered data')
plt.xlabel('Time [sec]')
plt.grid()
plt.legend()
plt.subplots_adjust(hspace=0.35)
plt.show()
else:
print ('Please, choose among choices, thanks.')
# ----- -----
def main():
sel = int (sys.argv[1])
foo(sel)
# ----- ----- ----- ----- ----- -----
if __name__ == '__main__':
main()