改良中位数无滞后滤波算法
原始数据情况
各种滤波算法介绍,见http://blog.csdn.net/u010657219/article/details/43309345
其中中位数滤波算法在对慢速,偶然因素引起的脉冲干扰的信号滤波效果比较突出。
但是如果一个信号(下图)既快速又有脉冲干扰,还希望滤波结果在没有脉冲干扰时没有滞后或滞后较小,那应该选哪种滤波算法呢?很显然,现有算法都不能满足要求。
首先,信号中有脉冲干扰,一般情况下,直接用中位数滤波就可以,但是这是一相对比较快速的信号,我们的系统要求滞后不能太多或者没有滞后。这时有人会说,“滤波肯定会带来滞后”,NO,我的改良滤波算法可以做到既不滞后,又能把脉冲干扰尽可能的消除。
滤波算法
int16 last_g_countervalue_l[30];
int16 last_g_countervalue_l_sort[30];
int16 g_countervalue_l_filter = 0;
int16 last_g_countervalue_l_filter[5];
void speedfeedbackfilter(void)
{
update_int16queue(last_g_countervalue_l,30,g_countervalue_l);
for(int i=0;i<30;i++)
{
last_g_countervalue_l_sort[i]=last_g_countervalue_l[i];
}
sort_int16queue(last_g_countervalue_l_sort,30);
templ=(last_g_countervalue_l_sort[14]+last_g_countervalue_l_sort[15])/2;
if(ABS(g_countervalue_l-templ)>6)
{
//g_countervalue_l_filter=templ;
g_countervalue_l_filter=(last_g_countervalue_l_filter[0]+last_g_countervalue_l_filter[1]+last_g_countervalue_l_filter[2]+last_g_countervalue_l_filter[3]+last_g_countervalue_l_filter[4])/5;
if(ABS(g_countervalue_l_filter-g_countervalue_l)<=10)
{
g_countervalue_l_filter=g_countervalue_l;
}
}
else
{
g_countervalue_l_filter=g_countervalue_l;
}
update_int16queue(last_g_countervalue_l_filter,5,g_countervalue_l_filter);
}
其中用到的子函数有:
update_int16queue,更新数组,参数分别是数组名,数组长度,要插入的新数据。
void update_int16queue(int16 *str,int length,int16 new_data)
{
for(int i=length-2;i>=0;i--)
{
*(str+i+1) = *(str+i);
}
*str = new_data;
}
sort_int16queue,排序数组。
void sort_int16queue(int16 *str,int length)
{
int i,j,k;
int16 temp;
for(i=0;i<length-1;i++)
{
k=i;
for(j=i+1;j<length;j++)
if(*(str+j)>*(str+k))
k=j;
if(k!=j)
{
temp=*(str+i);
*(str+i)=*(str+k);
*(str+k)=temp;
}
}
}
基本思想
计算连续若干场数据的中位数,和当前场比较,如果在一定范围内,认为没有脉冲干扰,滤波结果就是实际测量结果,如果超过一定范围,认为发生了脉冲干扰,根据前几场数据的斜率走向确定这场数据或者直接用算出来的中位数做为滤波结果。该算法经过实际测试,效果良好。
因为最近重装过系统,滤波结果的图找不到了,如果你的数据也有这种脉冲干扰,不妨试试。
应用范围
快速的数据中途会有连续若干个数突然急剧偏大或偏小,即所谓出现脉冲干扰,但概率较小。