23 #include "base/Optionpk.h"
24 #include "base/Vector2d.h"
25 #include "algorithms/Filter2d.h"
26 #include "imageclasses/ImgReaderGdal.h"
27 #include "imageclasses/ImgWriterGdal.h"
33 int main(
int argc,
char **argv) {
37 Optionpk<bool> disc_opt(
"circ",
"circular",
"circular disc kernel for dilation and erosion",
false);
38 Optionpk<string> postFilter_opt(
"f",
"filter",
"post processing filter: vito, etew_min, promorph (progressive morphological filter),open,close).");
40 Optionpk<double> maxSlope_opt(
"st",
"st",
"slope threshold used for morphological filtering. Use a low values to remove more height objects in flat terrains", 0.0);
41 Optionpk<double> hThreshold_opt(
"ht",
"ht",
"initial height threshold for progressive morphological filtering. Use low values to remove more height objects. Optionally, a maximum height threshold can be set via a second argument (e.g., -ht 0.2 -ht 2.5 sets an initial threshold at 0.2 m and caps the threshold at 2.5 m).", 0.2);
42 Optionpk<short> minChange_opt(
"minchange",
"minchange",
"Stop iterations when no more pixels are changed than this threshold.", 0);
43 Optionpk<std::string> otype_opt(
"ot",
"otype",
"Data type for output image ({Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/CInt16/CInt32/CFloat32/CFloat64}). Empty string: inherit type from input image",
"");
44 Optionpk<string> oformat_opt(
"of",
"oformat",
"Output image format (see also gdal_translate). Empty string: inherit from input image");
45 Optionpk<string> colorTable_opt(
"ct",
"ct",
"color table (file with 5 columns: id R G B ALFA (0: transparent, 255: solid). Use none to ommit color table");
46 Optionpk<string> option_opt(
"co",
"co",
"Creation option for output file. Multiple options can be specified.");
48 Optionpk<short> verbose_opt(
"v",
"verbose",
"verbose mode if > 0", 0,2);
51 maxSlope_opt.setHide(1);
52 hThreshold_opt.setHide(1);
53 minChange_opt.setHide(1);
55 oformat_opt.setHide(1);
56 colorTable_opt.setHide(1);
57 nodata_opt.setHide(1);
61 doProcess=input_opt.retrieveOption(argc,argv);
62 output_opt.retrieveOption(argc,argv);
64 postFilter_opt.retrieveOption(argc,argv);
65 dim_opt.retrieveOption(argc,argv);
66 disc_opt.retrieveOption(argc,argv);
67 maxSlope_opt.retrieveOption(argc,argv);
68 hThreshold_opt.retrieveOption(argc,argv);
69 minChange_opt.retrieveOption(argc,argv);
70 otype_opt.retrieveOption(argc,argv);
71 oformat_opt.retrieveOption(argc,argv);
72 colorTable_opt.retrieveOption(argc,argv);
73 nodata_opt.retrieveOption(argc,argv);
74 verbose_opt.retrieveOption(argc,argv);
76 catch(
string predefinedString){
77 std::cout << predefinedString << std::endl;
82 cout <<
"Usage: pkfilterdem -i input.txt -o output" << endl;
84 std::cout <<
"short option -h shows basic options only, use long option --help to show all options" << std::endl;
90 if(input_opt.empty()){
91 cerr <<
"Error: no input file selected, use option -i" << endl;
94 if(output_opt.empty()){
95 cerr <<
"Error: no outputWriter file selected, use option -o" << endl;
98 if(postFilter_opt.empty()){
99 cerr <<
"Error: no filter selected, use option -f" << endl;
102 input.open(input_opt[0]);
103 GDALDataType theType=GDT_Unknown;
105 cout <<
"possible output data types: ";
106 for(
int iType = 0; iType < GDT_TypeCount; ++iType){
108 cout <<
" " << GDALGetDataTypeName((GDALDataType)iType);
109 if( GDALGetDataTypeName((GDALDataType)iType) != NULL
110 && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
111 otype_opt[0].c_str()))
112 theType=(GDALDataType) iType;
114 if(theType==GDT_Unknown)
115 theType=input.getDataType();
118 std::cout << std::endl <<
"Output pixel type: " << GDALGetDataTypeName(theType) << endl;
120 string imageType=input.getImageType();
121 if(oformat_opt.size())
122 imageType=oformat_opt[0];
124 if(option_opt.findSubstring(
"INTERLEAVE=")==option_opt.end()){
125 string theInterleave=
"INTERLEAVE=";
126 theInterleave+=input.getInterleave();
127 option_opt.push_back(theInterleave);
131 cout <<
"opening output file " << output_opt[0] << endl;
132 outputWriter.open(output_opt[0],input.nrOfCol(),input.nrOfRow(),1,theType,imageType,option_opt);
134 outputWriter.setProjection(input.getProjection());
135 outputWriter.copyGeoTransform(input);
136 if(colorTable_opt.size())
137 outputWriter.setColorTable(colorTable_opt[0]);
140 if(nodata_opt.size()){
141 for(
int iband=0;iband<outputWriter.nrOfBand();++iband)
142 outputWriter.GDALSetNoDataValue(nodata_opt[0],iband);
148 input.readDataBlock(inputData,GDT_Float64,0,inputData.nCols()-1,0,inputData.nRows()-1);
151 std::cout <<
"Applying post processing filter: " << postFilter_opt[0] << std::endl;
161 dim_opt.insert(dim_opt.begin(),3);
162 if(dim_opt[0]>dim_opt[1]){
163 dim_opt.insert(dim_opt.begin(),dim_opt[1]);
164 dim_opt.erase(dim_opt.begin()+2);
168 if(nodata_opt.size()){
169 for(
int inodata=0;inodata<nodata_opt.size();++inodata)
170 theFilter.pushNoDataValue(nodata_opt[inodata]);
173 unsigned long int nchange=1;
174 if(postFilter_opt[0]==
"vito"){
181 vector<int> nlimit(4);
187 for(
int irow=0;irow<tmpData.nRows();++irow)
188 for(
int icol=0;icol<tmpData.nCols();++icol)
189 tmpData[irow][icol]=1;
190 for(
int iheight=0;iheight<hThreshold_opt.size();++iheight){
192 cout <<
"height: " << hThreshold_opt[iheight] << endl;
195 for(
int irow=0;irow<tmpMask.nRows();++irow)
196 for(
int icol=0;icol<tmpMask.nCols();++icol)
197 tmpMask[irow][icol]=1;
199 cout <<
"filtering NWSE" << endl;
293 theFilter.dsm2dtm_nwse(inputData,tmpData,hThreshold_opt[iheight],nlimit[iheight],dim_opt[0]);
295 cout <<
"filtering NESW" << endl;
296 theFilter.dsm2dtm_nesw(inputData,tmpData,hThreshold_opt[iheight],nlimit[iheight],dim_opt[0]);
298 cout <<
"filtering SENW" << endl;
299 theFilter.dsm2dtm_senw(inputData,tmpData,hThreshold_opt[iheight],nlimit[iheight],dim_opt[0]);
301 cout <<
"filtering SWNE" << endl;
302 theFilter.dsm2dtm_swne(inputData,tmpData,hThreshold_opt[iheight],nlimit[iheight],dim_opt[0]);
308 else if(postFilter_opt[0]==
"etew_min"){
315 while(nchange>minChange_opt[0]&&dim<=dim_opt[1]){
316 double hThreshold=maxSlope_opt[0]*dim;
317 nchange=theFilter.morphology(inputData,outputData,
"erode",dim,dim,disc_opt[0],hThreshold);
318 inputData=outputData;
320 std::cout <<
"iteration " << iteration <<
": " << nchange <<
" pixels changed" << std::endl;
324 else if(postFilter_opt[0]==
"promorph"){
329 double hThreshold=hThreshold_opt[0];
331 while(nchange>minChange_opt[0]&&dim<=dim_opt[1]){
332 std::cout <<
"iteration " << iteration <<
" with window size " << dim <<
" and dh_max: " << hThreshold << std::endl;
334 nchange=theFilter.morphology(inputData,outputData,
"erode",dim,dim,disc_opt[0],hThreshold);
335 theFilter.morphology(outputData,inputData,
"dilate",dim,dim,disc_opt[0],hThreshold);
336 theFilter.doit(inputData,outputData,
"median",dim,dim,1,disc_opt[0]);
337 inputData=outputData;
339 catch(std::string errorString){
340 cout << errorString << endl;
343 int newdim=(dim==1)? 3: 2*(dim-1)+1;
344 hThreshold=hThreshold_opt[0]+maxSlope_opt[0]*(newdim-dim)*input.getDeltaX();
346 if(hThreshold_opt.size()>1){
347 if(hThreshold>hThreshold_opt[1]){
348 hThreshold=hThreshold_opt[1];
351 std::cout <<
"iteration " << iteration <<
": " << nchange <<
" pixels changed" << std::endl;
355 else if(postFilter_opt[0]==
"open"){
357 theFilter.morphology(inputData,tmpData,
"erode",dim_opt[0],dim_opt[0],disc_opt[0],hThreshold_opt[0]);
358 theFilter.morphology(tmpData,outputData,
"dilate",dim_opt[0],dim_opt[0],disc_opt[0],hThreshold_opt[0]);
359 outputData=inputData;
361 catch(std::string errorString){
362 cout << errorString << endl;
366 else if(postFilter_opt[0]==
"close"){
368 theFilter.morphology(inputData,tmpData,
"dilate",dim_opt[0],dim_opt[0],disc_opt[0],hThreshold_opt[0]);
369 theFilter.morphology(tmpData,outputData,
"erode",dim_opt[0],dim_opt[0],disc_opt[0],hThreshold_opt[0]);
371 catch(std::string errorString){
372 cout << errorString << endl;
377 outputWriter.writeDataBlock(outputData,GDT_Float64,0,outputData.nCols()-1,0,outputData.nRows()-1);
382 outputWriter.close();