滑动窗口滤波的C语言实现(简单易移植)

0 前言

滑动窗口滤波,其实也是一种均值滤波,不同的是:均值滤波会使输出频率减少,而滑动窗口不会。比如,原始数据是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));%输入信号

%%%%%%%%%如果用自己的数据 ,格式如下:
% x = [1,2,5,4,6,4,4,1,5];
% t =(1:length(x))*0.02; %时间间隔为0.02s
%%%%%%%%%%%%%%

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')

效果如下:
在这里插入图片描述

2 c语言实现

我们将上边产生的输入信号保存为数组,模拟一个输入函数。(具体方式为,先复制到excel,设置单元格格式为数字,小数点后两位。然后放到word里面,把空格替换为’,')

c语言和matlab稍稍有点不同的就是:比如窗口为5,我是在接收第6个数据才进行滑动滤波,这样可以使代码更少一些。(不然在接收第5个数据的情况,得单独处理,因为这时候它不需要移除头部)


#include <stdio.h>
#include <string.h>

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;
  if (i == 296) //轮回
      i = 0;
  return (input_data[i++]);

}

/************************ 滑动窗口滤波器 *****************************/
#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里,显示。
在这里插入图片描述

正常运行,没得问题。至于滤波效果,可以通过调节窗口长度来观察结果。

  • 25
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值