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
- 对噪声类型不确定的情况,先用示波器看看噪声特征,再选滤波方法
均值滤波虽然简单,但用好了能解决大部分工程问题。下一章我们会聊中值滤波,它对付脉冲噪声特别拿手。