使用Remez交换算法计算minimax最优滤波器。
为有限脉冲响应(FIR)滤波器计算filter-coefficients,该滤波器的传递函数使用Remez交换算法将指定频带中期望增益和已实现增益之间的最大误差最小化。
参数:
numtaps:int过滤器中所需的抽头数。抽头数是过滤器中的项数,或过滤器顺序加一。
bands:array_like包含带边的单调序列。所有元素必须为非负且小于fs给出的采样频率的一半。
desired:array_like在每个指定频段中包含所需增益的频段大小的一半序列。
weight:array_like, 可选参数赋予每个频段区域的相对权重。重量的长度必须是带子长度的一半。
Hz:scalar, 可选参数不推荐使用。请改用`fs`。采样频率(单位:Hz)。默认值为1。
type:{‘bandpass’, ‘differentiator’, ‘hilbert’}, 可选参数过滤器类型:
‘bandpass’:flat response in bands. This is the default.
‘differentiator’:frequency proportional response in bands.
‘hilbert’filter with odd symmetry, that is, type III(for even order) or type IV (for odd order)
linear phase filters.
maxiter:int, 可选参数算法的最大迭代次数。默认值为25。
grid_density:int, 可选参数网格密度。用于的密集网格remez大小(numtaps + 1) * grid_density。默认值为16。
fs:float, 可选参数信号的采样频率。默认值为1。
返回值:
out:ndarray包含最佳(在极小意义上)滤波器系数的等级1数组。
参考文献:
1
J. H. McClellan和T. W. Parks,“设计最佳FIR线性相位数字滤波器的统一方法”,IEEE Trans。电路理论,第一卷。 CT-20,第697-701页,1973年。
2
J. H. McClellan,T。W. Parks和L. R. Rabiner,“用于设计最佳FIR线性相位数字滤波器的计算机程序”,IEEE Trans。音频Electroacoust。,第一卷。 AU-21,第506-525页,1973年。
例子:
在这些例子中remez用于创建带通,带阻,低通和高通滤波器。使用的参数是滤波器阶数,具有相应频率边界的阵列,所需的衰减值和采样频率。使用freqz计算并绘制相应的频率响应。
>>> from scipy import signal
>>> import matplotlib.pyplot as plt
>>> def plot_response(fs, w, h, title):
... "Utility function to plot response functions"
... fig = plt.figure()
... ax = fig.add_subplot(111)
... ax.plot(0.5*fs*w/np.pi, 20*np.log10(np.abs(h)))
... ax.set_ylim(-40, 5)
... ax.set_xlim(0, 0.5*fs)
... ax.grid(True)
... ax.set_xlabel('Frequency (Hz)')
... ax.set_ylabel('Gain (dB)')
... ax.set_title(title)
此示例根据小过渡宽度和高滤波器阶数显示了陡峭的低通过渡:
>>> fs = 22050.0 # Sample rate, Hz
>>> cutoff = 8000.0 # Desired cutoff frequency, Hz
>>> trans_width = 100 # Width of transition from pass band to stop band, Hz
>>> numtaps = 400 # Size of the FIR filter.
>>> taps = signal.remez(numtaps, [0, cutoff, cutoff + trans_width, 0.5*fs], [1, 0], Hz=fs)
>>> w, h = signal.freqz(taps, [1], worN=2000)
>>> plot_response(fs, w, h, "Low-pass Filter")
此示例显示了一个高通滤波器:
>>> fs = 22050.0 # Sample rate, Hz
>>> cutoff = 2000.0 # Desired cutoff frequency, Hz
>>> trans_width = 250 # Width of transition from pass band to stop band, Hz
>>> numtaps = 125 # Size of the FIR filter.
>>> taps = signal.remez(numtaps, [0, cutoff - trans_width, cutoff, 0.5*fs],
... [0, 1], Hz=fs)
>>> w, h = signal.freqz(taps, [1], worN=2000)
>>> plot_response(fs, w, h, "High-pass Filter")
对于以22 kHz采样的信号,使用Remez算法可计算出通带为2-5 kHz的带通滤波器。过渡宽度为260 Hz,滤波器阶数为10:
>>> fs = 22000.0 # Sample rate, Hz
>>> band = [2000, 5000] # Desired pass band, Hz
>>> trans_width = 260 # Width of transition from pass band to stop band, Hz
>>> numtaps = 10 # Size of the FIR filter.
>>> edges = [0, band[0] - trans_width, band[0], band[1],
... band[1] + trans_width, 0.5*fs]
>>> taps = signal.remez(numtaps, edges, [0, 1, 0], Hz=fs)
>>> w, h = signal.freqz(taps, [1], worN=2000)
>>> plot_response(fs, w, h, "Band-pass Filter")
可以看出,对于该带通滤波器,低阶会导致较高的纹波和较不陡峭的过渡。阻带的衰减非常低,通带的过冲很小。当然,所需的增益可以通过较高的滤波器阶数更好地近似。
下一个示例显示了一个带阻滤波器。由于滤波器阶数较高,因此过渡非常陡峭:
>>> fs = 20000.0 # Sample rate, Hz
>>> band = [6000, 8000] # Desired stop band, Hz
>>> trans_width = 200 # Width of transition from pass band to stop band, Hz
>>> numtaps = 175 # Size of the FIR filter.
>>> edges = [0, band[0] - trans_width, band[0], band[1], band[1] + trans_width, 0.5*fs]
>>> taps = signal.remez(numtaps, edges, [1, 0, 1], Hz=fs)
>>> w, h = signal.freqz(taps, [1], worN=2000)
>>> plot_response(fs, w, h, "Band-stop Filter")
>>> plt.show()