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.
LowPassFilter.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 "LowPassFilter.h"
23 
24 GRT_BEGIN_NAMESPACE
25 
26 //Register the LowPassFilter module with the PreProcessing base class
27 RegisterPreProcessingModule< LowPassFilter > LowPassFilter::registerModule("LowPassFilter");
28 
29 LowPassFilter::LowPassFilter(Float filterFactor,Float gain,UINT numDimensions,Float cutoffFrequency,Float delta){
30 
31  classType = "LowPassFilter";
32  preProcessingType = classType;
33  debugLog.setProceedingText("[DEBUG LowPassFilter]");
34  errorLog.setProceedingText("[ERROR LowPassFilter]");
35  warningLog.setProceedingText("[WARNING LowPassFilter]");
36  init(filterFactor,gain,numDimensions);
37 
38  if( cutoffFrequency != -1 && delta != -1 ){
39  setCutoffFrequency(cutoffFrequency, delta);
40  }
41 }
42 
44  classType = "LowPassFilter";
45  preProcessingType = classType;
46  debugLog.setProceedingText("[DEBUG LowPassFilter]");
47  errorLog.setProceedingText("[ERROR LowPassFilter]");
48  warningLog.setProceedingText("[WARNING LowPassFilter]");
49  *this = rhs;
50 }
51 
53 
54 }
55 
57  if(this!=&rhs){
58  this->filterFactor = rhs.filterFactor;
59  this->gain = rhs.gain;
60  this->yy = rhs.yy;
62  }
63  return *this;
64 }
65 
66 bool LowPassFilter::deepCopyFrom(const PreProcessing *preProcessing){
67 
68  if( preProcessing == NULL ) return false;
69 
70  if( this->getPreProcessingType() == preProcessing->getPreProcessingType() ){
71 
72  //Call the equals operator
73  *this = *(LowPassFilter*)preProcessing;
74 
75  return true;
76  }
77 
78  errorLog << "clone(const PreProcessing *preProcessing) - PreProcessing Types Do Not Match!" << std::endl;
79 
80  return false;
81 }
82 
83 bool LowPassFilter::process(const VectorFloat &inputVector){
84 
85  if( !initialized ){
86  errorLog << "process(const VectorFloat &inputVector) - Not initialized!" << std::endl;
87  return false;
88  }
89 
90  if( inputVector.size() != numInputDimensions ){
91  errorLog << "process(const VectorFloat &inputVector) - The size of the inputVector (" << inputVector.size() << ") does not match that of the filter (" << numInputDimensions << ")!" << std::endl;
92  return false;
93  }
94 
95  processedData = filter( inputVector );
96 
97  if( processedData.size() == numOutputDimensions ) return true;
98  return false;
99 
100 }
101 
103  if( initialized ) return init(filterFactor,gain,numInputDimensions);
104  return false;
105 }
106 
107 bool LowPassFilter::save( std::fstream &file ) const{
108 
109  if( !file.is_open() ){
110  errorLog << "save(fstream &file) - The file is not open!" << std::endl;
111  return false;
112  }
113 
114  file << "GRT_LOW_PASS_FILTER_FILE_V1.0" << std::endl;
115 
116  file << "NumInputDimensions: " << numInputDimensions << std::endl;
117  file << "NumOutputDimensions: " << numOutputDimensions << std::endl;
118  file << "FilterFactor: " << filterFactor << std::endl;
119  file << "Gain: " << gain << std::endl;
120 
121  return true;
122 }
123 
124 bool LowPassFilter::load( std::fstream &file ){
125 
126  if( !file.is_open() ){
127  errorLog << "load(fstream &file) - The file is not open!" << std::endl;
128  return false;
129  }
130 
131  std::string word;
132 
133  //Load the header
134  file >> word;
135 
136  if( word != "GRT_LOW_PASS_FILTER_FILE_V1.0" ){
137  errorLog << "load(fstream &file) - Invalid file format!" << std::endl;
138  return false;
139  }
140 
141  //Load the number of input dimensions
142  file >> word;
143  if( word != "NumInputDimensions:" ){
144  errorLog << "load(fstream &file) - Failed to read NumInputDimensions header!" << std::endl;
145  return false;
146  }
147  file >> numInputDimensions;
148 
149  //Load the number of output dimensions
150  file >> word;
151  if( word != "NumOutputDimensions:" ){
152  errorLog << "load(fstream &file) - Failed to read NumOutputDimensions header!" << std::endl;
153  return false;
154  }
155  file >> numOutputDimensions;
156 
157  //Load the filter factor
158  file >> word;
159  if( word != "FilterFactor:" ){
160  errorLog << "load(fstream &file) - Failed to read FilterFactor header!" << std::endl;
161  return false;
162  }
163  file >> filterFactor;
164 
165  //Load the number of output dimensions
166  file >> word;
167  if( word != "Gain:" ){
168  errorLog << "load(fstream &file) - Failed to read Gain header!" << std::endl;
169  return false;
170  }
171  file >> gain;
172 
173  //Init the filter module to ensure everything is initialized correctly
174  return init(filterFactor,gain,numInputDimensions);
175 }
176 
177 bool LowPassFilter::init(Float filterFactor,Float gain,UINT numDimensions){
178 
179  initialized = false;
180 
181  if( numDimensions == 0 ){
182  errorLog << "init(Float filterFactor,Float gain,UINT numDimensions) - NumDimensions must be greater than 0!" << std::endl;
183  return false;
184  }
185 
186  if( filterFactor <= 0 ){
187  errorLog << "init(Float filterFactor,Float gain,UINT numDimensions) - FilterFactor must be greater than 0!" << std::endl;
188  return false;
189  }
190 
191  if( gain <= 0 ){
192  errorLog << "init(Float filterFactor,Float gain,UINT numDimensions) - Gain must be greater than 0!" << std::endl;
193  return false;
194  }
195 
196  this->filterFactor = filterFactor;
197  this->gain = gain;
198  this->numInputDimensions = numDimensions;
199  this->numOutputDimensions = numDimensions;
200  yy.clear();
201  yy.resize(numDimensions,0);
202  processedData.clear();
203  processedData.resize(numDimensions,0);
204  initialized = true;
205 
206  return true;
207 }
208 
209 Float LowPassFilter::filter(Float x){
210 
211  //If the filter has not been initialised then return 0, otherwise filter x and return y
212  if( !initialized ){
213  errorLog << "filter(Float x) - The filter has not been initialized!" << std::endl;
214  return 0;
215  }
216 
217  VectorFloat y = filter(VectorFloat(1,x));
218 
219  if( y.size() == 0 ) return 0;
220  return y[0];
221 
222 }
223 
225 
226  if( !initialized ){
227  errorLog << "filter(const VectorFloat &x) - Not Initialized!" << std::endl;
228  return VectorFloat();
229  }
230 
231  if( x.size() != numInputDimensions ){
232  errorLog << "filter(const VectorFloat &x) - The Number Of Input Dimensions (" << numInputDimensions << ") does not match the size of the input vector (" << x.size() << ")!" << std::endl;
233  return VectorFloat();
234  }
235 
236  //Exponential moving average filter: lastOutput*alpha + (1.0f-alpha)*input;
237  for(UINT n=0; n<numInputDimensions; n++){
238  processedData[n] = (yy[n] * filterFactor) + (x[n] * (1.0 - filterFactor)) * gain;
239  yy[n] = processedData[n];
240  }
241  return processedData;
242 }
243 
244 bool LowPassFilter::setGain(Float gain){
245  if( gain > 0 ){
246  this->gain = gain;
247  reset();
248  return true;
249  }
250  errorLog << "setGain(Float gain) - Gain value must be greater than 0!" << std::endl;
251  return false;
252 }
253 
254 bool LowPassFilter::setFilterFactor(Float filterFactor){
255  if( filterFactor > 0 ){
256  this->filterFactor = filterFactor;
257  reset();
258  return true;
259  }
260  errorLog << "setFilterFactor(Float filterFactor) - FilterFactor value must be greater than 0!" << std::endl;
261  return false;
262 }
263 
264 bool LowPassFilter::setCutoffFrequency(Float cutoffFrequency,Float delta){
265  if( cutoffFrequency > 0 && delta > 0 ){
266  Float RC = (1.0/TWO_PI) /cutoffFrequency;
267  filterFactor = delta / (RC+delta);
268  reset();
269  return true;
270  }
271  return false;
272 }
273 
274 GRT_END_NAMESPACE
bool setFilterFactor(Float filterFactor)
LowPassFilter & operator=(const LowPassFilter &rhs)
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
virtual bool process(const VectorFloat &inputVector)
virtual bool reset()
Float gain
The gain factor of the filter.
Float filterFactor
The filter factor (alpha) of the filter.
LowPassFilter(Float filterFactor=0.1, Float gain=1, UINT numDimensions=1, Float cutoffFrequency=-1, Float delta=-1)
std::string getPreProcessingType() const
The class implements a low pass filter, this is based on an Exponential moving average filter: https:...
Float filter(const Float x)
VectorFloat yy
The previous output value(s)
bool setGain(Float gain)
virtual bool save(std::fstream &file) const
virtual ~LowPassFilter()
virtual bool deepCopyFrom(const PreProcessing *preProcessing)
virtual bool load(std::fstream &file)
bool copyBaseVariables(const PreProcessing *preProcessingModule)
bool setCutoffFrequency(Float cutoffFrequency, Float delta)