Mercurial > hg > qm-dsp
changeset 167:a82362d50144
Median filter standalone method, and tests
author | Chris Cannam |
---|---|
date | Mon, 07 Apr 2014 14:04:39 +0100 |
parents | 36bcde3c13d8 |
children | 2ca24037ae22 |
files | maths/MedianFilter.h tests/TestMedianFilter.cpp |
diffstat | 2 files changed, 95 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/maths/MedianFilter.h Mon Apr 07 13:43:48 2014 +0100 +++ b/maths/MedianFilter.h Mon Apr 07 14:04:39 2014 +0100 @@ -20,6 +20,7 @@ #include <cassert> #include <cmath> #include <iostream> +#include <vector> template <typename T> class MedianFilter @@ -70,6 +71,21 @@ for (int i = 0; i < m_size; ++i) m_sorted[i] = 0; } + static std::vector<T> filter(int size, const std::vector<T> &in) { + std::vector<T> out; + MedianFilter<T> f(size); + for (int i = 0; i < int(in.size()); ++i) { + f.push(in[i]); + T median = f.get(); + if (i >= size/2) out.push_back(median); + } + while (out.size() < in.size()) { + f.push(T()); + out.push_back(f.get()); + } + return out; + } + private: const int m_size; T *const m_frame;
--- a/tests/TestMedianFilter.cpp Mon Apr 07 13:43:48 2014 +0100 +++ b/tests/TestMedianFilter.cpp Mon Apr 07 14:04:39 2014 +0100 @@ -92,6 +92,85 @@ BOOST_CHECK_EQUAL(f.get(), 7); } +BOOST_AUTO_TEST_CASE(oddStandalone) +{ + // The standalone (static filter() method) function is intended to + // match e.g. MATLAB median filter, filtering a row at once + // assuming the values beyond its edges are zeroes. This basically + // just means it needs to compensate for the latency in the raw + // filter: + // + // Raw filter + // 1 3 5 7 -> 0 1 3 5 (N=3) + // (because at each step only the values up to that step are + // available) + // + // Standalone function: + // 1 3 5 7 -> 1 3 5 5 (N=3) + + std::vector<double> in; + in.push_back(1); + in.push_back(3); + in.push_back(5); + in.push_back(7); + + std::vector<double> out = MedianFilter<double>::filter(3, in); + BOOST_CHECK_EQUAL(out[0], 1); + BOOST_CHECK_EQUAL(out[1], 3); + BOOST_CHECK_EQUAL(out[2], 5); + BOOST_CHECK_EQUAL(out[3], 5); +} + +BOOST_AUTO_TEST_CASE(evenStandalone) +{ + // See above. But note that the even length does not match the + // MATLAB because it doesn't halve the middle, as MATLAB does + + std::vector<double> in; + in.push_back(1); + in.push_back(3); + in.push_back(5); + in.push_back(7); + + std::vector<double> out = MedianFilter<double>::filter(4, in); + BOOST_CHECK_EQUAL(out[0], 3); + BOOST_CHECK_EQUAL(out[1], 5); + BOOST_CHECK_EQUAL(out[2], 5); + BOOST_CHECK_EQUAL(out[3], 5); +} + +BOOST_AUTO_TEST_CASE(standaloneEmpty) +{ + std::vector<double> in; + std::vector<double> out1 = MedianFilter<double>::filter(3, in); + BOOST_CHECK_EQUAL(out1.size(), 0); + std::vector<double> out2 = MedianFilter<double>::filter(4, in); + BOOST_CHECK_EQUAL(out2.size(), 0); +} + +BOOST_AUTO_TEST_CASE(types) +{ + MedianFilter<double> dfilt(3); + dfilt.push(1.2); + BOOST_CHECK_EQUAL(dfilt.get(), 0.0); + dfilt.push(2.4); + BOOST_CHECK_EQUAL(dfilt.get(), 1.2); + dfilt.push(1e-6); + BOOST_CHECK_EQUAL(dfilt.get(), 1.2); + dfilt.push(1e6); + BOOST_CHECK_EQUAL(dfilt.get(), 2.4); + + MedianFilter<int> ifilt(3); + ifilt.push(1); + BOOST_CHECK_EQUAL(ifilt.get(), 0); + ifilt.push(2); + BOOST_CHECK_EQUAL(ifilt.get(), 1); + ifilt.push(0); + BOOST_CHECK_EQUAL(ifilt.get(), 1); + ifilt.push(1000); + BOOST_CHECK_EQUAL(ifilt.get(), 2); +} + BOOST_AUTO_TEST_SUITE_END()