annotate src/MedianFilter.h @ 117:aef4b62069ba adaptive_diagonals

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