指数移动平均(Exponential Moving Average, EMA)详解
指数移动平均是的一种特殊形式,它对历史数据的权重呈:越新的数据权重越大,越老的数据权重越小。这使得 EMA 对近期变化响应更快,同时计算量极低(只需一次乘法 + 一次加法),适合实时嵌入式系统、传感器去噪、姿态融合、金融K线等场景。
指数移动平均(Exponential Moving Average, EMA)详解
指数移动平均是加权移动平均的一种特殊形式,它对历史数据的权重呈指数衰减:越新的数据权重越大,越老的数据权重越小。
这使得 EMA 对近期变化响应更快,同时计算量极低(只需一次乘法 + 一次加法),适合实时嵌入式系统、传感器去噪、姿态融合、金融K线等场景。
核心公式(KaTeX)
[
EMA_t = \alpha \cdot x_t + (1 - \alpha) \cdot EMA_{t-1}
]
其中:
- ( x_t ):当前时刻原始采样值
- ( \alpha ):平滑因子(0 < α ≤ 1),越大越重视新数据
- ( EMA_{t-1} ):上一次 EMA 值(初始值通常取 ( x_0 ) 或简单平均)
α 的常见计算方式(按周期 N):
[
\alpha = \frac{2}{N + 1}
]
- N=5 → α≈0.333(最近数据权重约33%)
- N=10 → α≈0.182
- N=20 → α≈0.095(更平滑)
等价递归形式(更常用):
[
EMA_t = EMA_{t-1} + \alpha \cdot (x_t - EMA_{t-1})
]
EMA vs 简单移动平均(SMA)的本质区别
| 项目 | EMA | SMA(简单移动平均) |
|---|---|---|
| 权重 | 指数衰减(新数据权重最高) | 均匀权重 |
| 对突变的响应 | 更快(滞后 ≈ 1/α) | 滞后 ≈ (N-1)/2 个采样点 |
| 历史记忆 | 无限(但老数据权重趋近0) | 严格只看最近 N 个点 |
| 计算量 | O(1)(只需上次结果) | O(N)(每次都要重新求和) |
| 相位延迟 | 小 | 固定且较大 |
| 典型应用 | 姿态融合、电池SOC、实时趋势 | 温度/压力等极慢变信号 |
优点:
- 实时性极高(嵌入式单片机只需 2 行代码)
- 对白噪声抑制好,同时保留趋势
- 初始值收敛快(几周期后就稳定)
缺点:
- 对尖峰脉冲噪声(盐椒噪声)敏感(会把尖峰“拉”进趋势)
- α 调不好会过冲或响应太慢
C# 极简实现(推荐直接复制):
public class EMAFilter
{
private double ema;
private readonly double alpha;
public EMAFilter(double period = 10)
{
alpha = 2.0 / (period + 1);
ema = 0; // 第一次用 rawValue 初始化
}
public double Update(double newValue)
{
if (Math.Abs(ema) < 1e-9) ema = newValue; // 首次初始化
ema = alpha * newValue + (1 - alpha) * ema;
return ema;
}
}
中值滤波算法(Median Filter)详解
中值滤波是非线性滤波器,专门针对脉冲噪声(盐椒噪声、尖峰干扰)设计。它不做平均,而是把窗口内数据排序后取中间值,因此能完全剔除极端异常值,同时完美保留信号边沿(阶跃、方波)。
算法步骤
- 取当前时刻前后共 2k+1 个数据(奇数窗口长度,常见 3、5、7)
- 对这 2k+1 个数进行排序
- 输出排序后的中间值(第 k+1 个)
窗口长度为 5 的示例如下(假设原始序列含一个大尖峰):
原始窗口:[10, 12, 50, 11, 13]
排序后:[10, 11, 12, 13, 50]
→ 中值 = 12(完美剔除 50)
数学表达
[
y[n] = \text{median}{ x[n-k], \dots, x[n], \dots, x[n+k] }
]
C# 实现(窗口长度可配置):
public class MedianFilter
{
private readonly double[] buffer;
private readonly int windowSize; // 必须为奇数
private int index = 0;
public MedianFilter(int size = 5)
{
windowSize = size;
buffer = new double[size];
}
public double Update(double newValue)
{
buffer[index] = newValue;
index = (index + 1) % windowSize;
// 复制 + 排序(小窗口效率极高)
double[] sorted = (double[])buffer.Clone();
Array.Sort(sorted);
return sorted[windowSize / 2];
}
}
中值滤波对比分析(2025–2026 工程视角)
以下表格把中值滤波与前面讲过的几种主流滤波器做全面对比(针对传感器数据:IMU、Vce、温度、压力等):
| 滤波器类型 | 噪声类型最擅长 | 边沿/阶跃保留能力 | 计算量(单次) | 延迟 | 对白噪声抑制 | 对脉冲噪声抑制 | 典型应用场景 | 推荐场景优先级(传感器) |
|---|---|---|---|---|---|---|---|---|
| 中值滤波 | 盐椒/脉冲/尖峰 | ★★★★★(最佳) | O(N log N) | (N-1)/2 | ★★ | ★★★★★ | 编码器、超声、激光、Vce异常剔除 | ★★★★★(有尖峰时首选) |
| 简单移动平均 | 白噪声/高斯噪声 | ★★ | O(N) | (N-1)/2 | ★★★★ | ★★ | 温度、液位、慢变信号 | ★★★☆ |
| 指数移动平均 | 白噪声 + 趋势提取 | ★★★ | O(1) | ≈1/α | ★★★★ | ★★ | IMU 融合、SOC、实时趋势 | ★★★★★(计算资源紧张) |
| Kalman/EKF | 多传感器融合 + 动态模型 | ★★★★ | O(状态维度²) | 极小 | ★★★★★ | ★★★★ | 无人机、机器人、自动驾驶 | ★★★★★(高精度需求) |
| Madgwick/Mahony | IMU 噪声 + 漂移 | ★★★★ | O(1) | 极小 | ★★★★ | ★★★ | 9轴姿态融合 | ★★★★★(姿态专用) |
中值滤波独有优势:
- 完全免疫极端异常值(只要窗口内异常值不超过一半,就不会影响输出)—— 这是 EMA/SMA/Kalman 都做不到的
- 边沿无模糊(阶跃信号几乎零延迟保留)—— 适合位置、距离、开关信号
- 实现最简单(排序 + 取中位数)
中值滤波局限:
- 对白噪声(随机抖动)抑制较弱(输出仍会小幅抖)
- 计算量比 EMA 大(但窗口 5~7 时单片机完全无压力)
- 不适合需要“趋势预测”的场景(EMA/Kalman 更优)
组合使用推荐(工业最优实践):
- 先中值滤波(窗口 5)→ 剔除尖峰
- 再接 EMA(N=10)→ 平滑剩余白噪声
- 最后可选 Kalman 做多传感器融合
实际测试建议(针对你之前的 Vce 数据):
- 中值滤波(窗口 5)对 0、-1、0.2、0.11 这类极端值一次性剔除,输出直接稳定在 0.45
- EMA(α=0.2)也能稳定,但如果出现连续 3 个 0,会轻微拉低趋势
- 结论:有明显脉冲噪声时优先中值;纯白噪声 + 需要极低计算量时选 EMA
你现在是想把这些滤波器应用到 VceSat / IMU / 温度哪个场景?
需要我给你中值 + EMA 级联 C# 代码、窗口长度自动推荐公式,还是与你之前 FilterVceAndUpdate 的融合版?随时告诉我,我立刻给出完整可运行实现!
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐
所有评论(0)