pktools  2.6.3
Processing Kernel for geospatial data
Filter.h
1 /**********************************************************************
2 Filter.h: class for filtering
3 Copyright (C) 2008-2012 Pieter Kempeneers
4 
5 This file is part of pktools
6 
7 pktools is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 pktools is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with pktools. If not, see <http://www.gnu.org/licenses/>.
19 ***********************************************************************/
20 #ifndef _MYFILTER_H_
21 #define _MYFILTER_H_
22 
23 #include <vector>
24 #include <iostream>
25 extern "C" {
26 #include <gsl/gsl_sort.h>
27 #include <gsl/gsl_wavelet.h>
28 }
29 #include "StatFactory.h"
30 #include "imageclasses/ImgReaderGdal.h"
31 #include "imageclasses/ImgWriterGdal.h"
32 
33 namespace filter
34 {
35 
36  enum FILTER_TYPE { median=0, var=1 , min=2, max=3, sum=4, mean=5, minmax=6, dilate=7, erode=8, close=9, open=10, homog=11, sobelx=12, sobely=13, sobelxy=14, sobelyx=-14, smooth=15, density=16, mode=17, mixed=18, smoothnodata=19, threshold=20, ismin=21, ismax=22, heterog=23, order=24, stdev=25, dwt=26, dwti=27, dwt_cut=28, dwt_cut_from=29, savgolay=30, percentile=31};
37 
38  enum PADDING { symmetric=0, replicate=1, circular=2, zero=3};
39 
40 class Filter
41 {
42 public:
43  Filter(void);
44  Filter(const std::vector<double> &taps);
45  virtual ~Filter(){};
46 
47  void setPadding(const std::string& padString){
48  m_padding=padString;
49  };
50 
51  static const gsl_wavelet_type* getWaveletType(const std::string waveletType){
52  if(waveletType=="daubechies") return(gsl_wavelet_daubechies);
53  if(waveletType=="daubechies_centered") return(gsl_wavelet_daubechies_centered);
54  if(waveletType=="haar") return(gsl_wavelet_haar);
55  if(waveletType=="haar_centered") return(gsl_wavelet_haar_centered);
56  if(waveletType=="bspline") return(gsl_wavelet_bspline);
57  if(waveletType=="bspline_centered") return(gsl_wavelet_bspline_centered);
58  }
59  static FILTER_TYPE getFilterType(const std::string filterType){
60  std::map<std::string, FILTER_TYPE> m_filterMap;
61  initFilterMap(m_filterMap);
62  return m_filterMap[filterType];
63  };
64 
65  void setTaps(const std::vector<double> &taps, bool normalize=true);
66  void pushClass(short theClass=1){m_class.push_back(theClass);};
67  void pushMask(short theMask=0){m_mask.push_back(theMask);};
68  int pushNoDataValue(double noDataValue=0);//{m_mask.push_back(theMask);};
69  void pushThreshold(double theThreshold){m_threshold.push_back(theThreshold);};
70  void setThresholds(const std::vector<double>& theThresholds){m_threshold=theThresholds;};
71  template<class T> void filter(const std::vector<T>& input, std::vector<T>& output);
72  template<class T> void filter(const std::vector<T>& input, std::vector<T>& output, const std::string& method, int dim);
73  template<class T> void smooth(const std::vector<T>& input, std::vector<T>& output, short dim);
74  template<class T> void smoothNoData(const std::vector<T>& input, const std::string& interpolationType, std::vector<T>& output);
75  template<class T> void filter(T* input, int inputSize, std::vector<T>& output);
76  template<class T> void smooth(T* input, int inputSize, std::vector<T>& output, short dim);
77  //template<class T> void morphology(const std::vector<T>& input, std::vector<T>& output, const std::string& method, int dim, bool verbose=false);
78  void morphology(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& method, int dim, short verbose=0);
79  void filter(const ImgReaderGdal& input, ImgWriterGdal& output);
80  void stat(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& method);
81  void filter(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& method, int dim);
82  void getSavGolayCoefficients(std::vector<double> &c, int np, int nl, int nr, int ld, int m);
83  void ludcmp(std::vector<double> &a, std::vector<int> &indx, double &d);
84  void lubksb(std::vector<double> &a, std::vector<int> &indx, std::vector<double> &b);
85  /* void savgolay(const ImgReaderGdal& input, ImgWriterGdal& output, int np, int nl, int nr, int m); */
86  void smooth(const ImgReaderGdal& input, ImgWriterGdal& output, short dim);
87  void smoothNoData(const ImgReaderGdal& input, const std::string& interpolationType, ImgWriterGdal& output);
88  double getCentreWavelength(const std::vector<double> &wavelengthIn, const Vector2d<double>& srf, const std::string& interpolationType, double delta=1.0, bool verbose=false);
89  template<class T> double applySrf(const std::vector<double> &wavelengthIn, const std::vector<T>& input, const Vector2d<double>& srf, const std::string& interpolationType, T& output, double delta=1.0, bool normalize=false, bool verbose=false);
90  template<class T> double applySrf(const std::vector<double> &wavelengthIn, const Vector2d<T>& input, const Vector2d<double>& srf, const std::string& interpolationType, std::vector<T>& output, double delta=1.0, bool normalize=false, int down=1, bool transposeInput=false, bool verbose=false);
91 
92  template<class T> void applyFwhm(const std::vector<double> &wavelengthIn, const std::vector<T>& input, const std::vector<double> &wavelengthOut, const std::vector<double> &fwhm, const std::string& interpolationType, std::vector<T>& output, bool verbose=false);
93  template<class T> void applyFwhm(const std::vector<double> &wavelengthIn, const Vector2d<T>& input, const std::vector<double> &wavelengthOut, const std::vector<double> &fwhm, const std::string& interpolationType, Vector2d<T>& output, int down=1, bool verbose=false);
94  void dwtForward(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& wavelet_type, int family);
95  void dwtInverse(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& wavelet_type, int family);
96  void dwtCut(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& wavelet_type, int family, double cut);
97  void dwtForward(std::vector<double>& data, const std::string& wavelet_type, int family);
98  void dwtInverse(std::vector<double>& data, const std::string& wavelet_type, int family);
99  void dwtCut(std::vector<double>& data, const std::string& wavelet_type, int family, double cut);
100  void dwtCutFrom(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& wavelet_type, int family, int band);
101 
102 private:
103 
104  static void initFilterMap(std::map<std::string, FILTER_TYPE>& m_filterMap){
105  //initialize Map
106  m_filterMap["dwt"]=filter::dwt;
107  m_filterMap["dwti"]=filter::dwti;
108  m_filterMap["dwt_cut"]=filter::dwt_cut;
109  m_filterMap["dwt_cut_from"]=filter::dwt_cut_from;
110  m_filterMap["stdev"]=filter::stdev;
111  m_filterMap["var"]=filter::var;
112  m_filterMap["min"]=filter::min;
113  m_filterMap["max"]=filter::max;
114  m_filterMap["sum"]=filter::sum;
115  m_filterMap["mean"]=filter::mean;
116  m_filterMap["minmax"]=filter::minmax;
117  m_filterMap["dilate"]=filter::dilate;
118  m_filterMap["erode"]=filter::erode;
119  m_filterMap["close"]=filter::close;
120  m_filterMap["open"]=filter::open;
121  m_filterMap["homog"]=filter::homog;
122  m_filterMap["sobelx"]=filter::sobelx;
123  m_filterMap["sobely"]=filter::sobely;
124  m_filterMap["sobelxy"]=filter::sobelxy;
125  m_filterMap["sobelyx"]=filter::sobelyx;
126  m_filterMap["smooth"]=filter::smooth;
127  m_filterMap["density"]=filter::density;
128  m_filterMap["mode"]=filter::mode;
129  m_filterMap["mixed"]=filter::mixed;
130  m_filterMap["smoothnodata"]=filter::smoothnodata;
131  m_filterMap["threshold"]=filter::threshold;
132  m_filterMap["ismin"]=filter::ismin;
133  m_filterMap["ismax"]=filter::ismax;
134  m_filterMap["heterog"]=filter::heterog;
135  m_filterMap["order"]=filter::order;
136  m_filterMap["median"]=filter::median;
137  m_filterMap["savgolay"]=filter::savgolay;
138  m_filterMap["percentile"]=filter::percentile;
139  }
140 
141 
142  static PADDING getPadding(const std::string& padString){
143  std::map<std::string, PADDING> padMap;
144  padMap["zero"]=filter::zero;
145  padMap["symmetric"]=filter::symmetric;
146  padMap["replicate"]=filter::replicate;
147  padMap["circular"]=filter::circular;
148  return(padMap[padString]);
149  };
150 
151  std::vector<double> m_taps;
152  std::vector<short> m_class;
153  std::vector<short> m_mask;
154  std::string m_padding;
155  std::vector<double> m_noDataValues;
156  std::vector<double> m_threshold;
157 };
158 
159 
160 //input[band], output
161 //returns wavelength for which srf is maximum
162  template<class T> double Filter::applySrf(const std::vector<double> &wavelengthIn, const std::vector<T>& input, const Vector2d<double>& srf, const std::string& interpolationType, T& output, double delta, bool normalize, bool verbose)
163 {
164  assert(srf.size()==2);//[0]: wavelength, [1]: response function
165  int nband=srf[0].size();
166  double start=floor(wavelengthIn[0]);
167  double end=ceil(wavelengthIn.back());
168  if(verbose)
169  std::cout << "wavelengths in [" << start << "," << end << "]" << std::endl << std::flush;
170 
172 
173  gsl_interp_accel *acc;
174  stat.allocAcc(acc);
175  gsl_spline *spline;
176  stat.getSpline(interpolationType,nband,spline);
177  stat.initSpline(spline,&(srf[0][0]),&(srf[1][0]),nband);
178  if(verbose)
179  std::cout << "calculating norm of srf" << std::endl << std::flush;
180  double norm=0;
181  norm=gsl_spline_eval_integ(spline,srf[0].front(),srf[0].back(),acc);
182  if(verbose)
183  std::cout << "norm of srf: " << norm << std::endl << std::flush;
184  gsl_spline_free(spline);
185  gsl_interp_accel_free(acc);
186  //interpolate input and srf to delta
187 
188  std::vector<double> wavelength_fine;
189  for(double win=floor(wavelengthIn[0]);win<=ceil(wavelengthIn.back());win+=delta)
190  wavelength_fine.push_back(win);
191 
192  if(verbose)
193  std::cout << "interpolate wavelengths to " << wavelength_fine.size() << " entries " << std::endl;
194  std::vector<double> srf_fine;//spectral response function, interpolated for wavelength_fine
195 
196  stat.interpolateUp(srf[0],srf[1],wavelength_fine,interpolationType,srf_fine,verbose);
197  assert(srf_fine.size()==wavelength_fine.size());
198 
199  gsl_interp_accel *accOut;
200  stat.allocAcc(accOut);
201  gsl_spline *splineOut;
202  stat.getSpline(interpolationType,wavelength_fine.size(),splineOut);
203  assert(splineOut);
204 
205  assert(wavelengthIn.size()==input.size());
206  std::vector<double> input_fine;
207  std::vector<double> product(wavelength_fine.size());
208  std::vector<double> wavelengthOut(wavelength_fine.size());
209  stat.interpolateUp(wavelengthIn,input,wavelength_fine,interpolationType,input_fine,verbose);
210 
211  if(verbose)
212  std::cout << "input_fine.size(): " << input_fine.size() << std::endl;
213  for(int iband=0;iband<input_fine.size();++iband){
214  product[iband]=input_fine[iband]*srf_fine[iband];
215  wavelengthOut[iband]=wavelength_fine[iband]*srf_fine[iband];
216  }
217 
218  assert(input_fine.size()==srf_fine.size());
219  assert(input_fine.size()==wavelength_fine.size());
220  stat.initSpline(splineOut,&(wavelength_fine[0]),&(product[0]),wavelength_fine.size());
221  if(normalize)
222  output=gsl_spline_eval_integ(splineOut,start,end,accOut)/norm;
223  else
224  output=gsl_spline_eval_integ(splineOut,start,end,accOut);
225 
226  stat.initSpline(splineOut,&(wavelength_fine[0]),&(wavelengthOut[0]),wavelength_fine.size());
227  double centreWavelength=gsl_spline_eval_integ(splineOut,start,end,accOut)/norm;
228 
229  gsl_spline_free(splineOut);
230  gsl_interp_accel_free(accOut);
231 
232  return(centreWavelength);
233 }
234 
235 //input[band][sample], output[sample] (if !transposeInput)
236 //returns wavelength for which srf is maximum
237  template<class T> double Filter::applySrf(const std::vector<double> &wavelengthIn, const Vector2d<T>& input, const Vector2d<double>& srf, const std::string& interpolationType, std::vector<T>& output, double delta, bool normalize, int down, bool transposeInput, bool verbose)
238 {
239  assert(srf.size()==2);//[0]: wavelength, [1]: response function
240  int nband=srf[0].size();
241  unsigned int nsample=(transposeInput)? input.size():input[0].size();
242  output.resize((nsample+down-1)/down);
243  double start=floor(wavelengthIn[0]);
244  double end=ceil(wavelengthIn.back());
245  if(verbose)
246  std::cout << "wavelengths in [" << start << "," << end << "]" << std::endl << std::flush;
247 
249 
250  gsl_interp_accel *acc;
251  stat.allocAcc(acc);
252  gsl_spline *spline;
253  stat.getSpline(interpolationType,nband,spline);
254  stat.initSpline(spline,&(srf[0][0]),&(srf[1][0]),nband);
255  if(verbose)
256  std::cout << "calculating norm of srf" << std::endl << std::flush;
257  double norm=0;
258  norm=gsl_spline_eval_integ(spline,srf[0].front(),srf[0].back(),acc);
259  if(verbose)
260  std::cout << "norm of srf: " << norm << std::endl << std::flush;
261  gsl_spline_free(spline);
262  gsl_interp_accel_free(acc);
263  //interpolate input and srf to delta
264 
265  std::vector<double> wavelength_fine;
266  for(double win=floor(wavelengthIn[0]);win<=ceil(wavelengthIn.back());win+=delta)
267  wavelength_fine.push_back(win);
268 
269  if(verbose)
270  std::cout << "interpolate wavelengths to " << wavelength_fine.size() << " entries " << std::endl;
271  std::vector<double> srf_fine;//spectral response function, interpolated for wavelength_fine
272 
273  stat.interpolateUp(srf[0],srf[1],wavelength_fine,interpolationType,srf_fine,verbose);
274  assert(srf_fine.size()==wavelength_fine.size());
275 
276  gsl_interp_accel *accOut;
277  stat.allocAcc(accOut);
278  gsl_spline *splineOut;
279  stat.getSpline(interpolationType,wavelength_fine.size(),splineOut);
280  assert(splineOut);
281 
282  std::vector<double> wavelengthOut;
283  double centreWavelength=0;
284  for(int isample=0;isample<nsample;++isample){
285  if((isample+1+down/2)%down)
286  continue;
287  std::vector<T> inputValues;
288  if(transposeInput)
289  inputValues=input[isample];
290  else
291  input.selectCol(isample,inputValues);
292  assert(wavelengthIn.size()==inputValues.size());
293  std::vector<double> input_fine;
294  std::vector<double> product(wavelength_fine.size());
295  stat.interpolateUp(wavelengthIn,inputValues,wavelength_fine,interpolationType,input_fine,verbose);
296 
297  for(int iband=0;iband<input_fine.size();++iband){
298  product[iband]=input_fine[iband]*srf_fine[iband];
299  if(wavelengthOut.size()<input_fine.size())
300  wavelengthOut.push_back(wavelength_fine[iband]*srf_fine[iband]);
301  }
302 
303  assert(input_fine.size()==srf_fine.size());
304  assert(input_fine.size()==wavelength_fine.size());
305  stat.initSpline(splineOut,&(wavelength_fine[0]),&(product[0]),wavelength_fine.size());
306  if(normalize)
307  output[isample/down]=gsl_spline_eval_integ(splineOut,start,end,accOut)/norm;
308  else
309  output[isample/down]=gsl_spline_eval_integ(splineOut,start,end,accOut);
310 
311  stat.initSpline(splineOut,&(wavelength_fine[0]),&(wavelengthOut[0]),wavelength_fine.size());
312  if(centreWavelength>0);
313  else
314  centreWavelength=gsl_spline_eval_integ(splineOut,start,end,accOut)/norm;
315  }
316  gsl_spline_free(splineOut);
317  gsl_interp_accel_free(accOut);
318 
319  return(centreWavelength);
320 }
321 
322 template<class T> void Filter::applyFwhm(const std::vector<double> &wavelengthIn, const std::vector<T>& input, const std::vector<double> &wavelengthOut, const std::vector<double> &fwhm, const std::string& interpolationType, std::vector<T>& output, bool verbose){
323  double delta=1;//1 nm resolution
324  std::vector<double> stddev(fwhm.size());
325  for(int index=0;index<fwhm.size();++index)
326  stddev[index]=fwhm[index]/2.0/sqrt(2*log(2.0));//http://mathworld.wolfram.com/FullWidthatHalfMaximum.html
327  assert(wavelengthOut.size()==fwhm.size());
328  assert(wavelengthIn.size()==input.size());
329  assert(wavelengthIn[0]<=wavelengthOut[0]);
330  assert(wavelengthIn.back()>=wavelengthOut.back());
332  std::vector<double> input_fine;
333  std::vector<double> wavelength_fine;
334  for(double win=floor(wavelengthIn[0]);win<=ceil(wavelengthIn.back());win+=delta)
335  wavelength_fine.push_back(win);
336  if(verbose){
337  for(int index=0;index<wavelength_fine.size();++index)
338  std::cout << " " << wavelength_fine[index];
339  std::cout << std::endl;
340  std::cout << "interpolate input wavelength to " << delta << " nm resolution (size=" << wavelength_fine.size() << ")" << std::endl;
341  }
342  stat.interpolateUp(wavelengthIn,input,wavelength_fine,interpolationType,input_fine,verbose);
343  int nbandIn=wavelength_fine.size();
344 
345  int nbandOut=wavelengthOut.size();
346  output.resize(nbandOut);
347  Vector2d<double> tf(nbandIn,nbandOut);
348  for(int indexOut=0;indexOut<nbandOut;++indexOut){
349  double norm=0;
350  for(int indexIn=0;indexIn<nbandIn;++indexIn){
351  // tf(indexIn,indexOut)=
352  tf[indexIn][indexOut]=
353  exp((wavelengthOut[indexOut]-wavelength_fine[indexIn])
354  *(wavelength_fine[indexIn]-wavelengthOut[indexOut])
355  /2.0/stddev[indexOut]
356  /stddev[indexOut]);
357  tf[indexIn][indexOut]/=sqrt(2.0*M_PI);
358  tf[indexIn][indexOut]/=stddev[indexOut];
359  norm+=tf[indexIn][indexOut];
360  }
361  output[indexOut]=0;
362  for(int indexIn=0;indexIn<nbandIn;++indexIn)
363  output[indexOut]+=input_fine[indexIn]*tf[indexIn][indexOut]/norm;
364  }
365 }
366 
367 
368  //input[inBand][sample], output[outBand][sample]
369  template<class T> void Filter::applyFwhm(const std::vector<double> &wavelengthIn, const Vector2d<T>& input, const std::vector<double> &wavelengthOut, const std::vector<double> &fwhm, const std::string& interpolationType, Vector2d<T>& output, int down, bool verbose){
370  double delta=1;//1 nm resolution
371  std::vector<double> stddev(fwhm.size());
372  for(int index=0;index<fwhm.size();++index)
373  stddev[index]=fwhm[index]/2.0/sqrt(2*log(2.0));//http://mathworld.wolfram.com/FullWidthatHalfMaximum.html
375  std::vector<double> wavelength_fine;
376  for(double win=floor(wavelengthIn[0]);win<=ceil(wavelengthIn.back());win+=delta)
377  wavelength_fine.push_back(win);
378  assert(wavelengthOut.size()==fwhm.size());
379  assert(wavelengthIn[0]<=wavelengthOut[0]);
380  assert(wavelengthIn.back()>=wavelengthOut.back());
381  if(verbose){
382  for(int index=0;index<wavelength_fine.size();++index)
383  std::cout << " " << wavelength_fine[index];
384  std::cout << std::endl;
385  std::cout << "interpolate input wavelength to " << delta << " nm resolution (size=" << wavelength_fine.size() << ")" << std::endl;
386  }
387  int nbandIn=wavelength_fine.size();
388  int nbandOut=wavelengthOut.size();
389  output.resize(nbandOut,(input[0].size()+down-1)/down);
390 
391  Vector2d<double> tf(nbandIn,nbandOut);
392  std::vector<double> norm(nbandOut);
393  for(int indexOut=0;indexOut<nbandOut;++indexOut){
394  norm[indexOut]=0;
395  for(int indexIn=0;indexIn<nbandIn;++indexIn){
396  tf[indexIn][indexOut]=
397  exp((wavelengthOut[indexOut]-wavelength_fine[indexIn])
398  *(wavelength_fine[indexIn]-wavelengthOut[indexOut])
399  /2.0/stddev[indexOut]
400  /stddev[indexOut]);
401  tf[indexIn][indexOut]/=sqrt(2.0*M_PI);
402  tf[indexIn][indexOut]/=stddev[indexOut];
403  norm[indexOut]+=tf[indexIn][indexOut];
404  }
405  }
406 
407  for(int isample=0;isample<input[0].size();++isample){
408  if((isample+1+down/2)%down)
409  continue;
410  std::vector<T> inputValues;
411  input.selectCol(isample,inputValues);
412  assert(wavelengthIn.size()==inputValues.size());
413  for(int indexOut=0;indexOut<nbandOut;++indexOut){
414  std::vector<double> input_fine;
415  stat.interpolateUp(wavelengthIn,inputValues,wavelength_fine,interpolationType,input_fine,verbose);
416  output[indexOut][(isample+down-1)/down]=0;
417  for(int indexIn=0;indexIn<nbandIn;++indexIn){
418  output[indexOut][(isample+down-1)/down]+=input_fine[indexIn]*tf[indexIn][indexOut]/norm[indexOut];
419  }
420  }
421  }
422 }
423 
424  template<class T> void Filter::smooth(const std::vector<T>& input, std::vector<T>& output, short dim)
425 {
426  assert(dim>0);
427  m_taps.resize(dim);
428  for(int itap=0;itap<dim;++itap)
429  m_taps[itap]=1.0/dim;
430  filter(input,output);
431  }
432 
433  template<class T> void Filter::smoothNoData(const std::vector<T>& input, const std::string& interpolationType, std::vector<T>& output)
434 {
436  stat.setNoDataValues(m_noDataValues);
437  std::vector<double> abscis(input.size());
438  for(int i=0;i<abscis.size();++i)
439  abscis[i]=i;
440  stat.interpolateNoData(abscis,input,interpolationType,output);
441  }
442 
443 template<class T> void Filter::filter(const std::vector<T>& input, std::vector<T>& output)
444 {
445  assert(input.size()>=m_taps.size());
446  output.resize(input.size());
447  int i=0;
448  //start: extend input by padding
449  for(i=0;i<m_taps.size()/2;++i){
450  //todo:introduce nodata?
451  output[i]=m_taps[m_taps.size()/2]*input[i];
452  for(int t=1;t<=m_taps.size()/2;++t){
453  output[i]+=m_taps[m_taps.size()/2+t]*input[i+t];
454  if(i>=t)
455  output[i]+=m_taps[m_taps.size()/2-t]*input[i-t];
456  else{
457  switch(getPadding(m_padding)){
458  case(replicate):
459  output[i]+=m_taps[m_taps.size()/2-t]*input[0];
460  break;
461  case(circular):
462  output[i]+=m_taps[m_taps.size()/2-t]*input[input.size()+i-t];
463  break;
464  case(zero):
465  output[i]+=m_taps[m_taps.size()/2-t]*0;
466  break;
467  case(symmetric):
468  default:
469  output[i]+=m_taps[m_taps.size()/2-t]*input[t-i];
470  break;
471  }
472  }
473  }
474  }
475  //main
476  for(i=m_taps.size()/2;i<input.size()-m_taps.size()/2;++i){
477  //todo:introduce nodata
478  T leaveOut=(*(m_taps.begin()))*input[i-m_taps.size()/2];
479  T include=(m_taps.back())*input[i+m_taps.size()/2];
480  output[i]=0;
481  for(int t=0;t<m_taps.size();++t)
482  output[i]+=input[i-m_taps.size()/2+t]*m_taps[t];
483  }
484  //end: extend input by padding
485  for(i=input.size()-m_taps.size()/2;i<input.size();++i){
486  //todo:introduce nodata?
487  output[i]=m_taps[m_taps.size()/2]*input[i];
488  //todo:introduce nodata?
489  for(int t=1;t<=m_taps.size()/2;++t){
490  output[i]+=m_taps[m_taps.size()/2-t]*input[i-t];
491  if(i+t<input.size())
492  output[i]+=m_taps[m_taps.size()/2+t]*input[i+t];
493  else{
494  switch(getPadding(m_padding)){
495  case(replicate):
496  output[i]+=m_taps[m_taps.size()/2+t]*input.back();
497  break;
498  case(circular):
499  output[i]+=m_taps[m_taps.size()/2+t]*input[t-1];
500  break;
501  case(zero):
502  output[i]+=m_taps[m_taps.size()/2+t]*0;
503  break;
504  case(symmetric):
505  default:
506  output[i]+=m_taps[m_taps.size()/2+t]*input[i-t];
507  break;
508  }
509  }
510  //output[i]+=(m_taps[m_taps.size()/2+t]+m_taps[m_taps.size()/2-t])*input[i-t];
511  }
512  }
513 }
514 
515 //todo: filling statBuffer can be optimized (no need to clear and fill entire buffer, just push back new value...)
516  template<class T> void Filter::filter(const std::vector<T>& input, std::vector<T>& output, const std::string& method, int dim)
517 {
518  bool verbose=false;
519  assert(dim);
520  output.resize(input.size());
521  int i=0;
523  stat.setNoDataValues(m_noDataValues);
524  std::vector<T> statBuffer;
525  short binValue=0;
526  //start: extend input by padding
527  for(i=0;i<dim/2;++i){
528  binValue=0;
529  for(int iclass=0;iclass<m_class.size();++iclass){
530  if(input[i]==m_class[iclass]){
531  binValue=m_class[0];
532  break;
533  }
534  }
535  if(m_class.size())
536  statBuffer.push_back(binValue);
537  else
538  statBuffer.push_back(input[i]);
539 
540  for(int t=1;t<=dim/2;++t){
541  T theValue=input[i+t];
542  for(int iclass=0;iclass<m_class.size();++iclass){
543  if(theValue==m_class[iclass]){
544  binValue=m_class[0];
545  break;
546  }
547  }
548  if(m_class.size())
549  statBuffer.push_back(binValue);
550  else
551  statBuffer.push_back(theValue);
552 
553  if(i>=t){
554  theValue=input[i-t];
555  }
556  else{
557  switch(getPadding(m_padding)){
558  case(replicate):
559  theValue=input[0];
560  break;
561  case(circular):
562  theValue=input[input.size()+i-t];
563  break;
564  case(zero):
565  theValue=0;
566  break;
567  case(symmetric):
568  default:
569  theValue=input[t-i];
570  break;
571  }
572  }
573  for(int iclass=0;iclass<m_class.size();++iclass){
574  if(theValue==m_class[iclass]){
575  binValue=m_class[0];
576  break;
577  }
578  }
579  if(m_class.size())
580  statBuffer.push_back(binValue);
581  else
582  statBuffer.push_back(theValue);
583  }
584 
585  switch(getFilterType(method)){
586  case(filter::median):
587  output[i]=stat.median(statBuffer);
588  break;
589  case(filter::min):
590  case(filter::erode):
591  output[i]=stat.mymin(statBuffer);
592  break;
593  case(filter::max):
594  case(filter::dilate):
595  output[i]=stat.mymax(statBuffer);
596  break;
597  case(filter::sum):
598  output[i]=sqrt(stat.sum(statBuffer));
599  break;
600  case(filter::var):
601  output[i]=stat.var(statBuffer);
602  break;
603  case(filter::stdev):
604  output[i]=sqrt(stat.var(statBuffer));
605  break;
606  case(filter::mean):
607  output[i]=stat.mean(statBuffer);
608  break;
609  case(filter::percentile):
610  assert(m_threshold.size());
611  output[i]=stat.percentile(statBuffer,statBuffer.begin(),statBuffer.end(),m_threshold[0]);
612  break;
613  default:{
614  std::ostringstream ess;
615  ess << "method " << method << " (" << getFilterType(method) << ") not supported";
616  throw(ess.str());
617  break;
618  }
619  }
620  }
621  //main
622  statBuffer.clear();
623  for(i=dim/2;i<input.size()-dim/2;++i){
624  binValue=0;
625  for(int t=0;t<dim;++t){
626  for(int iclass=0;iclass<m_class.size();++iclass){
627  if(input[i-dim/2+t]==m_class[iclass]){
628  binValue=m_class[0];
629  break;
630  }
631  }
632  if(m_class.size())
633  statBuffer.push_back(binValue);
634  else
635  statBuffer.push_back(input[i-dim/2+t]);
636  }
637  switch(getFilterType(method)){
638  case(filter::median):
639  output[i]=stat.median(statBuffer);
640  break;
641  case(filter::min):
642  case(filter::erode):
643  output[i]=stat.mymin(statBuffer);
644  break;
645  case(filter::max):
646  case(filter::dilate):
647  output[i]=stat.mymax(statBuffer);
648  break;
649  case(filter::sum):
650  output[i]=sqrt(stat.sum(statBuffer));
651  break;
652  case(filter::var):
653  output[i]=stat.var(statBuffer);
654  break;
655  case(filter::mean):
656  output[i]=stat.mean(statBuffer);
657  break;
658  case(filter::percentile):
659  assert(m_threshold.size());
660  output[i]=stat.percentile(statBuffer,statBuffer.begin(),statBuffer.end(),m_threshold[0]);
661  break;
662  default:
663  std::string errorString="method not supported";
664  throw(errorString);
665  break;
666  }
667  statBuffer.clear();
668  }
669  //end: extend input by padding
670  for(i=input.size()-dim/2;i<input.size();++i){
671  binValue=0;
672  for(int iclass=0;iclass<m_class.size();++iclass){
673  if(input[i]==m_class[iclass]){
674  binValue=m_class[0];
675  break;
676  }
677  }
678  if(m_class.size())
679  statBuffer.push_back(binValue);
680  else
681  statBuffer.push_back(input[i]);
682 
683  for(int t=1;t<=dim/2;++t){
684  T theValue=input[i-t];
685  for(int iclass=0;iclass<m_class.size();++iclass){
686  if(theValue==m_class[iclass]){
687  binValue=m_class[0];
688  break;
689  }
690  }
691  if(m_class.size())
692  statBuffer.push_back(binValue);
693  else
694  statBuffer.push_back(theValue);
695  if(i+t<input.size())
696  theValue=input[i+t];
697  else{
698  switch(getPadding(m_padding)){
699  case(replicate):
700  theValue=input.back();
701  break;
702  case(circular):
703  theValue=input[t-1];
704  break;
705  case(zero):
706  theValue=0;
707  break;
708  case(symmetric):
709  default:
710  theValue=input[i-t];
711  break;
712  }
713  }
714  for(int iclass=0;iclass<m_class.size();++iclass){
715  if(theValue==m_class[iclass]){
716  binValue=m_class[0];
717  break;
718  }
719  }
720  if(m_class.size())
721  statBuffer.push_back(binValue);
722  else
723  statBuffer.push_back(theValue);
724  }
725  switch(getFilterType(method)){
726  case(filter::median):
727  output[i]=stat.median(statBuffer);
728  break;
729  case(filter::min):
730  case(filter::erode):
731  output[i]=stat.mymin(statBuffer);
732  break;
733  case(filter::max):
734  case(filter::dilate):
735  output[i]=stat.mymax(statBuffer);
736  break;
737  case(filter::sum):
738  output[i]=sqrt(stat.sum(statBuffer));
739  break;
740  case(filter::var):
741  output[i]=stat.var(statBuffer);
742  break;
743  case(filter::mean):
744  output[i]=stat.mean(statBuffer);
745  break;
746  case(filter::percentile):
747  assert(m_threshold.size());
748  output[i]=stat.percentile(statBuffer,statBuffer.begin(),statBuffer.end(),m_threshold[0]);
749  break;
750  default:
751  std::string errorString="method not supported";
752  throw(errorString);
753  break;
754  }
755  }
756  }
757 
758  template<class T> void Filter::smooth(T* input, int inputSize, std::vector<T>& output, short dim)
759 {
760  assert(dim>0);
761  m_taps.resize(dim);
762  for(int itap=0;itap<dim;++itap)
763  m_taps[itap]=1.0/dim;
764  filter(input,output);
765  }
766 
767 template<class T> void Filter::filter(T* input, int inputSize, std::vector<T>& output)
768 {
769  assert(inputSize>=m_taps.size());
770  output.resize(inputSize);
771  int i=0;
772 
773  //start: extend input by padding
774  for(i=0;i<m_taps.size()/2;++i){
775  //todo:introduce nodata
776  output[i]=m_taps[m_taps.size()/2]*input[i];
777 
778  for(int t=1;t<=m_taps.size()/2;++t){
779  output[i]+=m_taps[m_taps.size()/2+t]*input[i+t];
780  if(i>=t)
781  output[i]+=m_taps[m_taps.size()/2-t]*input[i-t];
782  else{
783  switch(getPadding(m_padding)){
784  case(replicate):
785  output[i]+=m_taps[m_taps.size()/2-t]*input[0];
786  break;
787  case(circular):
788  output[i]+=m_taps[m_taps.size()/2-t]*input[input.size()+i-t];
789  break;
790  case(zero):
791  output[i]+=m_taps[m_taps.size()/2-t]*0;
792  break;
793  case(symmetric):
794  default:
795  output[i]+=m_taps[m_taps.size()/2-t]*input[t-i];
796  break;
797  }
798  }
799  }
800  }
801  //main
802  for(i=m_taps.size()/2;i<input.size()-m_taps.size()/2;++i){
803  //todo:introduce nodata
804  T leaveOut=(*(m_taps.begin()))*input[i-m_taps.size()/2];
805  T include=(m_taps.back())*input[i+m_taps.size()/2];
806  output[i]=0;
807  for(int t=0;t<m_taps.size();++t)
808  output[i]+=input[i-m_taps.size()/2+t]*m_taps[t];
809  }
810  //end: extend input by padding
811  for(i=input.size()-m_taps.size()/2;i<input.size();++i){
812  //todo:introduce nodata
813  output[i]=m_taps[m_taps.size()/2]*input[i];
814  //todo:introduce nodata
815  for(int t=1;t<=m_taps.size()/2;++t){
816  output[i]+=m_taps[m_taps.size()/2-t]*input[i-t];
817  if(i+t<input.size())
818  output[i]+=m_taps[m_taps.size()/2+t]*input[i+t];
819  else{
820  switch(getPadding(m_padding)){
821  case(replicate):
822  output[i]+=m_taps[m_taps.size()/2+t]*input.back();
823  break;
824  case(circular):
825  output[i]+=m_taps[m_taps.size()/2+t]*input[t-1];
826  break;
827  case(zero):
828  output[i]+=m_taps[m_taps.size()/2+t]*0;
829  break;
830  case(symmetric):
831  default:
832  output[i]+=m_taps[m_taps.size()/2+t]*input[i-t];
833  break;
834  }
835  }
836  }
837  }
838 }
839 
840 }
841 
842 #endif /* _MYFILTER_H_ */