2. 均值滤波:基本原理、滑动窗口均值滤波、加权均值滤波、优缺点分析

说到滤波,均值滤波绝对是最基础、最常用的方法之一。我刚开始做嵌入式开发那会儿,第一个接触的滤波算法就是它。说白了,均值滤波就是用一段数据的平均值来代替当前值,让曲线变得平滑。

2.1 基本原理

均值滤波的核心思想很简单:用多个采样点的平均值来替代单个采样点。你想想看,如果传感器受到随机噪声干扰,那么多次采样的平均值应该更接近真实值。这就是大数定律在起作用。

数学表达式是这样的:

y[n] = (1/N) * Σ(x[i])  其中 i 从 n-N+1 到 n

这里的 N 就是窗口大小,x[i] 是原始采样值,y[n] 是滤波后的输出。N 越大,平滑效果越强,但延迟也越大。

核心要点:均值滤波假设噪声是零均值的随机噪声。如果噪声有偏,那均值滤波的效果就会打折扣。我在项目中遇到过温度传感器受电源纹波干扰的情况,均值滤波效果就不太理想。

2.2 滑动窗口均值滤波

实际工程中,我们很少用全局均值——那意味着要等所有数据采集完才能算,太慢了。更常用的是滑动窗口均值滤波,也叫移动平均滤波。

它的做法是:维护一个固定长度的窗口,每次新数据进来,窗口就向前滑动一格,丢掉最旧的数据,加入最新的数据,然后重新计算窗口内的平均值。

代码实现很简单:

#define WINDOW_SIZE 5

float buffer[WINDOW_SIZE] = {0};
int index = 0;
float sum = 0;

float moving_average(float new_sample) {
    sum -= buffer[index];        // 去掉最旧的数据
    buffer[index] = new_sample;  // 存入新数据
    sum += buffer[index];        // 加上新数据
    index = (index + 1) % WINDOW_SIZE;  // 循环索引
    return sum / WINDOW_SIZE;
}

这段代码有个小技巧:用 sum 变量缓存总和,每次只做一次减法和一次加法,不用每次都重新算全部 N 个数的和。嗯,这里要注意,如果窗口很大,float 精度可能会出问题,我吃过这个亏。

我的经验:窗口大小选 3-10 比较常见。选 3 时响应快但平滑效果一般,选 10 时平滑好但延迟明显。我曾经在电机转速检测中用过窗口大小为 8 的均值滤波,效果还不错。

2.3 加权均值滤波

普通均值滤波有个问题:所有采样点的权重都一样。但直觉告诉我们,越新的数据应该越重要。加权均值滤波就是来解决这个问题的。

加权均值滤波给每个采样点分配不同的权重,通常越新的数据权重越大。数学表达式:

y[n] = Σ(w[i] * x[i]) / Σ(w[i])  其中 i 从 n-N+1 到 n

w[i] 是权重系数,通常满足 w[n] > w[n-1] > ... > w[n-N+1]。

举个简单的例子,窗口大小为 3,权重设为 [1, 2, 3]:

y[n] = (1*x[n-2] + 2*x[n-1] + 3*x[n]) / (1+2+3)

这样最新的数据 x[n] 贡献最大,最旧的数据 x[n-2] 贡献最小。

还有一种常见的加权方式是指数加权移动平均(EWMA),它不需要固定窗口,而是用递归的方式:

y[n] = α * x[n] + (1-α) * y[n-1]

α 是平滑因子,取值范围 0 到 1。α 越大,对新数据越敏感,响应越快;α 越小,平滑效果越好。

避坑指南:我曾经在压力传感器项目里用过 EWMA,α 设成了 0.9,结果滤波后的数据抖动得厉害,跟没滤波差不多。后来改成 0.2,效果就好多了。α 的选取需要根据实际噪声水平来调,没有万能值。

2.4 优缺点分析

均值滤波的优点很明显,缺点也很突出。我整理了一个表格,方便你对比:

方面 优点 缺点
计算量 极低,适合嵌入式实时系统 滑动窗口需要维护缓冲区
平滑效果 对高斯白噪声效果很好 对脉冲噪声(尖峰)效果差
响应速度 加权均值滤波响应较快 普通均值滤波有固定延迟
实现难度 代码简单,容易调试 窗口大小需要手动调参
适用场景 温度、湿度等缓慢变化信号 快速变化信号会丢失细节

说白了,均值滤波就是个低通滤波器。它让低频信号通过,抑制高频噪声。但问题是,如果信号本身变化很快,均值滤波会把有用的高频成分也滤掉。

重要提醒:均值滤波对异常值非常敏感。如果传感器偶尔出现一个离谱的跳变值,均值滤波会把这个异常值平均到结果里,导致输出被拉偏。我建议在使用均值滤波之前,先做一次简单的限幅处理,把明显异常的数据剔除掉。

最后总结一下我的个人习惯:

  • 对缓慢变化的信号(如室温),用普通滑动窗口均值滤波,窗口大小 5-10
  • 对需要快速响应的场景(如按键检测),用加权均值滤波或 EWMA
  • 对噪声类型不确定的情况,先用示波器看看噪声特征,再选滤波方法

均值滤波虽然简单,但用好了能解决大部分工程问题。下一章我们会聊中值滤波,它对付脉冲噪声特别拿手。