A,_常用滤波算法">
当前位置:   article > 正文

几种常用的滤波算法_常用滤波算法

常用滤波算法

几种常用的滤波算法

一.修改记录

2024-01-26修改

1.中值滤波负数时失效,补充一下。

二.修改记录

1、限幅消抖滤波法(又称程序判断滤波法)

2、中位值滤波法

3、算术平均滤波法

4.一阶滞后滤波法

5.加权递推平均滤波法

6.消抖滤波法

7、递推平均滤波法(又称滑动平均滤波法)

8、中位值平均滤波法(又称防脉冲干扰平均滤波法)

9、限幅平均滤波法

嵌入式开发中经常会用到一些滤波算法,我整理了一些资料把这些算法封装成可以直接调用的函数,方便以后的开发,包括限幅滤波、中位值滤波法、 算术平均滤波法、一阶滞后滤波法、加权递推平均滤波法、消抖滤波法 ,其他的一些包括卡尔曼滤波什么的之后有机会再整理

  1. #include "filter.h"
  2. /*
  3. 限幅滤波
  4.   A方法: 根据经验判断,确定两次采样允许的最大偏差值(设为A),每次检测到新值时判断: 如果本次值与上次值之差<=A,则本次值有效,如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值。
  5.   B优点: 能有效克服因偶然因素引起的脉冲干扰。
  6.   C缺点: 无法抑制那种周期性的干扰,平滑度差。
  7. A值可根据实际情况调整
  8. value为有效值,new_value为当前采样值
  9. 滤波程序返回有效的实际值
  10. */
  11. #define DEVIATION 10
  12. float limit_filter(float new_value)
  13. {
  14. static int num = 0;
  15. static float value = 0; //需要赋一个初值
  16. num ++;
  17. if(num == 1)
  18. value = new_value;
  19. else
  20. {
  21. if ( ( new_value - value > DEVIATION ) || ( value - new_value > DEVIATION ))
  22. return value;
  23. }
  24. return new_value;
  25. }
  26. /*
  27. 中位值滤波法
  28.   A方法: 取之前采样的N次(N取奇数),把N次采样值按大小排列,取中间值为本次有效值。
  29.   B优点: 能有效克服因偶然因素引起的波动干扰,对温度、液位的变化缓慢的被测参数有良好的滤波效果。
  30.   C缺点: 对流量、速度等快速变化的参数不宜。
  31. 排序采用冒泡法 只需要移动最后一个元素即可
  32. */
  33. #define MIDDLE_FILTER_N 11
  34. float middle_filter( float new_value)
  35. {
  36. static float value_buf[MIDDLE_FILTER_N];
  37. float temp ;
  38. uint8_t count, i;
  39. for ( count = 0; count < MIDDLE_FILTER_N - 1; count++)
  40. {
  41. value_buf[count] = value_buf[count + 1] ;
  42. }
  43. value_buf[MIDDLE_FILTER_N - 1] = new_value;
  44. for (i = MIDDLE_FILTER_N; i > 0 ; i --)
  45. {
  46. #if 0
  47. if ( value_buf[i] < value_buf[i - 1] )
  48. {
  49. temp = value_buf[i];
  50. value_buf[i] = value_buf[i - 1];
  51. value_buf[i - 1] = temp;
  52. }
  53. #endif
  54. if(value_buf[i] > 0)
  55. {
  56. if ( value_buf[i] < value_buf[i - 1] )
  57. {
  58. temp = value_buf[i];
  59. value_buf[i] = value_buf[i - 1];
  60. value_buf[i - 1] = temp;
  61. }
  62. }
  63. else if(value_buf[i] < 0)
  64. {
  65. if ( value_buf[i] > value_buf[i - 1] )
  66. {
  67. temp = value_buf[i];
  68. value_buf[i] = value_buf[i - 1];
  69. value_buf[i - 1] = temp;
  70. }
  71. }
  72. }
  73. return value_buf[(MIDDLE_FILTER_N - 1) / 2];
  74. }
  75. /*
  76. 算术平均滤波法
  77. A方法: 连续取N个采样值进行算术平均运算,N值较大时:信号平滑度较高,但灵敏度较低;N值较小时:信号平滑度较低,但灵敏度较高。N值的选取:一般流量,N=12;压力:N=4。
  78.   B优点: 适用于对一般具有随机干扰的信号进行滤波,这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动。
  79.   C缺点: 对于测量速度较慢或要求数据计算速度较快的实时控制不适用,比较浪费RAM 。
  80. 无需每次求一编所有的和,减去第一个数据加上新数据
  81. */
  82. #define AVERAGE_N 12
  83. float average_filter(float new_value)
  84. {
  85. static float average_value_buf[AVERAGE_N];
  86. static float average_sum = 0;
  87. uint8_t count;
  88. average_sum -= average_value_buf[0];
  89. for ( count = 0; count < AVERAGE_N - 1; count++)
  90. {
  91. average_value_buf[count] = average_value_buf[count + 1] ;
  92. }
  93. average_value_buf[AVERAGE_N - 1] = new_value;
  94. average_sum += average_value_buf[11];
  95. return (average_sum /(AVERAGE_N * 1.0) );
  96. }
  97. /*
  98. 一阶滞后滤波法
  99. A方法: 取a=0~1,本次滤波结果=(1-a)*本次采样值+a*上次滤波结果。
  100.   B优点: 对周期性干扰具有良好的抑制作用,适用于波动频率较高的场合。
  101.   C缺点:相位滞后,灵敏度低,滞后程度取决于a值大小,不能消除滤波频率高于采样频率的1/2的干扰信号。
  102. 为加快程序处理速度假定基数为100,a=0~100
  103. */
  104. #define FIRST_LAG_PROPORTION 0.4
  105. float first_order_lag_filter( float new_value)
  106. {
  107. static float first_order_value , first_order_last_value;
  108. first_order_value = first_order_last_value;
  109. first_order_last_value = new_value;
  110. return (1 - FIRST_LAG_PROPORTION) * first_order_value + FIRST_LAG_PROPORTION * new_value;
  111. }
  112. /*
  113. 加权递推平均滤波法
  114.   A方法: 是对递推平均滤波法的改进,即不同时刻的数据加以不同的权,通常是,越接近现时刻的资料,权取得越大,给予新采样值的权系数越大,则灵敏度越高,但信号平滑度越低。
  115.   B优点: 适用于有较大纯滞后时间常数的对象和采样周期较短的系统。
  116.   C缺点: 对于纯滞后时间常数较小,采样周期较长,变化缓慢的信号,不能迅速反应系统当前所受干扰的严重程度,滤波效果差。
  117. coe数组为加权系数表,存在程序存储区。
  118. */
  119. #define WEIGHT_AVERAGE_N 12
  120. uint8_t coe[WEIGHT_AVERAGE_N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
  121. uint8_t sum_coe = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12;
  122. float weighted_filter(float new_value)
  123. {
  124. static float weight_average_buf[WEIGHT_AVERAGE_N];
  125. uint8_t count;
  126. float sum = 0;
  127. for ( count = 0; count < AVERAGE_N - 1 ; count++)
  128. {
  129. weight_average_buf[count] = weight_average_buf[count+ 1] ;
  130. }
  131. weight_average_buf[AVERAGE_N - 1] = new_value;
  132. for (count = 0 ; count < WEIGHT_AVERAGE_N; count++)
  133. sum += weight_average_buf[count] * coe[count];
  134. return (sum / (sum_coe * 1.0));
  135. }
  136. /*
  137. 消抖滤波法
  138.   A方法: 设置一个滤波计数器,将每次采样值与当前有效值比较: 如果采样值=当前有效值,则计数器清零。如果采样值<>当前有效值,则计数器+1,并判断计数器是否>=上限N(溢出),如果计数器溢出,则将本次值替换当前有效值,并清计数器。
  139.   B优点: 对于变化缓慢的被测参数有较好的滤波效果,可避免在临界值附近控制器的反复开/关跳动或显示器上数值抖动。
  140.   C缺点: 对于快速变化的参数不宜,如果在计数器溢出的那一次采样到的值恰好是干扰值,则会将干扰值当作有效值导入系统。
  141. */
  142. #define SHAKE_N 12
  143. float shake_filter( float new_value , float now_value)
  144. {
  145. static uint8_t count = 0;
  146. if(now_value != new_value)
  147. {
  148. count++;
  149. if (count >= SHAKE_N)
  150. {
  151. count = 0;
  152. return new_value;
  153. }
  154. }
  155. return now_value;
  156. }

本文链接:几种常用的滤波算法_给定系统函数如何进行滤波-CSDN博客

instance analysis1:限幅滤波:

  1. #include <stdio.h>
  2. /*
  3. 限幅滤波
  4.   A方法: 根据经验判断,确定两次采样允许的最大偏差值(设为A),每次检测到新值时判断: 如果本次值与上次值之差<=A,则本次值有效,如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值。
  5.   B优点: 能有效克服因偶然因素引起的脉冲干扰。
  6.   C缺点: 无法抑制那种周期性的干扰,平滑度差。
  7. A值可根据实际情况调整
  8. value为有效值,new_value为当前采样值
  9. 滤波程序返回有效的实际值
  10. */
  11. #define DEVIATION 10
  12. float limit_filter(float new_value)
  13. {
  14. static int num = 0;
  15. static float value = 0; //需要赋一个初值
  16. num ++;
  17. if(num == 1)
  18. value = new_value;
  19. else
  20. {
  21. if ( ( new_value - value > DEVIATION ) || ( value - new_value > DEVIATION ))
  22. return value;
  23. }
  24. return new_value;
  25. }
  26. int main()
  27. {
  28. int i = 0;
  29. float result = 0;
  30. int a[10] = {15,11,65536,13,31,15,16,17,68,15};
  31. for(i = 0; i < 10; i++)
  32. {
  33. result = limit_filter(a[i]);
  34. printf("result:%f \n", result);
  35. }
  36. return 0;
  37. }

 

65536大幅度值确实可以过滤

instance analysis2:中位值滤波法
  1. #include <stdio.h>
  2. /*
  3. 中位值滤波法
  4.   A方法: 取之前采样的N次(N取奇数),把N次采样值按大小排列,取中间值为本次有效值。
  5.   B优点: 能有效克服因偶然因素引起的波动干扰,对温度、液位的变化缓慢的被测参数有良好的滤波效果。
  6.   C缺点: 对流量、速度等快速变化的参数不宜。
  7. 排序采用冒泡法 只需要移动最后一个元素即可
  8. */
  9. #define MIDDLE_FILTER_N 11
  10. float middle_filter( float new_value)
  11. {
  12. static float value_buf[MIDDLE_FILTER_N];
  13. float temp ;
  14. unsigned char count, i;
  15. for ( count = 0; count < MIDDLE_FILTER_N - 1; count++)
  16. {
  17. value_buf[count] = value_buf[count + 1] ;
  18. }
  19. value_buf[MIDDLE_FILTER_N - 1] = new_value;
  20. //for (i = MIDDLE_FILTER_N; i > 0 ; i --)
  21. for (i = MIDDLE_FILTER_N-1; i > 0 ; i --)
  22. {
  23. #if 0
  24. if ( value_buf[i] < value_buf[i - 1] )
  25. {
  26. temp = value_buf[i];
  27. value_buf[i] = value_buf[i - 1];
  28. value_buf[i - 1] = temp;
  29. }
  30. #endif
  31. if(value_buf[i] > 0)
  32. {
  33. if ( value_buf[i] < value_buf[i - 1] )
  34. {
  35. temp = value_buf[i];
  36. value_buf[i] = value_buf[i - 1];
  37. value_buf[i - 1] = temp;
  38. }
  39. }
  40. else if(value_buf[i] < 0)
  41. {
  42. if ( value_buf[i] > value_buf[i - 1] )
  43. {
  44. temp = value_buf[i];
  45. value_buf[i] = value_buf[i - 1];
  46. value_buf[i - 1] = temp;
  47. }
  48. }
  49. }
  50. return value_buf[(MIDDLE_FILTER_N - 1) / 2];
  51. }
  52. int main()
  53. {
  54. int i = 0;
  55. float result = 0;
  56. int a[10] = {15,11,65536,13,31,15,16,17,68,15};
  57. for(i = 0; i < 10; i++)
  58. {
  59. result = middle_filter(a[i]);
  60. printf("result:%f \n", result);
  61. }
  62. return 0;
  63. }

打印截图: 

 

瞬间变化值不易过滤

instance analysis3 算术平均滤波法:

  1. #include <stdio.h>
  2. /*
  3. 算术平均滤波法
  4. A方法: 连续取N个采样值进行算术平均运算,N值较大时:信号平滑度较高,但灵敏度较低;N值较小时:信号平滑度较低,但灵敏度较高。N值的选取:一般流量,N=12;压力:N=4。
  5.   B优点: 适用于对一般具有随机干扰的信号进行滤波,这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动。
  6.   C缺点: 对于测量速度较慢或要求数据计算速度较快的实时控制不适用,比较浪费RAM 。
  7. 无需每次求一编所有的和,减去第一个数据加上新数据
  8. */
  9. #define AVERAGE_N 12
  10. float average_filter(float new_value)
  11. {
  12. static float average_value_buf[AVERAGE_N];
  13. static float average_sum = 0;
  14. unsigned char count;
  15. average_sum -= average_value_buf[0];
  16. for ( count = 0; count < AVERAGE_N - 1; count++)
  17. {
  18. average_value_buf[count] = average_value_buf[count + 1] ;
  19. }
  20. average_value_buf[AVERAGE_N - 1] = new_value;
  21. average_sum += average_value_buf[11];
  22. return (average_sum /(AVERAGE_N * 1.0) );
  23. }
  24. int main()
  25. {
  26. int i = 0;
  27. float result = 0;
  28. int a[10] = {15,11,65536,13,31,15,16,17,68,15};
  29. for(i = 0; i < 10; i++)
  30. {
  31. result = average_filter(a[i]);
  32. printf("result:%f \n", result);
  33. }
  34. return 0;
  35. }

第3个值改为65536

天啊,拉高了整体平均值。对有突变的大值不适用。

instance analysis4 一阶滞后滤波法:

  1. #include <stdio.h>
  2. /*
  3. 一阶滞后滤波法
  4. A方法: 取a=0~1,本次滤波结果=(1-a)*本次采样值+a*上次滤波结果。
  5.   B优点: 对周期性干扰具有良好的抑制作用,适用于波动频率较高的场合。
  6.   C缺点:相位滞后,灵敏度低,滞后程度取决于a值大小,不能消除滤波频率高于采样频率的1/2的干扰信号。
  7. 为加快程序处理速度假定基数为100,a=0~100
  8. */
  9. #define FIRST_LAG_PROPORTION 0.4
  10. float first_order_lag_filter( float new_value)
  11. {
  12. static float first_order_value , first_order_last_value;
  13. first_order_value = first_order_last_value;
  14. first_order_last_value = new_value;
  15. return (1 - FIRST_LAG_PROPORTION) * first_order_value + FIRST_LAG_PROPORTION * new_value;
  16. }
  17. int main()
  18. {
  19. int i = 0;
  20. float result = 0;
  21. int a[10] = {15,11,65,13,31,15,16,17,68,15};
  22. for(i = 0; i < 10; i++)
  23. {
  24. result = first_order_lag_filter(a[i]);
  25. printf("result:%f \n", result);
  26. }
  27. return 0;
  28. }

一般值可以,大值还是有点吓人。 

instance analysis5 加权递推平均滤波法:

  1. #include <stdio.h>
  2. #include <stdint.h>
  3. /*
  4. 加权递推平均滤波法
  5.   A方法: 是对递推平均滤波法的改进,即不同时刻的数据加以不同的权,通常是,越接近现时刻的资料,权取得越大,给予新采样值的权系数越大,则灵敏度越高,但信号平滑度越低。
  6.   B优点: 适用于有较大纯滞后时间常数的对象和采样周期较短的系统。
  7.   C缺点: 对于纯滞后时间常数较小,采样周期较长,变化缓慢的信号,不能迅速反应系统当前所受干扰的严重程度,滤波效果差。
  8. coe数组为加权系数表,存在程序存储区。
  9. */
  10. #define WEIGHT_AVERAGE_N 12
  11. uint8_t coe[WEIGHT_AVERAGE_N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
  12. uint8_t sum_coe = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12;
  13. float weighted_filter(float new_value)
  14. {
  15. static float weight_average_buf[WEIGHT_AVERAGE_N];
  16. uint8_t count;
  17. float sum = 0;
  18. for ( count = 0; count < WEIGHT_AVERAGE_N - 1 ; count++)
  19. {
  20. weight_average_buf[count] = weight_average_buf[count+ 1] ;
  21. }
  22. weight_average_buf[WEIGHT_AVERAGE_N - 1] = new_value;
  23. for (count = 0 ; count < WEIGHT_AVERAGE_N; count++)
  24. sum += weight_average_buf[count] * coe[count];
  25. return (sum / (sum_coe * 1.0));
  26. }
  27. int main()
  28. {
  29. int i = 0;
  30. float result = 0;
  31. int a[10] = {15,11,25,13,31,15,16,17,68,15};
  32. for(i = 0; i < 10; i++)
  33. {
  34. result = weighted_filter(a[i]);
  35. printf("result:%f \n", result);
  36. }
  37. return 0;
  38. }

第3个值改为255

 instance analysis6 消抖滤波法:

  1. #include <stdio.h>
  2. #include <stdint.h>
  3. /*
  4. 消抖滤波法
  5.   A方法: 设置一个滤波计数器,将每次采样值与当前有效值比较: 如果采样值=当前有效值,则计数器清零。如果采样值 >当前有效值,则计数器+1,并判断计数器是否>=上限N(溢出),如果计数器溢出,则将本次值替换当前有效值,并清计数器。
  6.   B优点: 对于变化缓慢的被测参数有较好的滤波效果,可避免在临界值附近控制器的反复开/关跳动或显示器上数值抖动。
  7.   C缺点: 对于快速变化的参数不宜,如果在计数器溢出的那一次采样到的值恰好是干扰值,则会将干扰值当作有效值导入系统。
  8. */
  9. #define SHAKE_N 12
  10. float shake_filter( float new_value , float now_value)
  11. {
  12. static uint8_t count = 0;
  13. if(now_value != new_value)
  14. {
  15. count++;
  16. if (count >= SHAKE_N)
  17. {
  18. count = 0;
  19. return new_value;
  20. }
  21. }
  22. return now_value;
  23. }
  24. int main()
  25. {
  26. int i = 0;
  27. float result = 0;
  28. int a[10] = {15,11,255,13,31,15,16,17,68,15};
  29. for(i = 0; i < 9; i++)
  30. {
  31. result = shake_filter(a[0],a[i+1]);
  32. printf("result:%f \n", result);
  33. }
  34. return 0;
  35. }

总结:滤波各有各的长度和不足,需要使用组合滤波。 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/1013026
推荐阅读
相关标签
  

闽ICP备14008679号