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