1.算法介绍
FIR 滤波算法的基本思路是设计一个窗函数,使得当前的输出y通过最近N个输入数据(x(0),x(-1),x(-2)...x(-n))计算得出,不同时刻占的权重都不一样,即FIR 滤波器的输入输出关系为:
其中,y(0)为当前时刻的输出,x(-n)为过去n时刻的输入,hz(n)为过去n时刻的权重。
也就是说,当前的输出不仅与当前的输入有关,还与历史输入有关,具体与多少历史输入有关,取决于窗n设置的大小,一般来说,窗设置越大,滤波效果越好,但同时也导致计算量增大,所以需要在运算量和滤波效果之间找到平衡点。
从FIR 滤波器的的输入输出关系可以看出,要实现FIR滤波器,其中最核心的一步就是设计hz(n)的值,即滤波参数。
2.算法参数设计
FIR 滤波器的参数设计,主要借助于 Matlab实现,这里我们以一个例子来讲述,输入为ECG心电图,采样率为250Hz,任务是将ECG数字信号的大于40Hz以上的频率滤掉,要求尽可能把大于40Hz的频率去掉、小于40Hz的信号幅度衰减做到最小(幅度响应可量化,这里为了简单不进行量化),同时信号不能出现失真,设计如下:
使用Matlab的fdatool工具,设计一个低通滤波器,设计参数如下:

经过反复测试,可以看出当使用least squares,窗长度设置为63时,可以得到比较好的幅度响应,即能很好的滤除不要的信号,又能很好的保留有用的信号。
接下来再看另外一个要求,也就是信号不能出现失真,也是数字滤波算法里面经常遇到的相位响应。我们知道,任意系统的信号都可以分解成多个正弦波叠加,为了使得输出信号不产生相位失真,保证所有这些正弦信号通过系统的时间是一样的即可,这个特性通过数学推导是成立的,这里就不展开描述,另外我们从Matlab里面的相位响应可以直接得出这个特性是成立的,算法的相位延迟响应如下:

3.算法验证
将上一章节设计的算法,导出Matlab文件,编写Matlab程序,进行验证。
1.导入原始信号,这里直接导入人体实际的心电图数据
%0.导入原始数据
orig_x = load('D:\Documents\MATLAB\ecg_test.txt');
figure(1);
subplot(4,1,1);
plot(orig_x);
title('原始信号');
2.生成噪声信号,这里直接生成60Hz的正弦波。
%1.生成噪声信号
fs = 60; %频率
N = length(orig_x); %采样点数
dt = 1/250; %采样间隔
n = dt:dt:N*dt;
noise = 80*sin(2*pi*fs*n);
subplot(4,1,2);
plot(noise);
title('噪声信号');
3.将原始心电图,叠加上生成的噪声信号
%2.信号叠加
orig_x_add_noise = orig_x + noise;
subplot(4,1,3);
plot(orig_x_add_noise);
title('叠加后的信号');
4.利用第2章生成的低通滤波算法,对叠加后的信号进行滤波
%3.低通滤波处理
ld = fir_lp_boke;
lp_output = filter(ld,orig_x_add_noise);
subplot(4,1,4);
plot(lp_output);
title('低通滤波后的信号');
运行结果如下图所示:

可以看出,在原始信号叠加了一个比较大的高频噪声后,经过FIR低通滤波器,噪声很好的被滤除掉了,原始信号也失真度很小。
4.结论
本文章主要对FIR 滤波器做了一个比较感性的介绍,最后通过实验进行验证,但没有对信号的幅度响应,相位响应等做比较严谨的数学推导,后续有时间补上。