GestureRecognitionToolkit  Version: 1.0 Revision: 04-03-15
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 namespace GRT{
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!" << endl;
90 
91  return false;
92 }
93 
94 
95 bool MedianFilter::process(const VectorDouble &inputVector){
96 
97  if( !initialized ){
98  errorLog << "process(const VectorDouble &inputVector) - The filter has not been initialized!" << endl;
99  return false;
100  }
101 
102  if( inputVector.size() != numInputDimensions ){
103  errorLog << "process(const VectorDouble &inputVector) - The size of the inputVector (" << inputVector.size() << ") does not match that of the filter (" << numInputDimensions << ")!" << 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(string filename) const{
120 
121  if( !initialized ){
122  errorLog << "saveModelToFile(string filename) - The MedianFilter has not been initialized" << 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(fstream &file) const{
140 
141  if( !file.is_open() ){
142  errorLog << "saveModelToFile(fstream &file) - The file is not open!" << endl;
143  return false;
144  }
145 
146  file << "GRT_MEDIAN_FILTER_FILE_V1.0" << endl;
147 
148  file << "NumInputDimensions: " << numInputDimensions << endl;
149  file << "NumOutputDimensions: " << numOutputDimensions << endl;
150  file << "FilterSize: " << filterSize << endl;
151 
152  return true;
153 }
154 
155 bool MedianFilter::loadModelFromFile(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 
172 
173  if( !file.is_open() ){
174  errorLog << "loadModelFromFile(fstream &file) - The file is not open!" << endl;
175  return false;
176  }
177 
178  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!" << 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!" << 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!" << 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!" << 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!" << 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!" << 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, VectorDouble(numInputDimensions,0) );
239 
240  if( !initialized ){
241  errorLog << "init(UINT filterSize,UINT numDimensions) - Failed to resize dataBuffer!" << endl;
242  }
243 
244  return initialized;
245 }
246 
247 double MedianFilter::filter(const double x){
248 
249  VectorDouble y = filter(VectorDouble(1,x));
250 
251  if( y.size() == 0 ) return 0;
252  return y[0];
253 }
254 
255 VectorDouble MedianFilter::filter(const VectorDouble &x){
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 VectorDouble &x) - The filter has not been initialized!" << endl;
260  return VectorDouble();
261  }
262 
263  if( x.size() != numInputDimensions ){
264  errorLog << "filter(const VectorDouble &x) - The size of the input vector (" << x.size() << ") does not match that of the number of dimensions of the filter (" << numInputDimensions << ")!" << endl;
265  return VectorDouble();
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
274  vector< double > tmp( inputSampleCounter );
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 
289 vector< VectorDouble > MedianFilter::getDataBuffer() const {
290 
291  if( !initialized ){
292  return vector< VectorDouble >();
293  }
294 
295  vector< VectorDouble > data(numInputDimensions,VectorDouble(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 }//End of namespace GRT
virtual bool deepCopyFrom(const PreProcessing *preProcessing)
MedianFilter & operator=(const MedianFilter &rhs)
Definition: AdaBoost.cpp:25
vector< VectorDouble > getDataBuffer() const
MedianFilter(UINT filterSize=5, UINT numDimensions=1)
UINT filterSize
The size of the filter.
Definition: MedianFilter.h:183
CircularBuffer< VectorDouble > dataBuffer
A buffer to store the previous N values, N = filterSize.
Definition: MedianFilter.h:185
The MedianFilter implements a simple median filter.
string getPreProcessingType() const
bool push_back(const T &value)
double filter(const double x)
bool resize(const unsigned int newBufferSize)
bool copyBaseVariables(const PreProcessing *preProcessingModule)
virtual bool reset()
virtual ~MedianFilter()
UINT inputSampleCounter
A counter to keep track of the number of input samples.
Definition: MedianFilter.h:184
virtual bool process(const VectorDouble &inputVector)
virtual bool saveModelToFile(string filename) const
virtual bool loadModelFromFile(string filename)