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.
ZeroCrossingCounter.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 "ZeroCrossingCounter.h"
23 
24 GRT_BEGIN_NAMESPACE
25 
26 //Define the string that will be used to identify the object
27 std::string ZeroCrossingCounter::id = "ZeroCrossingCounter";
28 std::string ZeroCrossingCounter::getId() { return ZeroCrossingCounter::id; }
29 
30 //Register the ZeroCrossingCounter module with the FeatureExtraction base class
32 
34 {
35  init(searchWindowSize,deadZoneThreshold,numDimensions,featureMode);
36 }
37 
39 {
40  //Invoke the equals operator to copy the data from the rhs instance to this instance
41  *this = rhs;
42 }
43 
45 
46 }
47 
49  if(this!=&rhs){
51  this->featureMode = rhs.featureMode;
53  this->derivative = rhs.derivative;
54  this->deadZone = rhs.deadZone;
55  this->dataBuffer = rhs.dataBuffer;
56 
58  }
59  return *this;
60 }
61 
63 
64  if( featureExtraction == NULL ) return false;
65 
66  if( this->getId() == featureExtraction->getId() ){
67  //Invoke the equals operator to copy the data from the rhs instance to this instance
68  *this = *dynamic_cast<const ZeroCrossingCounter*>(featureExtraction);
69  return true;
70  }
71 
72  errorLog << "deepCopyFrom(FeatureExtraction *featureExtraction) - FeatureExtraction Types Do Not Match!" << std::endl;
73 
74  return false;
75 }
76 
78 
79  if( !initialized ){
80  errorLog << "computeFeatures(const VectorFloat &inputVector) - Not initialized!" << std::endl;
81  return false;
82  }
83 
84  if( inputVector.getSize() != numInputDimensions ){
85  errorLog << "computeFeatures(const VectorFloat &inputVector) - The size of the inputVector (" << inputVector.getSize() << ") does not match that of the filter (" << numInputDimensions << ")!" << std::endl;
86  return false;
87  }
88 
89  update( inputVector );
90 
91  return true;
92 }
93 
95  if( initialized ){
96  return init( searchWindowSize, deadZoneThreshold, numInputDimensions, featureMode );
97  }
98  return false;
99 }
100 
101 bool ZeroCrossingCounter::save( std::fstream &file ) const{
102 
103  if( !file.is_open() ){
104  errorLog << "save(fstream &file) - The file is not open!" << std::endl;
105  return false;
106  }
107 
108  //Write the file header
109  file << "GRT_ZERO_CROSSING_COUNTER_FILE_V1.0" << std::endl;
110 
111  //Save the base settings to the file
113  errorLog << "saveFeatureExtractionSettingsToFile(fstream &file) - Failed to save base feature extraction settings to file!" << std::endl;
114  return false;
115  }
116 
117  //Write the zero crossing counter settings
118  file << "SearchWindowSize: " << searchWindowSize << std::endl;
119  file << "FeatureMode: " << featureMode << std::endl;
120  file << "DeadZoneThreshold: " << deadZoneThreshold << std::endl;
121 
122  return true;
123 }
124 
125 bool ZeroCrossingCounter::load( std::fstream &file ){
126 
127  if( !file.is_open() ){
128  errorLog << "load(fstream &file) - The file is not open!" << std::endl;
129  return false;
130  }
131 
132  std::string word;
133 
134  //Load the header
135  file >> word;
136 
137  if( word != "GRT_ZERO_CROSSING_COUNTER_FILE_V1.0" ){
138  errorLog << "load(fstream &file) - Invalid file format!" << std::endl;
139  return false;
140  }
141 
143  errorLog << "loadFeatureExtractionSettingsFromFile(fstream &file) - Failed to load base feature extraction settings from file!" << std::endl;
144  return false;
145  }
146 
147  file >> word;
148  if( word != "SearchWindowSize:" ){
149  errorLog << "load(fstream &file) - Failed to read SearchWindowSize header!" << std::endl;
150  return false;
151  }
152  file >> searchWindowSize;
153 
154  file >> word;
155  if( word != "FeatureMode:" ){
156  errorLog << "load(fstream &file) - Failed to read FeatureMode header!" << std::endl;
157  return false;
158  }
159  file >> featureMode;
160 
161  file >> word;
162  if( word != "DeadZoneThreshold:" ){
163  errorLog << "load(fstream &file) - Failed to read DeadZoneThreshold header!" << std::endl;
164  return false;
165  }
166  file >> deadZoneThreshold;
167 
168  //Init the ZeroCrossingCounter module to ensure everything is initialized correctly
169  return init(searchWindowSize,deadZoneThreshold,numInputDimensions,featureMode);
170 }
171 
172 bool ZeroCrossingCounter::init(const UINT searchWindowSize,const Float deadZoneThreshold,const UINT numDimensions,const UINT featureMode){
173 
174  initialized = false;
175  featureDataReady = false;
176 
177  if( searchWindowSize == 0 ){
178  errorLog << "init(UINT searchWindowSize,Float deadZoneThreshold,UINT numDimensions,UINT featureMode) - The searchWindowSize must be greater than zero!" << std::endl;
179  return false;
180  }
181 
182  if( deadZoneThreshold < 0 ){
183  errorLog << "init(UINT searchWindowSize,Float deadZoneThreshold,UINT numDimensions,UINT featureMode) - The deadZoneThreshold must be greater than zero!" << std::endl;
184  return false;
185  }
186 
187  if( numDimensions == 0 ){
188  errorLog << "init(UINT searchWindowSize,Float deadZoneThreshold,UINT numDimensions,UINT featureMode) - The numDimensions must be greater than zero!" << std::endl;
189  return false;
190  }
191 
192  if( featureMode != INDEPENDANT_FEATURE_MODE && featureMode != COMBINED_FEATURE_MODE ){
193  errorLog << "init(UINT searchWindowSize,Float deadZoneThreshold,UINT numDimensions,UINT featureMode) - Unkown feature mode!" << std::endl;
194  return false;
195  }
196 
197  //Setup the search variables
198  this->searchWindowSize = searchWindowSize;
199  this->featureMode = featureMode;
200  this->deadZoneThreshold = deadZoneThreshold;
201  numInputDimensions = numDimensions;
202  numOutputDimensions = (featureMode == INDEPENDANT_FEATURE_MODE ? TOTAL_NUM_ZERO_CROSSING_FEATURES * numInputDimensions : TOTAL_NUM_ZERO_CROSSING_FEATURES);
203  derivative.init(Derivative::FIRST_DERIVATIVE, 1.0, numInputDimensions, true, 5);
204  deadZone.init(-deadZoneThreshold,deadZoneThreshold,numInputDimensions);
205  dataBuffer.resize( searchWindowSize, VectorFloat(numInputDimensions,NAN) );
206  featureVector.resize(numOutputDimensions,0);
207 
208  //Flag that the zero crossing counter has been initialized
209  initialized = true;
210 
211  return true;
212 }
213 
214 
216  return update(VectorFloat(1,x));
217 }
218 
220 
221  if( !initialized ){
222  errorLog << "update(const VectorFloat &x) - Not Initialized!" << std::endl;
223  return VectorFloat();
224  }
225 
226  if( x.getSize() != numInputDimensions ){
227  errorLog << "update(const VectorFloat &x)- The Number Of Input Dimensions (" << numInputDimensions << ") does not match the size of the input vector (" << x.getSize() << ")!" << std::endl;
228  return VectorFloat();
229  }
230 
231  //Clear the feature vector
232  std::fill(featureVector.begin(),featureVector.end(),0);
233 
234  //Update the derivative data and
236 
237  //Dead zone the derivative data
239 
240  //Add the deadzone data to the buffer
242 
243  //Search the buffer for the zero crossing features
244  for(UINT j=0; j<numInputDimensions; j++){
245  UINT colIndex = (featureMode == INDEPENDANT_FEATURE_MODE ? (TOTAL_NUM_ZERO_CROSSING_FEATURES*j) : 0);
246  for(UINT i=1; i<dataBuffer.getSize(); i++){
247  //Search for a zero crossing
248  if( (dataBuffer[i][j] > 0 && dataBuffer[i-1][j] <= 0) || (dataBuffer[i][j] < 0 && dataBuffer[i-1][j] >= 0) ){
249  //Update the zero crossing count
250  featureVector[ NUM_ZERO_CROSSINGS_COUNTED + colIndex ]++;
251 
252  //Update the magnitude, search the last 5 values around the zero crossing to make sure we get the maxima of the peak
253  Float maxValue = 0;
254  UINT searchSize = i > 5 ? 5 : i;
255  for(UINT n=0; n<searchSize; n++){
256  Float value = fabs( dataBuffer[ i-n ][j] );
257  if( value > maxValue ) maxValue = value;
258  }
259  featureVector[ ZERO_CROSSING_MAGNITUDE + colIndex ] += maxValue;
260  }
261  }
262  }
263 
264  //Flag that the feature data has been computed
265  featureDataReady = true;
266 
267  return featureVector;
268 }
269 
271  if( searchWindowSize > 0 ){
272  this->searchWindowSize = searchWindowSize;
273  if( initialized ) return reset();
274  return true;
275  }
276  errorLog << "setSearchWindowSize(const UINT searchWindowSize) - The searchWindowSize must be larger than zero!" << std::endl;
277  return false;
278 }
279 
281  if( featureMode == INDEPENDANT_FEATURE_MODE || featureMode == COMBINED_FEATURE_MODE ){
282  this->featureMode = featureMode;
283  if( initialized ) return reset();
284  return true;
285  }
286  errorLog << "setFeatureMode(UINT featureMode) - Unkown feature mode!" << std::endl;
287  return false;
288 }
289 
291  if( deadZoneThreshold > 0 ){
292  this->deadZoneThreshold = deadZoneThreshold;
293  if( initialized ) return reset();
294  return true;
295  }
296  errorLog << "setDeadZoneThreshold(const Float deadZoneThreshold) - The deadZoneThreshold must be larger than zero!" << std::endl;
297  return false;
298 }
299 
300 GRT_END_NAMESPACE
bool push_back(const T &value)
std::string getId() const
Definition: GRTBase.cpp:85
bool setDeadZoneThreshold(const Float deadZoneThreshold)
DeadZone deadZone
Used to remove small amounts of noise from the data.
virtual bool save(std::fstream &file) const
virtual bool load(std::fstream &file)
bool saveFeatureExtractionSettingsToFile(std::fstream &file) const
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
virtual bool deepCopyFrom(const FeatureExtraction *featureExtraction)
Float filter(const Float x)
Definition: DeadZone.cpp:194
UINT getSize() const
Definition: Vector.h:201
Float computeDerivative(const Float x)
Definition: Derivative.cpp:248
CircularBuffer< VectorFloat > dataBuffer
A buffer used to store the previous derivative data.
ZeroCrossingCounter(const UINT searchWindowSize=20, const Float deadZoneThreshold=0.01, const UINT numDimensions=1, const UINT featureMode=INDEPENDANT_FEATURE_MODE)
UINT searchWindowSize
The size of the search window, i.e. the amount of previous data stored and searched.
bool init(Float lowerLimit, Float upperLimit, UINT numDimensions)
Definition: DeadZone.cpp:169
bool setFeatureMode(const UINT featureMode)
ZeroCrossingCounter & operator=(const ZeroCrossingCounter &rhs)
virtual bool computeFeatures(const VectorFloat &inputVector)
UINT featureMode
The featureMode controls how the features are added to the feature vector.
static std::string getId()
VectorFloat getProcessedData() const
bool init(const UINT derivativeOrder, const Float delta, const UINT numDimensions, const bool filterData, const UINT filterSize)
Definition: Derivative.cpp:207
bool loadFeatureExtractionSettingsFromFile(std::fstream &file)
Float deadZoneThreshold
The threshold value used for the dead zone filter.
Derivative derivative
Used to compute the derivative of the input signal.
VectorFloat update(const Float x)
bool copyBaseVariables(const FeatureExtraction *featureExtractionModule)
bool setSearchWindowSize(const UINT searchWindowSize)
unsigned int getSize() const
bool resize(const unsigned int newBufferSize)