MedianFilter.h
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  QM DSP Library
5 
6  Centre for Digital Music, Queen Mary, University of London.
7  This file Copyright 2010 Chris Cannam.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #ifndef MEDIAN_FILTER_H
17 #define MEDIAN_FILTER_H
18 
19 #include <algorithm>
20 #include <cassert>
21 #include <cmath>
22 #include <iostream>
23 #include <vector>
24 
25 template <typename T>
27 {
28 public:
29  MedianFilter(int size, float percentile = 50.f) :
30  m_size(size),
31  m_frame(new T[size]),
32  m_sorted(new T[size]),
33  m_sortend(m_sorted + size - 1) {
34  setPercentile(percentile);
35  reset();
36  }
37 
39  delete[] m_frame;
40  delete[] m_sorted;
41  }
42 
43  void setPercentile(float p) {
44  m_index = int((m_size * p) / 100.f);
45  if (m_index >= m_size) m_index = m_size-1;
46  if (m_index < 0) m_index = 0;
47  }
48 
49  void push(T value) {
50  if (value != value) { // nan
51  static bool warned = false;
52  if (!warned) {
53  std::cerr << "WARNING: MedianFilter::push: attempt to push NaN" << std::endl;
54  std::cerr << "WARNING: MedianFilter::push: (only one warning will be printed)" << std::endl;
55  warned = true;
56  }
57  return;
58  }
59  drop(m_frame[0]);
60  const int sz1 = m_size-1;
61  for (int i = 0; i < sz1; ++i) m_frame[i] = m_frame[i+1];
62  m_frame[m_size-1] = value;
63  put(value);
64  }
65 
66  T get() const {
67  return m_sorted[m_index];
68  }
69 
70  int getSize() const {
71  return m_size;
72  }
73 
74  T getAt(float percentile) {
75  int ix = int((m_size * percentile) / 100.f);
76  if (ix >= m_size) ix = m_size-1;
77  if (ix < 0) ix = 0;
78  return m_sorted[ix];
79  }
80 
81  void reset() {
82  for (int i = 0; i < m_size; ++i) m_frame[i] = 0;
83  for (int i = 0; i < m_size; ++i) m_sorted[i] = 0;
84  }
85 
86  static std::vector<T> filter(int size, const std::vector<T> &in) {
87  std::vector<T> out;
88  MedianFilter<T> f(size);
89  for (int i = 0; i < int(in.size()); ++i) {
90  f.push(in[i]);
91  T median = f.get();
92  if (i >= size/2) out.push_back(median);
93  }
94  while (out.size() < in.size()) {
95  f.push(T());
96  out.push_back(f.get());
97  }
98  return out;
99  }
100 
101 private:
102  const int m_size;
103  T *const m_frame;
104  T *const m_sorted;
105  T *const m_sortend;
106  int m_index;
107 
108  void put(T value) {
109  // precondition: m_sorted contains m_size-1 values, packed at start
110  // postcondition: m_sorted contains m_size values, one of which is value
111  T *point = std::lower_bound(m_sorted, m_sortend, value);
112  const int n = m_sortend - point;
113  for (int i = n; i > 0; --i) point[i] = point[i-1];
114  *point = value;
115  }
116 
117  void drop(T value) {
118  // precondition: m_sorted contains m_size values, one of which is value
119  // postcondition: m_sorted contains m_size-1 values, packed at start
120  T *point = std::lower_bound(m_sorted, m_sortend + 1, value);
121  if (*point != value) {
122  std::cerr << "WARNING: MedianFilter::drop: *point is " << *point
123  << ", expected " << value << std::endl;
124  }
125  const int n = m_sortend - point;
126  for (int i = 0; i < n; ++i) point[i] = point[i+1];
127  *m_sortend = T(0);
128  }
129 
130  MedianFilter(const MedianFilter &); // not provided
131  MedianFilter &operator=(const MedianFilter &); // not provided
132 };
133 
134 #endif
135 
T get() const
Definition: MedianFilter.h:66
void push(T value)
Definition: MedianFilter.h:49
int getSize() const
Definition: MedianFilter.h:70
T getAt(float percentile)
Definition: MedianFilter.h:74
MedianFilter(int size, float percentile=50.f)
Definition: MedianFilter.h:29
void setPercentile(float p)
Definition: MedianFilter.h:43
~MedianFilter()
Definition: MedianFilter.h:38
static std::vector< T > filter(int size, const std::vector< T > &in)
Definition: MedianFilter.h:86
Definition: MedianFilter.h:26
void reset()
Definition: MedianFilter.h:81