annotate maths/MedianFilter.h @ 164:4a70fff27b8f

Add median filter (originally from devuvuzelator code)
author Chris Cannam
date Fri, 04 Apr 2014 12:40:40 +0100
parents
children ec9f5b9801bd
rev   line source
Chris@164 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@164 2
Chris@164 3 #ifndef MEDIAN_FILTER_H
Chris@164 4 #define MEDIAN_FILTER_H
Chris@164 5
Chris@164 6 #include <algorithm>
Chris@164 7 #include <cassert>
Chris@164 8 #include <cmath>
Chris@164 9 #include <iostream>
Chris@164 10
Chris@164 11 template <typename T>
Chris@164 12 class MedianFilter
Chris@164 13 {
Chris@164 14 public:
Chris@164 15 MedianFilter(int size, float percentile = 50.f) :
Chris@164 16 m_size(size),
Chris@164 17 m_frame(new T[size]),
Chris@164 18 m_sorted(new T[size]),
Chris@164 19 m_sortend(m_sorted + size - 1) {
Chris@164 20 setPercentile(percentile);
Chris@164 21 reset();
Chris@164 22 }
Chris@164 23
Chris@164 24 ~MedianFilter() {
Chris@164 25 delete[] m_frame;
Chris@164 26 delete[] m_sorted;
Chris@164 27 }
Chris@164 28
Chris@164 29 void setPercentile(float p) {
Chris@164 30 m_index = int((m_size * p) / 100.f);
Chris@164 31 if (m_index >= m_size) m_index = m_size-1;
Chris@164 32 if (m_index < 0) m_index = 0;
Chris@164 33 }
Chris@164 34
Chris@164 35 void push(T value) {
Chris@164 36 if (value != value) return; // nan
Chris@164 37 drop(m_frame[0]);
Chris@164 38 const int sz1 = m_size-1;
Chris@164 39 for (int i = 0; i < sz1; ++i) m_frame[i] = m_frame[i+1];
Chris@164 40 m_frame[m_size-1] = value;
Chris@164 41 put(value);
Chris@164 42 }
Chris@164 43
Chris@164 44 T get() const {
Chris@164 45 return m_sorted[m_index];
Chris@164 46 }
Chris@164 47
Chris@164 48 T getAt(float percentile) {
Chris@164 49 int ix = int((m_size * percentile) / 100.f);
Chris@164 50 if (ix >= m_size) ix = m_size-1;
Chris@164 51 if (ix < 0) ix = 0;
Chris@164 52 return m_sorted[ix];
Chris@164 53 }
Chris@164 54
Chris@164 55 void reset() {
Chris@164 56 for (int i = 0; i < m_size; ++i) m_frame[i] = 0;
Chris@164 57 for (int i = 0; i < m_size; ++i) m_sorted[i] = 0;
Chris@164 58 }
Chris@164 59
Chris@164 60 private:
Chris@164 61 const int m_size;
Chris@164 62 T *const m_frame;
Chris@164 63 T *const m_sorted;
Chris@164 64 T *const m_sortend;
Chris@164 65 int m_index;
Chris@164 66
Chris@164 67 void put(T value) {
Chris@164 68 // precondition: m_sorted contains m_size-1 values, packed at start
Chris@164 69 // postcondition: m_sorted contains m_size values, one of which is value
Chris@164 70 T *point = std::lower_bound(m_sorted, m_sortend, value);
Chris@164 71 const int n = m_sortend - point;
Chris@164 72 for (int i = n; i > 0; --i) point[i] = point[i-1];
Chris@164 73 *point = value;
Chris@164 74 }
Chris@164 75
Chris@164 76 void drop(T value) {
Chris@164 77 // precondition: m_sorted contains m_size values, one of which is value
Chris@164 78 // postcondition: m_sorted contains m_size-1 values, packed at start
Chris@164 79 T *point = std::lower_bound(m_sorted, m_sortend + 1, value);
Chris@164 80 if (*point != value) {
Chris@164 81 std::cerr << "WARNING: MedianFilter::drop: *point is " << *point
Chris@164 82 << ", expected " << value << std::endl;
Chris@164 83 }
Chris@164 84 const int n = m_sortend - point;
Chris@164 85 for (int i = 0; i < n; ++i) point[i] = point[i+1];
Chris@164 86 *m_sortend = T(0);
Chris@164 87 }
Chris@164 88 };
Chris@164 89
Chris@164 90 #endif
Chris@164 91