GestureRecognitionToolkit  Version: 0.2.5
The Gesture Recognition Toolkit (GRT) is a cross-platform, open-source, c++ machine learning library for real-time gesture recognition.
MedianFilter.cpp
1 /*
2 GRT MIT License
3 Copyright (c) <2012> <Nicholas Gillian, Media Lab, MIT>
4 
5 Permission is hereby granted, free of charge, to any person obtaining a copy of this software
6 and associated documentation files (the "Software"), to deal in the Software without restriction,
7 including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
9 subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in all copies or substantial
12 portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
18 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 */
20 
21 #define GRT_DLL_EXPORTS
22 #include "MedianFilter.h"
23 
24 GRT_BEGIN_NAMESPACE
25 
26 //Define the string that will be used to identify the object
27 const std::string MedianFilter::id = "MedianFilter";
28 std::string MedianFilter::getId() { return MedianFilter::id; }
29 
30 //Register the MedianFilter module with the PreProcessing base class
32 
34 {
35  init(filterSize,numDimensions);
36 }
37 
39 {
40  //Zero this instance
41  this->filterSize = 0;
42  this->inputSampleCounter = 0;
43 
44  //Copy the settings from the rhs instance
45  *this = rhs;
46 }
47 
49 
50 }
51 
53  if(this!=&rhs){
54  //Clear this instance
55  this->filterSize = 0;
56  this->inputSampleCounter = 0;
57  this->dataBuffer.clear();
58 
59  //Copy from the rhs instance
60  if( rhs.initialized ){
61  this->init( rhs.filterSize, rhs.numInputDimensions );
62  this->dataBuffer = rhs.dataBuffer;
63  }
64 
65  //Copy the preprocessing base variables
67  }
68  return *this;
69 }
70 
71 bool MedianFilter::deepCopyFrom(const PreProcessing *preProcessing){
72 
73  if( preProcessing == NULL ) return false;
74 
75  if( this->getId() == preProcessing->getId() ){
76 
77  //Call the equals operator
78  *this = *dynamic_cast<const MedianFilter*>(preProcessing);
79 
80  return true;
81  }
82 
83  errorLog << "deepCopyFrom(const PreProcessing *preProcessing) - PreProcessing Types Do Not Match!" << std::endl;
84 
85  return false;
86 }
87 
88 
89 bool MedianFilter::process(const VectorFloat &inputVector){
90 
91  if( !initialized ){
92  errorLog << "process(const VectorFloat &inputVector) - The filter has not been initialized!" << std::endl;
93  return false;
94  }
95 
96  if( inputVector.size() != numInputDimensions ){
97  errorLog << "process(const VectorFloat &inputVector) - The size of the inputVector (" << inputVector.size() << ") does not match that of the filter (" << numInputDimensions << ")!" << std::endl;
98  return false;
99  }
100 
101  filter( inputVector );
102 
103  if( processedData.size() == numOutputDimensions ) return true;
104 
105  return false;
106 }
107 
109  if( initialized ) return init(filterSize,numInputDimensions);
110  return false;
111 }
112 
113 bool MedianFilter::save( std::fstream &file ) const{
114 
115  if( !file.is_open() ){
116  errorLog << "save(fstream &file) - The file is not open!" << std::endl;
117  return false;
118  }
119 
120  file << "GRT_MEDIAN_FILTER_FILE_V1.0" << std::endl;
121 
122  file << "NumInputDimensions: " << numInputDimensions << std::endl;
123  file << "NumOutputDimensions: " << numOutputDimensions << std::endl;
124  file << "FilterSize: " << filterSize << std::endl;
125 
126  return true;
127 }
128 
129 bool MedianFilter::load( std::fstream &file ){
130 
131  if( !file.is_open() ){
132  errorLog << "load(fstream &file) - The file is not open!" << std::endl;
133  return false;
134  }
135 
136  std::string word;
137 
138  //Load the header
139  file >> word;
140 
141  if( word != "GRT_MEDIAN_FILTER_FILE_V1.0" ){
142  errorLog << "load(fstream &file) - Invalid file format!" << std::endl;
143  return false;
144  }
145 
146  //Load the number of input dimensions
147  file >> word;
148  if( word != "NumInputDimensions:" ){
149  errorLog << "load(fstream &file) - Failed to read NumInputDimensions header!" << std::endl;
150  return false;
151  }
152  file >> numInputDimensions;
153 
154  //Load the number of output dimensions
155  file >> word;
156  if( word != "NumOutputDimensions:" ){
157  errorLog << "load(fstream &file) - Failed to read NumOutputDimensions header!" << std::endl;
158  return false;
159  }
160  file >> numOutputDimensions;
161 
162  //Load the filter factor
163  file >> word;
164  if( word != "FilterSize:" ){
165  errorLog << "load(fstream &file) - Failed to read FilterSize header!" << std::endl;
166  return false;
167  }
168  file >> filterSize;
169 
170  //Init the filter module to ensure everything is initialized correctly
171  return init(filterSize,numInputDimensions);
172 }
173 
174 bool MedianFilter::init(const UINT filterSize,const UINT numDimensions){
175 
176  //Cleanup the old memory
177  initialized = false;
178  inputSampleCounter = 0;
179 
180  if( filterSize == 0 ){
181  errorLog << "init(UINT filterSize,UINT numDimensions) - Filter size can not be zero!" << std::endl;
182  return false;
183  }
184 
185  if( numDimensions == 0 ){
186  errorLog << "init(UINT filterSize,UINT numDimensions) - The number of dimensions must be greater than zero!" << std::endl;
187  return false;
188  }
189 
190  //Resize the filter
191  this->filterSize = filterSize;
192  this->numInputDimensions = numDimensions;
193  this->numOutputDimensions = numDimensions;
194  processedData.clear();
195  processedData.resize(numDimensions,0);
196  initialized = dataBuffer.resize( filterSize, VectorFloat(numInputDimensions,0) );
197 
198  if( !initialized ){
199  errorLog << "init(UINT filterSize,UINT numDimensions) - Failed to resize dataBuffer!" << std::endl;
200  }
201 
202  return initialized;
203 }
204 
205 Float MedianFilter::filter(const Float x){
206 
207  VectorFloat y = filter(VectorFloat(1,x));
208 
209  if( y.size() == 0 ) return 0;
210  return y[0];
211 }
212 
214 
215  //If the filter has not been initialised then return 0, otherwise filter x and return y
216  if( !initialized ){
217  errorLog << "filter(const VectorFloat &x) - The filter has not been initialized!" << std::endl;
218  return VectorFloat();
219  }
220 
221  if( x.getSize() != numInputDimensions ){
222  errorLog << "filter(const VectorFloat &x) - The size of the input Vector (" << x.getSize() << ") does not match that of the number of dimensions of the filter (" << numInputDimensions << ")!" << std::endl;
223  return VectorFloat();
224  }
225 
227 
228  //Add the new value to the buffer
229  dataBuffer.push_back( x );
230 
231  //Compute the median value for each dimension
233  for(unsigned int j=0; j<numInputDimensions; j++){
234  for(unsigned int i=0; i<inputSampleCounter; i++) {
235  tmp[i] = dataBuffer[i][j];
236  }
237  std::sort(tmp.begin(),tmp.end());
238 
239  //Get the median value
240  unsigned int medianIndex = (inputSampleCounter/2);
241  processedData[j] = tmp[ medianIndex ];
242  }
243 
244  return processedData;
245 }
246 
247 UINT MedianFilter::getFilterSize() const { return filterSize; }
248 
249 VectorFloat MedianFilter::getFilteredData() const { return processedData; }
250 
252 
253  if( !initialized ){
254  return Vector< VectorFloat >();
255  }
256 
257  Vector< VectorFloat > data(numInputDimensions,VectorFloat(inputSampleCounter));
258  for(unsigned int j=0; j<numInputDimensions; j++){
259  for(unsigned int i=0; i<inputSampleCounter; i++){
260  data[j][i] = dataBuffer[i][j];
261  }
262  }
263  return data;
264 }
265 
266 GRT_END_NAMESPACE
bool push_back(const T &value)
Vector< VectorFloat > getDataBuffer() const
std::string getId() const
Definition: GRTBase.cpp:85
virtual bool load(std::fstream &file)
VectorFloat getFilteredData() const
MedianFilter & operator=(const MedianFilter &rhs)
virtual bool reset()
virtual bool process(const VectorFloat &inputVector)
Float filter(const Float x)
CircularBuffer< VectorFloat > dataBuffer
A buffer to store the previous N values, N = filterSize.
Definition: MedianFilter.h:178
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
UINT getSize() const
Definition: Vector.h:201
The MedianFilter implements a simple median filter: https://en.wikipedia.org/wiki/Median_filter.
Definition: MedianFilter.h:38
UINT filterSize
The size of the filter.
Definition: MedianFilter.h:176
virtual ~MedianFilter()
static std::string getId()
UINT inputSampleCounter
A counter to keep track of the number of input samples.
Definition: MedianFilter.h:177
virtual bool save(std::fstream &file) const
UINT getFilterSize() const
MedianFilter(const UINT filterSize=5, const UINT numDimensions=1)
bool copyBaseVariables(const PreProcessing *preProcessingModule)
virtual bool deepCopyFrom(const PreProcessing *preProcessing)
bool resize(const unsigned int newBufferSize)