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.
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 //Define the string that will be used to identify the object
27 const std::string ParticleClassifier::id = "ParticleClassifier";
28 std::string ParticleClassifier::getId() { return ParticleClassifier::id; }
29 
30 //Register the ParticleClassifier module with the Classifier base class
32 
33 ParticleClassifier::ParticleClassifier( const unsigned int numParticles,const Float sensorNoise,const Float transitionSigma,const Float phaseSigma,const Float velocitySigma ) : Classifier( ParticleClassifier::getId() )
34 {
35  this->numParticles = numParticles;
36  this->sensorNoise = sensorNoise;
37  this->transitionSigma = transitionSigma;
38  this->phaseSigma = phaseSigma;
39  this->velocitySigma = velocitySigma;
40  useNullRejection = true;
41  supportsNullRejection = true;
42  classifierMode = TIMESERIES_CLASSIFIER_MODE;
43 }
44 
46 {
47  *this = rhs;
48 }
49 
51 {
52 }
53 
55 
56  if( this != &rhs ){
57 
58  this->numParticles = rhs.numParticles;
59  this->sensorNoise = rhs.sensorNoise;
60  this->transitionSigma = rhs.transitionSigma;
61  this->phaseSigma = rhs.phaseSigma;
62  this->velocitySigma = rhs.velocitySigma;
63  this->particleFilter = rhs.particleFilter;
64 
65  //Copy the classifier variables
66  copyBaseVariables( (Classifier*)&rhs );
67  }
68  return *this;
69 }
70 
72  if( classifier == NULL ) return false;
73 
74  if( this->getId() == classifier->getId() ){
75  const ParticleClassifier *ptr = dynamic_cast<const ParticleClassifier*>(classifier);
76 
77  this->numParticles = ptr->numParticles;
78  this->sensorNoise = ptr->sensorNoise;
79  this->transitionSigma = ptr->transitionSigma;
80  this->phaseSigma = ptr->phaseSigma;
81  this->velocitySigma = ptr->velocitySigma;
82  this->particleFilter = ptr->particleFilter;
83 
84  //Copy the classifier variables
85  return copyBaseVariables( classifier );
86  }
87  return false;
88 }
89 
91 
92  clear();
93 
94  numClasses = trainingData.getNumClasses();
95  numInputDimensions = trainingData.getNumDimensions();
96  ranges = trainingData.getRanges();
97 
98  //Scale the training data if needed
99  if( useScaling ){
100  trainingData.scale(0, 1);
101  }
102 
103  //Train the particle filter
104  particleFilter.train( numParticles, trainingData, sensorNoise, transitionSigma, phaseSigma, velocitySigma );
105 
106  classLabels.resize(numClasses);
107  classLikelihoods.resize(numClasses,0);
108  classDistances.resize(numClasses,0);
109 
110  for(unsigned int i=0; i<numClasses; i++){
111  classLabels[i] = trainingData.getClassTracker()[i].classLabel;
112  }
113 
114  trained = true;
115  converged = true;
116 
117  return trained;
118 }
119 
121 
122  if( !trained ){
123  errorLog << __GRT_LOG__ << " The model has not been trained!" << std::endl;
124  return false;
125  }
126 
127  if( numInputDimensions != inputVector.getSize() ){
128  errorLog << __GRT_LOG__ << " The number of features in the model " << numInputDimensions << " does not match that of the input vector " << inputVector.getSize() << 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
std::string getId() const
Definition: GRTBase.cpp:85
#define DEFAULT_NULL_LIKELIHOOD_VALUE
Definition: Classifier.h:33
virtual bool filter(SENSOR_DATA &data)
virtual ~ParticleClassifier(void)
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
UINT getSize() const
Definition: Vector.h:201
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:101
UINT getClassLabelIndexValue(const UINT classLabel) const
Definition: Classifier.cpp:213
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:132
bool scale(const Float minTarget, const Float maxTarget)
static std::string getId()
virtual bool deepCopyFrom(const Classifier *classifier)
virtual bool clear()
Definition: Classifier.cpp:151
This is the main base class that all GRT Classification algorithms should inherit from...
Definition: Classifier.h:41
VectorFloat getStateEstimation() const
Float scale(const Float &x, const Float &minSource, const Float &maxSource, const Float &minTarget, const Float &maxTarget, const bool constrain=false)
Definition: GRTBase.h:184