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