GestureRecognitionToolkit  Version: 0.2.0
The Gesture Recognition Toolkit (GRT) is a cross-platform, open-source, c++ machine learning library for real-time gesture recognition.
ClassLabelTimeoutFilter.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
23 
24 GRT_BEGIN_NAMESPACE
25 
26 //Register the ClassLabelTimeoutFilter module with the PostProcessing base class
27 RegisterPostProcessingModule< ClassLabelTimeoutFilter > ClassLabelTimeoutFilter::registerModule("ClassLabelTimeoutFilter");
28 
29 ClassLabelTimeoutFilter::ClassLabelTimeoutFilter(unsigned long timeoutDuration,UINT filterMode){
30  classType = "ClassLabelTimeoutFilter";
31  postProcessingType = classType;
32  postProcessingInputMode = INPUT_MODE_PREDICTED_CLASS_LABEL;
33  postProcessingOutputMode = OUTPUT_MODE_PREDICTED_CLASS_LABEL;
34  debugLog.setProceedingText("[DEBUG ClassLabelTimeoutFilter]");
35  errorLog.setProceedingText("[ERROR ClassLabelTimeoutFilter]");
36  warningLog.setProceedingText("[WARNING ClassLabelTimeoutFilter]");
37  init(timeoutDuration,filterMode);
38 }
39 
41 
42  classType = "ClassLabelTimeoutFilter";
43  postProcessingType = classType;
44  postProcessingInputMode = INPUT_MODE_PREDICTED_CLASS_LABEL;
45  postProcessingOutputMode = OUTPUT_MODE_PREDICTED_CLASS_LABEL;
46  debugLog.setProceedingText("[DEBUG ClassLabelTimeoutFilter]");
47  errorLog.setProceedingText("[ERROR ClassLabelTimeoutFilter]");
48  warningLog.setProceedingText("[WARNING ClassLabelTimeoutFilter]");
49 
50  //Copy the classLabelTimeoutFilter values
51  this->filteredClassLabel = rhs.filteredClassLabel;
52  this->filterMode = rhs.filterMode;
53  this->timeoutDuration = rhs.timeoutDuration;
54  this->classLabelTimers = rhs.classLabelTimers;
55 
56  //Clone the post processing base variables
58 }
59 
61 
62 }
63 
65 
66  if( this != &rhs ){
67  //Copy the classLabelTimeoutFilter values
68  this->filteredClassLabel = rhs.filteredClassLabel;
69  this->filterMode = rhs.filterMode;
70  this->timeoutDuration = rhs.timeoutDuration;
71  this->classLabelTimers = rhs.classLabelTimers;
72 
73  //Clone the post processing base variables
75  }
76  return *this;
77 }
78 
80 
81  if( postProcessing == NULL ) return false;
82 
83  if( this->getPostProcessingType() == postProcessing->getPostProcessingType() ){
84 
85  ClassLabelTimeoutFilter *ptr = (ClassLabelTimeoutFilter*)postProcessing;
86 
87  //Clone the classLabelTimeoutFilter values
88  this->filteredClassLabel = ptr->filterMode;
89  this->filterMode = ptr->filterMode;
90  this->timeoutDuration = ptr->timeoutDuration;
91  this->classLabelTimers = ptr->classLabelTimers;
92 
93  //Clone the post processing base variables
94  return copyBaseVariables( postProcessing );
95  }
96  return false;
97 }
98 
100 
101 #ifdef GRT_SAFE_CHECKING
102  if( !initialized ){
103  errorLog << "process(const VectorDouble &inputVector) - Not initialized!" << std::endl;
104  return false;
105  }
106 
107  if( inputVector.getSize() != numInputDimensions ){
108  errorLog << "process(const VectorDouble &inputVector) - The size of the inputVector (" << inputVector.getSize() << ") does not match that of the filter (" << numInputDimensions << ")!" << std::endl;
109  return false;
110  }
111 #endif
112 
113  //Use only the first value (as that is the predicted class label)
114  processedData[0] = filter( (UINT)inputVector[0] );
115  return true;
116 }
117 
119  filteredClassLabel = 0;
120  classLabelTimers.clear();
121  processedData.clear();
122  processedData.resize(1,0);
123  return true;
124 }
125 
126 bool ClassLabelTimeoutFilter::init(unsigned long timeoutDuration,UINT filterMode){
127 
128  initialized = false;
129 
130  if( filterMode != ALL_CLASS_LABELS && filterMode != INDEPENDENT_CLASS_LABELS ){
131  errorLog << "init(double timeoutDuration,UINT filterMode) - Unkown filter mode!" << std::endl;
132  return false;
133  }
134 
135  this->timeoutDuration = timeoutDuration;
136  this->filterMode = filterMode;
137  numInputDimensions = 1;
138  numOutputDimensions = 1;
139  initialized = reset();
140  return true;
141 }
142 
143 UINT ClassLabelTimeoutFilter::filter(UINT predictedClassLabel){
144 
145  //If we get the NULL class and there are no active timers running then we do not need to do anything
146  if( predictedClassLabel == 0 && classLabelTimers.size() == 0 ){
147  filteredClassLabel = predictedClassLabel;
148  return filteredClassLabel;
149  }
150 
151  bool matchFound = false;
153 
154  switch( filterMode ){
155  case ALL_CLASS_LABELS:
156 
157  //Have we seen any class label yet, if not then just start the timer and return the current class label
158  if( classLabelTimers.size() == 0 ){
159  filteredClassLabel = predictedClassLabel;
160  classLabelTimers.push_back( ClassLabelAndTimer(predictedClassLabel,timeoutDuration) );
161  }else{
162  //Otherwise check to see if the timer has timed-out
163  if( classLabelTimers[0].timerReached() ){
164  //Clear the timer
165  classLabelTimers.clear();
166 
167  //Check if the current predictedClassLabel is a valid gesture, if so then recursively call this function
168  //to start a new filter
169  filteredClassLabel = 0;
170  if( predictedClassLabel ){
171  filteredClassLabel = filter( predictedClassLabel );
172  }
173 
174  }else filteredClassLabel = 0;
175  }
176 
177  break;
178  case INDEPENDENT_CLASS_LABELS:
179 
180  //Search the classLabelTimers buffer to find a matching class label
181  if( classLabelTimers.size() > 0 ){
182  iter = classLabelTimers.begin();
183 
184  while( iter != classLabelTimers.end() ){
185  if( iter->getClassLabel() == predictedClassLabel ){
186  //Check to see if the timer for this class has elapsed
187  if( iter->timerReached() ){
188  //Reset the timer for this label
189  iter->set(predictedClassLabel,timeoutDuration);
190 
191  //Signal that a match was found
192  matchFound = true;
193  filteredClassLabel = predictedClassLabel;
194  break;
195  }else filteredClassLabel = 0;
196 
197  //Update the iterator
198  iter++;
199  }else{
200  if( iter->timerReached() ){
201  //Erase the current timer from the buffer
202  iter = classLabelTimers.erase( iter );
203  }else iter++;
204  }
205  }
206 
207  }
208 
209  //If a match has not been found then create a new timer
210  if( !matchFound ){
211  classLabelTimers.push_back( ClassLabelAndTimer(predictedClassLabel,timeoutDuration) );
212  filteredClassLabel = predictedClassLabel;
213  }
214 
215  break;
216  }
217 
218  return filteredClassLabel;
219 }
220 
222 
223  for(UINT i=0; i<classLabelTimers.getSize(); i++){
224  if( classLabelTimers[i].timerReached() ){
225  return true;
226  }
227  }
228 
229  return false;
230 }
231 
232 bool ClassLabelTimeoutFilter::saveModelToFile( std::string filename ) const{
233 
234  if( !initialized ){
235  errorLog << "saveModelToFile(string filename) - The ClassLabelTimeoutFilter has not been initialized" << std::endl;
236  return false;
237  }
238 
239  std::fstream file;
240  file.open(filename.c_str(), std::ios::out);
241 
242  if( !saveModelToFile( file ) ){
243  file.close();
244  return false;
245  }
246 
247  file.close();
248 
249  return true;
250 }
251 
252 bool ClassLabelTimeoutFilter::saveModelToFile( std::fstream &file ) const{
253 
254  if( !file.is_open() ){
255  errorLog << "saveModelToFile(fstream &file) - The file is not open!" << std::endl;
256  return false;
257  }
258 
259  file << "GRT_CLASS_LABEL_TIMEOUT_FILTER_FILE_V1.0" << std::endl;
260  file << "NumInputDimensions: " << numInputDimensions << std::endl;
261  file << "NumOutputDimensions: " << numOutputDimensions << std::endl;
262  file << "FilterMode: " << filterMode << std::endl;
263  file << "TimeoutDuration: " << timeoutDuration << std::endl;
264 
265  return true;
266 }
267 
268 bool ClassLabelTimeoutFilter::loadModelFromFile( std::string filename ){
269 
270  std::fstream file;
271  file.open(filename.c_str(), std::ios::in);
272 
273  if( !loadModelFromFile( file ) ){
274  file.close();
275  initialized = false;
276  return false;
277  }
278 
279  file.close();
280 
281  return true;
282 }
283 
285 
286  if( !file.is_open() ){
287  errorLog << "loadModelFromFile(fstream &file) - The file is not open!" << std::endl;
288  return false;
289  }
290 
291  std::string word;
292 
293  //Load the header
294  file >> word;
295 
296  if( word != "GRT_CLASS_LABEL_TIMEOUT_FILTER_FILE_V1.0" ){
297  errorLog << "loadModelFromFile(fstream &file) - Invalid file format!" << std::endl;
298  return false;
299  }
300 
301  file >> word;
302  if( word != "NumInputDimensions:" ){
303  errorLog << "loadModelFromFile(fstream &file) - Failed to read NumInputDimensions header!" << std::endl;
304  return false;
305  }
306  file >> numInputDimensions;
307 
308  //Load the number of output dimensions
309  file >> word;
310  if( word != "NumOutputDimensions:" ){
311  errorLog << "loadModelFromFile(fstream &file) - Failed to read NumOutputDimensions header!" << std::endl;
312  return false;
313  }
314  file >> numOutputDimensions;
315 
316  //Load the filterMode
317  file >> word;
318  if( word != "FilterMode:" ){
319  errorLog << "loadModelFromFile(fstream &file) - Failed to read FilterMode header!" << std::endl;
320  return false;
321  }
322  file >> filterMode;
323 
324  file >> word;
325  if( word != "TimeoutDuration:" ){
326  errorLog << "loadModelFromFile(fstream &file) - Failed to read TimeoutDuration header!" << std::endl;
327  return false;
328  }
329  file >> timeoutDuration;
330 
331  //Init the classLabelTimeoutFilter module to ensure everything is initialized correctly
332  return init(timeoutDuration,filterMode);
333 }
334 
335 bool ClassLabelTimeoutFilter::setTimeoutDuration(unsigned long timeoutDuration){
336  this->timeoutDuration = timeoutDuration;
337  if( initialized ){
338  return reset();
339  }
340  return true;
341 }
342 
344  if( filterMode != ALL_CLASS_LABELS && filterMode != INDEPENDENT_CLASS_LABELS ) return false;
345  this->filterMode = filterMode;
346  if( initialized ){
347  return reset();
348  }
349  return true;
350 }
351 
352 GRT_END_NAMESPACE
ClassLabelTimeoutFilter(unsigned long timeoutDuration=1000, UINT filterMode=ALL_CLASS_LABELS)
The Class Label Timeout Filter is a useful post-processing module which debounces a gesture (i...
virtual bool process(const VectorDouble &inputVector)
UINT filter(UINT predictedClassLabel)
std::string getPostProcessingType() const
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
UINT getSize() const
Definition: Vector.h:191
bool copyBaseVariables(const PostProcessing *postProcessingModule)
bool setTimeoutDuration(unsigned long timeoutDuration)
virtual bool loadModelFromFile(std::string filename)
bool init()
ClassLabelTimeoutFilter & operator=(const ClassLabelTimeoutFilter &rhs)
Definition: Vector.h:41
virtual bool saveModelToFile(std::string filename) const
bool setFilterMode(UINT filterMode)
virtual bool deepCopyFrom(const PostProcessing *postProcessing)