pktools  2.6.4
Processing Kernel for geospatial data
Filter2d.h
1 /**********************************************************************
2 Filter2d.h: class for filtering images
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 _MYFILTER2D_H_
21 #define _MYFILTER2D_H_
22 
23 #ifndef PI
24 #define PI 3.1415926535897932384626433832795
25 #endif
26 
27 #ifndef DEG2RAD
28 #define DEG2RAD(DEG) (DEG/180.0*PI)
29 #endif
30 
31 #ifndef RAD2DEG
32 #define RAD2DEG(RAD) (RAD/PI*180)
33 #endif
34 
35 #ifdef WIN32
36 #include <process.h>
37 #define getpid _getpid
38 #endif
39 
40 #include <assert.h>
41 #include <math.h>
42 #include <limits>
43 #include <vector>
44 #include <string>
45 #include <map>
46 extern "C" {
47 #include <gsl/gsl_sort.h>
48 #include <gsl/gsl_wavelet.h>
49 #include <gsl/gsl_wavelet2d.h>
50 #include <gsl/gsl_rng.h>
51 #include <gsl/gsl_randist.h>
52 }
53 #include "base/Vector2d.h"
54 #include "Filter.h"
55 #include "imageclasses/ImgReaderGdal.h"
56 #include "imageclasses/ImgWriterGdal.h"
57 #include "algorithms/StatFactory.h"
58 
59 namespace filter2d
60 {
61  enum FILTER_TYPE { median=100, var=101 , min=102, max=103, sum=104, mean=105, minmax=106, dilate=107, erode=108, close=109, open=110, homog=111, sobelx=112, sobely=113, sobelxy=114, sobelyx=115, smooth=116, density=117, mode=118, mixed=119, threshold=120, ismin=121, ismax=122, heterog=123, order=124, stdev=125, mrf=126, dwt=127, dwti=128, dwt_cut=129, scramble=130, shift=131, linearfeature=132, smoothnodata=133, countid=134, dwt_cut_from=135, savgolay=136, percentile=137};
62 
63  enum RESAMPLE { NEAR = 0, BILINEAR = 1, BICUBIC = 2 };//bicubic not supported yet...
64 
65 class Filter2d
66 {
67 public:
68  Filter2d(void);
69  Filter2d(const Vector2d<double> &taps);
70  virtual ~Filter2d(){};
71  static FILTER_TYPE getFilterType(const std::string filterType){
72  std::map<std::string, FILTER_TYPE> m_filterMap;
73  initMap(m_filterMap);
74  return m_filterMap[filterType];
75  };
76  static const RESAMPLE getResampleType(const std::string resampleType){
77  if(resampleType=="near") return(NEAR);
78  else if(resampleType=="bilinear") return(BILINEAR);
79  else{
80  std::string errorString="resampling type not supported: ";
81  errorString+=resampleType;
82  errorString+=" use near or bilinear";
83  throw(errorString);
84  }
85  };
86 
87  void setTaps(const Vector2d<double> &taps);
88  /* void setNoValue(double noValue=0){m_noValue=noValue;}; */
89  void pushClass(short theClass=1){m_class.push_back(theClass);};
90  int pushNoDataValue(double noDataValue=0);//{m_mask.push_back(theMask);};
91  void pushThreshold(double theThreshold){m_threshold.push_back(theThreshold);};
92  void setThresholds(const std::vector<double>& theThresholds){m_threshold=theThresholds;};
93  void setClasses(const std::vector<short>& theClasses){m_class=theClasses;};
94  void filter(const ImgReaderGdal& input, ImgWriterGdal& output, bool absolute=false, bool normalize=false, bool noData=false);
95  void smooth(const ImgReaderGdal& input, ImgWriterGdal& output,int dim);
96  void smooth(const ImgReaderGdal& input, ImgWriterGdal& output,int dimX, int dimY);
97  void smoothNoData(const ImgReaderGdal& input, ImgWriterGdal& output,int dim);
98  void smoothNoData(const ImgReaderGdal& input, ImgWriterGdal& output,int dimX, int dimY);
99  template<class T1, class T2> void filter(const Vector2d<T1>& inputVector, Vector2d<T2>& outputVector);
100  template<class T1, class T2> void smooth(const Vector2d<T1>& inputVector, Vector2d<T2>& outputVector,int dim);
101  template<class T1, class T2> void smooth(const Vector2d<T1>& inputVector, Vector2d<T2>& outputVector,int dimX, int dimY);
102  void dwtForward(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& wavelet_type, int family);
103  void dwtInverse(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& wavelet_type, int family);
104  void dwtCut(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& wavelet_type, int family, double cut, bool verbose=false);
105  template<class T> void dwtForward(Vector2d<T>& data, const std::string& wavelet_type, int family);
106  template<class T> void dwtInverse(Vector2d<T>& data, const std::string& wavelet_type, int family);
107  template<class T> void dwtCut(Vector2d<T>& data, const std::string& wavelet_type, int family, double cut);
108  void majorVoting(const std::string& inputFilename, const std::string& outputFilename,int dim=0,const std::vector<int> &prior=std::vector<int>());
109  /* void homogeneousSpatial(const std::string& inputFilename, const std::string& outputFilename, int dim, bool disc=false, int noValue=0); */
110  void doit(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& method, int dim, short down=1, bool disc=false);
111  void doit(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& method, int dimX, int dimY, short down=1, bool disc=false);
112  void mrf(const ImgReaderGdal& input, ImgWriterGdal& output, int dimX, int dimY, double beta, bool eightConnectivity=true, short down=1, bool verbose=false);
113  void mrf(const ImgReaderGdal& input, ImgWriterGdal& output, int dimX, int dimY, Vector2d<double> beta, bool eightConnectivity=true, short down=1, bool verbose=false);
114  template<class T1, class T2> void doit(const Vector2d<T1>& inputVector, Vector2d<T2>& outputVector, const std::string& method, int dimX, int dimY, short down=1, bool disc=false);
115  void median(const std::string& inputFilename, const std::string& outputFilename, int dim, bool disc=false);
116  void var(const std::string& inputFilename, const std::string& outputFilename, int dim, bool disc=false);
117  void morphology(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& method, int dimX, int dimY, const std::vector<double> &angle, bool disc=false);
118  template<class T> unsigned long int morphology(const Vector2d<T>& input, Vector2d<T>& output, const std::string& method, int dimX, int dimY, bool disc=false, double hThreshold=0);
119  template<class T> unsigned long int dsm2dtm_nwse(const Vector2d<T>& inputDSM, Vector2d<T>& outputMask, double hThreshold, int nlimit, int dim=3);
120  template<class T> unsigned long int dsm2dtm_nesw(const Vector2d<T>& inputDSM, Vector2d<T>& outputMask, double hThreshold, int nlimit, int dim=3);
121  template<class T> unsigned long int dsm2dtm_senw(const Vector2d<T>& inputDSM, Vector2d<T>& outputMask, double hThreshold, int nlimit, int dim=3);
122  template<class T> unsigned long int dsm2dtm_swne(const Vector2d<T>& inputDSM, Vector2d<T>& outputMask, double hThreshold, int nlimit, int dim=3);
123  template<class T> void shadowDsm(const Vector2d<T>& input, Vector2d<T>& output, double sza, double saa, double pixelSize, short shadowFlag=1);
124  void shadowDsm(const ImgReaderGdal& input, ImgWriterGdal& output, double sza, double saa, double pixelSize, short shadowFlag=1);
125  void dwt_texture(const std::string& inputFilename, const std::string& outputFilename,int dim, int scale, int down=1, int iband=0, bool verbose=false);
126  void shift(const ImgReaderGdal& input, ImgWriterGdal& output, double offsetX=0, double offsetY=0, double randomSigma=0, RESAMPLE resample=BILINEAR, bool verbose=false);
127  template<class T> void shift(const Vector2d<T>& input, Vector2d<T>& output, double offsetX=0, double offsetY=0, double randomSigma=0, RESAMPLE resample=NEAR, bool verbose=false);
128  void linearFeature(const Vector2d<float>& input, std::vector< Vector2d<float> >& output, float angle=361, float angleStep=1, float maxDistance=0, float eps=0, bool l1=true, bool a1=true, bool l2=true, bool a2=true, bool verbose=false);
129  void linearFeature(const ImgReaderGdal& input, ImgWriterGdal& output, float angle=361, float angleStep=1, float maxDistance=0, float eps=0, bool l1=true, bool a1=true, bool l2=true, bool a2=true, int band=0, bool verbose=false);
130 
131 private:
132  static void initMap(std::map<std::string, FILTER_TYPE>& m_filterMap){
133  //initialize selMap
134  m_filterMap["median"]=filter2d::median;
135  m_filterMap["var"]=filter2d::var;
136  m_filterMap["min"]=filter2d::min;
137  m_filterMap["max"]=filter2d::max;
138  m_filterMap["sum"]=filter2d::sum;
139  m_filterMap["mean"]=filter2d::mean;
140  m_filterMap["minmax"]=filter2d::minmax;
141  m_filterMap["dilate"]=filter2d::dilate;
142  m_filterMap["erode"]=filter2d::erode;
143  m_filterMap["close"]=filter2d::close;
144  m_filterMap["open"]=filter2d::open;
145  m_filterMap["homog"]=filter2d::homog;
146  m_filterMap["sobelx"]=filter2d::sobelx;
147  m_filterMap["sobely"]=filter2d::sobely;
148  m_filterMap["sobelxy"]=filter2d::sobelxy;
149  m_filterMap["sobelyx"]=filter2d::sobelyx;
150  m_filterMap["smooth"]=filter2d::smooth;
151  m_filterMap["density"]=filter2d::density;
152  m_filterMap["mode"]=filter2d::mode;
153  m_filterMap["mixed"]=filter2d::mixed;
154  m_filterMap["smoothnodata"]=filter2d::smoothnodata;
155  m_filterMap["threshold"]=filter2d::threshold;
156  m_filterMap["ismin"]=filter2d::ismin;
157  m_filterMap["ismax"]=filter2d::ismax;
158  m_filterMap["heterog"]=filter2d::heterog;
159  m_filterMap["order"]=filter2d::order;
160  m_filterMap["stdev"]=filter2d::stdev;
161  m_filterMap["mrf"]=filter2d::mrf;
162  m_filterMap["dwt"]=filter2d::dwt;
163  m_filterMap["dwti"]=filter2d::dwti;
164  m_filterMap["dwt_cut"]=filter2d::dwt_cut;
165  m_filterMap["dwt_cut_from"]=filter2d::dwt_cut_from;
166  m_filterMap["scramble"]=filter2d::scramble;
167  m_filterMap["shift"]=filter2d::shift;
168  m_filterMap["linearfeature"]=filter2d::linearfeature;
169  m_filterMap["countid"]=filter2d::countid;
170  m_filterMap["savgolay"]=filter2d::savgolay;
171  m_filterMap["percentile"]=filter2d::percentile;
172  }
173 
174  Vector2d<double> m_taps;
175  /* double m_noValue; */
176  std::vector<short> m_class;
177  /* std::vector<short> m_mask; */
178  std::vector<double> m_noDataValues;
179  std::vector<double> m_threshold;
180 };
181 
182 
183  template<class T1, class T2> void Filter2d::smooth(const Vector2d<T1>& inputVector, Vector2d<T2>& outputVector,int dim)
184  {
185  smooth(inputVector,outputVector,dim,dim);
186  }
187 
188  template<class T1, class T2> void Filter2d::smooth(const Vector2d<T1>& inputVector, Vector2d<T2>& outputVector,int dimX, int dimY)
189  {
190  m_taps.resize(dimY);
191  for(int j=0;j<dimY;++j){
192  m_taps[j].resize(dimX);
193  for(int i=0;i<dimX;++i)
194  m_taps[j][i]=1.0/dimX/dimY;
195  }
196  filter(inputVector,outputVector);
197  }
198 
199  template<class T1, class T2> void Filter2d::filter(const Vector2d<T1>& inputVector, Vector2d<T2>& outputVector)
200  {
201  outputVector.resize(inputVector.size());
202  int dimX=m_taps[0].size();//horizontal!!!
203  int dimY=m_taps.size();//vertical!!!
204  Vector2d<T1> inBuffer(dimY);
205  std::vector<T2> outBuffer(inputVector[0].size());
206  //initialize last half of inBuffer
207  int indexI=0;
208  int indexJ=0;
209  //initialize last half of inBuffer
210  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
211  inBuffer[indexJ]=inputVector[abs(j)];
212  ++indexJ;
213  }
214 
215  for(int y=0;y<inputVector.size();++y){
216  if(y){//inBuffer already initialized for y=0
217  //erase first line from inBuffer
218  inBuffer.erase(inBuffer.begin());
219  //read extra line and push back to inBuffer if not out of bounds
220  if(y+dimY/2<inputVector.size()){
221  //allocate buffer
222  inBuffer.push_back(inputVector[y+dimY/2]);
223  }
224  else{
225  int over=y+dimY/2-inputVector.nRows();
226  int index=(inBuffer.size()-1)-over;
227  assert(index>=0);
228  assert(index<inBuffer.size());
229  inBuffer.push_back(inBuffer[index]);
230  }
231  }
232  for(int x=0;x<inputVector.nCols();++x){
233  outBuffer[x]=0;
234  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
235  for(int i=-(dimX-1)/2;i<=dimX/2;++i){
236  indexI=x+i;
237  indexJ=(dimY-1)/2+j;
238  //check if out of bounds
239  if(x<(dimX-1)/2)
240  indexI=x+abs(i);
241  else if(x>=inputVector.nCols()-(dimX-1)/2)
242  indexI=x-abs(i);
243  if(y<(dimY-1)/2)
244  indexJ=(dimY-1)/2+abs(j);
245  else if(y>=inputVector.nRows()-(dimY-1)/2)
246  indexJ=(dimY-1)/2-abs(j);
247  outBuffer[x]+=(m_taps[(dimY-1)/2+j][(dimX-1)/2+i]*inBuffer[indexJ][indexI]);
248  }
249  }
250  }
251  //copy outBuffer to outputVector
252  outputVector[y]=outBuffer;
253  }
254  }
255 
256 template<class T1, class T2> void Filter2d::doit(const Vector2d<T1>& inputVector, Vector2d<T2>& outputVector, const std::string& method, int dimX, int dimY, short down, bool disc)
257 {
258  const char* pszMessage;
259  void* pProgressArg=NULL;
260  GDALProgressFunc pfnProgress=GDALTermProgress;
261  double progress=0;
262  pfnProgress(progress,pszMessage,pProgressArg);
263 
264  double noDataValue=0;
265  if(m_noDataValues.size())
266  noDataValue=m_noDataValues[0];
267 
268  assert(dimX);
269  assert(dimY);
270 
272  outputVector.resize((inputVector.size()+down-1)/down);
273  Vector2d<T1> inBuffer(dimY);
274  std::vector<T2> outBuffer((inputVector[0].size()+down-1)/down);
275  int indexI=0;
276  int indexJ=0;
277  //initialize last half of inBuffer
278  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
279  inBuffer[indexJ]=inputVector[abs(j)];
280  ++indexJ;
281  }
282  for(int y=0;y<inputVector.size();++y){
283  if(y){//inBuffer already initialized for y=0
284  //erase first line from inBuffer
285  inBuffer.erase(inBuffer.begin());
286  //read extra line and push back to inBuffer if not out of bounds
287  if(y+dimY/2<inputVector.size())
288  inBuffer.push_back(inputVector[y+dimY/2]);
289  else{
290  int over=y+dimY/2-inputVector.size();
291  int index=(inBuffer.size()-1)-over;
292  assert(index>=0);
293  assert(index<inBuffer.size());
294  inBuffer.push_back(inBuffer[index]);
295  }
296  }
297  if((y+1+down/2)%down)
298  continue;
299  for(int x=0;x<inputVector[0].size();++x){
300  if((x+1+down/2)%down)
301  continue;
302  outBuffer[x/down]=0;
303  std::vector<double> windowBuffer;
304  std::map<int,int> occurrence;
305  int centre=dimX*(dimY-1)/2+(dimX-1)/2;
306  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
307  for(int i=-(dimX-1)/2;i<=dimX/2;++i){
308  indexI=x+i;
309  //check if out of bounds
310  if(indexI<0)
311  indexI=-indexI;
312  else if(indexI>=inputVector[0].size())
313  indexI=inputVector[0].size()-i;
314  if(y+j<0)
315  indexJ=-j;
316  else if(y+j>=inputVector.size())
317  indexJ=(dimY>2) ? (dimY-1)/2-j : 0;
318  else
319  indexJ=(dimY-1)/2+j;
320  bool masked=false;
321  for(int imask=0;imask<m_noDataValues.size();++imask){
322  if(inBuffer[indexJ][indexI]==m_noDataValues[imask]){
323  masked=true;
324  break;
325  }
326  }
327  if(!masked){
328  std::vector<short>::const_iterator vit=m_class.begin();
329  //todo: test if this works (only add occurrence if within defined classes)!
330  if(!m_class.size())
331  ++occurrence[inBuffer[indexJ][indexI]];
332  else{
333  while(vit!=m_class.end()){
334  if(inBuffer[indexJ][indexI]==*(vit++))
335  ++occurrence[inBuffer[indexJ][indexI]];
336  }
337  }
338  windowBuffer.push_back(inBuffer[indexJ][indexI]);
339  }
340  }
341  }
342  switch(getFilterType(method)){
343  case(filter2d::median):
344  if(windowBuffer.empty())
345  outBuffer[x/down]=noDataValue;
346  else
347  outBuffer[x/down]=stat.median(windowBuffer);
348  break;
349  case(filter2d::var):{
350  if(windowBuffer.empty())
351  outBuffer[x/down]=noDataValue;
352  else
353  outBuffer[x/down]=stat.var(windowBuffer);
354  break;
355  }
356  case(filter2d::stdev):{
357  if(windowBuffer.empty())
358  outBuffer[x/down]=noDataValue;
359  else
360  outBuffer[x/down]=sqrt(stat.var(windowBuffer));
361  break;
362  }
363  case(filter2d::mean):{
364  if(windowBuffer.empty())
365  outBuffer[x/down]=noDataValue;
366  else
367  outBuffer[x/down]=stat.mean(windowBuffer);
368  break;
369  }
370  case(filter2d::min):{
371  if(windowBuffer.empty())
372  outBuffer[x/down]=noDataValue;
373  else
374  outBuffer[x/down]=stat.mymin(windowBuffer);
375  break;
376  }
377  case(filter2d::ismin):{
378  if(windowBuffer.empty())
379  outBuffer[x/down]=noDataValue;
380  else
381  outBuffer[x/down]=(stat.mymin(windowBuffer)==windowBuffer[centre])? 1:0;
382  break;
383  }
384  case(filter2d::minmax):{
385  double min=0;
386  double max=0;
387  if(windowBuffer.empty())
388  outBuffer[x/down]=noDataValue;
389  else{
390  stat.minmax(windowBuffer,windowBuffer.begin(),windowBuffer.end(),min,max);
391  if(min!=max)
392  outBuffer[x/down]=0;
393  else
394  outBuffer[x/down]=windowBuffer[centre];//centre pixels
395  }
396  break;
397  }
398  case(filter2d::max):{
399  if(windowBuffer.empty())
400  outBuffer[x/down]=noDataValue;
401  else
402  outBuffer[x/down]=stat.mymax(windowBuffer);
403  break;
404  }
405  case(filter2d::ismax):{
406  if(windowBuffer.empty())
407  outBuffer[x/down]=noDataValue;
408  else
409  outBuffer[x/down]=(stat.mymax(windowBuffer)==windowBuffer[centre])? 1:0;
410  break;
411  }
412  case(filter2d::order):{
413  if(windowBuffer.empty())
414  outBuffer[x/down]=noDataValue;
415  else{
416  double lbound=0;
417  double ubound=dimX*dimY;
418  double theMin=stat.mymin(windowBuffer);
419  double theMax=stat.mymax(windowBuffer);
420  double scale=(ubound-lbound)/(theMax-theMin);
421  outBuffer[x/down]=static_cast<short>(scale*(windowBuffer[centre]-theMin)+lbound);
422  }
423  break;
424  }
425  case(filter2d::sum):{
426  outBuffer[x/down]=stat.sum(windowBuffer);
427  break;
428  }
429  case(filter2d::percentile):{
430  assert(m_threshold.size());
431  outBuffer[x/down]=stat.percentile(windowBuffer,windowBuffer.begin(),windowBuffer.end(),m_threshold[0]);
432  break;
433  }
434  case(filter2d::homog):
435  if(occurrence.size()==1)//all values in window must be the same
436  outBuffer[x/down]=inBuffer[(dimY-1)/2][x];
437  else//favorize original value in case of ties
438  outBuffer[x/down]=noDataValue;
439  break;
440  case(filter2d::heterog):{
441  for(std::vector<double>::const_iterator wit=windowBuffer.begin();wit!=windowBuffer.end();++wit){
442  if(wit==windowBuffer.begin()+windowBuffer.size()/2)
443  continue;
444  else if(*wit!=inBuffer[(dimY-1)/2][x])
445  outBuffer[x/down]=1;
446  else if(*wit==inBuffer[(dimY-1)/2][x]){//todo:wit mag niet central pixel zijn
447  outBuffer[x/down]=noDataValue;
448  break;
449  }
450  }
451  break;
452  }
453  case(filter2d::density):{
454  if(windowBuffer.size()){
455  std::vector<short>::const_iterator vit=m_class.begin();
456  while(vit!=m_class.end())
457  outBuffer[x/down]+=100.0*occurrence[*(vit++)]/windowBuffer.size();
458  }
459  else
460  outBuffer[x/down]=noDataValue;
461  break;
462  }
463  case(filter2d::countid):{
464  if(windowBuffer.size())
465  outBuffer[x/down]=occurrence.size();
466  else
467  outBuffer[x/down]=noDataValue;
468  break;
469  }
470  case(filter2d::mode):{
471  if(occurrence.size()){
472  std::map<int,int>::const_iterator maxit=occurrence.begin();
473  for(std::map<int,int>::const_iterator mit=occurrence.begin();mit!=occurrence.end();++mit){
474  if(mit->second>maxit->second)
475  maxit=mit;
476  }
477  if(occurrence[inBuffer[(dimY-1)/2][x]]<maxit->second)//
478  outBuffer[x/down]=maxit->first;
479  else//favorize original value in case of ties
480  outBuffer[x/down]=inBuffer[(dimY-1)/2][x];
481  }
482  else
483  outBuffer[x/down]=noDataValue;
484  break;
485  }
486  case(filter2d::threshold):{
487  assert(m_class.size()==m_threshold.size());
488  if(windowBuffer.size()){
489  outBuffer[x/down]=inBuffer[(dimY-1)/2][x];//initialize with original value (in case thresholds not met)
490  for(int iclass=0;iclass<m_class.size();++iclass){
491  if(100.0*(occurrence[m_class[iclass]])/windowBuffer.size()>m_threshold[iclass])
492  outBuffer[x/down]=m_class[iclass];
493  }
494  }
495  else
496  outBuffer[x/down]=noDataValue;
497  break;
498  }
499  case(filter2d::scramble):{//could be done more efficiently window by window with random shuffling entire buffer and assigning entire buffer at once to output image...
500  if(windowBuffer.size()){
501  int randomIndex=std::rand()%windowBuffer.size();
502  if(randomIndex>=windowBuffer.size())
503  outBuffer[x/down]=windowBuffer.back();
504  else if(randomIndex<0)
505  outBuffer[x/down]=windowBuffer[0];
506  else
507  outBuffer[x/down]=windowBuffer[randomIndex];
508  }
509  else
510  outBuffer[x/down]=noDataValue;
511  break;
512  }
513  case(filter2d::mixed):{
514  enum MixType { BF=11, CF=12, MF=13, NF=20, W=30 };
515  double nBF=occurrence[BF];
516  double nCF=occurrence[CF];
517  double nMF=occurrence[MF];
518  double nNF=occurrence[NF];
519  double nW=occurrence[W];
520  if(windowBuffer.size()){
521  if((nBF+nCF+nMF)&&(nBF+nCF+nMF>=nNF+nW)){//forest
522  if(nBF/(nBF+nCF)>=0.75)
523  outBuffer[x/down]=BF;
524  else if(nCF/(nBF+nCF)>=0.75)
525  outBuffer[x/down]=CF;
526  else
527  outBuffer[x/down]=MF;
528  }
529  else{//non-forest
530  if(nW&&(nW>=nNF))
531  outBuffer[x/down]=W;
532  else
533  outBuffer[x/down]=NF;
534  }
535  }
536  else
537  outBuffer[x/down]=inBuffer[indexJ][indexI];
538  break;
539  }
540  default:
541  break;
542  }
543  }
544  progress=(1.0+y/down);
545  progress+=(outputVector.size());
546  progress/=outputVector.size();
547  pfnProgress(progress,pszMessage,pProgressArg);
548  //copy outBuffer to outputVector
549  outputVector[y/down]=outBuffer;
550  }
551 }
552 
553 // class Compare_mapValue{
554 // public:
555 // int operator() (const map<int,int>::value_type& v1, const map<int, int>::value_type& v2) const{
556 // return (v1.second)>(v2.second);
557 // }
558 // };
559 
560 template<class T> void Filter2d::shift(const Vector2d<T>& input, Vector2d<T>& output, double offsetX, double offsetY, double randomSigma, RESAMPLE resample, bool verbose){
561  output.resize(input.nRows(),input.nCols());
562  const gsl_rng_type *rangenType;
563  gsl_rng *rangen;
564  gsl_rng_env_setup();
565  rangenType=gsl_rng_default;
566  rangen=gsl_rng_alloc(rangenType);
567  long seed=time(NULL)*getpid();
568  gsl_rng_set(rangen,seed);
569  const char* pszMessage;
570  void* pProgressArg=NULL;
571  GDALProgressFunc pfnProgress=GDALTermProgress;
572  double progress=0;
573  pfnProgress(progress,pszMessage,pProgressArg);
574  for(int j=0;j<input.nRows();++j){
575  for(int i=0;i<input.nCols();++i){
576  T theValue=0;
577  double randomX=0;
578  double randomY=0;
579  if(randomSigma>0){
580  randomX=gsl_ran_gaussian(rangen,randomSigma);
581  randomY=gsl_ran_gaussian(rangen,randomSigma);
582  }
583  double readCol=i+offsetX+randomX;
584  double readRow=j+offsetY+randomY;
585  if(readRow<0)
586  readRow=0;
587  if(readRow>input.nRows()-1)
588  readRow=input.nRows()-1;
589  if(readCol<0)
590  readCol=0;
591  if(readCol>input.nCols()-1)
592  readCol=input.nCols()-1;
593  switch(resample){
594  case(BILINEAR):{
595  double lowerRow=readRow-0.5;
596  double upperRow=readRow+0.5;
597  lowerRow=static_cast<int>(lowerRow);
598  upperRow=static_cast<int>(upperRow);
599  double lowerCol=readCol-0.5;
600  double upperCol=readCol+0.5;
601  lowerCol=static_cast<int>(lowerCol);
602  upperCol=static_cast<int>(upperCol);
603  assert(lowerRow>=0);
604  assert(lowerRow<input.nRows());
605  assert(lowerCol>=0);
606  assert(lowerCol<input.nCols());
607  assert(upperRow>=0);
608  assert(upperRow<input.nRows());
609  assert(upperCol>=0);
610  if(upperCol>=input.nCols()){
611  std::cout << "upperCol: " << upperCol << std::endl;
612  std::cout << "readCol: " << readCol << std::endl;
613  std::cout << "readCol+0.5: " << readCol+0.5 << std::endl;
614  std::cout << "static_cast<int>(readCol+0.5): " << static_cast<int>(readCol+0.5) << std::endl;
615  }
616  assert(upperCol<input.nCols());
617  double c00=input[lowerRow][lowerCol];
618  double c11=input[upperRow][upperCol];
619  double c01=input[lowerRow][upperCol];
620  double c10=input[upperRow][lowerCol];
621  double a=(upperCol-readCol)*c00+(readCol-lowerCol)*c01;
622  double b=(upperCol-readCol)*c10+(readCol-lowerCol)*c11;
623  theValue=(upperRow-readRow)*a+(readRow-lowerRow)*b;
624  break;
625  }
626  default:
627  theValue=input[static_cast<int>(readRow)][static_cast<int>(readCol)];
628  break;
629  }
630  assert(j>=0);
631  assert(j<output.nRows());
632  assert(i>=0);
633  assert(i<output.nCols());
634  output[j][i]=theValue;
635  }
636  progress=(1.0+j);
637  progress/=output.nRows();
638  pfnProgress(progress,pszMessage,pProgressArg);
639  }
640  gsl_rng_free(rangen);
641 }
642 
643 template<class T> unsigned long int Filter2d::morphology(const Vector2d<T>& input, Vector2d<T>& output, const std::string& method, int dimX, int dimY, bool disc, double hThreshold)
644 {
645  const char* pszMessage;
646  void* pProgressArg=NULL;
647  GDALProgressFunc pfnProgress=GDALTermProgress;
648  double progress=0;
649  pfnProgress(progress,pszMessage,pProgressArg);
650 
651  double noDataValue=0;
652  if(m_noDataValues.size())
653  noDataValue=m_noDataValues[0];
654 
655  unsigned long int nchange=0;
656  assert(dimX);
657  assert(dimY);
659  Vector2d<T> inBuffer(dimY,input.nCols());
660  output.clear();
661  output.resize(input.nRows(),input.nCols());
662  int indexI=0;
663  int indexJ=0;
664  //initialize last half of inBuffer
665  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
666  for(int i=0;i<input.nCols();++i)
667  inBuffer[indexJ][i]=input[abs(j)][i];
668  ++indexJ;
669  }
670  for(int y=0;y<input.nRows();++y){
671  if(y){//inBuffer already initialized for y=0
672  //erase first line from inBuffer
673  inBuffer.erase(inBuffer.begin());
674  //read extra line and push back to inBuffer if not out of bounds
675  if(y+dimY/2<input.nRows()){
676  //allocate buffer
677  inBuffer.push_back(inBuffer.back());
678  for(int i=0;i<input.nCols();++i)
679  inBuffer[inBuffer.size()-1][i]=input[y+dimY/2][i];
680  }
681  else{
682  int over=y+dimY/2-input.nRows();
683  int index=(inBuffer.size()-1)-over;
684  assert(index>=0);
685  assert(index<inBuffer.size());
686  inBuffer.push_back(inBuffer[index]);
687  }
688  }
689  for(int x=0;x<input.nCols();++x){
690  output[y][x]=0;
691  double currentValue=inBuffer[(dimY-1)/2][x];
692  std::vector<double> statBuffer;
693  bool currentMasked=false;
694  for(int imask=0;imask<m_noDataValues.size();++imask){
695  if(currentValue==m_noDataValues[imask]){
696  currentMasked=true;
697  break;
698  }
699  }
700  output[y][x]=currentValue;//introduced due to hThreshold
701  if(currentMasked){
702  output[y][x]=currentValue;
703  }
704  else{
705  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
706  for(int i=-(dimX-1)/2;i<=dimX/2;++i){
707  double d2=i*i+j*j;//square distance
708  if(disc&&(d2>(dimX/2)*(dimY/2)))
709  continue;
710  indexI=x+i;
711  //check if out of bounds
712  if(indexI<0)
713  indexI=-indexI;
714  else if(indexI>=input.nCols())
715  indexI=input.nCols()-i;
716  if(y+j<0)
717  indexJ=-j;
718  else if(y+j>=input.nRows())
719  indexJ=(dimY>2) ? (dimY-1)/2-j : 0;
720  else
721  indexJ=(dimY-1)/2+j;
722  if(inBuffer[indexJ][indexI]==noDataValue)
723  continue;
724  bool masked=false;
725  for(int imask=0;imask<m_noDataValues.size();++imask){
726  if(inBuffer[indexJ][indexI]==m_noDataValues[imask]){
727  masked=true;
728  break;
729  }
730  }
731  if(!masked){
732  short binValue=0;
733  for(int iclass=0;iclass<m_class.size();++iclass){
734  if(inBuffer[indexJ][indexI]==m_class[iclass]){
735  binValue=1;
736  break;
737  }
738  }
739  if(m_class.size())
740  statBuffer.push_back(binValue);
741  else
742  statBuffer.push_back(inBuffer[indexJ][indexI]);
743  }
744  }
745  }
746  if(statBuffer.size()){
747  switch(getFilterType(method)){
748  case(filter2d::dilate):
749  if(output[y][x]<stat.mymax(statBuffer)-hThreshold){
750  output[y][x]=stat.mymax(statBuffer);
751  ++nchange;
752  }
753  break;
754  case(filter2d::erode):
755  if(output[y][x]>stat.mymin(statBuffer)+hThreshold){
756  output[y][x]=stat.mymin(statBuffer);
757  ++nchange;
758  }
759  break;
760  default:
761  std::ostringstream ess;
762  ess << "Error: morphology method " << method << " not supported, choose " << filter2d::dilate << " (dilate) or " << filter2d::erode << " (erode)" << std::endl;
763  throw(ess.str());
764  break;
765  }
766  if(output[y][x]&&m_class.size())
767  output[y][x]=m_class[0];
768  // else{
769  // assert(m_noDataValues.size());
770  // output[x]=m_noDataValues[0];
771  // }
772  }
773  else
774  output[y][x]=noDataValue;
775  }
776  }
777  progress=(1.0+y);
778  progress/=output.nRows();
779  pfnProgress(progress,pszMessage,pProgressArg);
780  }
781  return nchange;
782 }
783 
784  template<class T> unsigned long int Filter2d::dsm2dtm_nwse(const Vector2d<T>& inputDSM, Vector2d<T>& outputMask, double hThreshold, int nlimit, int dim)
785 {
786  const char* pszMessage;
787  void* pProgressArg=NULL;
788  GDALProgressFunc pfnProgress=GDALTermProgress;
789  double progress=0;
790  pfnProgress(progress,pszMessage,pProgressArg);
791 
792  Vector2d<T> tmpDSM(inputDSM);
793  double noDataValue=0;
794  if(m_noDataValues.size())
795  noDataValue=m_noDataValues[0];
796 
797  unsigned long int nchange=0;
798  int dimX=dim;
799  int dimY=dim;
800  assert(dimX);
801  assert(dimY);
803  Vector2d<T> inBuffer(dimY,inputDSM.nCols());
804  if(outputMask.size()!=inputDSM.nRows())
805  outputMask.resize(inputDSM.nRows());
806  int indexI=0;
807  int indexJ=0;
808  //initialize last half of inBuffer
809  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
810  for(int i=0;i<inputDSM.nCols();++i)
811  inBuffer[indexJ][i]=tmpDSM[abs(j)][i];
812  ++indexJ;
813  }
814  for(int y=0;y<tmpDSM.nRows();++y){
815  if(y){//inBuffer already initialized for y=0
816  //erase first line from inBuffer
817  inBuffer.erase(inBuffer.begin());
818  //read extra line and push back to inBuffer if not out of bounds
819  if(y+dimY/2<tmpDSM.nRows()){
820  //allocate buffer
821  inBuffer.push_back(inBuffer.back());
822  for(int i=0;i<tmpDSM.nCols();++i)
823  inBuffer[inBuffer.size()-1][i]=tmpDSM[y+dimY/2][i];
824  }
825  else{
826  int over=y+dimY/2-tmpDSM.nRows();
827  int index=(inBuffer.size()-1)-over;
828  assert(index>=0);
829  assert(index<inBuffer.size());
830  inBuffer.push_back(inBuffer[index]);
831  }
832  }
833  for(int x=0;x<tmpDSM.nCols();++x){
834  double centerValue=inBuffer[(dimY-1)/2][x];
835  short nmasked=0;
836  std::vector<T> neighbors;
837  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
838  for(int i=-(dimX-1)/2;i<=dimX/2;++i){
839  indexI=x+i;
840  //check if out of bounds
841  if(indexI<0)
842  indexI=-indexI;
843  else if(indexI>=tmpDSM.nCols())
844  indexI=tmpDSM.nCols()-i;
845  if(y+j<0)
846  indexJ=-j;
847  else if(y+j>=tmpDSM.nRows())
848  indexJ=(dimY>2) ? (dimY-1)/2-j : 0;
849  else
850  indexJ=(dimY-1)/2+j;
851  double difference=(centerValue-inBuffer[indexJ][indexI]);
852  if(i||j)//skip centerValue
853  neighbors.push_back(inBuffer[indexJ][indexI]);
854  if(difference>hThreshold)
855  ++nmasked;
856  }
857  }
858  if(nmasked<=nlimit){
859  ++nchange;
860  //reset pixel in outputMask
861  outputMask[y][x]=0;
862  }
863  else{
864  //reset pixel height in tmpDSM
865  sort(neighbors.begin(),neighbors.end());
866  assert(neighbors.size()>1);
867  inBuffer[(dimY-1)/2][x]=neighbors[1];
868  /* inBuffer[(dimY-1)/2][x]=stat.mymin(neighbors); */
869  }
870  }
871  progress=(1.0+y);
872  progress/=outputMask.nRows();
873  pfnProgress(progress,pszMessage,pProgressArg);
874  }
875  return nchange;
876 }
877 
878  template<class T> unsigned long int Filter2d::dsm2dtm_nesw(const Vector2d<T>& inputDSM, Vector2d<T>& outputMask, double hThreshold, int nlimit, int dim)
879 {
880  const char* pszMessage;
881  void* pProgressArg=NULL;
882  GDALProgressFunc pfnProgress=GDALTermProgress;
883  double progress=0;
884  pfnProgress(progress,pszMessage,pProgressArg);
885 
886  Vector2d<T> tmpDSM(inputDSM);
887  double noDataValue=0;
888  if(m_noDataValues.size())
889  noDataValue=m_noDataValues[0];
890 
891  unsigned long int nchange=0;
892  int dimX=dim;
893  int dimY=dim;
894  assert(dimX);
895  assert(dimY);
897  Vector2d<T> inBuffer(dimY,inputDSM.nCols());
898  if(outputMask.size()!=inputDSM.nRows())
899  outputMask.resize(inputDSM.nRows());
900  int indexI=0;
901  int indexJ=0;
902  //initialize last half of inBuffer
903  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
904  for(int i=0;i<inputDSM.nCols();++i)
905  inBuffer[indexJ][i]=tmpDSM[abs(j)][i];
906  ++indexJ;
907  }
908  for(int y=0;y<tmpDSM.nRows();++y){
909  if(y){//inBuffer already initialized for y=0
910  //erase first line from inBuffer
911  inBuffer.erase(inBuffer.begin());
912  //read extra line and push back to inBuffer if not out of bounds
913  if(y+dimY/2<tmpDSM.nRows()){
914  //allocate buffer
915  inBuffer.push_back(inBuffer.back());
916  for(int i=0;i<tmpDSM.nCols();++i)
917  inBuffer[inBuffer.size()-1][i]=tmpDSM[y+dimY/2][i];
918  }
919  else{
920  int over=y+dimY/2-tmpDSM.nRows();
921  int index=(inBuffer.size()-1)-over;
922  assert(index>=0);
923  assert(index<inBuffer.size());
924  inBuffer.push_back(inBuffer[index]);
925  }
926  }
927  for(int x=tmpDSM.nCols()-1;x>=0;--x){
928  double centerValue=inBuffer[(dimY-1)/2][x];
929  short nmasked=0;
930  std::vector<T> neighbors;
931  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
932  for(int i=-(dimX-1)/2;i<=dimX/2;++i){
933  indexI=x+i;
934  //check if out of bounds
935  if(indexI<0)
936  indexI=-indexI;
937  else if(indexI>=tmpDSM.nCols())
938  indexI=tmpDSM.nCols()-i;
939  if(y+j<0)
940  indexJ=-j;
941  else if(y+j>=tmpDSM.nRows())
942  indexJ=(dimY>2) ? (dimY-1)/2-j : 0;
943  else
944  indexJ=(dimY-1)/2+j;
945  double difference=(centerValue-inBuffer[indexJ][indexI]);
946  if(i||j)//skip centerValue
947  neighbors.push_back(inBuffer[indexJ][indexI]);
948  if(difference>hThreshold)
949  ++nmasked;
950  }
951  }
952  if(nmasked<=nlimit){
953  ++nchange;
954  //reset pixel in outputMask
955  outputMask[y][x]=0;
956  }
957  else{
958  //reset pixel height in tmpDSM
959  sort(neighbors.begin(),neighbors.end());
960  assert(neighbors.size()>1);
961  inBuffer[(dimY-1)/2][x]=neighbors[1];
962  /* inBuffer[(dimY-1)/2][x]=stat.mymin(neighbors); */
963  }
964  }
965  progress=(1.0+y);
966  progress/=outputMask.nRows();
967  pfnProgress(progress,pszMessage,pProgressArg);
968  }
969  return nchange;
970 }
971 
972  template<class T> unsigned long int Filter2d::dsm2dtm_senw(const Vector2d<T>& inputDSM, Vector2d<T>& outputMask, double hThreshold, int nlimit, int dim)
973 {
974  const char* pszMessage;
975  void* pProgressArg=NULL;
976  GDALProgressFunc pfnProgress=GDALTermProgress;
977  double progress=0;
978  pfnProgress(progress,pszMessage,pProgressArg);
979 
980  Vector2d<T> tmpDSM(inputDSM);
981  double noDataValue=0;
982  if(m_noDataValues.size())
983  noDataValue=m_noDataValues[0];
984 
985  unsigned long int nchange=0;
986  int dimX=dim;
987  int dimY=dim;
988  assert(dimX);
989  assert(dimY);
991  Vector2d<T> inBuffer(dimY,inputDSM.nCols());
992  if(outputMask.size()!=inputDSM.nRows())
993  outputMask.resize(inputDSM.nRows());
994  int indexI=0;
995  int indexJ=inputDSM.nRows()-1;
996  //initialize first half of inBuffer
997  for(int j=inputDSM.nRows()-dimY/2;j<inputDSM.nRows();--j){
998  for(int i=0;i<inputDSM.nCols();++i)
999  inBuffer[indexJ][i]=tmpDSM[abs(j)][i];
1000  ++indexJ;
1001  }
1002  for(int y=tmpDSM.nRows()-1;y>=0;--y){
1003  if(y<tmpDSM.nRows()-1){//inBuffer already initialized for y=tmpDSM.nRows()-1
1004  //erase last line from inBuffer
1005  inBuffer.erase(inBuffer.end()-1);
1006  //read extra line and insert to inBuffer if not out of bounds
1007  if(y-dimY/2>0){
1008  //allocate buffer
1009  inBuffer.insert(inBuffer.begin(),inBuffer.back());
1010  for(int i=0;i<tmpDSM.nCols();++i)
1011  inBuffer[0][i]=tmpDSM[y-dimY/2][i];
1012  }
1013  else{
1014  inBuffer.insert(inBuffer.begin(),inBuffer[abs(y-dimY/2)]);
1015  }
1016  }
1017  for(int x=tmpDSM.nCols()-1;x>=0;--x){
1018  double centerValue=inBuffer[(dimY-1)/2][x];
1019  short nmasked=0;
1020  std::vector<T> neighbors;
1021  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
1022  for(int i=-(dimX-1)/2;i<=dimX/2;++i){
1023  indexI=x+i;
1024  //check if out of bounds
1025  if(indexI<0)
1026  indexI=-indexI;
1027  else if(indexI>=tmpDSM.nCols())
1028  indexI=tmpDSM.nCols()-i;
1029  if(y+j<0)
1030  indexJ=-j;
1031  else if(y+j>=tmpDSM.nRows())
1032  indexJ=(dimY>2) ? (dimY-1)/2-j : 0;
1033  else
1034  indexJ=(dimY-1)/2+j;
1035  double difference=(centerValue-inBuffer[indexJ][indexI]);
1036  if(i||j)//skip centerValue
1037  neighbors.push_back(inBuffer[indexJ][indexI]);
1038  if(difference>hThreshold)
1039  ++nmasked;
1040  }
1041  }
1042  if(nmasked<=nlimit){
1043  ++nchange;
1044  //reset pixel in outputMask
1045  outputMask[y][x]=0;
1046  }
1047  else{
1048  //reset pixel height in tmpDSM
1049  sort(neighbors.begin(),neighbors.end());
1050  assert(neighbors.size()>1);
1051  inBuffer[(dimY-1)/2][x]=neighbors[1];
1052  /* inBuffer[(dimY-1)/2][x]=stat.mymin(neighbors); */
1053  }
1054  }
1055  progress=(1.0+y);
1056  progress/=outputMask.nRows();
1057  pfnProgress(progress,pszMessage,pProgressArg);
1058  }
1059  return nchange;
1060 }
1061 
1062  template<class T> unsigned long int Filter2d::dsm2dtm_swne(const Vector2d<T>& inputDSM, Vector2d<T>& outputMask, double hThreshold, int nlimit, int dim)
1063 {
1064  const char* pszMessage;
1065  void* pProgressArg=NULL;
1066  GDALProgressFunc pfnProgress=GDALTermProgress;
1067  double progress=0;
1068  pfnProgress(progress,pszMessage,pProgressArg);
1069 
1070  Vector2d<T> tmpDSM(inputDSM);
1071  double noDataValue=0;
1072  if(m_noDataValues.size())
1073  noDataValue=m_noDataValues[0];
1074 
1075  unsigned long int nchange=0;
1076  int dimX=dim;
1077  int dimY=dim;
1078  assert(dimX);
1079  assert(dimY);
1081  Vector2d<T> inBuffer(dimY,inputDSM.nCols());
1082  if(outputMask.size()!=inputDSM.nRows())
1083  outputMask.resize(inputDSM.nRows());
1084  int indexI=0;
1085  int indexJ=0;
1086  //initialize first half of inBuffer
1087  for(int j=inputDSM.nRows()-dimY/2;j<inputDSM.nRows();--j){
1088  for(int i=0;i<inputDSM.nCols();++i)
1089  inBuffer[indexJ][i]=tmpDSM[abs(j)][i];
1090  ++indexJ;
1091  }
1092  for(int y=tmpDSM.nRows()-1;y>=0;--y){
1093  if(y<tmpDSM.nRows()-1){//inBuffer already initialized for y=0
1094  //erase last line from inBuffer
1095  inBuffer.erase(inBuffer.end()-1);
1096  //read extra line and insert to inBuffer if not out of bounds
1097  if(y-dimY/2>0){
1098  //allocate buffer
1099  inBuffer.insert(inBuffer.begin(),inBuffer.back());
1100  for(int i=0;i<tmpDSM.nCols();++i)
1101  inBuffer[0][i]=tmpDSM[y-dimY/2][i];
1102  }
1103  else{
1104  inBuffer.insert(inBuffer.begin(),inBuffer[abs(y-dimY/2)]);
1105  }
1106  }
1107  for(int x=0;x<tmpDSM.nCols();++x){
1108  double centerValue=inBuffer[(dimY-1)/2][x];
1109  short nmasked=0;
1110  std::vector<T> neighbors;
1111  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
1112  for(int i=-(dimX-1)/2;i<=dimX/2;++i){
1113  indexI=x+i;
1114  //check if out of bounds
1115  if(indexI<0)
1116  indexI=-indexI;
1117  else if(indexI>=tmpDSM.nCols())
1118  indexI=tmpDSM.nCols()-i;
1119  if(y+j<0)
1120  indexJ=-j;
1121  else if(y+j>=tmpDSM.nRows())
1122  indexJ=(dimY>2) ? (dimY-1)/2-j : 0;
1123  else
1124  indexJ=(dimY-1)/2+j;
1125  double difference=(centerValue-inBuffer[indexJ][indexI]);
1126  if(i||j)//skip centerValue
1127  neighbors.push_back(inBuffer[indexJ][indexI]);
1128  if(difference>hThreshold)
1129  ++nmasked;
1130  }
1131  }
1132  if(nmasked<=nlimit){
1133  ++nchange;
1134  //reset pixel in outputMask
1135  outputMask[y][x]=0;
1136  }
1137  else{
1138  //reset pixel height in tmpDSM
1139  sort(neighbors.begin(),neighbors.end());
1140  assert(neighbors.size()>1);
1141  inBuffer[(dimY-1)/2][x]=neighbors[1];
1142  /* inBuffer[(dimY-1)/2][x]=stat.mymin(neighbors); */
1143  }
1144  }
1145  progress=(1.0+y);
1146  progress/=outputMask.nRows();
1147  pfnProgress(progress,pszMessage,pProgressArg);
1148  }
1149  return nchange;
1150 }
1151 
1152  template<class T> void Filter2d::shadowDsm(const Vector2d<T>& input, Vector2d<T>& output, double sza, double saa, double pixelSize, short shadowFlag)
1153 {
1154  unsigned int ncols=input.nCols();
1155  output.clear();
1156  output.resize(input.nRows(),ncols);
1157  //do we need to initialize output?
1158  // for(int y=0;y<output.nRows();++y)
1159  // for(int x=0;x<output.nCols();++x)
1160  // output[y][x]=0;
1161  int indexI=0;
1162  int indexJ=0;
1163  const char* pszMessage;
1164  void* pProgressArg=NULL;
1165  GDALProgressFunc pfnProgress=GDALTermProgress;
1166  double progress=0;
1167  pfnProgress(progress,pszMessage,pProgressArg);
1168  for(int y=0;y<input.nRows();++y){
1169  for(int x=0;x<input.nCols();++x){
1170  double currentValue=input[y][x];
1171  int theDist=static_cast<int>(sqrt((currentValue*tan(DEG2RAD(sza))/pixelSize)*(currentValue*tan(DEG2RAD(sza))/pixelSize)));//in pixels
1172  double theDir=DEG2RAD(saa)+PI/2.0;
1173  if(theDir<0)
1174  theDir+=2*PI;
1175  for(int d=0;d<theDist;++d){//d in pixels
1176  indexI=x+d*cos(theDir);//in pixels
1177  indexJ=y+d*sin(theDir);//in pixels
1178  if(indexJ<0||indexJ>=input.size())
1179  continue;
1180  if(indexI<0||indexI>=input[indexJ].size())
1181  continue;
1182  if(input[indexJ][indexI]<currentValue-d*pixelSize/tan(DEG2RAD(sza))){//in m
1183  output[indexJ][indexI]=shadowFlag;
1184  }
1185  }
1186  }
1187  progress=(1.0+y);
1188  progress/=output.nRows();
1189  pfnProgress(progress,pszMessage,pProgressArg);
1190  }
1191 }
1192 
1193 template<class T> void Filter2d::dwtForward(Vector2d<T>& theBuffer, const std::string& wavelet_type, int family){
1194  const char* pszMessage;
1195  void* pProgressArg=NULL;
1196  GDALProgressFunc pfnProgress=GDALTermProgress;
1197  double progress=0;
1198  pfnProgress(progress,pszMessage,pProgressArg);
1199 
1200  int nRow=theBuffer.size();
1201  assert(nRow);
1202  int nCol=theBuffer[0].size();
1203  assert(nCol);
1204  //make sure data size if power of 2
1205  while(theBuffer.size()&(theBuffer.size()-1))
1206  theBuffer.push_back(theBuffer.back());
1207  for(int irow=0;irow<theBuffer.size();++irow)
1208  while(theBuffer[irow].size()&(theBuffer[irow].size()-1))
1209  theBuffer[irow].push_back(theBuffer[irow].back());
1210  std::vector<double> vdata(theBuffer.size()*theBuffer[0].size());
1211  double* data=&(vdata[0]);
1212  for(int irow=0;irow<theBuffer.size();++irow){
1213  for(int icol=0;icol<theBuffer[0].size();++icol){
1214  int index=irow*theBuffer[0].size()+icol;
1215  data[index]=theBuffer[irow][icol];
1216  }
1217  }
1218  int nsize=theBuffer.size()*theBuffer[0].size();
1219  gsl_wavelet *w;
1220  gsl_wavelet_workspace *work;
1221  assert(nsize);
1222  w=gsl_wavelet_alloc(filter::Filter::getWaveletType(wavelet_type),family);
1223  work=gsl_wavelet_workspace_alloc(nsize);
1224  gsl_wavelet2d_nstransform_forward (w, data, theBuffer.size(), theBuffer.size(),theBuffer[0].size(), work);
1225  theBuffer.erase(theBuffer.begin()+nRow,theBuffer.end());
1226  for(int irow=0;irow<theBuffer.size();++irow){
1227  theBuffer[irow].erase(theBuffer[irow].begin()+nCol,theBuffer[irow].end());
1228  for(int icol=0;icol<theBuffer[irow].size();++icol){
1229  int index=irow*theBuffer[irow].size()+icol;
1230  theBuffer[irow][icol]=data[index];
1231  }
1232  progress=(1.0+irow);
1233  progress/=theBuffer.nRows();
1234  pfnProgress(progress,pszMessage,pProgressArg);
1235  }
1236  gsl_wavelet_free (w);
1237  gsl_wavelet_workspace_free (work);
1238 }
1239 
1240 template<class T> void Filter2d::dwtInverse(Vector2d<T>& theBuffer, const std::string& wavelet_type, int family){
1241  const char* pszMessage;
1242  void* pProgressArg=NULL;
1243  GDALProgressFunc pfnProgress=GDALTermProgress;
1244  double progress=0;
1245  pfnProgress(progress,pszMessage,pProgressArg);
1246 
1247  int nRow=theBuffer.size();
1248  assert(nRow);
1249  int nCol=theBuffer[0].size();
1250  assert(nCol);
1251  //make sure data size if power of 2
1252  while(theBuffer.size()&(theBuffer.size()-1))
1253  theBuffer.push_back(theBuffer.back());
1254  for(int irow=0;irow<theBuffer.size();++irow)
1255  while(theBuffer[irow].size()&(theBuffer[irow].size()-1))
1256  theBuffer[irow].push_back(theBuffer[irow].back());
1257  std::vector<double> vdata(theBuffer.size()*theBuffer[0].size());
1258  double* data=&(vdata[0]);
1259  //double data[theBuffer.size()*theBuffer[0].size()];
1260  for(int irow=0;irow<theBuffer.size();++irow){
1261  for(int icol=0;icol<theBuffer[0].size();++icol){
1262  int index=irow*theBuffer[0].size()+icol;
1263  data[index]=theBuffer[irow][icol];
1264  }
1265  }
1266  int nsize=theBuffer.size()*theBuffer[0].size();
1267  gsl_wavelet *w;
1268  gsl_wavelet_workspace *work;
1269  assert(nsize);
1270  w=gsl_wavelet_alloc(filter::Filter::getWaveletType(wavelet_type),family);
1271  work=gsl_wavelet_workspace_alloc(nsize);
1272  gsl_wavelet2d_nstransform_inverse (w, data, theBuffer.size(), theBuffer.size(),theBuffer[0].size(), work);
1273  theBuffer.erase(theBuffer.begin()+nRow,theBuffer.end());
1274  for(int irow=0;irow<theBuffer.size();++irow){
1275  theBuffer[irow].erase(theBuffer[irow].begin()+nCol,theBuffer[irow].end());
1276  for(int icol=0;icol<theBuffer[irow].size();++icol){
1277  int index=irow*theBuffer[irow].size()+icol;
1278  theBuffer[irow][icol]=data[index];
1279  }
1280  progress=(1.0+irow);
1281  progress/=theBuffer.nRows();
1282  pfnProgress(progress,pszMessage,pProgressArg);
1283  }
1284  gsl_wavelet_free (w);
1285  gsl_wavelet_workspace_free (work);
1286 }
1287 
1288 template<class T> void Filter2d::dwtCut(Vector2d<T>& theBuffer, const std::string& wavelet_type, int family, double cut){
1289  const char* pszMessage;
1290  void* pProgressArg=NULL;
1291  GDALProgressFunc pfnProgress=GDALTermProgress;
1292  double progress=0;
1293  pfnProgress(progress,pszMessage,pProgressArg);
1294 
1295  int nRow=theBuffer.size();
1296  assert(nRow);
1297  int nCol=theBuffer[0].size();
1298  assert(nCol);
1299  //make sure data size if power of 2
1300  while(theBuffer.size()&(theBuffer.size()-1))
1301  theBuffer.push_back(theBuffer.back());
1302  for(int irow=0;irow<theBuffer.size();++irow)
1303  while(theBuffer[irow].size()&(theBuffer[irow].size()-1))
1304  theBuffer[irow].push_back(theBuffer[irow].back());
1305  double* data=new double[theBuffer.size()*theBuffer[0].size()];
1306  double* abscoeff=new double[theBuffer.size()*theBuffer[0].size()];
1307  size_t* p=new size_t[theBuffer.size()*theBuffer[0].size()];
1308  for(int irow=0;irow<theBuffer.size();++irow){
1309  for(int icol=0;icol<theBuffer[0].size();++icol){
1310  int index=irow*theBuffer[0].size()+icol;
1311  assert(index<theBuffer.size()*theBuffer[0].size());
1312  data[index]=theBuffer[irow][icol];
1313  }
1314  }
1315  int nsize=theBuffer.size()*theBuffer[0].size();
1316  gsl_wavelet *w;
1317  gsl_wavelet_workspace *work;
1318  assert(nsize);
1319  w=gsl_wavelet_alloc(filter::Filter::getWaveletType(wavelet_type),family);
1320  work=gsl_wavelet_workspace_alloc(nsize);
1321  gsl_wavelet2d_nstransform_forward (w, data, theBuffer.size(), theBuffer[0].size(),theBuffer[0].size(), work);
1322  for(int irow=0;irow<theBuffer.size();++irow){
1323  for(int icol=0;icol<theBuffer[0].size();++icol){
1324  int index=irow*theBuffer[0].size()+icol;
1325  abscoeff[index]=fabs(data[index]);
1326  }
1327  }
1328  int nc=(100-cut)/100.0*nsize;
1329  gsl_sort_index(p,abscoeff,1,nsize);
1330  for(int i=0;(i+nc)<nsize;i++)
1331  data[p[i]]=0;
1332  gsl_wavelet2d_nstransform_inverse (w, data, theBuffer.size(), theBuffer[0].size(),theBuffer[0].size(), work);
1333  for(int irow=0;irow<theBuffer.size();++irow){
1334  for(int icol=0;icol<theBuffer[irow].size();++icol){
1335  int index=irow*theBuffer[irow].size()+icol;
1336  theBuffer[irow][icol]=data[index];
1337  }
1338  progress=(1.0+irow);
1339  progress/=theBuffer.nRows();
1340  pfnProgress(progress,pszMessage,pProgressArg);
1341  }
1342  theBuffer.erase(theBuffer.begin()+nRow,theBuffer.end());
1343  for(int irow=0;irow<theBuffer.size();++irow)
1344  theBuffer[irow].erase(theBuffer[irow].begin()+nCol,theBuffer[irow].end());
1345  delete[] data;
1346  delete[] abscoeff;
1347  delete[] p;
1348  gsl_wavelet_free (w);
1349  gsl_wavelet_workspace_free (work);
1350 
1351 }
1352 
1353 }
1354 
1355 #endif /* _MYFILTER_H_ */