目录
前言:
一、去极值平均滤波核心本质与应用场景
1. 什么是去极值平均滤波
2. 解决的核心痛点
3. 典型工业落地场景
二、核心实现原理
三、工业级设计规范
四、完整可复用源码
1、filter_mean_exc.h
2、filter_mean_exc.c
五、实战演示
六、进阶优化方向
七、面试考点与易错坑点
面试问答
常见坑点
总结
前言:
在嵌入式高精度数据采集场景中,普通滑动平均滤波易受极端干扰值影响,中值滤波又会损失较多有效采样信息。
去极值平均滤波通过剔除一组数据中的最大、最小值后再取平均,在抗脉冲干扰与保留真实数据精度之间取得最佳平衡,是工业仪表、传感器校准、稳态监测等高可靠场景的标配滤波方案。
一、去极值平均滤波核心本质与应用场景
1. 什么是去极值平均滤波
去极值平均滤波也叫防脉冲干扰平均滤波。
连续采一组数据,排序后去掉一个最大值、一个最小值,剩下的数据求平均。
既可以剔除尖峰干扰,又能保留大部分有效数据,精度比普通均值、中值滤波更高。
核心特性
- 抗脉冲干扰、剔除异常极值
- 数据利用率高、输出更接近真实值
- 适合稳态高精度采集
- 算法简单、MCU 负担小
2. 解决的核心痛点
- 普通均值滤波被极值带偏,结果不准。
- 中值滤波浪费有效数据,精度不够。
- 工业采集偶尔出现毛刺、跳变,导致数据失真。
- 仪器仪表、校准设备需要更高精度的平滑结果。
3. 典型工业落地场景
- 仪器仪表高精度采集
- 温湿度、压力、称重传感器滤波
- 电池电压、电量高精度监测
- 工业校准、检测设备数据预处理
- 强电磁环境下稳态数据降噪
二、核心实现原理
- 连续采集 N 个点存入数组
- 对数据从小到大排序
- 去掉第一个(最小)和最后一个(最大)
- 对中间数据求和取平均
三、工业级设计规范
- 结构体多实例,支持多路传感器独立滤波
- 窗口大小可配置,推荐 5~15 奇数
- 完整参数校验、空指针保护
- 纯静态内存,无 malloc
四、完整可复用源码
1、filter_mean_exc.h
#ifndef FILTER_MEAN_EXC_H #define FILTER_MEAN_EXC_H #include <stdint.h> #ifdef __cplusplus extern "C" { #endif #define FILTER_MEAN_EXC_MAX_SIZE 15 typedef struct { int32_t buf[FILTER_MEAN_EXC_MAX_SIZE]; uint8_t size; uint8_t cnt; } filter_mean_exc_t; void filter_mean_exc_init(filter_mean_exc_t *f, uint8_t size); int32_t filter_mean_exc_calc(filter_mean_exc_t *f, int32_t val); #ifdef __cplusplus } #endif #endif2、filter_mean_exc.c
#include "filter_mean_exc.h" static void sort(int32_t *arr, uint8_t len) { for (uint8_t i = 0; i < len - 1; i++) { for (uint8_t j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j + 1]) { int32_t tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } } void filter_mean_exc_init(filter_mean_exc_t *f, uint8_t size) { if (!f || size < 3 || size > FILTER_MEAN_EXC_MAX_SIZE) return; f->size = size; f->cnt = 0; } int32_t filter_mean_exc_calc(filter_mean_exc_t *f, int32_t val) { if (!f || f->size < 3) return val; if (f->cnt < f->size) { f->buf[f->cnt++] = val; } if (f->cnt < f->size) { return val; } sort(f->buf, f->size); int64_t sum = 0; for (uint8_t i = 1; i < f->size - 1; i++) { sum += f->buf[i]; } uint8_t valid = f->size - 2; return (int32_t)(sum / valid); }五、实战演示
#include <stdio.h> #include "filter_mean_exc.h" int main(void) { filter_mean_exc_t f; filter_mean_exc_init(&f, 5); int32_t data[] = {100, 102, 200, 99, 101, 100, 0, 103, 101, 98}; for (int i = 0; i < 10; i++) { int32_t res = filter_mean_exc_calc(&f, data[i]); printf("raw: %4d, filtered: %4d\n", data[i], res); } return 0; }六、进阶优化方向
- 自适应窗口:根据波动自动调整采样点数
- 去掉多个极值:干扰强时剔除 2 个最大 2 个最小
- 滑动去极值平均:不用攒满再算,实时滑动输出
- 配合限幅:先拦突变再去极值,双重抗干扰
七、面试考点与易错坑点
面试问答
Q1:去极值平均滤波和普通均值滤波区别?
答:去极值会剔除最大最小值,不受极端干扰影响,精度更高。
Q2:和中值滤波区别?
答:中值只取中间一个点,去极值平均用中间一批数据,精度更高、更稳定。
Q3:为什么窗口至少要 3 个点?
答:至少 3 个点才能去掉 1 个最大 1 个最小,剩下至少 1 个有效数据。
Q4:适合什么信号?
答:适合缓慢变化、偶尔有脉冲干扰的稳态信号。
Q5:为什么不适合快速变化信号?
答:需要攒满一组数据才输出,有明显滞后,跟不上快速变化。
Q6:工程上一般窗口设多少?
答:5、7、9 居多,兼顾精度与实时性。
常见坑点
- 窗口太小,去掉极值后数据太少,波动大
- 窗口太大,滞后明显,实时性差
- 未做排序,直接头尾剔除导致错误
- 多路传感器共用同一个结构体实例,数据混乱
- 数组越界、未做长度校验
总结
去极值平均滤波是嵌入式高精度稳态采集首选滤波算法,能有效剔除脉冲干扰,同时保留大部分有效数据,精度优于均值和中值滤波。
代码轻量、无依赖、工业级鲁棒,可直接用于仪器仪表、传感器采集、工业检测设备。
创作不易,如果对你有帮助,欢迎点赞、收藏、转发。