annotate tests/TestMedianFilter.cpp @ 209:ccd2019190bf msvc

Some MSVC fixes, including (temporarily, probably) renaming the FFT source file to avoid getting it mixed up with the Vamp SDK one in our object dir
author Chris Cannam
date Thu, 01 Feb 2018 16:34:08 +0000
parents 5ec47007b873
children 2de6184b2ce0
rev   line source
Chris@166 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@166 2
Chris@166 3 #include "maths/MedianFilter.h"
Chris@166 4
Chris@166 5 #include <cmath>
Chris@182 6 #include <cstdlib>
Chris@166 7
Chris@166 8 #define BOOST_TEST_DYN_LINK
Chris@166 9 #define BOOST_TEST_MAIN
Chris@166 10
Chris@166 11 #include <boost/test/unit_test.hpp>
Chris@166 12
Chris@166 13 BOOST_AUTO_TEST_SUITE(TestMedianFilter)
Chris@166 14
Chris@166 15 BOOST_AUTO_TEST_CASE(odd)
Chris@166 16 {
Chris@166 17 // A median filter of size N always retains a pool of N elements,
Chris@166 18 // which start out all-zero. So the output median will remain zero
Chris@166 19 // until N/2 elements have been pushed.
Chris@166 20 MedianFilter<double> f(3);
Chris@166 21 f.push(1); // 0 0 1
Chris@166 22 BOOST_CHECK_EQUAL(f.get(), 0);
Chris@166 23 BOOST_CHECK_EQUAL(f.get(), 0);
Chris@166 24 f.push(-3); // 0 1 -3
Chris@166 25 BOOST_CHECK_EQUAL(f.get(), 0);
Chris@166 26 f.push(5); // 1 -3 5
Chris@166 27 BOOST_CHECK_EQUAL(f.get(), 1);
Chris@166 28 f.push(7); // -3 5 7
Chris@166 29 BOOST_CHECK_EQUAL(f.get(), 5);
Chris@166 30 BOOST_CHECK_EQUAL(f.get(), 5);
Chris@166 31 f.push(3); // 5 7 3
Chris@166 32 BOOST_CHECK_EQUAL(f.get(), 5);
Chris@166 33 f.push(3); // 7 3 3
Chris@166 34 BOOST_CHECK_EQUAL(f.get(), 3);
Chris@166 35 }
Chris@166 36
Chris@166 37 BOOST_AUTO_TEST_CASE(even)
Chris@166 38 {
Chris@166 39 // Our median does not halve the difference (should it??), it just
Chris@166 40 // returns the next element from the input set
Chris@166 41 MedianFilter<double> f(4);
Chris@166 42 f.push(1); // 0 0 0 1
Chris@166 43 BOOST_CHECK_EQUAL(f.get(), 0);
Chris@166 44 BOOST_CHECK_EQUAL(f.get(), 0);
Chris@166 45 f.push(-3); // 0 0 1 -3
Chris@166 46 BOOST_CHECK_EQUAL(f.get(), 0);
Chris@166 47 f.push(5); // 0 1 -3 5
Chris@166 48 BOOST_CHECK_EQUAL(f.get(), 1);
Chris@166 49 f.push(7); // 1 -3 5 7
Chris@166 50 BOOST_CHECK_EQUAL(f.get(), 5);
Chris@166 51 BOOST_CHECK_EQUAL(f.get(), 5);
Chris@166 52 f.push(3); // -3 5 7 3
Chris@166 53 BOOST_CHECK_EQUAL(f.get(), 5);
Chris@166 54 f.push(3); // 5 7 3 3
Chris@166 55 BOOST_CHECK_EQUAL(f.get(), 5);
Chris@166 56 }
Chris@166 57
Chris@166 58 BOOST_AUTO_TEST_CASE(odd75)
Chris@166 59 {
Chris@166 60 MedianFilter<double> f(5, 75.f);
Chris@166 61 f.push(1); // 0 0 0 0 1
Chris@166 62 BOOST_CHECK_EQUAL(f.get(), 0);
Chris@166 63 BOOST_CHECK_EQUAL(f.get(), 0);
Chris@166 64 f.push(-3); // 0 0 0 1 -3
Chris@166 65 BOOST_CHECK_EQUAL(f.get(), 0);
Chris@166 66 f.push(5); // 0 0 1 -3 5
Chris@166 67 BOOST_CHECK_EQUAL(f.get(), 1);
Chris@166 68 f.push(7); // 0 1 -3 5 7
Chris@166 69 BOOST_CHECK_EQUAL(f.get(), 5);
Chris@166 70 BOOST_CHECK_EQUAL(f.get(), 5);
Chris@166 71 f.push(3); // 0 -3 5 7 3
Chris@166 72 BOOST_CHECK_EQUAL(f.get(), 5);
Chris@166 73 f.push(3); // 0 5 7 3 3
Chris@166 74 BOOST_CHECK_EQUAL(f.get(), 5);
Chris@166 75 }
Chris@166 76
Chris@166 77 BOOST_AUTO_TEST_CASE(even75)
Chris@166 78 {
Chris@166 79 MedianFilter<double> f(4, 75.f);
Chris@166 80 f.push(1); // 0 0 0 1
Chris@166 81 BOOST_CHECK_EQUAL(f.get(), 1);
Chris@166 82 BOOST_CHECK_EQUAL(f.get(), 1);
Chris@166 83 f.push(-3); // 0 0 1 -3
Chris@166 84 BOOST_CHECK_EQUAL(f.get(), 1);
Chris@166 85 f.push(5); // 0 1 -3 5
Chris@166 86 BOOST_CHECK_EQUAL(f.get(), 5);
Chris@166 87 f.push(7); // 1 -3 5 7
Chris@166 88 BOOST_CHECK_EQUAL(f.get(), 7);
Chris@166 89 BOOST_CHECK_EQUAL(f.get(), 7);
Chris@166 90 f.push(3); // -3 5 7 3
Chris@166 91 BOOST_CHECK_EQUAL(f.get(), 7);
Chris@166 92 f.push(3); // 5 7 3 3
Chris@166 93 BOOST_CHECK_EQUAL(f.get(), 7);
Chris@166 94 }
Chris@166 95
Chris@167 96 BOOST_AUTO_TEST_CASE(oddStandalone)
Chris@167 97 {
Chris@167 98 // The standalone (static filter() method) function is intended to
Chris@167 99 // match e.g. MATLAB median filter, filtering a row at once
Chris@167 100 // assuming the values beyond its edges are zeroes. This basically
Chris@167 101 // just means it needs to compensate for the latency in the raw
Chris@167 102 // filter:
Chris@167 103 //
Chris@167 104 // Raw filter
Chris@167 105 // 1 3 5 7 -> 0 1 3 5 (N=3)
Chris@167 106 // (because at each step only the values up to that step are
Chris@167 107 // available)
Chris@167 108 //
Chris@167 109 // Standalone function:
Chris@167 110 // 1 3 5 7 -> 1 3 5 5 (N=3)
Chris@167 111
Chris@167 112 std::vector<double> in;
Chris@167 113 in.push_back(1);
Chris@167 114 in.push_back(3);
Chris@167 115 in.push_back(5);
Chris@167 116 in.push_back(7);
Chris@167 117
Chris@167 118 std::vector<double> out = MedianFilter<double>::filter(3, in);
Chris@167 119 BOOST_CHECK_EQUAL(out[0], 1);
Chris@167 120 BOOST_CHECK_EQUAL(out[1], 3);
Chris@167 121 BOOST_CHECK_EQUAL(out[2], 5);
Chris@167 122 BOOST_CHECK_EQUAL(out[3], 5);
Chris@167 123 }
Chris@167 124
Chris@167 125 BOOST_AUTO_TEST_CASE(evenStandalone)
Chris@167 126 {
Chris@167 127 // See above. But note that the even length does not match the
Chris@167 128 // MATLAB because it doesn't halve the middle, as MATLAB does
Chris@167 129
Chris@167 130 std::vector<double> in;
Chris@167 131 in.push_back(1);
Chris@167 132 in.push_back(3);
Chris@167 133 in.push_back(5);
Chris@167 134 in.push_back(7);
Chris@167 135
Chris@167 136 std::vector<double> out = MedianFilter<double>::filter(4, in);
Chris@167 137 BOOST_CHECK_EQUAL(out[0], 3);
Chris@167 138 BOOST_CHECK_EQUAL(out[1], 5);
Chris@167 139 BOOST_CHECK_EQUAL(out[2], 5);
Chris@167 140 BOOST_CHECK_EQUAL(out[3], 5);
Chris@167 141 }
Chris@167 142
Chris@167 143 BOOST_AUTO_TEST_CASE(standaloneEmpty)
Chris@167 144 {
Chris@167 145 std::vector<double> in;
Chris@167 146 std::vector<double> out1 = MedianFilter<double>::filter(3, in);
Chris@167 147 BOOST_CHECK_EQUAL(out1.size(), 0);
Chris@167 148 std::vector<double> out2 = MedianFilter<double>::filter(4, in);
Chris@167 149 BOOST_CHECK_EQUAL(out2.size(), 0);
Chris@167 150 }
Chris@167 151
Chris@167 152 BOOST_AUTO_TEST_CASE(types)
Chris@167 153 {
Chris@167 154 MedianFilter<double> dfilt(3);
Chris@167 155 dfilt.push(1.2);
Chris@167 156 BOOST_CHECK_EQUAL(dfilt.get(), 0.0);
Chris@167 157 dfilt.push(2.4);
Chris@167 158 BOOST_CHECK_EQUAL(dfilt.get(), 1.2);
Chris@167 159 dfilt.push(1e-6);
Chris@167 160 BOOST_CHECK_EQUAL(dfilt.get(), 1.2);
Chris@167 161 dfilt.push(1e6);
Chris@167 162 BOOST_CHECK_EQUAL(dfilt.get(), 2.4);
Chris@167 163
Chris@167 164 MedianFilter<int> ifilt(3);
Chris@167 165 ifilt.push(1);
Chris@167 166 BOOST_CHECK_EQUAL(ifilt.get(), 0);
Chris@167 167 ifilt.push(2);
Chris@167 168 BOOST_CHECK_EQUAL(ifilt.get(), 1);
Chris@167 169 ifilt.push(0);
Chris@167 170 BOOST_CHECK_EQUAL(ifilt.get(), 1);
Chris@167 171 ifilt.push(1000);
Chris@167 172 BOOST_CHECK_EQUAL(ifilt.get(), 2);
Chris@167 173 }
Chris@167 174
Chris@182 175 BOOST_AUTO_TEST_CASE(inf)
Chris@182 176 {
Chris@182 177 // Inf and -Inf should behave normally
Chris@182 178 double pinf = strtod("Inf", 0);
Chris@182 179 double ninf = strtod("-Inf", 0);
Chris@182 180 MedianFilter<double> dfilt(3);
Chris@182 181 dfilt.push(1.0);
Chris@182 182 dfilt.push(2.0);
Chris@182 183 dfilt.push(pinf);
Chris@182 184 BOOST_CHECK_EQUAL(dfilt.get(), 2.0);
Chris@182 185 dfilt.push(pinf);
Chris@182 186 BOOST_CHECK_EQUAL(dfilt.get(), pinf);
Chris@182 187 dfilt.push(pinf);
Chris@182 188 BOOST_CHECK_EQUAL(dfilt.get(), pinf);
Chris@182 189 dfilt.push(2.0);
Chris@182 190 BOOST_CHECK_EQUAL(dfilt.get(), pinf);
Chris@182 191 dfilt.push(1.0);
Chris@182 192 BOOST_CHECK_EQUAL(dfilt.get(), 2.0);
Chris@182 193 dfilt.push(ninf);
Chris@182 194 BOOST_CHECK_EQUAL(dfilt.get(), 1.0);
Chris@182 195 dfilt.push(pinf);
Chris@182 196 BOOST_CHECK_EQUAL(dfilt.get(), 1.0);
Chris@182 197 dfilt.push(ninf);
Chris@182 198 BOOST_CHECK_EQUAL(dfilt.get(), ninf);
Chris@182 199 }
Chris@182 200
Chris@182 201 BOOST_AUTO_TEST_CASE(nan)
Chris@182 202 {
Chris@182 203 // The filter should never accept a NaN, because it breaks sorting
Chris@182 204 // and comparison and that will break the filter. Instead it
Chris@182 205 // should insert 0.
Chris@182 206 double nan = strtod("NaN", 0);
Chris@182 207 MedianFilter<double> dfilt(3);
Chris@182 208 dfilt.push(1.0);
Chris@182 209 dfilt.push(2.0);
Chris@182 210 dfilt.push(nan);
Chris@182 211 BOOST_CHECK_EQUAL(dfilt.get(), 1.0);
Chris@182 212 dfilt.push(nan);
Chris@182 213 BOOST_CHECK_EQUAL(dfilt.get(), 0.0);
Chris@182 214 dfilt.push(-11.0);
Chris@182 215 BOOST_CHECK_EQUAL(dfilt.get(), 0.0);
Chris@182 216 dfilt.push(-1.0);
Chris@182 217 BOOST_CHECK_EQUAL(dfilt.get(), -1.0);
Chris@182 218 }
Chris@182 219
Chris@166 220 BOOST_AUTO_TEST_SUITE_END()
Chris@166 221
Chris@166 222