概述
??这是我们在做嵌入式软件开发处理数据时常用且简单的一些滤波算法,包括平均值滤波、中值滤波,一阶滞后滤波,防抖滤波,限幅滤波等。
平均值滤波
1.逻辑: ??向缓存区内装载数据(根据标志位确定是否滑窗处理),缓存区内数据求平均并返回。
2.滤波器结构体:
typedef struct
{
uint16_t len;
uint16_t index;
int *buf;
}filter_t;
3.参数: filter为结构体,也就是需要处理的数据组的控制块 data为待处理数据 moving_enable为一个布尔型标志位,确定此滤波器是否有滑动窗口效果 返回值:滤波后结果
4.Code:
float average_filter(filter_t *filter,const int data,bool moving_enable)
{
int i;
float sum = 0;
if(!moving_enable){
filter->buf[filter->index++ % filter->len] = data;
}
else{
for(i = 0; i<filter->len-1; i++){
filter->buf[i] = filter->buf[i+1];
}
filter->buf[filter->len-1] = data;
}
for(i = 0; i < filter->len; i++){
sum += filter->buf[i];
}
return(sum / filter->len);
}
中值滤波
1.逻辑: ??向缓存区内装载数据(根据标志位确定是否滑窗处理),再创建一个临时缓存区用于排序后的数据存储。将数据进行排序(冒泡排序等),根据缓存区长度的奇偶属性求得中位值并返回。 2.滤波器结构体及参数:同上
float mid_filter(filter_t *filter,const int data,bool moving_enable)
{
int temp_swap;
int temp_buf[filter->len];
unsigned int i,j;
if(!moving_enable){
filter->buf[filter->index++ % filter->len] = data;
}
else{
for(i = 0; i<filter->len-1; i++){
filter->buf[i] = filter->buf[i+1];
}
filter->buf[filter->len-1] = data;
}
memcpy(temp_buf,filter->buf,filter->len * sizeof(int));
for (j=0;j<filter->len-1;j++){
for (i=0;i<filter->len-j-1;i++){
if ( temp_buf[i]>temp_buf[i+1] ){
temp_swap = temp_buf[i];
temp_buf[i] = temp_buf[i+1];
temp_buf[i+1] = temp_swap;
}
}
}
printf("%s \n",__FUNCTION__);
print_int_buffer(temp_buf,filter->len);
if(filter->len & 1){
//printf("temp_buf[%d]: %.2f \n",filter->len/ 2,(float)temp_buf[filter->len / 2]);
return (float)temp_buf[filter->len / 2];
}
else{
//printf("(temp_buf[%d] + temp_buf[%d])/2 : %.2f \n",filter->len / 2-1,filter->len / 2,(float)(temp_buf[filter->len / 2] + temp_buf[filter->len / 2 + 1]) / 2);
return (float)(temp_buf[filter->len / 2 -1 ] + temp_buf[filter->len / 2]) / 2;
}
}
一阶滞后滤波
??使用比例分配方式使得每一帧的数据结果直接受上一帧的结果影响,间接受数次之前的结果影响,影响强度由比例参数k确定,以此抑制抖动
float lowpass_filter(float data,float k)
{
static float result = 0;
printf(" %s : result = %.2f * %.2f + %.2f * %.2f \n",__FUNCTION__,data,k,result,(1-k));
result = data * k + result *(1-k) ;
return result;
}
防抖滤波
??当数据改变,两次(如有需要可改写此次数)采样数据相同时,才输出确定可用的新数据,否则判定为杂波,使用旧数据
float debounce(float data)
{
static float result ,last_value = 0;
printf(" last: %.2f data %.2f \n",result,data);
result = (data == last_value ? data : result);
last_value = data;
return result;
}
限幅滤波
??当数据超出设定的范围时判定为杂波,使用旧数据。可根据参数limit_direction确定限制的方向是向里还是向外
#define ABS(x) ( (x)>(0) ? (x): (-x) )
float limit_filter(float data,float limit,bool limit_direction)
{
static float result ;
printf(" last: %.2f data %.2f \n",result,data);
if(!limit_direction){
if(ABS(data - result) < limit){
result = data;
}
}
else{
if(ABS(data - result) >= limit){
result = data;
}
}
return result;
}
注: 1.可重入性: ??平均值滤波和中值滤波使用结构体,模块化的同时也是为了实现可重入性,因后面的三个滤波函数使用场景较轻量型,并没有使用结构体,所以不具备可重入性(多组数据多线程并行使用)。 2.利弊 ??多个滤波器是可以叠加使用的,但是那样对我们的ram及运行速度等的时空损耗较大,滤波器是把双刃剑,应该视情况设计使用 3.源码github地址:https://github.com/AntigravityC/some-filter
|