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).",
"GTiff");
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 omit 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)
161 std::cout << std::endl <<
"Output pixel type: " << GDALGetDataTypeName(theType) << endl;
164 if(oformat_opt.size())
165 imageType=oformat_opt[0];
167 if(option_opt.findSubstring(
"INTERLEAVE=")==option_opt.end()){
168 string theInterleave=
"INTERLEAVE=";
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);
179 if(colorTable_opt.size())
183 if(nodata_opt.size()){
184 for(
int iband=0;iband<outputWriter.
nrOfBand();++iband)
191 input.
readDataBlock(inputData,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 std::cout <<
"writing data block" << std::endl;
421 std::cout <<
"outputData.nCols(): " << outputData.nCols() << std::endl;
422 std::cout <<
"outputData.nRows(): " << outputData.nRows() << std::endl;
423 std::cout <<
"outputWriter.nrOfCol(): " << outputWriter.
nrOfCol() << std::endl;
424 std::cout <<
"outputWriter.nrOfRow(): " << outputWriter.
nrOfRow() << std::endl;
425 std::cout <<
"outputWriter.getDataType(): " << outputWriter.
getDataType() << std::endl;
429 outputWriter.
writeDataBlock(outputData,0,outputData.nCols()-1,0,outputData.nRows()-1);
431 catch(std::string errorString){
432 cout << errorString << endl;
439 outputWriter.
close();
void close(void)
Set the memory (in MB) to cache a number of rows in memory.
int nrOfCol(void) const
Get the number of columns of this dataset.
void setColorTable(const std::string &filename, int band=0)
Set the color table using an (ASCII) file with 5 columns (value R G B alpha)
int nrOfRow(void) const
Get the number of rows of this dataset.
double getDeltaX(void) const
Get the pixel cell spacing in x.
void copyGeoTransform(const ImgRasterGdal &imgSrc)
Copy geotransform information from another georeferenced image.
bool writeDataBlock(Vector2d< T > &buffer2d, int minCol, int maxCol, int minRow, int maxRow, int band=0)
Write pixel cell values for a range of columns and rows for a specific band (all indices start counti...
void open(const std::string &filename, const ImgReaderGdal &imgSrc, const std::vector< std::string > &options=std::vector< std::string >())
Open an image for writing, copying image attributes from a source image. Image is directly written to...
std::string getProjection(void) const
Get the projection string (deprecated, use getProjectionRef instead)
GDALDataType getDataType(int band=0) const
Get the GDAL datatype for this dataset.
CPLErr setProjection(const std::string &projection)
Set the projection for this dataset in well known text (wkt) format.
void close(void)
Close the image.
void readDataBlock(Vector2d< T > &buffer2d, int minCol, int maxCol, int minRow, int maxRow, int band=0)
Read pixel cell values for a range of columns and rows for a specific band (all indices start countin...
CPLErr GDALSetNoDataValue(double noDataValue, int band=0)
Set the GDAL (internal) no data value for this data set. Only a single no data value per band is supp...
void open(const std::string &filename, const GDALAccess &readMode=GA_ReadOnly)
Open an image.
int nrOfBand(void) const
Get the number of bands of this dataset.
std::string getInterleave() const
Get the band coding (interleave)