Python实现FIR带通滤波器

1、FIR算法实现

y ( 0 ) = ∑ 0 N h ( i ) x ( i ) y(0)=\sum _{0}^Nh(i)x(i) y(0)=0Nh(i)x(i)

class filter:
    def __init__(self,order,h):
        self.order=order
        self.h=h
        self.output=[]
    def FIR_Filter(self,vi):
        for i in range(len(vi)):
            sum=0
            if i < self.order:
                for j in range(i):
                    sum=sum + self.h[j]*vi[i-j]
            else:      
                for j in range(self.order):
                    sum=sum + self.h[j]*vi[i-j]
                
            self.output.append(sum)   
        return self.output
        
       

IIR滤波算法可访问该博文:
Python 实现巴特沃斯滤波器

2、利用fdatool生成带通滤波参数

也可以自行计算,详见博文:FIR 带通滤波器参数设计流程
在这里插入图片描述

Weight=[ -0.001509991125, 0.001329824561, 0.005089743994,0.0004591136531,-0.003339873627,
   0.002003055066, -0.01155735459, -0.02634175681,  0.01259854902,    0.036990989,
   0.001854708185,  0.03572623804,  0.06532743573,  -0.1264344603,  -0.2432653308,
    0.07677905262,   0.3491531909,  0.07677905262,  -0.2432653308,  -0.1264344603,
    0.06532743573,  0.03572623804, 0.001854708185,    0.036990989,  0.01259854902,
   -0.02634175681, -0.01155735459, 0.002003055066,-0.003339873627,0.0004591136531,
   0.005089743994, 0.001329824561]

2.1 生成数据源

x=np.linspace(0,1,1200)
#设置需要采样的信号,频率分量有50,150和500
y=np.sin(2*np.pi*50*x) + np.sin(2*np.pi*150*x)+np.sin(2*np.pi*500*x)

利用FIR滤波:

FIR_filter=filter(32,Weight)
output = FIR_filter.FIR_Filter(y)

利用FFT分析比较:

分析源信号:

yy=fft(y)                     #快速傅里叶变换
yf=abs(fft(y))                # 取模
yf1=abs(fft(y))/((len(x)/2))           #归一化处理
yf2 = yf1[range(int(len(x)/2))]  #由于对称性,只取一半区间
plt.figure(1)
plt.plot(xf,yf1,'r') #显示原始信号的FFT模值

在这里插入图片描述
分析FIR滤波后的数据:

yy_1=fft(output)                     #快速傅里叶变换
yf_1=abs(fft(output))                # 取模
yf1_1=abs(fft(output))/((len(x)/2))           #归一化处理
yf2_1 = yf1_1[range(int(len(x)/2))]  #由于对称性,只取一半区间
plt.plot(xf,yf1_1,'r') #显示原始信号的FFT模值

在这里插入图片描述滤波后的信号与原数据比较:
在这里插入图片描述参考源码:

Weight=[ -0.001509991125, 0.001329824561, 0.005089743994,0.0004591136531,-0.003339873627,
   0.002003055066, -0.01155735459, -0.02634175681,  0.01259854902,    0.036990989,
   0.001854708185,  0.03572623804,  0.06532743573,  -0.1264344603,  -0.2432653308,
    0.07677905262,   0.3491531909,  0.07677905262,  -0.2432653308,  -0.1264344603,
    0.06532743573,  0.03572623804, 0.001854708185,    0.036990989,  0.01259854902,
   -0.02634175681, -0.01155735459, 0.002003055066,-0.003339873627,0.0004591136531,
   0.005089743994, 0.001329824561]
class filter:
    def __init__(self,order,h):
        self.order=order
        self.h=h
        self.output=[]
    def FIR_Filter(self,vi):
        for i in range(len(vi)):
            sum=0
            if i < self.order:
                for j in range(i):
                    sum=sum + self.h[j]*vi[i-j]
            else:      
                for j in range(self.order):
                    sum=sum + self.h[j]*vi[i-j]
                
            self.output.append(sum)   
        return self.output
        

#采样点选择1400个,因为设置的信号频率分量最高为600Hz,根据采样定理知采样频率要大于信号频率2倍,所以这里设置采样频率为1400Hz(即一秒内有1400个采样点)
x=np.linspace(0,1,1200)
#设置需要采样的信号,频率分量有180,390和600
y=np.sin(2*np.pi*50*x) + np.sin(2*np.pi*150*x)+np.sin(2*np.pi*500*x)
yc=np.sin(2*np.pi*150*x)
yy=fft(y)                     #快速傅里叶变换
yf=abs(fft(y))                # 取模
yf1=abs(fft(y))/((len(x)/2))           #归一化处理
yf2 = yf1[range(int(len(x)/2))]  #由于对称性,只取一半区间
plt.figure(1)
plt.plot(xf,yf1,'r') #显示原始信号的FFT模值

#混合波的FFT(双边频率范围)
xf = np.arange(len(y))        # 频率
FIR_filter=filter(32,Weight)
output = FIR_filter.FIR_Filter(y)

yy_1=fft(output)                     #快速傅里叶变换
yf_1=abs(fft(output))                # 取模
yf1_1=abs(fft(output))/((len(x)/2))           #归一化处理
yf2_1 = yf1_1[range(int(len(x)/2))]  #由于对称性,只取一半区间

plt.figure(2)
plt.plot(y[0:50],'r') #显示原始信号的FFT模值
plt.plot(output[0:50],'b') #显示原始信号的FFT模值
#plt.plot(yc[0:50],'y') #显示原始信号的FFT模值
plt.figure(3)
#plt.plot(xf,yf1,'b') #显示原始信号的FFT模值
plt.plot(xf,yf1_1,'r') #显示原始信号的FFT模值
FIR数字滤波器是一种常见的数字滤波器,窗口函数是一种常用的设计FIR数字滤波器的方法。窗口函数可以将理想低通滤波器的频率响应变换为有限长度的实际滤波器的频率响应。常用的窗口函数有矩形窗、汉宁窗、海明窗等。 窗口函数法设计FIR数字滤波器的原理和方法如下: 1. 确定滤波器的阶数N和截止频率fc。 2. 根据截止频率fc和采样频率fs计算出归一化截止频率Wc=2πfc/fs。 3. 根据窗口函数的类型选择合适的窗口函数,并计算出窗口函数的系数。 4. 根据窗口函数的系数和滤波器的阶数N计算出滤波器的系数。 5. 对滤波器的系数进行归一化处理,使得滤波器的幅频响应在截止频率处为-3dB。 线性相位FIR数字滤波器具有相位响应为线性函数的特性,可以保持信号的相位不变。窗口长度对滤波器特性的影响主要表现在窗口长度越长,滤波器的频率响应越接近于理想低通滤波器,但是窗口长度过长会导致滤波器的延迟时间增加。 下面是一个使用汉宁窗设计FIR数字滤波器Python代码示例: ```python import numpy as np import matplotlib.pyplot as plt # 设计FIR数字滤波器 N = 51 # 滤波器阶数 fc = 1000 # 截止频率 fs = 8000 # 采样频率 Wc = 2 * np.pi * fc / fs # 归一化截止频率 h = np.zeros(N) for n in range(N): if n == (N-1)/2: h[n] = Wc / np.pi else: h[n] = np.sin(Wc*(n-(N-1)/2)) / (np.pi*(n-(N-1)/2)) h[n] = h[n] * 0.5 * (1 - np.cos(2*np.pi*n/(N-1))) # 汉宁窗 # 绘制滤波器的幅频响应 w, H = signal.freqz(h) plt.plot(w/np.pi*fs/2, 20*np.log10(np.abs(H))) plt.xlabel('Frequency (Hz)') plt.ylabel('Magnitude (dB)') plt.title('Frequency Response') plt.show() ```
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值