- 0 前言
- 1 matlab 实现
- 2 c语言实现
滑动窗口滤波,其实也是一种均值滤波,不同的是:均值滤波会使输出频率减少,而滑动窗口不会。比如,原始数据是6hz,而均值滤波是每2个取平均,那么它的输出频率将变成3hz。
下面结合图片进行说明:
现在有数据x1-x6,均值滤波数量和滑动窗口长度均取2,滤波输出如下:
通过图片,应该很容易理解他们的区别了。
1 matlab 实现首先生成一个原始信号:x = sin(t) + 0.25*rand(size(t)),然后设计窗口大小为5的滑动滤波算法。
t = (0:0.02:10);% 时间序列
x = sin(t) + 0.25*rand(size(t));%输入信号
window_size = 5; % 设置滑动窗口长度
y=zeros(size(t)) %初始化
sum=0;
for i=1:length(t) %遍历
if i< window_size %不满窗口,保留原始值
sum=sum+x(i);
y(i)=x(i);
end
if i== window_size%等于窗口,不用去掉头部
sum=sum+x(i)
y(i)=sum/window_size
end
if i> window_size
head=x(i-5);
sum=sum-head;%去掉头部
sum=sum+x(i);%添加尾部
y(i)=sum/window_size;
end
end
% 绘图对比
plot(t,x)
hold on
plot(t,y)
legend('input','output')
效果如下:
我们将上边产生的输入信号保存为数组,模拟一个输入函数。(具体方式为,先复制到excel,设置单元格格式为数字,小数点后两位。然后放到word里面,把空格替换为’,')
c语言和matlab稍稍有点不同的就是:比如窗口为5,我是在接收第6个数据才进行滑动滤波,这样可以使代码更少一些。(不然在接收第5个数据的情况,得单独处理,因为这时候它不需要移除头部)
#include#include float input_data[] = { 0.03, 0.16, 0.11, 0.08, 0.12, 0.11, 0.29, 0.33, 0.36, 0.25, 0.42, 0.37, 0.24, 0.34, 0.41, 0.45, 0.43, 0.54, 0.39, 0.61, 0.60, 0.49, 0.58, 0.52, 0.48, 0.61, 0.70, 0.71, 0.77, 0.63, 0.66, 0.62, 0.68, 0.75, 0.77, 0.68, 0.69, 0.77, 0.90, 0.75, 0.84, 0.76, 0.96, 0.95, 0.91, 0.88, 0.92, 1.03, 1.05, 0.96, 0.97, 1.08, 1.01, 1.07, 1.05, 1.01, 0.96, 1.06, 0.96, 0.97, 1.15, 0.97, 1.11, 1.06, 1.11, 1.15, 1.04, 0.98, 1.19, 1.07, 1.15, 1.21, 1.06, 1.24, 1.20, 1.20, 1.16, 1.14, 1.10, 1.21, 1.15, 1.19, 1.24, 1.19, 1.21, 1.11, 1.21, 1.07, 1.03, 1.10, 0.98, 1.18, 1.03, 1.13, 1.15, 1.12, 1.10, 0.99, 1.04, 1.15, 0.97, 0.95, 0.96, 1.08, 0.96, 1.01, 0.90, 0.86, 0.91, 0.88, 1.04, 1.03, 0.79, 0.92, 0.77, 0.85, 0.86, 0.93, 0.86, 0.75, 0.90, 0.85, 0.79, 0.85, 0.71, 0.68, 0.74, 0.59, 0.64, 0.58, 0.72, 0.68, 0.65, 0.69, 0.65, 0.56, 0.41, 0.41, 0.50, 0.59, 0.55, 0.55, 0.54, 0.37, 0.34, 0.44, 0.27, 0.44, 0.41, 0.25, 0.23, 0.29, 0.28, 0.28, 0.21, 0.07, 0.16, 0.01, 0.17, 0.13, 0.09, -0.02, 0.08, 0.06, -0.05, -0.15, 0.03, 0.00, -0.09, -0.06, -0.06, -0.19, -0.07, -0.17, -0.26, -0.28, -0.15, -0.30, -0.37, -0.19, -0.28, -0.21, -0.43, -0.29, -0.39, -0.38, -0.54, -0.42, -0.42, -0.47, -0.60, -0.50, -0.63, -0.45, -0.52, -0.52, -0.54, -0.56, -0.49, -0.70, -0.64, -0.56, -0.66, -0.60, -0.76, -0.65, -0.60, -0.80, -0.74, -0.85, -0.82, -0.71, -0.67, -0.81, -0.90, -0.69, -0.81, -0.70, -0.86, -0.77, -0.95, -0.83, -0.88, -0.88, -0.73, -0.79, -0.90, -0.83, -0.88, -0.85, -0.75, -0.84, -0.96, -0.79, -0.82, -0.97, -0.96, -0.93, -0.89, -0.87, -0.93, -0.79, -0.79, -0.92, -0.83, -0.96, -0.81, -0.89, -0.80, -0.89, -0.79, -0.85, -0.85, -0.89, -0.75, -0.72, -0.69, -0.78, -0.85, -0.74, -0.83, -0.77, -0.65, -0.75, -0.61, -0.74, -0.65, -0.66, -0.77, -0.68, -0.54, -0.75, -0.65, -0.67, -0.66, -0.62, -0.46, -0.55, -0.46, -0.56, -0.52, -0.38, -0.57, -0.57, -0.39, -0.32, -0.51, -0.35, -0.46, -0.31, -0.31, -0.44, -0.23, -0.16, -0.28, -0.29}; float get_data(void)//模拟输入 { static int i = 0; return (input_data[i++]); if (i == 296) //轮回 i = 0; } #define window_size 5 //滑动窗口长度 float buffer[window_size] = {0}; //滑动窗口数据buf float sliding_average_filter(float value) { static int data_num = 0; float output = 0; if (data_num < window_size) //不满窗口,先填充 { buffer[data_num++] = value; output = value; //返回相同的值 } else { int i = 0; float sum = 0; memcpy(&buffer[0], &buffer[1], (window_size - 1) * 4); //将1之后的数据移到0之后,即移除头部 buffer[window_size - 1] = value; //即添加尾部 for (i = 0; i < window_size; i++) //每一次都计算,可以避免累计浮点计算误差 sum += buffer[i]; output = sum / window_size; } return output; } void main(void) { float result[296]; for (int i = 0; i < 296; i++) { result[i] = sliding_average_filter(get_data()); printf("%f,", result[i]); } }
将打印的数据,可以复制到matlab里,显示。
正常运行,没得问题。至于滤波效果,可以通过调节窗口长度来观察结果。



