GestureRecognitionToolkit  Version: 0.1.0
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 #include "MedianFilter.h"
22 
23 GRT_BEGIN_NAMESPACE
24 
25 //Register the MedianFilter module with the PreProcessing base class
26 RegisterPreProcessingModule< MedianFilter > MedianFilter::registerModule("MedianFilter");
27 
28 MedianFilter::MedianFilter(UINT filterSize,UINT numDimensions){
29 
30  classType = "MedianFilter";
31  preProcessingType = classType;
32  debugLog.setProceedingText("[DEBUG MedianFilter]");
33  errorLog.setProceedingText("[ERROR MedianFilter]");
34  warningLog.setProceedingText("[WARNING MedianFilter]");
35  init(filterSize,numDimensions);
36 }
37 
39 
40  classType = "MedianFilter";
41  preProcessingType = classType;
42  debugLog.setProceedingText("[DEBUG MedianFilter]");
43  errorLog.setProceedingText("[ERROR MedianFilter]");
44  warningLog.setProceedingText("[WARNING MedianFilter]");
45 
46  //Zero this instance
47  this->filterSize = 0;
48  this->inputSampleCounter = 0;
49 
50  //Copy the settings from the rhs instance
51  *this = rhs;
52 }
53 
55 
56 }
57 
59  if(this!=&rhs){
60  //Clear this instance
61  this->filterSize = 0;
62  this->inputSampleCounter = 0;
63  this->dataBuffer.clear();
64 
65  //Copy from the rhs instance
66  if( rhs.initialized ){
67  this->init( rhs.filterSize, rhs.numInputDimensions );
68  this->dataBuffer = rhs.dataBuffer;
69  }
70 
71  //Copy the preprocessing base variables
73  }
74  return *this;
75 }
76 
77 bool MedianFilter::deepCopyFrom(const PreProcessing *preProcessing){
78 
79  if( preProcessing == NULL ) return false;
80 
81  if( this->getPreProcessingType() == preProcessing->getPreProcessingType() ){
82 
83  //Call the equals operator
84  *this = *(MedianFilter*)preProcessing;
85 
86  return true;
87  }
88 
89  errorLog << "clone(const PreProcessing *preProcessing) - PreProcessing Types Do Not Match!" << std::endl;
90 
91  return false;
92 }
93 
94 
95 bool MedianFilter::process(const VectorFloat &inputVector){
96 
97  if( !initialized ){
98  errorLog << "process(const VectorFloat &inputVector) - The filter has not been initialized!" << std::endl;
99  return false;
100  }
101 
102  if( inputVector.size() != numInputDimensions ){
103  errorLog << "process(const VectorFloat &inputVector) - The size of the inputVector (" << inputVector.size() << ") does not match that of the filter (" << numInputDimensions << ")!" << std::endl;
104  return false;
105  }
106 
107  filter( inputVector );
108 
109  if( processedData.size() == numOutputDimensions ) return true;
110 
111  return false;
112 }
113 
115  if( initialized ) return init(filterSize,numInputDimensions);
116  return false;
117 }
118 
119 bool MedianFilter::saveModelToFile( std::string filename ) const{
120 
121  if( !initialized ){
122  errorLog << "saveModelToFile(string filename) - The MedianFilter has not been initialized" << std::endl;
123  return false;
124  }
125 
126  std::fstream file;
127  file.open(filename.c_str(), std::ios::out);
128 
129  if( !saveModelToFile( file ) ){
130  file.close();
131  return false;
132  }
133 
134  file.close();
135 
136  return true;
137 }
138 
139 bool MedianFilter::saveModelToFile( std::fstream &file ) const{
140 
141  if( !file.is_open() ){
142  errorLog << "saveModelToFile(fstream &file) - The file is not open!" << std::endl;
143  return false;
144  }
145 
146  file << "GRT_MEDIAN_FILTER_FILE_V1.0" << std::endl;
147 
148  file << "NumInputDimensions: " << numInputDimensions << std::endl;
149  file << "NumOutputDimensions: " << numOutputDimensions << std::endl;
150  file << "FilterSize: " << filterSize << std::endl;
151 
152  return true;
153 }
154 
155 bool MedianFilter::loadModelFromFile( std::string filename ){
156 
157  std::fstream file;
158  file.open(filename.c_str(), std::ios::in);
159 
160  if( !loadModelFromFile( file ) ){
161  file.close();
162  initialized = false;
163  return false;
164  }
165 
166  file.close();
167 
168  return true;
169 }
170 
171 bool MedianFilter::loadModelFromFile( std::fstream &file ){
172 
173  if( !file.is_open() ){
174  errorLog << "loadModelFromFile(fstream &file) - The file is not open!" << std::endl;
175  return false;
176  }
177 
178  std::string word;
179 
180  //Load the header
181  file >> word;
182 
183  if( word != "GRT_MEDIAN_FILTER_FILE_V1.0" ){
184  errorLog << "loadModelFromFile(fstream &file) - Invalid file format!" << std::endl;
185  return false;
186  }
187 
188  //Load the number of input dimensions
189  file >> word;
190  if( word != "NumInputDimensions:" ){
191  errorLog << "loadModelFromFile(fstream &file) - Failed to read NumInputDimensions header!" << std::endl;
192  return false;
193  }
194  file >> numInputDimensions;
195 
196  //Load the number of output dimensions
197  file >> word;
198  if( word != "NumOutputDimensions:" ){
199  errorLog << "loadModelFromFile(fstream &file) - Failed to read NumOutputDimensions header!" << std::endl;
200  return false;
201  }
202  file >> numOutputDimensions;
203 
204  //Load the filter factor
205  file >> word;
206  if( word != "FilterSize:" ){
207  errorLog << "loadModelFromFile(fstream &file) - Failed to read FilterSize header!" << std::endl;
208  return false;
209  }
210  file >> filterSize;
211 
212  //Init the filter module to ensure everything is initialized correctly
213  return init(filterSize,numInputDimensions);
214 }
215 
216 bool MedianFilter::init(UINT filterSize,UINT numDimensions){
217 
218  //Cleanup the old memory
219  initialized = false;
220  inputSampleCounter = 0;
221 
222  if( filterSize == 0 ){
223  errorLog << "init(UINT filterSize,UINT numDimensions) - Filter size can not be zero!" << std::endl;
224  return false;
225  }
226 
227  if( numDimensions == 0 ){
228  errorLog << "init(UINT filterSize,UINT numDimensions) - The number of dimensions must be greater than zero!" << std::endl;
229  return false;
230  }
231 
232  //Resize the filter
233  this->filterSize = filterSize;
234  this->numInputDimensions = numDimensions;
235  this->numOutputDimensions = numDimensions;
236  processedData.clear();
237  processedData.resize(numDimensions,0);
238  initialized = dataBuffer.resize( filterSize, VectorFloat(numInputDimensions,0) );
239 
240  if( !initialized ){
241  errorLog << "init(UINT filterSize,UINT numDimensions) - Failed to resize dataBuffer!" << std::endl;
242  }
243 
244  return initialized;
245 }
246 
247 Float MedianFilter::filter(const Float x){
248 
249  VectorFloat y = filter(VectorFloat(1,x));
250 
251  if( y.size() == 0 ) return 0;
252  return y[0];
253 }
254 
256 
257  //If the filter has not been initialised then return 0, otherwise filter x and return y
258  if( !initialized ){
259  errorLog << "filter(const VectorFloat &x) - The filter has not been initialized!" << std::endl;
260  return VectorFloat();
261  }
262 
263  if( x.getSize() != numInputDimensions ){
264  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;
265  return VectorFloat();
266  }
267 
269 
270  //Add the new value to the buffer
271  dataBuffer.push_back( x );
272 
273  //Compute the median value for each dimension
275  for(unsigned int j=0; j<numInputDimensions; j++){
276  for(unsigned int i=0; i<inputSampleCounter; i++) {
277  tmp[i] = dataBuffer[i][j];
278  }
279  std::sort(tmp.begin(),tmp.end());
280 
281  //Get the median value
282  unsigned int medianIndex = (inputSampleCounter/2);
283  processedData[j] = tmp[ medianIndex ];
284  }
285 
286  return processedData;
287 }
288 
290 
291  if( !initialized ){
292  return Vector< VectorFloat >();
293  }
294 
295  Vector< VectorFloat > data(numInputDimensions,VectorFloat(inputSampleCounter));
296  for(unsigned int j=0; j<numInputDimensions; j++){
297  for(unsigned int i=0; i<inputSampleCounter; i++){
298  data[j][i] = dataBuffer[i][j];
299  }
300  }
301  return data;
302 }
303 
304 GRT_END_NAMESPACE
305 
bool push_back(const T &value)
Vector< VectorFloat > getDataBuffer() 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:185
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
unsigned int getSize() const
Definition: Vector.h:193
UINT filterSize
The size of the filter.
Definition: MedianFilter.h:183
The MedianFilter implements a simple median filter.
virtual ~MedianFilter()
UINT inputSampleCounter
A counter to keep track of the number of input samples.
Definition: MedianFilter.h:184
std::string getPreProcessingType() const
virtual bool saveModelToFile(std::string filename) const
bool copyBaseVariables(const PreProcessing *preProcessingModule)
MedianFilter(UINT filterSize=5, UINT numDimensions=1)
virtual bool deepCopyFrom(const PreProcessing *preProcessing)
virtual bool loadModelFromFile(std::string filename)
bool resize(const unsigned int newBufferSize)