pktools  2.6.3
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  outBuffer[x/down]=windowBuffer[randomIndex];
503  }
504  else
505  outBuffer[x/down]=noDataValue;
506  break;
507  }
508  case(filter2d::mixed):{
509  enum MixType { BF=11, CF=12, MF=13, NF=20, W=30 };
510  double nBF=occurrence[BF];
511  double nCF=occurrence[CF];
512  double nMF=occurrence[MF];
513  double nNF=occurrence[NF];
514  double nW=occurrence[W];
515  if(windowBuffer.size()){
516  if((nBF+nCF+nMF)&&(nBF+nCF+nMF>=nNF+nW)){//forest
517  if(nBF/(nBF+nCF)>=0.75)
518  outBuffer[x/down]=BF;
519  else if(nCF/(nBF+nCF)>=0.75)
520  outBuffer[x/down]=CF;
521  else
522  outBuffer[x/down]=MF;
523  }
524  else{//non-forest
525  if(nW&&(nW>=nNF))
526  outBuffer[x/down]=W;
527  else
528  outBuffer[x/down]=NF;
529  }
530  }
531  else
532  outBuffer[x/down]=inBuffer[indexJ][indexI];
533  break;
534  }
535  default:
536  break;
537  }
538  }
539  progress=(1.0+y/down);
540  progress+=(outputVector.size());
541  progress/=outputVector.size();
542  pfnProgress(progress,pszMessage,pProgressArg);
543  //copy outBuffer to outputVector
544  outputVector[y/down]=outBuffer;
545  }
546 }
547 
548 // class Compare_mapValue{
549 // public:
550 // int operator() (const map<int,int>::value_type& v1, const map<int, int>::value_type& v2) const{
551 // return (v1.second)>(v2.second);
552 // }
553 // };
554 
555 template<class T> void Filter2d::shift(const Vector2d<T>& input, Vector2d<T>& output, double offsetX, double offsetY, double randomSigma, RESAMPLE resample, bool verbose){
556  output.resize(input.nRows(),input.nCols());
557  const gsl_rng_type *rangenType;
558  gsl_rng *rangen;
559  gsl_rng_env_setup();
560  rangenType=gsl_rng_default;
561  rangen=gsl_rng_alloc(rangenType);
562  long seed=time(NULL)*getpid();
563  gsl_rng_set(rangen,seed);
564  const char* pszMessage;
565  void* pProgressArg=NULL;
566  GDALProgressFunc pfnProgress=GDALTermProgress;
567  double progress=0;
568  pfnProgress(progress,pszMessage,pProgressArg);
569  for(int j=0;j<input.nRows();++j){
570  for(int i=0;i<input.nCols();++i){
571  T theValue=0;
572  double randomX=0;
573  double randomY=0;
574  if(randomSigma>0){
575  randomX=gsl_ran_gaussian(rangen,randomSigma);
576  randomY=gsl_ran_gaussian(rangen,randomSigma);
577  }
578  double readCol=i+offsetX+randomX;
579  double readRow=j+offsetY+randomY;
580  if(readRow<0)
581  readRow=0;
582  if(readRow>input.nRows()-1)
583  readRow=input.nRows()-1;
584  if(readCol<0)
585  readCol=0;
586  if(readCol>input.nCols()-1)
587  readCol=input.nCols()-1;
588  switch(resample){
589  case(BILINEAR):{
590  double lowerRow=readRow-0.5;
591  double upperRow=readRow+0.5;
592  lowerRow=static_cast<int>(lowerRow);
593  upperRow=static_cast<int>(upperRow);
594  double lowerCol=readCol-0.5;
595  double upperCol=readCol+0.5;
596  lowerCol=static_cast<int>(lowerCol);
597  upperCol=static_cast<int>(upperCol);
598  assert(lowerRow>=0);
599  assert(lowerRow<input.nRows());
600  assert(lowerCol>=0);
601  assert(lowerCol<input.nCols());
602  assert(upperRow>=0);
603  assert(upperRow<input.nRows());
604  assert(upperCol>=0);
605  if(upperCol>=input.nCols()){
606  std::cout << "upperCol: " << upperCol << std::endl;
607  std::cout << "readCol: " << readCol << std::endl;
608  std::cout << "readCol+0.5: " << readCol+0.5 << std::endl;
609  std::cout << "static_cast<int>(readCol+0.5): " << static_cast<int>(readCol+0.5) << std::endl;
610  }
611  assert(upperCol<input.nCols());
612  double c00=input[lowerRow][lowerCol];
613  double c11=input[upperRow][upperCol];
614  double c01=input[lowerRow][upperCol];
615  double c10=input[upperRow][lowerCol];
616  double a=(upperCol-readCol)*c00+(readCol-lowerCol)*c01;
617  double b=(upperCol-readCol)*c10+(readCol-lowerCol)*c11;
618  theValue=(upperRow-readRow)*a+(readRow-lowerRow)*b;
619  break;
620  }
621  default:
622  theValue=input[static_cast<int>(readRow)][static_cast<int>(readCol)];
623  break;
624  }
625  assert(j>=0);
626  assert(j<output.nRows());
627  assert(i>=0);
628  assert(i<output.nCols());
629  output[j][i]=theValue;
630  }
631  progress=(1.0+j);
632  progress/=output.nRows();
633  pfnProgress(progress,pszMessage,pProgressArg);
634  }
635  gsl_rng_free(rangen);
636 }
637 
638 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)
639 {
640  const char* pszMessage;
641  void* pProgressArg=NULL;
642  GDALProgressFunc pfnProgress=GDALTermProgress;
643  double progress=0;
644  pfnProgress(progress,pszMessage,pProgressArg);
645 
646  double noDataValue=0;
647  if(m_noDataValues.size())
648  noDataValue=m_noDataValues[0];
649 
650  unsigned long int nchange=0;
651  assert(dimX);
652  assert(dimY);
654  Vector2d<T> inBuffer(dimY,input.nCols());
655  output.clear();
656  output.resize(input.nRows(),input.nCols());
657  int indexI=0;
658  int indexJ=0;
659  //initialize last half of inBuffer
660  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
661  for(int i=0;i<input.nCols();++i)
662  inBuffer[indexJ][i]=input[abs(j)][i];
663  ++indexJ;
664  }
665  for(int y=0;y<input.nRows();++y){
666  if(y){//inBuffer already initialized for y=0
667  //erase first line from inBuffer
668  inBuffer.erase(inBuffer.begin());
669  //read extra line and push back to inBuffer if not out of bounds
670  if(y+dimY/2<input.nRows()){
671  //allocate buffer
672  inBuffer.push_back(inBuffer.back());
673  for(int i=0;i<input.nCols();++i)
674  inBuffer[inBuffer.size()-1][i]=input[y+dimY/2][i];
675  }
676  else{
677  int over=y+dimY/2-input.nRows();
678  int index=(inBuffer.size()-1)-over;
679  assert(index>=0);
680  assert(index<inBuffer.size());
681  inBuffer.push_back(inBuffer[index]);
682  }
683  }
684  for(int x=0;x<input.nCols();++x){
685  output[y][x]=0;
686  double currentValue=inBuffer[(dimY-1)/2][x];
687  std::vector<double> statBuffer;
688  bool currentMasked=false;
689  for(int imask=0;imask<m_noDataValues.size();++imask){
690  if(currentValue==m_noDataValues[imask]){
691  currentMasked=true;
692  break;
693  }
694  }
695  output[y][x]=currentValue;//introduced due to hThreshold
696  if(currentMasked){
697  output[y][x]=currentValue;
698  }
699  else{
700  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
701  for(int i=-(dimX-1)/2;i<=dimX/2;++i){
702  double d2=i*i+j*j;//square distance
703  if(disc&&(d2>(dimX/2)*(dimY/2)))
704  continue;
705  indexI=x+i;
706  //check if out of bounds
707  if(indexI<0)
708  indexI=-indexI;
709  else if(indexI>=input.nCols())
710  indexI=input.nCols()-i;
711  if(y+j<0)
712  indexJ=-j;
713  else if(y+j>=input.nRows())
714  indexJ=(dimY>2) ? (dimY-1)/2-j : 0;
715  else
716  indexJ=(dimY-1)/2+j;
717  if(inBuffer[indexJ][indexI]==noDataValue)
718  continue;
719  bool masked=false;
720  for(int imask=0;imask<m_noDataValues.size();++imask){
721  if(inBuffer[indexJ][indexI]==m_noDataValues[imask]){
722  masked=true;
723  break;
724  }
725  }
726  if(!masked){
727  short binValue=0;
728  for(int iclass=0;iclass<m_class.size();++iclass){
729  if(inBuffer[indexJ][indexI]==m_class[iclass]){
730  binValue=1;
731  break;
732  }
733  }
734  if(m_class.size())
735  statBuffer.push_back(binValue);
736  else
737  statBuffer.push_back(inBuffer[indexJ][indexI]);
738  }
739  }
740  }
741  if(statBuffer.size()){
742  switch(getFilterType(method)){
743  case(filter2d::dilate):
744  if(output[y][x]<stat.mymax(statBuffer)-hThreshold){
745  output[y][x]=stat.mymax(statBuffer);
746  ++nchange;
747  }
748  break;
749  case(filter2d::erode):
750  if(output[y][x]>stat.mymin(statBuffer)+hThreshold){
751  output[y][x]=stat.mymin(statBuffer);
752  ++nchange;
753  }
754  break;
755  default:
756  std::ostringstream ess;
757  ess << "Error: morphology method " << method << " not supported, choose " << filter2d::dilate << " (dilate) or " << filter2d::erode << " (erode)" << std::endl;
758  throw(ess.str());
759  break;
760  }
761  if(output[y][x]&&m_class.size())
762  output[y][x]=m_class[0];
763  // else{
764  // assert(m_noDataValues.size());
765  // output[x]=m_noDataValues[0];
766  // }
767  }
768  else
769  output[y][x]=noDataValue;
770  }
771  }
772  progress=(1.0+y);
773  progress/=output.nRows();
774  pfnProgress(progress,pszMessage,pProgressArg);
775  }
776  return nchange;
777 }
778 
779  template<class T> unsigned long int Filter2d::dsm2dtm_nwse(const Vector2d<T>& inputDSM, Vector2d<T>& outputMask, double hThreshold, int nlimit, int dim)
780 {
781  const char* pszMessage;
782  void* pProgressArg=NULL;
783  GDALProgressFunc pfnProgress=GDALTermProgress;
784  double progress=0;
785  pfnProgress(progress,pszMessage,pProgressArg);
786 
787  Vector2d<T> tmpDSM(inputDSM);
788  double noDataValue=0;
789  if(m_noDataValues.size())
790  noDataValue=m_noDataValues[0];
791 
792  unsigned long int nchange=0;
793  int dimX=dim;
794  int dimY=dim;
795  assert(dimX);
796  assert(dimY);
798  Vector2d<T> inBuffer(dimY,inputDSM.nCols());
799  if(outputMask.size()!=inputDSM.nRows())
800  outputMask.resize(inputDSM.nRows());
801  int indexI=0;
802  int indexJ=0;
803  //initialize last half of inBuffer
804  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
805  for(int i=0;i<inputDSM.nCols();++i)
806  inBuffer[indexJ][i]=tmpDSM[abs(j)][i];
807  ++indexJ;
808  }
809  for(int y=0;y<tmpDSM.nRows();++y){
810  if(y){//inBuffer already initialized for y=0
811  //erase first line from inBuffer
812  inBuffer.erase(inBuffer.begin());
813  //read extra line and push back to inBuffer if not out of bounds
814  if(y+dimY/2<tmpDSM.nRows()){
815  //allocate buffer
816  inBuffer.push_back(inBuffer.back());
817  for(int i=0;i<tmpDSM.nCols();++i)
818  inBuffer[inBuffer.size()-1][i]=tmpDSM[y+dimY/2][i];
819  }
820  else{
821  int over=y+dimY/2-tmpDSM.nRows();
822  int index=(inBuffer.size()-1)-over;
823  assert(index>=0);
824  assert(index<inBuffer.size());
825  inBuffer.push_back(inBuffer[index]);
826  }
827  }
828  for(int x=0;x<tmpDSM.nCols();++x){
829  double centerValue=inBuffer[(dimY-1)/2][x];
830  short nmasked=0;
831  std::vector<T> neighbors;
832  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
833  for(int i=-(dimX-1)/2;i<=dimX/2;++i){
834  indexI=x+i;
835  //check if out of bounds
836  if(indexI<0)
837  indexI=-indexI;
838  else if(indexI>=tmpDSM.nCols())
839  indexI=tmpDSM.nCols()-i;
840  if(y+j<0)
841  indexJ=-j;
842  else if(y+j>=tmpDSM.nRows())
843  indexJ=(dimY>2) ? (dimY-1)/2-j : 0;
844  else
845  indexJ=(dimY-1)/2+j;
846  double difference=(centerValue-inBuffer[indexJ][indexI]);
847  if(i||j)//skip centerValue
848  neighbors.push_back(inBuffer[indexJ][indexI]);
849  if(difference>hThreshold)
850  ++nmasked;
851  }
852  }
853  if(nmasked<=nlimit){
854  ++nchange;
855  //reset pixel in outputMask
856  outputMask[y][x]=0;
857  }
858  else{
859  //reset pixel height in tmpDSM
860  sort(neighbors.begin(),neighbors.end());
861  assert(neighbors.size()>1);
862  inBuffer[(dimY-1)/2][x]=neighbors[1];
863  /* inBuffer[(dimY-1)/2][x]=stat.mymin(neighbors); */
864  }
865  }
866  progress=(1.0+y);
867  progress/=outputMask.nRows();
868  pfnProgress(progress,pszMessage,pProgressArg);
869  }
870  return nchange;
871 }
872 
873  template<class T> unsigned long int Filter2d::dsm2dtm_nesw(const Vector2d<T>& inputDSM, Vector2d<T>& outputMask, double hThreshold, int nlimit, int dim)
874 {
875  const char* pszMessage;
876  void* pProgressArg=NULL;
877  GDALProgressFunc pfnProgress=GDALTermProgress;
878  double progress=0;
879  pfnProgress(progress,pszMessage,pProgressArg);
880 
881  Vector2d<T> tmpDSM(inputDSM);
882  double noDataValue=0;
883  if(m_noDataValues.size())
884  noDataValue=m_noDataValues[0];
885 
886  unsigned long int nchange=0;
887  int dimX=dim;
888  int dimY=dim;
889  assert(dimX);
890  assert(dimY);
892  Vector2d<T> inBuffer(dimY,inputDSM.nCols());
893  if(outputMask.size()!=inputDSM.nRows())
894  outputMask.resize(inputDSM.nRows());
895  int indexI=0;
896  int indexJ=0;
897  //initialize last half of inBuffer
898  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
899  for(int i=0;i<inputDSM.nCols();++i)
900  inBuffer[indexJ][i]=tmpDSM[abs(j)][i];
901  ++indexJ;
902  }
903  for(int y=0;y<tmpDSM.nRows();++y){
904  if(y){//inBuffer already initialized for y=0
905  //erase first line from inBuffer
906  inBuffer.erase(inBuffer.begin());
907  //read extra line and push back to inBuffer if not out of bounds
908  if(y+dimY/2<tmpDSM.nRows()){
909  //allocate buffer
910  inBuffer.push_back(inBuffer.back());
911  for(int i=0;i<tmpDSM.nCols();++i)
912  inBuffer[inBuffer.size()-1][i]=tmpDSM[y+dimY/2][i];
913  }
914  else{
915  int over=y+dimY/2-tmpDSM.nRows();
916  int index=(inBuffer.size()-1)-over;
917  assert(index>=0);
918  assert(index<inBuffer.size());
919  inBuffer.push_back(inBuffer[index]);
920  }
921  }
922  for(int x=tmpDSM.nCols()-1;x>=0;--x){
923  double centerValue=inBuffer[(dimY-1)/2][x];
924  short nmasked=0;
925  std::vector<T> neighbors;
926  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
927  for(int i=-(dimX-1)/2;i<=dimX/2;++i){
928  indexI=x+i;
929  //check if out of bounds
930  if(indexI<0)
931  indexI=-indexI;
932  else if(indexI>=tmpDSM.nCols())
933  indexI=tmpDSM.nCols()-i;
934  if(y+j<0)
935  indexJ=-j;
936  else if(y+j>=tmpDSM.nRows())
937  indexJ=(dimY>2) ? (dimY-1)/2-j : 0;
938  else
939  indexJ=(dimY-1)/2+j;
940  double difference=(centerValue-inBuffer[indexJ][indexI]);
941  if(i||j)//skip centerValue
942  neighbors.push_back(inBuffer[indexJ][indexI]);
943  if(difference>hThreshold)
944  ++nmasked;
945  }
946  }
947  if(nmasked<=nlimit){
948  ++nchange;
949  //reset pixel in outputMask
950  outputMask[y][x]=0;
951  }
952  else{
953  //reset pixel height in tmpDSM
954  sort(neighbors.begin(),neighbors.end());
955  assert(neighbors.size()>1);
956  inBuffer[(dimY-1)/2][x]=neighbors[1];
957  /* inBuffer[(dimY-1)/2][x]=stat.mymin(neighbors); */
958  }
959  }
960  progress=(1.0+y);
961  progress/=outputMask.nRows();
962  pfnProgress(progress,pszMessage,pProgressArg);
963  }
964  return nchange;
965 }
966 
967  template<class T> unsigned long int Filter2d::dsm2dtm_senw(const Vector2d<T>& inputDSM, Vector2d<T>& outputMask, double hThreshold, int nlimit, int dim)
968 {
969  const char* pszMessage;
970  void* pProgressArg=NULL;
971  GDALProgressFunc pfnProgress=GDALTermProgress;
972  double progress=0;
973  pfnProgress(progress,pszMessage,pProgressArg);
974 
975  Vector2d<T> tmpDSM(inputDSM);
976  double noDataValue=0;
977  if(m_noDataValues.size())
978  noDataValue=m_noDataValues[0];
979 
980  unsigned long int nchange=0;
981  int dimX=dim;
982  int dimY=dim;
983  assert(dimX);
984  assert(dimY);
986  Vector2d<T> inBuffer(dimY,inputDSM.nCols());
987  if(outputMask.size()!=inputDSM.nRows())
988  outputMask.resize(inputDSM.nRows());
989  int indexI=0;
990  int indexJ=inputDSM.nRows()-1;
991  //initialize first half of inBuffer
992  for(int j=inputDSM.nRows()-dimY/2;j<inputDSM.nRows();--j){
993  for(int i=0;i<inputDSM.nCols();++i)
994  inBuffer[indexJ][i]=tmpDSM[abs(j)][i];
995  ++indexJ;
996  }
997  for(int y=tmpDSM.nRows()-1;y>=0;--y){
998  if(y<tmpDSM.nRows()-1){//inBuffer already initialized for y=tmpDSM.nRows()-1
999  //erase last line from inBuffer
1000  inBuffer.erase(inBuffer.end()-1);
1001  //read extra line and insert to inBuffer if not out of bounds
1002  if(y-dimY/2>0){
1003  //allocate buffer
1004  inBuffer.insert(inBuffer.begin(),inBuffer.back());
1005  for(int i=0;i<tmpDSM.nCols();++i)
1006  inBuffer[0][i]=tmpDSM[y-dimY/2][i];
1007  }
1008  else{
1009  inBuffer.insert(inBuffer.begin(),inBuffer[abs(y-dimY/2)]);
1010  }
1011  }
1012  for(int x=tmpDSM.nCols()-1;x>=0;--x){
1013  double centerValue=inBuffer[(dimY-1)/2][x];
1014  short nmasked=0;
1015  std::vector<T> neighbors;
1016  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
1017  for(int i=-(dimX-1)/2;i<=dimX/2;++i){
1018  indexI=x+i;
1019  //check if out of bounds
1020  if(indexI<0)
1021  indexI=-indexI;
1022  else if(indexI>=tmpDSM.nCols())
1023  indexI=tmpDSM.nCols()-i;
1024  if(y+j<0)
1025  indexJ=-j;
1026  else if(y+j>=tmpDSM.nRows())
1027  indexJ=(dimY>2) ? (dimY-1)/2-j : 0;
1028  else
1029  indexJ=(dimY-1)/2+j;
1030  double difference=(centerValue-inBuffer[indexJ][indexI]);
1031  if(i||j)//skip centerValue
1032  neighbors.push_back(inBuffer[indexJ][indexI]);
1033  if(difference>hThreshold)
1034  ++nmasked;
1035  }
1036  }
1037  if(nmasked<=nlimit){
1038  ++nchange;
1039  //reset pixel in outputMask
1040  outputMask[y][x]=0;
1041  }
1042  else{
1043  //reset pixel height in tmpDSM
1044  sort(neighbors.begin(),neighbors.end());
1045  assert(neighbors.size()>1);
1046  inBuffer[(dimY-1)/2][x]=neighbors[1];
1047  /* inBuffer[(dimY-1)/2][x]=stat.mymin(neighbors); */
1048  }
1049  }
1050  progress=(1.0+y);
1051  progress/=outputMask.nRows();
1052  pfnProgress(progress,pszMessage,pProgressArg);
1053  }
1054  return nchange;
1055 }
1056 
1057  template<class T> unsigned long int Filter2d::dsm2dtm_swne(const Vector2d<T>& inputDSM, Vector2d<T>& outputMask, double hThreshold, int nlimit, int dim)
1058 {
1059  const char* pszMessage;
1060  void* pProgressArg=NULL;
1061  GDALProgressFunc pfnProgress=GDALTermProgress;
1062  double progress=0;
1063  pfnProgress(progress,pszMessage,pProgressArg);
1064 
1065  Vector2d<T> tmpDSM(inputDSM);
1066  double noDataValue=0;
1067  if(m_noDataValues.size())
1068  noDataValue=m_noDataValues[0];
1069 
1070  unsigned long int nchange=0;
1071  int dimX=dim;
1072  int dimY=dim;
1073  assert(dimX);
1074  assert(dimY);
1076  Vector2d<T> inBuffer(dimY,inputDSM.nCols());
1077  if(outputMask.size()!=inputDSM.nRows())
1078  outputMask.resize(inputDSM.nRows());
1079  int indexI=0;
1080  int indexJ=0;
1081  //initialize first half of inBuffer
1082  for(int j=inputDSM.nRows()-dimY/2;j<inputDSM.nRows();--j){
1083  for(int i=0;i<inputDSM.nCols();++i)
1084  inBuffer[indexJ][i]=tmpDSM[abs(j)][i];
1085  ++indexJ;
1086  }
1087  for(int y=tmpDSM.nRows()-1;y>=0;--y){
1088  if(y<tmpDSM.nRows()-1){//inBuffer already initialized for y=0
1089  //erase last line from inBuffer
1090  inBuffer.erase(inBuffer.end()-1);
1091  //read extra line and insert to inBuffer if not out of bounds
1092  if(y-dimY/2>0){
1093  //allocate buffer
1094  inBuffer.insert(inBuffer.begin(),inBuffer.back());
1095  for(int i=0;i<tmpDSM.nCols();++i)
1096  inBuffer[0][i]=tmpDSM[y-dimY/2][i];
1097  }
1098  else{
1099  inBuffer.insert(inBuffer.begin(),inBuffer[abs(y-dimY/2)]);
1100  }
1101  }
1102  for(int x=0;x<tmpDSM.nCols();++x){
1103  double centerValue=inBuffer[(dimY-1)/2][x];
1104  short nmasked=0;
1105  std::vector<T> neighbors;
1106  for(int j=-(dimY-1)/2;j<=dimY/2;++j){
1107  for(int i=-(dimX-1)/2;i<=dimX/2;++i){
1108  indexI=x+i;
1109  //check if out of bounds
1110  if(indexI<0)
1111  indexI=-indexI;
1112  else if(indexI>=tmpDSM.nCols())
1113  indexI=tmpDSM.nCols()-i;
1114  if(y+j<0)
1115  indexJ=-j;
1116  else if(y+j>=tmpDSM.nRows())
1117  indexJ=(dimY>2) ? (dimY-1)/2-j : 0;
1118  else
1119  indexJ=(dimY-1)/2+j;
1120  double difference=(centerValue-inBuffer[indexJ][indexI]);
1121  if(i||j)//skip centerValue
1122  neighbors.push_back(inBuffer[indexJ][indexI]);
1123  if(difference>hThreshold)
1124  ++nmasked;
1125  }
1126  }
1127  if(nmasked<=nlimit){
1128  ++nchange;
1129  //reset pixel in outputMask
1130  outputMask[y][x]=0;
1131  }
1132  else{
1133  //reset pixel height in tmpDSM
1134  sort(neighbors.begin(),neighbors.end());
1135  assert(neighbors.size()>1);
1136  inBuffer[(dimY-1)/2][x]=neighbors[1];
1137  /* inBuffer[(dimY-1)/2][x]=stat.mymin(neighbors); */
1138  }
1139  }
1140  progress=(1.0+y);
1141  progress/=outputMask.nRows();
1142  pfnProgress(progress,pszMessage,pProgressArg);
1143  }
1144  return nchange;
1145 }
1146 
1147  template<class T> void Filter2d::shadowDsm(const Vector2d<T>& input, Vector2d<T>& output, double sza, double saa, double pixelSize, short shadowFlag)
1148 {
1149  unsigned int ncols=input.nCols();
1150  output.clear();
1151  output.resize(input.nRows(),ncols);
1152  //do we need to initialize output?
1153  // for(int y=0;y<output.nRows();++y)
1154  // for(int x=0;x<output.nCols();++x)
1155  // output[y][x]=0;
1156  int indexI=0;
1157  int indexJ=0;
1158  const char* pszMessage;
1159  void* pProgressArg=NULL;
1160  GDALProgressFunc pfnProgress=GDALTermProgress;
1161  double progress=0;
1162  pfnProgress(progress,pszMessage,pProgressArg);
1163  for(int y=0;y<input.nRows();++y){
1164  for(int x=0;x<input.nCols();++x){
1165  double currentValue=input[y][x];
1166  int theDist=static_cast<int>(sqrt((currentValue*tan(DEG2RAD(sza))/pixelSize)*(currentValue*tan(DEG2RAD(sza))/pixelSize)));//in pixels
1167  double theDir=DEG2RAD(saa)+PI/2.0;
1168  if(theDir<0)
1169  theDir+=2*PI;
1170  for(int d=0;d<theDist;++d){//d in pixels
1171  indexI=x+d*cos(theDir);//in pixels
1172  indexJ=y+d*sin(theDir);//in pixels
1173  if(indexJ<0||indexJ>=input.size())
1174  continue;
1175  if(indexI<0||indexI>=input[indexJ].size())
1176  continue;
1177  if(input[indexJ][indexI]<currentValue-d*pixelSize/tan(DEG2RAD(sza))){//in m
1178  output[indexJ][indexI]=shadowFlag;
1179  }
1180  }
1181  }
1182  progress=(1.0+y);
1183  progress/=output.nRows();
1184  pfnProgress(progress,pszMessage,pProgressArg);
1185  }
1186 }
1187 
1188 template<class T> void Filter2d::dwtForward(Vector2d<T>& theBuffer, const std::string& wavelet_type, int family){
1189  const char* pszMessage;
1190  void* pProgressArg=NULL;
1191  GDALProgressFunc pfnProgress=GDALTermProgress;
1192  double progress=0;
1193  pfnProgress(progress,pszMessage,pProgressArg);
1194 
1195  int nRow=theBuffer.size();
1196  assert(nRow);
1197  int nCol=theBuffer[0].size();
1198  assert(nCol);
1199  //make sure data size if power of 2
1200  while(theBuffer.size()&(theBuffer.size()-1))
1201  theBuffer.push_back(theBuffer.back());
1202  for(int irow=0;irow<theBuffer.size();++irow)
1203  while(theBuffer[irow].size()&(theBuffer[irow].size()-1))
1204  theBuffer[irow].push_back(theBuffer[irow].back());
1205  std::vector<double> vdata(theBuffer.size()*theBuffer[0].size());
1206  double* data=&(vdata[0]);
1207  for(int irow=0;irow<theBuffer.size();++irow){
1208  for(int icol=0;icol<theBuffer[0].size();++icol){
1209  int index=irow*theBuffer[0].size()+icol;
1210  data[index]=theBuffer[irow][icol];
1211  }
1212  }
1213  int nsize=theBuffer.size()*theBuffer[0].size();
1214  gsl_wavelet *w;
1215  gsl_wavelet_workspace *work;
1216  assert(nsize);
1217  w=gsl_wavelet_alloc(filter::Filter::getWaveletType(wavelet_type),family);
1218  work=gsl_wavelet_workspace_alloc(nsize);
1219  gsl_wavelet2d_nstransform_forward (w, data, theBuffer.size(), theBuffer.size(),theBuffer[0].size(), work);
1220  theBuffer.erase(theBuffer.begin()+nRow,theBuffer.end());
1221  for(int irow=0;irow<theBuffer.size();++irow){
1222  theBuffer[irow].erase(theBuffer[irow].begin()+nCol,theBuffer[irow].end());
1223  for(int icol=0;icol<theBuffer[irow].size();++icol){
1224  int index=irow*theBuffer[irow].size()+icol;
1225  theBuffer[irow][icol]=data[index];
1226  }
1227  progress=(1.0+irow);
1228  progress/=theBuffer.nRows();
1229  pfnProgress(progress,pszMessage,pProgressArg);
1230  }
1231  gsl_wavelet_free (w);
1232  gsl_wavelet_workspace_free (work);
1233 }
1234 
1235 template<class T> void Filter2d::dwtInverse(Vector2d<T>& theBuffer, const std::string& wavelet_type, int family){
1236  const char* pszMessage;
1237  void* pProgressArg=NULL;
1238  GDALProgressFunc pfnProgress=GDALTermProgress;
1239  double progress=0;
1240  pfnProgress(progress,pszMessage,pProgressArg);
1241 
1242  int nRow=theBuffer.size();
1243  assert(nRow);
1244  int nCol=theBuffer[0].size();
1245  assert(nCol);
1246  //make sure data size if power of 2
1247  while(theBuffer.size()&(theBuffer.size()-1))
1248  theBuffer.push_back(theBuffer.back());
1249  for(int irow=0;irow<theBuffer.size();++irow)
1250  while(theBuffer[irow].size()&(theBuffer[irow].size()-1))
1251  theBuffer[irow].push_back(theBuffer[irow].back());
1252  std::vector<double> vdata(theBuffer.size()*theBuffer[0].size());
1253  double* data=&(vdata[0]);
1254  //double data[theBuffer.size()*theBuffer[0].size()];
1255  for(int irow=0;irow<theBuffer.size();++irow){
1256  for(int icol=0;icol<theBuffer[0].size();++icol){
1257  int index=irow*theBuffer[0].size()+icol;
1258  data[index]=theBuffer[irow][icol];
1259  }
1260  }
1261  int nsize=theBuffer.size()*theBuffer[0].size();
1262  gsl_wavelet *w;
1263  gsl_wavelet_workspace *work;
1264  assert(nsize);
1265  w=gsl_wavelet_alloc(filter::Filter::getWaveletType(wavelet_type),family);
1266  work=gsl_wavelet_workspace_alloc(nsize);
1267  gsl_wavelet2d_nstransform_inverse (w, data, theBuffer.size(), theBuffer.size(),theBuffer[0].size(), work);
1268  theBuffer.erase(theBuffer.begin()+nRow,theBuffer.end());
1269  for(int irow=0;irow<theBuffer.size();++irow){
1270  theBuffer[irow].erase(theBuffer[irow].begin()+nCol,theBuffer[irow].end());
1271  for(int icol=0;icol<theBuffer[irow].size();++icol){
1272  int index=irow*theBuffer[irow].size()+icol;
1273  theBuffer[irow][icol]=data[index];
1274  }
1275  progress=(1.0+irow);
1276  progress/=theBuffer.nRows();
1277  pfnProgress(progress,pszMessage,pProgressArg);
1278  }
1279  gsl_wavelet_free (w);
1280  gsl_wavelet_workspace_free (work);
1281 }
1282 
1283 template<class T> void Filter2d::dwtCut(Vector2d<T>& theBuffer, const std::string& wavelet_type, int family, double cut){
1284  const char* pszMessage;
1285  void* pProgressArg=NULL;
1286  GDALProgressFunc pfnProgress=GDALTermProgress;
1287  double progress=0;
1288  pfnProgress(progress,pszMessage,pProgressArg);
1289 
1290  int nRow=theBuffer.size();
1291  assert(nRow);
1292  int nCol=theBuffer[0].size();
1293  assert(nCol);
1294  //make sure data size if power of 2
1295  while(theBuffer.size()&(theBuffer.size()-1))
1296  theBuffer.push_back(theBuffer.back());
1297  for(int irow=0;irow<theBuffer.size();++irow)
1298  while(theBuffer[irow].size()&(theBuffer[irow].size()-1))
1299  theBuffer[irow].push_back(theBuffer[irow].back());
1300  double* data=new double[theBuffer.size()*theBuffer[0].size()];
1301  double* abscoeff=new double[theBuffer.size()*theBuffer[0].size()];
1302  size_t* p=new size_t[theBuffer.size()*theBuffer[0].size()];
1303  for(int irow=0;irow<theBuffer.size();++irow){
1304  for(int icol=0;icol<theBuffer[0].size();++icol){
1305  int index=irow*theBuffer[0].size()+icol;
1306  assert(index<theBuffer.size()*theBuffer[0].size());
1307  data[index]=theBuffer[irow][icol];
1308  }
1309  }
1310  int nsize=theBuffer.size()*theBuffer[0].size();
1311  gsl_wavelet *w;
1312  gsl_wavelet_workspace *work;
1313  assert(nsize);
1314  w=gsl_wavelet_alloc(filter::Filter::getWaveletType(wavelet_type),family);
1315  work=gsl_wavelet_workspace_alloc(nsize);
1316  gsl_wavelet2d_nstransform_forward (w, data, theBuffer.size(), theBuffer[0].size(),theBuffer[0].size(), work);
1317  for(int irow=0;irow<theBuffer.size();++irow){
1318  for(int icol=0;icol<theBuffer[0].size();++icol){
1319  int index=irow*theBuffer[0].size()+icol;
1320  abscoeff[index]=fabs(data[index]);
1321  }
1322  }
1323  int nc=(100-cut)/100.0*nsize;
1324  gsl_sort_index(p,abscoeff,1,nsize);
1325  for(int i=0;(i+nc)<nsize;i++)
1326  data[p[i]]=0;
1327  gsl_wavelet2d_nstransform_inverse (w, data, theBuffer.size(), theBuffer[0].size(),theBuffer[0].size(), work);
1328  for(int irow=0;irow<theBuffer.size();++irow){
1329  for(int icol=0;icol<theBuffer[irow].size();++icol){
1330  int index=irow*theBuffer[irow].size()+icol;
1331  theBuffer[irow][icol]=data[index];
1332  }
1333  progress=(1.0+irow);
1334  progress/=theBuffer.nRows();
1335  pfnProgress(progress,pszMessage,pProgressArg);
1336  }
1337  theBuffer.erase(theBuffer.begin()+nRow,theBuffer.end());
1338  for(int irow=0;irow<theBuffer.size();++irow)
1339  theBuffer[irow].erase(theBuffer[irow].begin()+nCol,theBuffer[irow].end());
1340  delete[] data;
1341  delete[] abscoeff;
1342  delete[] p;
1343  gsl_wavelet_free (w);
1344  gsl_wavelet_workspace_free (work);
1345 
1346 }
1347 
1348 }
1349 
1350 #endif /* _MYFILTER_H_ */