经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
滑动窗口滤波器原理分析及详细代码讲解实现
来源:cnblogs  作者:Sharemaker  时间:2023/1/20 9:21:59  对本文有异议

前言

  在嵌入式开发程序中涉及数据采样如传感器采样,AD采样等如果直接读取信号后,将信号值直接参与后续逻辑处理,若程序无软件滤波,会导致静态或者动态采样时:

        1、信号曲线相对没有那么平滑。

        2、同时可能存在脉冲干扰导致逻辑判断错误。

        在信号处理系统中,输入信号通常含有各种噪声和干扰。为对信号进行准确的测量和控制,必须削弱或滤除被测信号中的噪声和干扰。因此在工程应用需要使用软件滤波,软件滤波也称数字滤波,是通过一定的算法削弱噪声的影响。在实际的开发过程中使用了滑动窗口滤波算法来对传感器的数据采样进行滤波处理。


一、图解滑动窗口滤波器的原理

        1、建立采样窗口和滤波窗口,自定义各窗口长度大小。

?编辑

        2、当数据样本点数未填满采样窗口,对采样窗口内的数据累加做平均值计算。

        例如此时采样窗口内数据采样点只有4个,小于定义的采样窗口长度,则将4个值累加后再做平均值计算。

?编辑

         3、当数据样本点数已填满采样窗口,进行冒泡排序后,去除n个最大值及最小值后,对滤波窗口内的数据累加做平均值运算。

        例如此时采样窗口内数据采样点有7个,已填满定义长度大小的采样窗口,则分别去除自定义的1个最大值和1个最小值后,对剩余滤波窗口内的数据累加后再做平均值计算。

?编辑

        4、新的数据样本到来,移除采样窗口中时间最早的点(FIFO),重复上述3操作。

?编辑


二、滑动窗口滤波器的特点

        1、经过滤波处理后,滤除了噪声干扰,数据波动稳定平滑。

        2、每采样一个新数据,就将最早采集的那个数据丢掉,因此每进行一次采样,就可计算出一个新的平均值,从而加快了数据处理的速度。

        3、可以根据实时性的要求和需要滤波后数据的平滑度来设置采样窗口和滤波窗口的大小。

        4、当采样的数据量非常大时,这时的采样窗口会设置很大,那么窗口需要消耗一定的内存空间。

        5、当采样数据越多,数据实时性越差,当数据突然发生较大变化时,不能被立刻检测到,无法及时处理突发事件。


三、滑动窗口滤波器的C++代码实现

1、基本思路

        1、在工程根目录下新建filter文件夹,将源文件filter.cpp和头filter.h放在文件夹中供修改调用。 

        2、头文件:

        (1)定义滤波算法函数中的可修改宏值;

        (2)声明定义的滤波函数模板;

        (3)使用extern的方式声明实例化后的模板函数。    

        3、源文件:

        (1)定义需要使用滤波算法的函数模板;

        (2)在定义的函数模板后进行函数实例化操作,通过这样的方法实现具体的模板函数。       

2、头文件filter.h

  1. 1 #ifndef _FILTER_H_
  2. 2 #define _FILTER_H_
  3. 3
  4. 4 #define MAX_SENSOR_NUM 9 //使用滤波时的传感器数量
  5. 5 #define MAX_DATA_NUM 9 //最大采样点数量,即采样窗口长度
  6. 6 #define WINDOW_DATA_NUM 5 //滤波窗口长度
  7. 7 //去除采样窗口内最大最小值的数量,这里去除两个最大和两个最小
  8. 8 #define REMOVE_MAXMIN_NUM ((MAX_DATA_NUM - WINDOW_DATA_NUM)/2)
  9. 9
  10. 10 //extern double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM];
  11. 11
  12. 12 //声明定义的函数模板
  13. 13 template<typename InType> InType Filter_SlidingWindowAvg(int index, InType data);
  14. 14 //使用extern的方式声明实例化后的模板函数,根据实际需要自定义数据类型
  15. 15 extern template short Filter_SlidingWindowAvg(int index, short data);
  16. 16 extern template unsigned int Filter_SlidingWindowAvg(int index, unsigned int data);
  17. 17
  18. 18 #endif

3、源文件filter.c

  1. 1 #include <algorithm>
  2. 2 #include "Filter.h"
  3. 3
  4. 4 using namespace std;
  5. 5 //定义各个传感器的数据采样点列表
  6. 6 double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM] = {0};
  7. 7 //滑窗均值滤波,使用函数模板可用于适配不同数据类型的采样点
  8. 8 template<typename InType>
  9. 9 InType Filter_SlidingWindowAvg(int index, InType data)
  10. 10 {
  11. 11 static int dataNum[MAX_SENSOR_NUM] = {0}; //定义记录传感器的采样点个数
  12. 12 int i;
  13. 13 double sum = 0;
  14. 14 double out = 0;
  15. 15 double array[MAX_DATA_NUM] = {0};
  16. 16
  17. 17 //数据采样点在采样窗口内移动,FIFO操作
  18. 18 for(i = MAX_DATA_NUM - 2; i >= 0; i--)
  19. 19 m_dataList[index][i+1] = m_dataList[index][i];
  20. 20
  21. 21 m_dataList[index][0] = data;
  22. 22 //数据采样点数量小于采样窗口长度,对采样窗口数据累加后进行平均值运算
  23. 23 if(dataNum[index] < MAX_DATA_NUM)
  24. 24 {
  25. 25 dataNum[index]++;
  26. 26 for(i = 0; i < dataNum[index]; i++)
  27. 27 {
  28. 28 sum += m_dataList[index][i];
  29. 29 }
  30. 30 out = sum / dataNum[index];
  31. 31 }
  32. 32 //数据采样点已填满采样窗口,进行排序后,去除n个最大值及最小值后,对滤波窗口内的数据累加后进
  33. 33 //行平均值运算
  34. 34 else
  35. 35 {
  36. 36 for(i = 0; i < MAX_DATA_NUM; i++)
  37. 37 {
  38. 38 array[i] = m_dataList[index][i];
  39. 39 }
  40. 40 //利用C++标准库的sort函数进行排序,这里使用默认的升序
  41. 41 sort(array, array + MAX_DATA_NUM);
  42. 42
  43. 43 int start = (MAX_DATA_NUM - WINDOW_DATA_NUM) / 2; //start = REMOVE_MAXMIN_NUM
  44. 44
  45. 45 for(i = start; i < start + WINDOW_DATA_NUM; i++)
  46. 46 {
  47. 47 sum += array[i];
  48. 48 }
  49. 49 out = sum / WINDOW_DATA_NUM;
  50. 50 }
  51. 51 return out;
  52. 52 }
  53. 53
  54. 54 //对函数模板进行函数实例化操作,根据实际需要自定义数据类型
  55. 55 template short Filter_SlidingWindowAvg(int index, short data);
  56. 56 template unsigned int Filter_SlidingWindowAvg(int index, unsigned int data);

四、滑动窗口滤波器的C代码实现

1、基本思路

        1、在工程根目录下新建filter文件夹,将头filter.h和源文件filter.c放在文件夹中供修改调用。

        2、头文件:

        (1)定义滤波算法函数中的可修改宏值;

        (2)声明定义的滤波算法函数;

        3、源文件:

        (1)定义冒泡排序功能函数;           

        (2)定义滤波算法功能函数。        

2、头文件filter.h

  1. 1 #ifndef _FILTER_H_
  2. 2 #define _FILTER_H_
  3. 3
  4. 4 #define MAX_SENSOR_NUM 9 //使用滤波时的传感器数量
  5. 5 #define MAX_DATA_NUM 9 //最大采样点数量,即采样窗口长度
  6. 6 #define WINDOW_DATA_NUM 5 //滤波窗口长度
  7. 7 //去除采样窗口内最大最小值的数量,这里去除两个最大和两个最小
  8. 8 #define REMOVE_MAXMIN_NUM ((MAX_DATA_NUM - WINDOW_DATA_NUM)/2)
  9. 9
  10. 10 //extern double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM];
  11. 11
  12. 12 //声明定义的函数
  13. 13 double Filter_SlidingWindowAvg(int index, double data);
  14. 14
  15. 15 #endif

3、源文件filter.c

  1. 1 #include "Filter.h"
  2. 2
  3. 3 //定义各个传感器的数据采样点列表
  4. 4 double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM] = {0};
  5. 5
  6. 6 //冒泡排序
  7. 7 void BubbleSort(int array[], int len)
  8. 8 {
  9. 9 int temp;
  10. 10 //外层循环控制排序的趟数,n个元素排序需要循环n-1次
  11. 11 for(int i=0; i<len-1; i++)
  12. 12 {
  13. 13 //内层循环控制比较的次数,n个元素第i趟比较n-i次
  14. 14 for(int j=0; j<len-1-i; j++)
  15. 15 {
  16. 16 //比较相邻的元素大小 目的:将最大的元素选出到移动到最后
  17. 17 if(array[j] > array[j+1])
  18. 18 {
  19. 19 temp = array[j];
  20. 20 array[j] = array[j+1];
  21. 21 array[j+1] = temp;
  22. 22 }
  23. 23 }
  24. 24 }
  25. 25 }
  26. 26
  27. 27 //滑窗均值滤波,这里采样点data数据类型和滤波后返回值数据类型都是double,实际使用可根据需要定义
  28. 28 //其他数据类型
  29. 29 double Filter_SlidingWindowAvg(int index, double data)
  30. 30 {
  31. 31 static int dataNum[MAX_SENSOR_NUM] = {0}; //定义记录传感器的采样点个数
  32. 32 int i;
  33. 33 double sum = 0;
  34. 34 double out = 0;
  35. 35 double array[MAX_DATA_NUM] = {0};
  36. 36
  37. 37 //数据采样点在采样窗口内移动,FIFO操作
  38. 38 for(i = MAX_DATA_NUM - 2; i >= 0; i--)
  39. 39 m_dataList[index][i+1] = m_dataList[index][i];
  40. 40
  41. 41 m_dataList[index][0] = data;
  42. 42 //数据采样点数量小于采样窗口长度,对采样窗口数据累加后进行平均值运算
  43. 43 if(dataNum[index] < MAX_DATA_NUM)
  44. 44 {
  45. 45 dataNum[index]++;
  46. 46 for(i = 0; i < dataNum[index]; i++)
  47. 47 {
  48. 48 sum += m_dataList[index][i];
  49. 49 }
  50. 50 out = sum / dataNum[index];
  51. 51 }
  52. 52 //数据采样点已填满采样窗口,进行排序后,去除n个最大值及最小值后,对滤波窗口内的数据累加后进
  53. 53 //行平均值运算
  54. 54 else
  55. 55 {
  56. 56 for(i = 0; i < MAX_DATA_NUM; i++)
  57. 57 {
  58. 58 array[i] = m_dataList[index][i];
  59. 59 }
  60. 60 //调用冒泡排序函数
  61. 61 BubbleSort(array, MAX_DATA_NUM);
  62. 62
  63. 63 int start = (MAX_DATA_NUM - WINDOW_DATA_NUM) / 2; //start = REMOVE_MAXMIN_NUM
  64. 64
  65. 65 for(i = start; i < start + WINDOW_DATA_NUM; i++)
  66. 66 {
  67. 67 sum += array[i];
  68. 68 }
  69. 69 out = sum / WINDOW_DATA_NUM;
  70. 70 }
  71. 71 return out;
  72. 72 }

更多技术内容和书籍资料获取敬请关注微信公众号“明解嵌入式”
?

 

 

原文链接:https://www.cnblogs.com/Sharemaker/p/17062418.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号