# HG changeset patch # User Chris Cannam # Date 1396875879 -3600 # Node ID a82362d501442e10c5b7583a64c57bc08e6e27da # Parent 36bcde3c13d8112fa7a51b19e37d638b8440ea76 Median filter standalone method, and tests diff -r 36bcde3c13d8 -r a82362d50144 maths/MedianFilter.h --- 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 #include #include +#include template class MedianFilter @@ -70,6 +71,21 @@ for (int i = 0; i < m_size; ++i) m_sorted[i] = 0; } + static std::vector filter(int size, const std::vector &in) { + std::vector out; + MedianFilter 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; diff -r 36bcde3c13d8 -r a82362d50144 tests/TestMedianFilter.cpp --- 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 in; + in.push_back(1); + in.push_back(3); + in.push_back(5); + in.push_back(7); + + std::vector out = MedianFilter::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 in; + in.push_back(1); + in.push_back(3); + in.push_back(5); + in.push_back(7); + + std::vector out = MedianFilter::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 in; + std::vector out1 = MedianFilter::filter(3, in); + BOOST_CHECK_EQUAL(out1.size(), 0); + std::vector out2 = MedianFilter::filter(4, in); + BOOST_CHECK_EQUAL(out2.size(), 0); +} + +BOOST_AUTO_TEST_CASE(types) +{ + MedianFilter 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 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()