GestureRecognitionToolkit  Version: 0.1.0
The Gesture Recognition Toolkit (GRT) is a cross-platform, open-source, c++ machine learning library for real-time gesture recognition.
MovementIndex.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 #include "MovementIndex.h"
22 
23 GRT_BEGIN_NAMESPACE
24 
25 //Register the MovementIndex module with the FeatureExtraction base class
26 RegisterFeatureExtractionModule< MovementIndex > MovementIndex::registerModule("MovementIndex");
27 
28 MovementIndex::MovementIndex(UINT bufferLength,UINT numDimensions){
29 
30  classType = "MovementIndex";
31  featureExtractionType = classType;
32  debugLog.setProceedingText("[DEBUG MovementIndex]");
33  errorLog.setProceedingText("[ERROR MovementIndex]");
34  warningLog.setProceedingText("[WARNING MovementIndex]");
35  init(bufferLength,numDimensions);
36 }
37 
39 
40  classType = "MovementIndex";
41  featureExtractionType = classType;
42  debugLog.setProceedingText("[DEBUG MovementIndex]");
43  errorLog.setProceedingText("[ERROR MovementIndex]");
44  warningLog.setProceedingText("[WARNING MovementIndex]");
45 
46  //Invoke the equals operator to copy the data from the rhs instance to this instance
47  *this = rhs;
48 }
49 
51 
52 }
53 
55  if(this!=&rhs){
56  this->bufferLength = rhs.bufferLength;
57  this->dataBuffer = rhs.dataBuffer;
58 
59  //Copy the base variables
61  }
62  return *this;
63 }
64 
65 bool MovementIndex::deepCopyFrom(const FeatureExtraction *featureExtraction){
66 
67  if( featureExtraction == NULL ) return false;
68 
69  if( this->getFeatureExtractionType() == featureExtraction->getFeatureExtractionType() ){
70 
71  //Invoke the equals operator to copy the data from the rhs instance to this instance
72  *this = *(MovementIndex*)featureExtraction;
73 
74  return true;
75  }
76 
77  errorLog << "clone(FeatureExtraction *featureExtraction) - FeatureExtraction Types Do Not Match!" << std::endl;
78 
79  return false;
80 }
81 
83 
84  if( !initialized ){
85  errorLog << "computeFeatures(const VectorFloat &inputVector) - Not initialized!" << std::endl;
86  return false;
87  }
88 
89  if( inputVector.getSize() != numInputDimensions ){
90  errorLog << "computeFeatures(const VectorFloat &inputVector) - The size of the inputVector (" << inputVector.getSize() << ") does not match that of the filter (" << numInputDimensions << ")!" << std::endl;
91  return false;
92  }
93 
94  featureVector = update( inputVector );
95 
96  return true;
97 }
98 
100  if( initialized ){
101  return init(bufferLength,numInputDimensions);
102  }
103  return false;
104 }
105 
106 bool MovementIndex::saveModelToFile( std::string filename ) const{
107 
108  std::fstream file;
109  file.open(filename.c_str(), std::ios::out);
110 
111  if( !saveModelToFile( file ) ){
112  return false;
113  }
114 
115  file.close();
116 
117  return true;
118 }
119 
120 bool MovementIndex::loadModelFromFile( std::string filename ){
121 
122  std::fstream file;
123  file.open(filename.c_str(), std::ios::in);
124 
125  if( !loadModelFromFile( file ) ){
126  return false;
127  }
128 
129  //Close the file
130  file.close();
131 
132  return true;
133 }
134 
135 bool MovementIndex::saveModelToFile( std::fstream &file ) const{
136 
137  if( !file.is_open() ){
138  errorLog << "saveModelToFile(fstream &file) - The file is not open!" << std::endl;
139  return false;
140  }
141 
142  //Write the file header
143  file << "GRT_MOVEMENT_INDEX_FILE_V1.0" << std::endl;
144 
145  //Save the base settings to the file
147  errorLog << "saveFeatureExtractionSettingsToFile(fstream &file) - Failed to save base feature extraction settings to file!" << std::endl;
148  return false;
149  }
150 
151  //Write the movement index settings to the file
152  file << "BufferLength: " << bufferLength << std::endl;
153 
154  return true;
155 }
156 
157 bool MovementIndex::loadModelFromFile( std::fstream &file ){
158 
159  if( !file.is_open() ){
160  errorLog << "loadModelFromFile(fstream &file) - The file is not open!" << std::endl;
161  return false;
162  }
163 
164  std::string word;
165 
166  //Load the header
167  file >> word;
168 
169  if( word != "GRT_MOVEMENT_INDEX_FILE_V1.0" ){
170  errorLog << "loadModelFromFile(fstream &file) - Invalid file format!" << std::endl;
171  return false;
172  }
173 
175  errorLog << "loadFeatureExtractionSettingsFromFile(fstream &file) - Failed to load base feature extraction settings from file!" << std::endl;
176  return false;
177  }
178 
179  //Load the BufferLength
180  file >> word;
181  if( word != "BufferLength:" ){
182  errorLog << "loadModelFromFile(fstream &file) - Failed to read BufferLength header!" << std::endl;
183  return false;
184  }
185  file >> bufferLength;
186 
187  //Init the MovementIndex module to ensure everything is initialized correctly
188  return init(bufferLength,numInputDimensions);
189 }
190 
191 bool MovementIndex::init(UINT bufferLength,UINT numDimensions){
192 
193  initialized = false;
194 
195  if( bufferLength == 0 ){
196  errorLog << "init(...) - The number of bufferLength must be greater than zero!" << std::endl;
197  return false;
198  }
199 
200  if( numDimensions == 0 ){
201  errorLog << "init(...) - The number of dimensions must be greater than zero!" << std::endl;
202  return false;
203  }
204 
205  this->bufferLength = bufferLength;
206  this->numInputDimensions = numDimensions;
207  this->numOutputDimensions = numInputDimensions;
208  featureDataReady = false;
209 
210  //Resize the feature vector
211  featureVector.resize(numInputDimensions);
212 
213  //Resize the raw trajectory data buffer
214  dataBuffer.resize( bufferLength, VectorFloat(numInputDimensions,0) );
215 
216  //Flag that the zero crossing counter has been initialized
217  initialized = true;
218 
219  return true;
220 }
221 
222 
224  return update(VectorFloat(1,x));
225 }
226 
228 
229 #ifdef GRT_SAFE_CHECKING
230  if( !initialized ){
231  errorLog << "update(const VectorFloat &x) - Not Initialized!" << std::endl;
232  return VectorFloat();
233  }
234 
235  if( x.getSize() != numInputDimensions ){
236  errorLog << "update(const VectorFloat &x)- The Number Of Input Dimensions (" << numInputDimensions << ") does not match the size of the input vector (" << x.getSize() << ")!" << std::endl;
237  return VectorFloat();
238  }
239 #endif
240 
241  //Add the new data to the trajectory data buffer
242  dataBuffer.push_back( x );
243 
244  //Only flag that the feature data is ready if the trajectory data is full
245  if( !dataBuffer.getBufferFilled() ){
246  featureDataReady = false;
247  for(UINT i=0; i<featureVector.getSize(); i++){
248  featureVector[i] = 0;
249  }
250  return featureVector;
251  }else featureDataReady = true;
252 
253  //Compute the movement index (which is the RMS error)
254  VectorFloat mu(numInputDimensions,0);
255 
256  //Compute mu
257  for(UINT j=0; j<numInputDimensions; j++){
258  for(UINT i=0; i<dataBuffer.getSize(); i++){
259  mu[j] += dataBuffer[i][j];
260  }
261  mu[j] /= Float(dataBuffer.getSize());
262  }
263 
264  for(UINT j=0; j<numInputDimensions; j++){
265  featureVector[j] = 0;
266  for(UINT i=0; i<dataBuffer.getSize(); i++){
267  featureVector[j] += grt_sqr( dataBuffer[i][j] - mu[j] );
268  }
269  featureVector[j] = grt_sqrt( featureVector[j]/Float(dataBuffer.getSize()) );
270  }
271 
272  return featureVector;
273 }
274 
276  if( initialized ){
277  return dataBuffer;
278  }
280 }
281 
282 GRT_END_NAMESPACE
bool push_back(const T &value)
virtual ~MovementIndex()
bool saveFeatureExtractionSettingsToFile(std::fstream &file) const
bool getBufferFilled() const
virtual bool saveModelToFile(std::string filename) const
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
virtual bool deepCopyFrom(const FeatureExtraction *featureExtraction)
unsigned int getSize() const
Definition: Vector.h:193
std::string getFeatureExtractionType() const
virtual bool loadModelFromFile(std::string filename)
virtual bool reset()
bool loadFeatureExtractionSettingsFromFile(std::fstream &file)
MovementIndex & operator=(const MovementIndex &rhs)
MovementIndex(UINT bufferLength=100, UINT numDimensions=1)
This class implements the MovementIndex feature module. The MovementIndex module computes the amount ...
VectorFloat update(Float x)
virtual bool computeFeatures(const VectorFloat &inputVector)
bool copyBaseVariables(const FeatureExtraction *featureExtractionModule)
unsigned int getSize() const
bool resize(const unsigned int newBufferSize)
CircularBuffer< VectorFloat > getData()