Matlab 与 Python 基于窗函数的滤波器设计对比 之 凯瑟窗

6 篇文章 0 订阅
2 篇文章 7 订阅

Kaiser 窗近似于扁长椭圆形窗,它使主瓣能量与旁瓣能量之比最大。对于特定长度的 Kaiser 窗,参数 β 控制相对旁瓣衰减。对于给定的 β,相对旁瓣衰减相对于窗长度是固定的。随着 β 的增加,相对旁瓣衰减降低,主瓣宽度增加。(以上内容来自: Kaiser 窗)

凯瑟窗的参数估计

MatlabPython都提供了kaiserord函数, 用于估算特定频率响应条件下的Kaiser窗的阶数(阶数为窗长度-1)和 β \beta β参数.

python中的kaiserord特指scipy.signal模块中的kaiserord函数.

Matlab 中的 kaiserord

Matlab中的函数语法形式如下:

  1. [n,Wn,beta,ftype] = kaiserord(f,a,dev)
  2. [n,Wn,beta,ftype] = kaiserord(f,a,dev,fs)
  3. c = kaiserord(f,a,dev,fs,‘cell’)

参数:

  • f : 通带边界频率阻带截止频率构成的向量, 对于低通高通滤波器, f的长度为2, 对于带通带阻滤波器, f的长度为4; 形式1中的f为数字归一化频率.
  • a: 频带幅度. 低通为[1, 0], 高通为[0, 1], 带通为[0,1,0], 带阻为[1,0,1]
  • dev: 最大允许偏差(线性值).
  • fs: 采样率

返回值:

  • n: 滤波器阶数. n = 窗长度 - 1
  • Wn: 数字归一化频率
  • bata: β \beta β参数
  • ftype: 滤波器类型. 取值: 'low' | 'bandpass' | 'high' | 'stop' | 'DC-0' | 'DC-1'

Python 中的 kaiserord

Python中的函数定义如下:

numtaps, beta = scipy.signal.kaiserord(ripple, width)

参数:

  • ripple: 最大允许偏差(dB)
  • width: 数字归一化的过渡带宽, 等于通带边界频率与阻带截止频率的差.
    返回值:
  • numtaps: 窗的长度.
  • beta: β \beta β参数

区别

因为线性相位特性为Type II(当win_len为偶数时)的滤波器无法实现高通滤波器和带阻滤波器(这里不做论证, 感兴趣的自行查找). 因此使用Matlab中的kaiserord 估算高通和带阻滤波器的阶数时, 阶数n必为偶数(win_len为奇数), 但python中的scipy.signal.kaiserord并不知道要实现何种滤波器, 因此numtaps可能为偶数 (参见:高通滤波器设计示例带阻滤波器设计示例).

基于窗函数的滤波器设计函数

Matlab中使用fir1函数实现基于窗函数的滤波器设计, python中使用scipy.signal.firwin函数来实现. 这两个函数都能够实现Type I(当win_len为奇数时) 和 Type II(当win_len为偶数时)的滤波器设计.

Matlab 中的 fir1

Matlab中的fir1的语法形式如下:

  • b = fir1(n,Wn,ftype, window, scaleopt)

参数:

  • n: 滤波器阶数
  • Wn: 归一化数字频率
  • ftype: 滤波器类型. 取值: ‘low’ | ‘bandpass’ | ‘high’ | ‘stop’ | ‘DC-0’ | ‘DC-1’
  • window: 窗向量
  • scaleopt: 缩放选项. 取值: ‘scale’ (默认) | ‘noscale’
    • ‘scale’: 对系数进行缩放, 使得通带的幅频响应为 0 dB.
    • ‘noscale’: 不对系数进行缩放.

返回值:

b: 滤波器系数

Python 中的 firwin

python中的firwin的语法形式如下:

scipy.signal.firwin(numtaps, cutoff, width=None, window='hamming', pass_zero=True, scale=True, nyq=None, fs=None)

参数:

  • numtaps: 窗长度.
  • cutoff: 截止频率. 对于低通和高通, 该参数为一个数值;对于带通和带阻, 该参数为一个二元元组.
  • width: 过渡带带宽.
  • window: 窗的名字, 或者包含窗名和参数的元组, 如: ('kaiser', beta).
  • scale: 是否缩放滤波器系数, 使得通带中心频率的幅度响应为0 dB.
  • pass_zero: 表示直流信号(频率为0)是否通过. 取值: TrueFalse, 也可直接给滤波器的类型: { ‘bandpass’, ‘lowpass’, ‘highpass’, ‘bandstop’}. 对于低通和带阻, 该参数设为: True, 对于高通和带通, 该参数设为False.

返回值:

  • h: 滤波器系数

区别

Matlab中的fir1函数同python中的scipy.signal.firwin函数完成相同的功能. 就凯瑟窗而言, 主要区别如下:

  • Matlabfir1函数不需要指定滤波器的类型(低通, 高通, 带通或带阻), 因为已经在kaiserord已经指定了滤波器类型. 而python中的firwin函数需要通过pass_zero参数指定滤波器类型.
  • fir1函数使用滤波器的阶数n, 而firwin函数使用窗长度numtaps

滤波器设计举例

以下设计示例中, MatlabPython生成的滤波器系数完全相同.

低通滤波器设计

基于凯瑟窗, 设计一个低通滤波器, 采样频率为1000 Hz, 通带边界频率为 150 Hz, 阻带截止频率为200 Hz, 通带最大允许偏差为0.05, 阻带最大允许偏差为 0.01.

  • 使用Matlab 设计此滤波器
figure;
fs = 1000;
fcuts = [150, 200];
mags = [1, 0];
devs = [0.05, 0.01];
[n,Wn,beta,ftype] = kaiserord(fcuts,mags,devs,fs);
hh = fir1(n,Wn,ftype,kaiser(n+1,beta),'noscale');
freqz(hh,1,1024,fs)
title('低通滤波器')

在这里插入图片描述

  • 使用Python设计此滤波器
import numpy as np
from scipy import signal
from matplotlib import pyplot as plt

fs = 1000
fcuts = np.array([150, 200]) / (fs / 2)
devs = np.array([0.05, 0.01])
ripple = np.min(20 * np.log10(devs))
width = fcuts[1] - fcuts[0]
numtaps, beta = signal.kaiserord(ripple, width)
taps = signal.firwin(numtaps, np.mean(fcuts), window=('kaiser', beta), 
                     scale=False)
w, h = signal.freqz(taps, fs=fs)
plt.plot(w, np.log10(np.abs(h)) * 20)
plt.grid(True)

高通滤波器设计

基于凯瑟窗, 设计一个高通滤波器, 采样频率为1000 Hz, 通带边界频率为 350 Hz, 阻带截止频率为300 Hz, 阻带最大允许偏差为0.05, 通带最大允许偏差为 0.01.

  • 使用Matlab 设计此滤波器
figure;
fs = 1000;
fcuts = [300, 350];
mags = [0, 1];
devs = [0.05, 0.01];
[n,Wn,beta,ftype] = kaiserord(fcuts,mags,devs,fs);
hh = fir1(n,Wn,ftype,kaiser(n+1,beta),'noscale');
freqz(hh,1,1024,fs)
title('高通滤波器')

在这里插入图片描述

  • 使用Python 设计此滤波器
import numpy as np
from scipy import signal
from matplotlib import pyplot as plt

fs = 1000
fcuts = np.array([300, 350]) / (fs / 2)
devs = np.array([0.05, 0.01])
ripple = np.min(20 * np.log10(devs))
width = fcuts[1] - fcuts[0]
numtaps, beta = signal.kaiserord(ripple, width)
if numtaps % 2 == 0:
    numtaps += 1
taps = signal.firwin(numtaps, np.mean(fcuts), window=('kaiser', beta), 
                     scale=False, pass_zero=False)
w, h = signal.freqz(taps, fs=fs)
plt.plot(w, np.log10(np.abs(h)) * 20)
plt.grid(True)

带通滤波器设计

基于凯瑟窗, 设计一个带通滤波器, 采样频率为1000 Hz, 通带边界频率分别为 200 Hz300 Hz, 阻带截止频率分别为150 Hz350 Hz, 通带最大允许偏差为 0.05, 阻带最大允许偏差为 0.01.

  • 使用Matlab 设计此滤波器
figure;
fs = 1000;
fcuts = [150, 200, 300, 350];
mags = [0, 1, 0];
devs = [0.01, 0.05, 0.01];
[n,Wn,beta,ftype] = kaiserord(fcuts,mags,devs,fs);
hh = fir1(n,Wn,ftype,kaiser(n+1,beta),'noscale');
freqz(hh,1,1024,fs)
title('带通滤波器')

在这里插入图片描述

  • 使用Python 设计此滤波器
import numpy as np
from scipy import signal
from matplotlib import pyplot as plt

fs = 1000
fcuts = np.array([150, 200, 300, 350]) / (fs / 2)
devs = np.array([0.01, 0.05, 0.01])
ripple = np.min(20 * np.log10(devs))
width = np.min(fcuts[1::2] - fcuts[0::2])
numtaps, beta = signal.kaiserord(ripple, width)
taps = signal.firwin(numtaps, (fcuts[1] - width / 2, fcuts[2] + width / 2), 
                     window=('kaiser', beta), scale=False, pass_zero=False)
w, h = signal.freqz(taps, fs=fs)
plt.plot(w, np.log10(np.abs(h)) * 20)
plt.grid(True)

带阻滤波器设计

基于凯瑟窗, 设计一个带阻滤波器, 采样频率为1000 Hz, 通带边界频率分别为150 Hz350 Hz, 阻带截止频率分别为 200 Hz300 Hz, 阻带最大允许偏差为 0.05, 通带最大允许偏差为 0.01.

  • 使用Matlab 设计此滤波器
figure;
fs = 1000;
fcuts = [150, 200, 300, 350];
mags = [1, 0, 1];
devs = [0.01, 0.05, 0.01];
[n,Wn,beta,ftype] = kaiserord(fcuts,mags,devs,fs);
hh = fir1(n,Wn,ftype,kaiser(n+1,beta),'noscale');
freqz(hh,1,1024,fs)
title('带阻滤波器')

在这里插入图片描述

  • 使用Python 设计此滤波器
import numpy as np
from scipy import signal
from matplotlib import pyplot as plt

fs = 1000
fcuts = np.array([150, 200, 300, 350]) / (fs / 2)
devs = np.array([0.01, 0.05, 0.01])
ripple = np.min(20 * np.log10(devs))
width = np.min(fcuts[1::2] - fcuts[0::2])
numtaps, beta = signal.kaiserord(ripple, width)
if numtaps % 2 == 0:
    numtaps += 1
taps = signal.firwin(numtaps, (fcuts[1] - width / 2, fcuts[2] + width / 2), 
                     window=('kaiser', beta), scale=False)
w, h = signal.freqz(taps, fs=fs)
plt.plot(w, np.log10(np.abs(h)) * 20)
plt.grid(True)

以上内容为个人的经验总结. 有不当之处, 欢迎留言指正!!!

  • 6
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
设计步骤: 1、语音信号的采集 利用Windows下的录音机录制一段自己的话音,或采用其它软件截取一段音乐信号,然后在Matlab软件平台下,利用函数wavread对语音信号进行采样,记住采样频率和采样点数。 2、语音信号的频谱分析 在Matlab中,可以利用函数FFT对信号进行快速傅立叶变换,得到信号的频谱特性,要求学生首先画出语音信号的时域波形,然后对语音信号进行频谱分析。 3、对语音信号分别加入正弦噪声和高斯白噪声,使信噪比为(学号)dB,画出加噪信号的时域波形和频谱图;关于噪声信号,噪声类型分为如下几种:(1)白噪声;(2)单频噪声(正弦干扰);(3)多频噪声(多正弦干扰);(4)其他干扰,如低频、高频、带限噪声,或chirp干扰、充激干扰。 4、设计数字滤波器,并画出其频率响应。 对叠加噪声前后的信号进行频谱分析,确定降噪的滤波器指标;或者根据如下给定的滤波器性能指标: (1) 低通滤波器的性能指标: =1000Hz, =1200Hz, =1dB, =100dB; (2) 高通滤波器的性能指标: =4800Hz, =5000Hz, =100dB, =1dB. (3) 带通滤波器的性能指标: =1200Hz, =3000Hz, =1000Hz, =3200Hz, =100dB, =1dB。 采用窗函数设计上面要求的3种滤波器,并画出滤波器的频率响应; 5、用滤波器对信号进行滤波 用自己设计滤波器对加噪信号进行滤波,画出滤波后信号的时域波形及频谱,并对滤波前后的信号进行对比,分析信号的变化; 6、回放语音信号,分析滤波前后的语音变化,验证滤波效果

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

falwat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值