几种滑动平均滤波器的c++模板实现

说明

本文中几种滑动平均的公式及说明可点击此处

滑动平均模板类

#pragma once
#include <queue>
#include <list>

namespace ns_filter {
   template <typename T, int M>
   class SMA
   {
   public:
      static_assert(M>1, "SMA require window width>1");

      SMA() :_last_flt_value{ 0 } {};
      ~SMA() {};
      T apply(const T& raw) {
         _queue.push(raw);

         if (_queue.size() > M) {
            _last_flt_value += ((raw - _queue.front()) / M);
            _queue.pop();
         } else {
            _last_flt_value = (_last_flt_value * (_queue.size() - 1) + raw) / _queue.size();
         }

         return _last_flt_value;
      }

   private:
      std::queue<T> _queue;
      T _last_flt_value{0};
   };

   template <typename T, int M>
   class WMA
   {
   public:
      static_assert(M > 1, "WMA require window width>1");

      WMA() {};
      ~WMA() {};
      T apply(const T& raw) {
         _ls.push_back(raw);

         if (_ls.size() > M) {
            _ls.pop_front();
         }

         int sz = _ls.size();
         int den = sz * (sz + 1) / 2;
         int w = 1;
         T sum{0};
         for (auto v : _ls) {
            sum += (w * v);
            ++w;
         }

         return sum/den;
      }

   private:
      std::list<T> _ls;
   };

   template <typename T>
   class EMA
   {
   public:
      EMA() = delete;
      EMA(double alpha) { _alpha = alpha; };
      ~EMA() {};
      T apply(const T& raw) {
         if (_initlized == false) {
            _last_y = raw;
            _initlized = true;
         }
         else {
            _last_y = _alpha * _last_y + (1 - _alpha) * raw;
         }
         return _last_y;
      }

   private:
      T _last_y;
      double _alpha = 0.1f;
      bool _initlized = false;
   };
}

使用与测试

测试代码

#include "gtest/gtest.h"
#include "lowPassFilter.h"

TEST(Testfilter, TestEMA) {
   ns_filter::EMA<double> flt2(0.1);
   double r = flt2.apply(1);
   EXPECT_TRUE(abs(r - 1) < 1e-5);

   r = flt2.apply(2);
   EXPECT_TRUE(abs(r - 1.9) < 1e-5);

   r = flt2.apply(4);
   EXPECT_TRUE(abs(r - 0.19-3.6) < 1e-5);

   r = flt2.apply(3);
   EXPECT_TRUE(abs(r - 0.019-0.36-2.7) < 1e-5);
}

TEST(Testfilter, TestSMA) {
   ns_filter::SMA<double> flt(3);
   double r = flt.apply(1);
   EXPECT_TRUE(abs(r - 1) < 1e-5);

   r = flt.apply(2);
   EXPECT_TRUE(abs(r - 1.5) < 1e-5);

   r = flt.apply(4);
   EXPECT_TRUE(abs(r - 7.0 / 3) < 1e-5);

   r = flt.apply(3);
   EXPECT_TRUE(abs(r - 3) < 1e-5);
}

TEST(Testfilter, TestWMA) {
   ns_filter::WMA<double> flt2(3);
   double r = flt2.apply(1);
   EXPECT_TRUE(abs(r - 1) < 1e-5);

   r = flt2.apply(2);
   EXPECT_TRUE(abs(r - 5.0 / 3) < 1e-5);

   r = flt2.apply(4);
   EXPECT_TRUE(abs(r - (1 + 4 + 12) * 1.0 / (1 + 2 + 3)) < 1e-5);

   r = flt2.apply(3);
   EXPECT_TRUE(abs(r - (2 + 8 + 9) * 1.0 / (1 + 2 + 3)) < 1e-5);
}

google test测试结果

visual studio 和 cygwin下测试结果如下,
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/iceboy314159/article/details/106178469