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