一般而言,对于硬件收集来的各种数据都是要进行滤波的,滤波的手法有很多种,只是一般都不会在java层进行。但是也有一些特别小巧实用易懂的方法,可以用来对数据进行滤波,譬如中值滤波算法。
该算法在波形类数据中经常会用上,主要效果是突出特征波形,使得波形更加”凹凸有致“。但是也有一定副作用,那就是如果波形本身就非常漂亮,那就有可能将其特征波形稍稍磨平——当然这种效果基本还是在能接受范围内。
中值滤波算法主要思路是,对于心电数据中的某一个点n,选取一个周围的长度为N的区间(从搜索到的论文资料来看,该区间的选择有在该点之后也有在该点之前,可见对于区间的选取并不是固定的,要通过结果来对比效果如何,本文最后选择的是[x-m,x+m]),然后对该区间内的数进行排序,取中间的值作为该点对应的漂移值,然后用n减去该值即是滤波后的值。
设心电波形的函数为f(x),取区间[x-m,x+m]的值进行排序,设mid[n-m,n+m]为区间内排序后处于中间的数,则f(mid[n-m,n+m])则是对应的漂移值。将式子串起来易得:
n'=n-f(mid[x-m,x+m])
由上述式子可见,基本上没有复杂的运算,但是对于m值的选取需要大家好好斟酌——m选得太大,一方面需要抛弃的点会更多(由式子可知心电数据开始和结尾的m个点无法进行滤波,也就是说这2m个点必须被抛弃,否则会引起和滤波后的数据放在一起组成心电波形的话会引起误检),另一方面会加大系统的负担,虽然排序的时间复杂度不高,但是因为每个点都要跟前后m个数据进行排序,因此m值每增大一点,系统负担就会增大一分。而如果m选得太小,可想而知该漂移值被噪声和波动影响的成分会大得多,具体表现就是使得滤波后的波形失真较严重,可能会引起更严重的误检。
将上述思路写成java代码,大致如下:
for(int i=45;i<dataY.size()-45;i++){ List<Float> sortList=new ArrayList<Float>(dataY.subList(i-45, i+45)); Collections.sort(sortList); float mid=sortList.get(sortList.size()/2); newDataListY.add((dataY.get(i)-mid)); }
从代码可以非常清楚地知道,这个算法有多简洁了^_^而且由于java自带的排序算法,所以又帮我们省了不少时间~
结果对比:
滤波前
滤波后
对于一个这么廉价的算法,这个结果已经非常能接受了~