Arduino Filters master
Filter library for Arduino
MedianFilter.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <AH/STL/algorithm> // std::partial_sort_copy
4#include <AH/STL/array> // std::array
5#include <AH/STL/cstdint> // uint8_t
6
9
10#if 0
11
31template <uint8_t N, class T = float>
32class MedianFilter {
33 public:
37 MedianFilter() = default;
38
47 MedianFilter(T initialValue) {
48 std::fill(previousInputs.begin(), previousInputs.end(), initialValue);
49 }
50
61 T operator()(T x) {
62 // Insert the new input into the ring buffer, overwriting the oldest
63 // input.
65 if (++index == N)
66 index = 0;
67
68 // Calculate the median of the buffer by sorting the first half. A copy
69 // should be made to keep the order of the buffer intact.
70 const uint8_t halfSize = N / 2 + 1;
71 std::array<T, halfSize> sorted;
72 std::partial_sort_copy(previousInputs.begin(), previousInputs.end(),
73 sorted.begin(), sorted.end());
74
75 // If the length of the ring buffer is odd, then the median is its
76 // center element, which is the final element of `sorted`.
77 // If the length of the ring buffer is even, then we need to take the
78 // average of its two center elements, which are the final two elements
79 // of `sorted`.
80 if (N % 2 == 0)
81 return (sorted.end()[-2] + sorted.end()[-1]) / 2;
82 else
83 return sorted.end()[-1];
84 }
85
86 private:
88 uint8_t index = 0;
90 std::array<T, N> previousInputs = {};
91};
92
93#else
94
110template <uint8_t N, class T = float>
112 public:
116 MedianFilter() = default;
117
126 MedianFilter(T initialValue) {
127 std::fill(previousInputs.begin(), previousInputs.end(), initialValue);
128 }
129
140 T operator()(T x) {
141 // Insert the new input into the ring buffer, overwriting the oldest
142 // input.
144 if (++index == N)
145 index = 0;
146
147 // Calculate the median of the buffer by sorting it just enough to find
148 // the middle element. A copy should be made to keep the order of the
149 // buffer intact.
150 std::array<T, N> sorted = previousInputs;
151 auto halfWay = sorted.begin() + N / 2;
152 std::nth_element(sorted.begin(), halfWay, sorted.end());
153
154 // If the length of the ring buffer is odd, then the median is its
155 // center element.
156 // If the length of the ring buffer is even, then we need to take the
157 // average of its two center elements.
158 if (N % 2 == 0) {
159 auto beforeHalfWay = std::max_element(sorted.begin(), halfWay);
160 return (*halfWay + *beforeHalfWay) / 2;
161 } else {
162 return *halfWay;
163 }
164 }
165
166 private:
168 uint8_t index = 0;
170 std::array<T, N> previousInputs = {{}};
171};
172
173#endif
174
175
Class for Median Filters.
MedianFilter(T initialValue)
Construct a new Median Filter, and initialize it with the given value.
MedianFilter()=default
Construct a new Median Filter (zero initialized).
T operator()(T x)
Calculate the output for a given input .
uint8_t index
The last index in the ring buffer.
std::array< T, N > previousInputs
A ring buffer to keep track of the N last inputs.