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.
ParticleClassifier.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 "ParticleClassifier.h"
23 
24 GRT_BEGIN_NAMESPACE
25 
26 //Register the ParticleClassifier module with the Classifier base class
27 RegisterClassifierModule< ParticleClassifier > ParticleClassifier::registerModule("ParticleClassifier");
28 
29 ParticleClassifier::ParticleClassifier( const unsigned int numParticles,const Float sensorNoise,const Float transitionSigma,const Float phaseSigma,const Float velocitySigma )
30 {
31  this->numParticles = numParticles;
32  this->sensorNoise = sensorNoise;
33  this->transitionSigma = transitionSigma;
34  this->phaseSigma = phaseSigma;
35  this->velocitySigma = velocitySigma;
36  useNullRejection = true;
37  supportsNullRejection = true;
38  classType = "ParticleClassifier";
39  classifierType = classType;
40  classifierMode = TIMESERIES_CLASSIFIER_MODE;
41  debugLog.setProceedingText("[DEBUG ParticleClassifier]");
42  errorLog.setProceedingText("[ERROR ParticleClassifier]");
43  trainingLog.setProceedingText("[TRAINING ParticleClassifier]");
44  warningLog.setProceedingText("[WARNING ParticleClassifier]");
45 }
46 
48  *this = rhs;
49 }
50 
52 {
53 }
54 
56 
57  if( this != &rhs ){
58 
59  this->numParticles = rhs.numParticles;
60  this->sensorNoise = rhs.sensorNoise;
61  this->transitionSigma = rhs.transitionSigma;
62  this->phaseSigma = rhs.phaseSigma;
63  this->velocitySigma = rhs.velocitySigma;
64  this->particleFilter = rhs.particleFilter;
65 
66  //Copy the classifier variables
67  copyBaseVariables( (Classifier*)&rhs );
68  }
69  return *this;
70 }
71 
73  if( classifier == NULL ) return false;
74 
75  if( this->getClassifierType() == classifier->getClassifierType() ){
76  ParticleClassifier *ptr = (ParticleClassifier*)classifier;
77 
78  this->numParticles = ptr->numParticles;
79  this->sensorNoise = ptr->sensorNoise;
80  this->transitionSigma = ptr->transitionSigma;
81  this->phaseSigma = ptr->phaseSigma;
82  this->velocitySigma = ptr->velocitySigma;
83  this->particleFilter = ptr->particleFilter;
84 
85  //Copy the classifier variables
86  return copyBaseVariables( classifier );
87  }
88  return false;
89 }
90 
92 
93  clear();
94 
95  numClasses = trainingData.getNumClasses();
96  numInputDimensions = trainingData.getNumDimensions();
97  ranges = trainingData.getRanges();
98 
99  //Scale the training data if needed
100  if( useScaling ){
101  trainingData.scale(0, 1);
102  }
103 
104  //Train the particle filter
105  particleFilter.train( numParticles, trainingData, sensorNoise, transitionSigma, phaseSigma, velocitySigma );
106 
107  classLabels.resize(numClasses);
108  classLikelihoods.resize(numClasses,0);
109  classDistances.resize(numClasses,0);
110 
111  for(unsigned int i=0; i<numClasses; i++){
112  classLabels[i] = trainingData.getClassTracker()[i].classLabel;
113  }
114 
115  trained = true;
116 
117  return trained;
118 }
119 
121 
122  if( !trained ){
123  errorLog << "predict_(VectorDouble &inputVector) - The model has not been trained!" << std::endl;
124  return false;
125  }
126 
127  if( numInputDimensions != inputVector.size() ){
128  errorLog << "predict_(VectorDouble &inputVector) - The number of features in the model " << numInputDimensions << " does not match that of the input vector " << inputVector.size() << std::endl;
129  return false;
130  }
131 
132  //Scale the input data if needed
133  if( useScaling ){
134  for(unsigned int j=0; j<numInputDimensions; j++){
135  inputVector[j] = scale(inputVector[j],ranges[j].minValue,ranges[j].maxValue,0,1);
136  }
137  }
138 
139  predictedClassLabel = 0;
140  maxLikelihood = 0;
141  std::fill(classLikelihoods.begin(),classLikelihoods.end(),0);
142  std::fill(classDistances.begin(),classDistances.end(),0);
143 
144  //Update the particle filter
145  particleFilter.filter( inputVector );
146 
147  //Count the number of particles per class
148  unsigned int gestureTemplate = 0;
149  unsigned int gestureLabel = 0;
150  unsigned int gestureIndex = 0;
151  for(unsigned int i=0; i<numParticles; i++){
152  gestureTemplate = (unsigned int)particleFilter[i].x[0]; //The first element in the state vector is the gesture template index
153  gestureLabel = particleFilter.gestureTemplates[ gestureTemplate ].classLabel;
154  gestureIndex = getClassLabelIndexValue( gestureLabel );
155 
156  classDistances[ gestureIndex ] += particleFilter[i].w;
157  }
158 
159  bool rejectPrediction = false;
160  if( useNullRejection ){
161  if( particleFilter.getWeightSum() < 1.0e-5 ){
162  rejectPrediction = true;
163  }
164  }
165 
166  //Compute the class likelihoods
167  for(unsigned int i=0; i<numClasses; i++){
168 
169  classLikelihoods[ i ] = rejectPrediction ? 0 : classDistances[i];
170 
171  if( classLikelihoods[i] > maxLikelihood ){
172  predictedClassLabel = classLabels[i];
173  maxLikelihood = classLikelihoods[i];
174  }
175  }
176 
177  //Estimate the phase
178  phase = particleFilter.getStateEstimation()[1]; //The 2nd element in the state vector is the estimatied phase
179 
180  return true;
181 
182 }
183 
185 
187 
188  particleFilter.clear();
189 
190  return true;
191 }
192 
194 
196 
197  particleFilter.reset();
198 
199  return true;
200 }
201 
202 bool ParticleClassifier::save( std::fstream &file ) const{
203 
204  if(!file.is_open())
205  {
206  errorLog <<"save(fstream &file) - The file is not open!" << std::endl;
207  return false;
208  }
209 
210  return true;
211 }
212 
213 bool ParticleClassifier::load( std::fstream &file ){
214 
215  clear();
216 
217  if(!file.is_open())
218  {
219  errorLog << "load(string filename) - Could not open file to load model" << std::endl;
220  return false;
221  }
222 
223  //Flag that the model is trained
224  trained = true;
225 
226  //Resize the prediction results to make sure it is setup for realtime prediction
227  maxLikelihood = DEFAULT_NULL_LIKELIHOOD_VALUE;
228  bestDistance = DEFAULT_NULL_DISTANCE_VALUE;
229  classLikelihoods.resize(numClasses,DEFAULT_NULL_LIKELIHOOD_VALUE);
230  classDistances.resize(numClasses,DEFAULT_NULL_DISTANCE_VALUE);
231 
232  return true;
233 }
234 
235 const Vector< ParticleClassifierGestureTemplate >& ParticleClassifier::getGestureTemplates() const{
236  return particleFilter.gestureTemplates;
237 }
238 
239 const ParticleClassifierParticleFilter& ParticleClassifier::getParticleFilter() const {
240  return particleFilter;
241 }
242 
243 VectorDouble ParticleClassifier::getStateEstimation() const{
244  return particleFilter.getStateEstimation();
245 }
246 
247 Float ParticleClassifier::getPhase() const{
248  if( trained ){
249  return particleFilter.getStateEstimation()[1];
250  }
251  return 0;
252 }
253 
254 Float ParticleClassifier::getVelocity() const{
255  if( trained ){
256  return particleFilter.getStateEstimation()[2];
257  }
258  return 0;
259 }
260 
261 bool ParticleClassifier::setNumParticles(const unsigned int numParticles){
262 
263  clear();
264 
265  this->numParticles = numParticles;
266 
267  return true;
268 }
269 
270 bool ParticleClassifier::setSensorNoise(const unsigned int sensorNoise){
271 
272  clear();
273 
274  this->sensorNoise = sensorNoise;
275 
276  return true;
277 }
278 
279 bool ParticleClassifier::setTransitionSigma(const unsigned int transitionSigma){
280 
281  clear();
282 
283  this->transitionSigma = transitionSigma;
284 
285  return true;
286 }
287 
288 bool ParticleClassifier::setPhaseSigma(const unsigned int phaseSigma){
289 
290  clear();
291 
292  this->phaseSigma = phaseSigma;
293 
294  return true;
295 }
296 
297 bool ParticleClassifier::setVelocitySigma(const unsigned int velocitySigma){
298 
299  clear();
300 
301  this->velocitySigma = velocitySigma;
302 
303  return true;
304 }
305 
306 GRT_END_NAMESPACE
Float getWeightSum() const
#define DEFAULT_NULL_LIKELIHOOD_VALUE
Definition: Classifier.h:38
virtual bool filter(SENSOR_DATA &data)
Float scale(const Float &x, const Float &minSource, const Float &maxSource, const Float &minTarget, const Float &maxTarget, const bool constrain=false)
Definition: MLBase.h:353
virtual ~ParticleClassifier(void)
std::string getClassifierType() const
Definition: Classifier.cpp:161
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
UINT getClassLabelIndexValue(UINT classLabel) const
Definition: Classifier.cpp:195
virtual bool load(std::fstream &file)
ParticleClassifier & operator=(const ParticleClassifier &rhs)
Vector< ClassTracker > getClassTracker() const
virtual bool save(std::fstream &file) const
virtual bool predict_(VectorFloat &inputVector)
virtual bool train_(TimeSeriesClassificationData &trainingData)
bool copyBaseVariables(const Classifier *classifier)
Definition: Classifier.cpp:93
ParticleClassifier(const unsigned int numParticles=2000, const Float sensorNoise=20.0, const Float transitionSigma=0.005, const Float phaseSigma=0.1, const Float velocitySigma=0.01)
virtual bool reset()
Definition: Classifier.cpp:123
bool scale(const Float minTarget, const Float maxTarget)
virtual bool deepCopyFrom(const Classifier *classifier)
virtual bool clear()
Definition: Classifier.cpp:142
VectorFloat getStateEstimation() const