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.
ClassLabelFilter.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 "ClassLabelFilter.h"
23 
24 GRT_BEGIN_NAMESPACE
25 
26 //Register the ClassLabelFilter module with the PostProcessing base class
27 RegisterPostProcessingModule< ClassLabelFilter > ClassLabelFilter::registerModule("ClassLabelFilter");
28 
29 ClassLabelFilter::ClassLabelFilter(UINT minimumCount,UINT bufferSize){
30  classType = "ClassLabelFilter";
31  postProcessingType = classType;
32  postProcessingInputMode = INPUT_MODE_PREDICTED_CLASS_LABEL;
33  postProcessingOutputMode = OUTPUT_MODE_PREDICTED_CLASS_LABEL;
34  debugLog.setProceedingText("[DEBUG ClassLabelFilter]");
35  errorLog.setProceedingText("[ERROR ClassLabelFilter]");
36  warningLog.setProceedingText("[WARNING ClassLabelFilter]");
37  init(minimumCount,bufferSize);
38 }
39 
41 
42  classType = "ClassLabelFilter";
43  postProcessingType = classType;
44  postProcessingInputMode = INPUT_MODE_PREDICTED_CLASS_LABEL;
45  postProcessingOutputMode = OUTPUT_MODE_PREDICTED_CLASS_LABEL;
46  debugLog.setProceedingText("[DEBUG ClassLabelFilter]");
47  errorLog.setProceedingText("[ERROR ClassLabelFilter]");
48  warningLog.setProceedingText("[WARNING ClassLabelFilter]");
49 
50  //Copy the ClassLabelFilter values
52  this->minimumCount = rhs.minimumCount;
53  this->bufferSize = rhs.bufferSize;
54  this->buffer = rhs.buffer;
55 
56  //Clone the post processing base variables
58 }
59 
61 
62 }
63 
65 
66  if( this != &rhs ){
67  //Copy the ClassLabelFilter values
69  this->minimumCount = rhs.minimumCount;
70  this->bufferSize = rhs.bufferSize;
71  this->buffer = rhs.buffer;
72 
73  //Clone the post processing base variables
75  }
76 
77  return *this;
78 }
79 
80 bool ClassLabelFilter::deepCopyFrom(const PostProcessing *postProcessing){
81 
82  if( postProcessing == NULL ) return false;
83 
84  if( this->getPostProcessingType() == postProcessing->getPostProcessingType() ){
85 
86  ClassLabelFilter *ptr = (ClassLabelFilter*)postProcessing;
87 
88  //Clone the ClassLabelFilter values
90  this->minimumCount = ptr->minimumCount;
91  this->bufferSize = ptr->bufferSize;
92  this->buffer = ptr->buffer;
93 
94  //Clone the post processing base variables
95  copyBaseVariables( postProcessing );
96  return true;
97  }
98  return false;
99 }
100 
101 bool ClassLabelFilter::process(const VectorDouble &inputVector){
102 
103  if( !initialized ){
104  errorLog << "process(const VectorDouble &inputVector) - Not initialized!" << std::endl;
105  return false;
106  }
107 
108  if( inputVector.getSize() != numInputDimensions ){
109  errorLog << "process(const VectorDouble &inputVector) - The size of the inputVector (" << inputVector.getSize() << ") does not match that of the filter (" << numInputDimensions << ")!" << std::endl;
110  return false;
111  }
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  processedData.clear();
121  processedData.resize(1,0);
122  buffer.clear();
123  if( bufferSize > 0 ){
124  initialized = buffer.resize(bufferSize,0);
125  }else initialized = false;
126  return true;
127 }
128 
129 bool ClassLabelFilter::init(UINT minimumCount,UINT bufferSize){
130 
131  initialized = false;
132 
133  if( minimumCount < 1 ){
134  errorLog << "init(UINT minimumCount,UINT bufferSize) - MinimumCount must be greater than or equal to 1!" << std::endl;
135  return false;
136  }
137 
138  if( bufferSize < 1 ){
139  errorLog << "init(UINT minimumCount,UINT bufferSize) - BufferSize must be greater than or equal to 1!" << std::endl;
140  return false;
141  }
142 
143  if( bufferSize < minimumCount ){
144  errorLog << "init(UINT minimumCount,UINT bufferSize) - The buffer size must be greater than or equal to the minimum count!" << std::endl;
145  return false;
146  }
147 
148  this->minimumCount = minimumCount;
149  this->bufferSize = bufferSize;
150  numInputDimensions = 1;
151  numOutputDimensions = 1;
152  initialized = reset();
153  return true;
154 }
155 
156 UINT ClassLabelFilter::filter(UINT predictedClassLabel){
157 
158  if( !initialized ){
159  errorLog << "filter(UINT predictedClassLabel) - The filter has not been initialized!" << std::endl;
160  filteredClassLabel = 0;
161  return 0;
162  }
163 
164  //Add the current predictedClassLabel to the buffer
165  buffer.push_back( predictedClassLabel );
166 
167  //Count the class values in the buffer, automatically start with the first value in the buffer
168  Vector< ClassTracker > classTracker( 1, ClassTracker( buffer[0], 1 ) );
169 
170  UINT maxCount = classTracker[0].counter;
171  UINT maxClass = classTracker[0].classLabel;
172  bool classLabelFound = false;
173 
174  for(UINT i=1; i<bufferSize; i++){
175  classLabelFound = false;
176  UINT currentCount = 0;
177  UINT currentClassLabel = buffer[i];
178  for(UINT k=0; k<classTracker.size(); k++){
179  if( currentClassLabel == classTracker[k].classLabel ){
180  classTracker[k].counter++;
181  classLabelFound = true;
182  currentCount = classTracker[k].counter;
183  break;
184  }
185  }
186 
187  //If we have not found the class label then we need to add this class to the classTracker
188  if( !classLabelFound ){
189  classTracker.push_back( ClassTracker(currentClassLabel,1) );
190  currentCount = 1;
191  }
192 
193  //Check to see if we should update the max count and maxClass (ignoring class label 0)
194  if( currentCount > maxCount && currentClassLabel != 0 ){
195  maxCount = currentCount;
196  maxClass = currentClassLabel;
197  }
198  }
199 
200  //printf("minimumCount: %i maxCount: %i maxClass: %i\n",minimumCount,maxCount,maxClass);
201 
202  if( maxCount >= minimumCount ){
203  filteredClassLabel = maxClass;
204  }else filteredClassLabel = 0;
205 
206  return filteredClassLabel;
207 }
208 
209 bool ClassLabelFilter::saveModelToFile( std::string filename ) const{
210 
211  if( !initialized ){
212  errorLog << "saveModelToFile(string filename) - The ClassLabelFilter has not been initialized" << std::endl;
213  return false;
214  }
215 
216  std::fstream file;
217  file.open(filename.c_str(), std::ios::out);
218 
219  if( !saveModelToFile( file ) ){
220  file.close();
221  return false;
222  }
223 
224  file.close();
225 
226  return true;
227 }
228 
229 bool ClassLabelFilter::saveModelToFile( std::fstream &file ) const{
230 
231  if( !file.is_open() ){
232  errorLog << "saveModelToFile(fstream &file) - The file is not open!" << std::endl;
233  return false;
234  }
235 
236  file << "GRT_CLASS_LABEL_FILTER_FILE_V1.0" << std::endl;
237  file << "NumInputDimensions: " << numInputDimensions << std::endl;
238  file << "NumOutputDimensions: " << numOutputDimensions << std::endl;
239  file << "MinimumCount: " << minimumCount << std::endl;
240  file << "BufferSize: " << bufferSize << std::endl;
241 
242  return true;
243 }
244 
245 bool ClassLabelFilter::loadModelFromFile( std::string filename ){
246 
247  std::fstream file;
248  file.open(filename.c_str(), std::ios::in);
249 
250  if( !loadModelFromFile( file ) ){
251  file.close();
252  initialized = false;
253  return false;
254  }
255 
256  file.close();
257 
258  return true;
259 }
260 
261 bool ClassLabelFilter::loadModelFromFile( std::fstream &file ){
262 
263  if( !file.is_open() ){
264  errorLog << "loadModelFromFile(fstream &file) - The file is not open!" << std::endl;
265  return false;
266  }
267 
268  std::string word;
269 
270  //Load the header
271  file >> word;
272 
273  if( word != "GRT_CLASS_LABEL_FILTER_FILE_V1.0" ){
274  errorLog << "loadModelFromFile(fstream &file) - Invalid file format!" << std::endl;
275  return false;
276  }
277 
278  file >> word;
279  if( word != "NumInputDimensions:" ){
280  errorLog << "loadModelFromFile(fstream &file) - Failed to read NumInputDimensions header!" << std::endl;
281  return false;
282  }
283  file >> numInputDimensions;
284 
285  //Load the number of output dimensions
286  file >> word;
287  if( word != "NumOutputDimensions:" ){
288  errorLog << "loadModelFromFile(fstream &file) - Failed to read NumOutputDimensions header!" << std::endl;
289  return false;
290  }
291  file >> numOutputDimensions;
292 
293  //Load the minimumCount
294  file >> word;
295  if( word != "MinimumCount:" ){
296  errorLog << "loadModelFromFile(fstream &file) - Failed to read MinimumCount header!" << std::endl;
297  return false;
298  }
299  file >> minimumCount;
300 
301  file >> word;
302  if( word != "BufferSize:" ){
303  errorLog << "loadModelFromFile(fstream &file) - Failed to read BufferSize header!" << std::endl;
304  return false;
305  }
306  file >> bufferSize;
307 
308  //Init the classLabelFilter module to ensure everything is initialized correctly
309  return init(minimumCount,bufferSize);
310 }
311 
312 bool ClassLabelFilter::setMinimumCount(UINT minimumCount){
313  this->minimumCount = minimumCount;
314  if( initialized ){
315  return reset();
316  }
317  return true;
318 }
319 
320 bool ClassLabelFilter::setBufferSize(UINT bufferSize){
321  this->bufferSize = bufferSize;
322  if( initialized ){
323  return reset();
324  }
325  return true;
326 }
327 
328 GRT_END_NAMESPACE
bool push_back(const T &value)
std::string getPostProcessingType() const
virtual bool reset()
ClassLabelFilter(UINT minimumCount=1, UINT bufferSize=1)
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
UINT getSize() const
Definition: Vector.h:191
virtual bool process(const VectorDouble &inputVector)
virtual bool saveModelToFile(std::string filename) const
bool setMinimumCount(UINT minimumCount)
UINT filter(UINT predictedClassLabel)
bool copyBaseVariables(const PostProcessing *postProcessingModule)
UINT minimumCount
The minimum count sets the minimum number of class label values that must be present in the class lab...
CircularBuffer< UINT > buffer
The class label filter buffer.
virtual bool deepCopyFrom(const PostProcessing *postProcessing)
UINT bufferSize
The size of the Class Label Filter buffer.
bool init()
UINT filteredClassLabel
The most recent filtered class label value.
virtual bool loadModelFromFile(std::string filename)
bool setBufferSize(UINT bufferSize)
The Class Label Filter is a useful post-processing module which can remove erroneous or sporadic pred...
ClassLabelFilter & operator=(const ClassLabelFilter &rhs)
bool resize(const unsigned int newBufferSize)
virtual ~ClassLabelFilter()