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"
76 int main(
int argc,
char **argv) {
80 Optionpk<bool> disc_opt(
"circ",
"circular",
"circular disc kernel for dilation and erosion",
false);
81 Optionpk<string> postFilter_opt(
"f",
"filter",
"post processing filter: vito, etew_min, promorph (progressive morphological filter),open,close).");
83 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);
84 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);
85 Optionpk<short> minChange_opt(
"minchange",
"minchange",
"Stop iterations when no more pixels are changed than this threshold.", 0);
86 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",
"");
87 Optionpk<string> oformat_opt(
"of",
"oformat",
"Output image format (see also gdal_translate). Empty string: inherit from input image");
88 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");
89 Optionpk<string> option_opt(
"co",
"co",
"Creation option for output file. Multiple options can be specified.");
91 Optionpk<short> verbose_opt(
"v",
"verbose",
"verbose mode if > 0", 0,2);
94 maxSlope_opt.setHide(1);
95 hThreshold_opt.setHide(1);
96 minChange_opt.setHide(1);
98 oformat_opt.setHide(1);
99 colorTable_opt.setHide(1);
100 nodata_opt.setHide(1);
104 doProcess=input_opt.retrieveOption(argc,argv);
105 output_opt.retrieveOption(argc,argv);
107 postFilter_opt.retrieveOption(argc,argv);
108 dim_opt.retrieveOption(argc,argv);
109 disc_opt.retrieveOption(argc,argv);
110 maxSlope_opt.retrieveOption(argc,argv);
111 hThreshold_opt.retrieveOption(argc,argv);
112 minChange_opt.retrieveOption(argc,argv);
113 otype_opt.retrieveOption(argc,argv);
114 oformat_opt.retrieveOption(argc,argv);
115 colorTable_opt.retrieveOption(argc,argv);
116 nodata_opt.retrieveOption(argc,argv);
117 verbose_opt.retrieveOption(argc,argv);
119 catch(
string predefinedString){
120 std::cout << predefinedString << std::endl;
125 cout <<
"Usage: pkfilterdem -i input.txt -o output" << endl;
127 std::cout <<
"short option -h shows basic options only, use long option --help to show all options" << std::endl;
133 if(input_opt.empty()){
134 cerr <<
"Error: no input file selected, use option -i" << endl;
137 if(output_opt.empty()){
138 cerr <<
"Error: no outputWriter file selected, use option -o" << endl;
141 if(postFilter_opt.empty()){
142 cerr <<
"Error: no filter selected, use option -f" << endl;
145 input.open(input_opt[0]);
146 GDALDataType theType=GDT_Unknown;
148 cout <<
"possible output data types: ";
149 for(
int iType = 0; iType < GDT_TypeCount; ++iType){
151 cout <<
" " << GDALGetDataTypeName((GDALDataType)iType);
152 if( GDALGetDataTypeName((GDALDataType)iType) != NULL
153 && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
154 otype_opt[0].c_str()))
155 theType=(GDALDataType) iType;
157 if(theType==GDT_Unknown)
158 theType=input.getDataType();
161 std::cout << std::endl <<
"Output pixel type: " << GDALGetDataTypeName(theType) << endl;
163 string imageType=input.getImageType();
164 if(oformat_opt.size())
165 imageType=oformat_opt[0];
167 if(option_opt.findSubstring(
"INTERLEAVE=")==option_opt.end()){
168 string theInterleave=
"INTERLEAVE=";
169 theInterleave+=input.getInterleave();
170 option_opt.push_back(theInterleave);
174 cout <<
"opening output file " << output_opt[0] << endl;
175 outputWriter.open(output_opt[0],input.nrOfCol(),input.nrOfRow(),1,theType,imageType,option_opt);
177 outputWriter.setProjection(input.getProjection());
178 outputWriter.copyGeoTransform(input);
179 if(colorTable_opt.size())
180 outputWriter.setColorTable(colorTable_opt[0]);
183 if(nodata_opt.size()){
184 for(
int iband=0;iband<outputWriter.nrOfBand();++iband)
185 outputWriter.GDALSetNoDataValue(nodata_opt[0],iband);
191 input.readDataBlock(inputData,GDT_Float64,0,inputData.nCols()-1,0,inputData.nRows()-1);
194 std::cout <<
"Applying post processing filter: " << postFilter_opt[0] << std::endl;
204 dim_opt.insert(dim_opt.begin(),3);
205 if(dim_opt[0]>dim_opt[1]){
206 dim_opt.insert(dim_opt.begin(),dim_opt[1]);
207 dim_opt.erase(dim_opt.begin()+2);
211 if(nodata_opt.size()){
212 for(
int inodata=0;inodata<nodata_opt.size();++inodata)
213 theFilter.pushNoDataValue(nodata_opt[inodata]);
216 unsigned long int nchange=1;
217 if(postFilter_opt[0]==
"vito"){
224 vector<int> nlimit(4);
230 for(
int irow=0;irow<tmpData.nRows();++irow)
231 for(
int icol=0;icol<tmpData.nCols();++icol)
232 tmpData[irow][icol]=1;
233 for(
int iheight=0;iheight<hThreshold_opt.size();++iheight){
235 cout <<
"height: " << hThreshold_opt[iheight] << endl;
238 for(
int irow=0;irow<tmpMask.nRows();++irow)
239 for(
int icol=0;icol<tmpMask.nCols();++icol)
240 tmpMask[irow][icol]=1;
242 cout <<
"filtering NWSE" << endl;
336 theFilter.dsm2dtm_nwse(inputData,tmpData,hThreshold_opt[iheight],nlimit[iheight],dim_opt[0]);
338 cout <<
"filtering NESW" << endl;
339 theFilter.dsm2dtm_nesw(inputData,tmpData,hThreshold_opt[iheight],nlimit[iheight],dim_opt[0]);
341 cout <<
"filtering SENW" << endl;
342 theFilter.dsm2dtm_senw(inputData,tmpData,hThreshold_opt[iheight],nlimit[iheight],dim_opt[0]);
344 cout <<
"filtering SWNE" << endl;
345 theFilter.dsm2dtm_swne(inputData,tmpData,hThreshold_opt[iheight],nlimit[iheight],dim_opt[0]);
351 else if(postFilter_opt[0]==
"etew_min"){
358 while(nchange>minChange_opt[0]&&dim<=dim_opt[1]){
359 double hThreshold=maxSlope_opt[0]*dim;
360 nchange=theFilter.morphology(inputData,outputData,
"erode",dim,dim,disc_opt[0],hThreshold);
361 inputData=outputData;
363 std::cout <<
"iteration " << iteration <<
": " << nchange <<
" pixels changed" << std::endl;
367 else if(postFilter_opt[0]==
"promorph"){
372 double hThreshold=hThreshold_opt[0];
374 while(nchange>minChange_opt[0]&&dim<=dim_opt[1]){
375 std::cout <<
"iteration " << iteration <<
" with window size " << dim <<
" and dh_max: " << hThreshold << std::endl;
377 nchange=theFilter.morphology(inputData,outputData,
"erode",dim,dim,disc_opt[0],hThreshold);
378 theFilter.morphology(outputData,inputData,
"dilate",dim,dim,disc_opt[0],hThreshold);
379 theFilter.doit(inputData,outputData,
"median",dim,dim,1,disc_opt[0]);
380 inputData=outputData;
382 catch(std::string errorString){
383 cout << errorString << endl;
386 int newdim=(dim==1)? 3: 2*(dim-1)+1;
387 hThreshold=hThreshold_opt[0]+maxSlope_opt[0]*(newdim-dim)*input.getDeltaX();
389 if(hThreshold_opt.size()>1){
390 if(hThreshold>hThreshold_opt[1]){
391 hThreshold=hThreshold_opt[1];
394 std::cout <<
"iteration " << iteration <<
": " << nchange <<
" pixels changed" << std::endl;
398 else if(postFilter_opt[0]==
"open"){
400 theFilter.morphology(inputData,tmpData,
"erode",dim_opt[0],dim_opt[0],disc_opt[0],hThreshold_opt[0]);
401 theFilter.morphology(tmpData,outputData,
"dilate",dim_opt[0],dim_opt[0],disc_opt[0],hThreshold_opt[0]);
402 outputData=inputData;
404 catch(std::string errorString){
405 cout << errorString << endl;
409 else if(postFilter_opt[0]==
"close"){
411 theFilter.morphology(inputData,tmpData,
"dilate",dim_opt[0],dim_opt[0],disc_opt[0],hThreshold_opt[0]);
412 theFilter.morphology(tmpData,outputData,
"erode",dim_opt[0],dim_opt[0],disc_opt[0],hThreshold_opt[0]);
414 catch(std::string errorString){
415 cout << errorString << endl;
420 outputWriter.writeDataBlock(outputData,GDT_Float64,0,outputData.nCols()-1,0,outputData.nRows()-1);
425 outputWriter.close();