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