22 #include "imageclasses/ImgReaderGdal.h"
23 #include "imageclasses/ImgWriterGdal.h"
24 #include "imageclasses/ImgReaderOgr.h"
25 #include "lasclasses/FileReaderLas.h"
26 #include "algorithms/StatFactory.h"
27 #include "algorithms/Filter2d.h"
31 int main(
int argc,
char **argv) {
33 Optionpk<string> attribute_opt(
"n",
"name",
"names of the attribute to select: intensity, return, nreturn, z",
"z");
39 Optionpk<unsigned short> classes_opt(
"class",
"class",
"classes to keep: 0 (created, never classified), 1 (unclassified), 2 (ground), 3 (low vegetation), 4 (medium vegetation), 5 (high vegetation), 6 (building), 7 (low point, noise), 8 (model key-point), 9 (water), 10 (reserved), 11 (reserved), 12 (overlap)");
40 Optionpk<string> composite_opt(
"comp",
"comp",
"composite for multiple points in cell (min, max, median, mean, sum, first, last, profile (percentile height values), percentile, number (point density)). Last: overwrite cells with latest point",
"last");
41 Optionpk<string> filter_opt(
"fir",
"filter",
"filter las points (first,last,single,multiple,all).",
"all");
46 Optionpk<string> projection_opt(
"a_srs",
"a_srs",
"assign the projection for the output file in epsg code, e.g., epsg:3035 for European LAEA projection");
47 Optionpk<double> ulx_opt(
"ulx",
"ulx",
"Upper left x value bounding box (in geocoordinates if georef is true). 0 is read from input file", 0.0);
48 Optionpk<double> uly_opt(
"uly",
"uly",
"Upper left y value bounding box (in geocoordinates if georef is true). 0 is read from input file", 0.0);
49 Optionpk<double> lrx_opt(
"lrx",
"lrx",
"Lower right x value bounding box (in geocoordinates if georef is true). 0 is read from input file", 0.0);
50 Optionpk<double> lry_opt(
"lry",
"lry",
"Lower right y value bounding box (in geocoordinates if georef is true). 0 is read from input file", 0.0);
51 Optionpk<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",
"Byte");
52 Optionpk<string> oformat_opt(
"of",
"oformat",
"Output image format (see also gdal_translate). Empty string: inherit from input image",
"GTiff");
53 Optionpk<double> dx_opt(
"dx",
"dx",
"Output resolution in x (in meter)", 1.0);
54 Optionpk<double> dy_opt(
"dy",
"dy",
"Output resolution in y (in meter)", 1.0);
55 Optionpk<short> nbin_opt(
"nbin",
"nbin",
"Number of percentile bins for calculating percentile height value profile (=number of output bands)", 10.0);
56 Optionpk<double> percentile_opt(
"perc",
"perc",
"Percentile value used for rule percentile",95);
57 Optionpk<short> nodata_opt(
"nodata",
"nodata",
"nodata value to put in image", 0);
58 Optionpk<string> option_opt(
"co",
"co",
"Creation option for output file. Multiple options can be specified.");
59 Optionpk<string> colorTable_opt(
"ct",
"ct",
"color table (file with 5 columns: id R G B ALFA (0: transparent, 255: solid)");
63 percentile_opt.setHide(1);
64 nodata_opt.setHide(1);
65 option_opt.setHide(1);
66 colorTable_opt.setHide(1);
70 doProcess=input_opt.retrieveOption(argc,argv);
71 attribute_opt.retrieveOption(argc,argv);
72 returns_opt.retrieveOption(argc,argv);
73 classes_opt.retrieveOption(argc,argv);
74 composite_opt.retrieveOption(argc,argv);
75 filter_opt.retrieveOption(argc,argv);
76 output_opt.retrieveOption(argc,argv);
77 projection_opt.retrieveOption(argc,argv);
78 ulx_opt.retrieveOption(argc,argv);
79 uly_opt.retrieveOption(argc,argv);
80 lrx_opt.retrieveOption(argc,argv);
81 lry_opt.retrieveOption(argc,argv);
82 otype_opt.retrieveOption(argc,argv);
83 oformat_opt.retrieveOption(argc,argv);
84 dx_opt.retrieveOption(argc,argv);
85 dy_opt.retrieveOption(argc,argv);
86 nbin_opt.retrieveOption(argc,argv);
87 percentile_opt.retrieveOption(argc,argv);
88 nodata_opt.retrieveOption(argc,argv);
89 option_opt.retrieveOption(argc,argv);
90 colorTable_opt.retrieveOption(argc,argv);
91 verbose_opt.retrieveOption(argc,argv);
93 catch(
string predefinedString){
94 std::cout << predefinedString << std::endl;
100 cout <<
"pklas2img -i lasfile -o output" << endl;
102 std::cout <<
"short option -h shows basic options only, use long option --help to show all options" << std::endl;
108 double dfComplete=0.0;
109 const char* pszMessage;
110 void* pProgressArg=NULL;
111 GDALProgressFunc pfnProgress=GDALTermProgress;
119 GDALDataType theType=GDT_Unknown;
121 cout <<
"possible output data types: ";
122 for(
int iType = 0; iType < GDT_TypeCount; ++iType){
124 cout <<
" " << GDALGetDataTypeName((GDALDataType)iType);
125 if( GDALGetDataTypeName((GDALDataType)iType) != NULL
126 && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
127 otype_opt[0].c_str()))
128 theType=(GDALDataType) iType;
131 if(theType==GDT_Unknown)
132 cout <<
"Unknown output pixel type: " << otype_opt[0] << endl;
134 cout <<
"Output pixel type: " << GDALGetDataTypeName(theType) << endl;
142 unsigned long int totalPoints=0;
143 unsigned long int nPoints=0;
144 unsigned long int ipoint=0;
145 for(
int iinput=0;iinput<input_opt.size();++iinput){
149 lasReader.open(input_opt[iinput]);
151 catch(
string errorString){
152 cerr << errorString << endl;
156 cerr <<
"Error opening input " << input_opt[iinput] << endl;
159 nPoints=lasReader.getPointCount();
160 totalPoints+=nPoints;
162 if(ulx_opt[0]>=lrx_opt[0]||uly_opt[0]<=lry_opt[0]){
163 double ulx,uly,lrx,lry;
164 lasReader.getExtent(ulx,uly,lrx,lry);
168 ulx=ulx-dx_opt[0]/2.0;
169 lrx=ulx+dx_opt[0]/2.0;
172 uly=lry+dy_opt[0]/2.0;
173 lry=lry-dy_opt[0]/2.0;
176 maxLRX=(lrx>maxLRX)?lrx:maxLRX;
177 maxULY=(uly>maxULY)?uly:maxULY;
178 minULX=(ulx<minULX)?ulx:minULX;
179 minLRY=(lry<minLRY)?lry:minLRY;
197 std::cout << setprecision(12) <<
"--ulx=" << minULX <<
" --uly=" << maxULY <<
" --lrx=" << maxLRX <<
" --lry=" << minLRY << std::endl;
198 std::cout <<
"total number of points before filtering: " << totalPoints << std::endl;
199 std::cout <<
"filter set to " << filter_opt[0] << std::endl;
202 int ncol=ceil(maxLRX-minULX)/dx_opt[0];
203 int nrow=ceil(maxULY-minLRY)/dy_opt[0];
205 int nband=(composite_opt[0]==
"profile")? nbin_opt[0] : 1;
206 if(!output_opt.size()){
207 cerr <<
"Error: no output file defined" << endl;
211 cout <<
"opening output file " << output_opt[0] << endl;
212 outputWriter.open(output_opt[0],ncol,nrow,nband,theType,oformat_opt[0],option_opt);
213 outputWriter.GDALSetNoDataValue(nodata_opt[0]);
222 outputWriter.setGeoTransform(gt);
223 if(projection_opt.size()){
224 string projectionString=outputWriter.setProjectionProj4(projection_opt[0]);
226 cout <<
"projection: " << projectionString << endl;
228 if(!outputWriter.isGeoRef())
229 cout <<
"Warning: output image " << output_opt[0] <<
" is not georeferenced!" << endl;
230 if(colorTable_opt.size())
231 outputWriter.setColorTable(colorTable_opt[0]);
234 inputData.resize(nrow,ncol);
236 for(
int irow=0;irow<nrow;++irow)
237 for(
int icol=0;icol<ncol;++icol)
238 outputData[irow][icol]=0;
240 cout <<
"Reading " << input_opt.size() <<
" point cloud files" << endl;
241 pfnProgress(progress,pszMessage,pProgressArg);
242 for(
int iinput=0;iinput<input_opt.size();++iinput){
245 lasReader.open(input_opt[iinput]);
247 catch(
string errorString){
248 cout << errorString << endl;
252 if(lasReader.isCompressed())
253 cout <<
"Reading compressed point cloud " << input_opt[iinput]<< endl;
255 cout <<
"Reading uncompressed point cloud " << input_opt[iinput] << endl;
260 if(returns_opt.size())
261 lasReader.addReturnsFilter(returns_opt);
262 if(classes_opt.size())
263 lasReader.addClassFilter(classes_opt);
264 lasReader.setFilters();
266 if(attribute_opt[0]!=
"z"){
267 vector<boost::uint16_t> returnsVector;
268 vector<string>::iterator ait=attribute_opt.begin();
269 while(ait!=attribute_opt.end()){
270 if(*ait==
"intensity"){
272 std::cout <<
"writing intensity" << std::endl;
275 else if(*ait==
"return"){
277 std::cout <<
"writing return number" << std::endl;
280 else if(*ait==
"nreturn"){
282 std::cout <<
"writing number of returns" << std::endl;
286 attribute_opt.erase(ait);
289 liblas::Point thePoint(&(lasReader.getHeader()));
290 while(lasReader.readNextPoint(thePoint)){
291 progress=
static_cast<float>(ipoint)/totalPoints;
292 pfnProgress(progress,pszMessage,pProgressArg);
294 cout <<
"reading point " << ipoint << endl;
295 if(thePoint.GetX()<minULX||thePoint.GetX()>=maxLRX||thePoint.GetY()>=maxULY||thePoint.GetY()<minLRY)
297 if((filter_opt[0]==
"single")&&(thePoint.GetNumberOfReturns()!=1))
299 if((filter_opt[0]==
"multiple")&&(thePoint.GetNumberOfReturns()<2))
301 if((filter_opt[0]==
"last")&&(thePoint.GetReturnNumber()!=thePoint.GetNumberOfReturns()))
303 if((filter_opt[0]==
"first")&&(thePoint.GetReturnNumber()!=1))
306 outputWriter.geo2image(thePoint.GetX(),thePoint.GetY(),dcol,drow);
307 int icol=
static_cast<int>(dcol);
308 int irow=
static_cast<int>(drow);
309 if(irow<0||irow>=nrow){
314 if(icol<0||icol>=ncol){
323 if(composite_opt[0]==
"number")
324 outputData[irow][icol]+=1;
325 else if(attribute_opt[0]==
"z")
326 inputData[irow][icol].push_back(thePoint.GetZ());
327 else if(attribute_opt[0]==
"intensity")
328 inputData[irow][icol].push_back(thePoint.GetIntensity());
329 else if(attribute_opt[0]==
"return")
330 inputData[irow][icol].push_back(thePoint.GetReturnNumber());
331 else if(attribute_opt[0]==
"nreturn")
332 inputData[irow][icol].push_back(thePoint.GetNumberOfReturns());
334 std::string errorString=
"attribute not supported";
340 std::cout <<
"number of points: " << ipoint << std::endl;
344 pfnProgress(progress,pszMessage,pProgressArg);
346 std::cout <<
"processing LiDAR points" << std::endl;
348 pfnProgress(progress,pszMessage,pProgressArg);
356 for(
int irow=0;irow<nrow;++irow){
357 if(composite_opt[0]==
"number")
360 for(
int icol=0;icol<ncol;++icol){
361 std::vector<double> profile;
362 if(!inputData[irow][icol].size())
363 outputData[irow][icol]=(
static_cast<double>((nodata_opt[0])));
366 if(composite_opt[0]==
"min")
367 outputData[irow][icol]=stat.mymin(inputData[irow][icol]);
368 else if(composite_opt[0]==
"max")
369 outputData[irow][icol]=stat.mymax(inputData[irow][icol]);
370 else if(composite_opt[0]==
"median")
371 outputData[irow][icol]=stat.median(inputData[irow][icol]);
372 else if(composite_opt[0]==
"percentile")
373 outputData[irow][icol]=stat.percentile(inputData[irow][icol],inputData[irow][icol].begin(),inputData[irow][icol].end(),percentile_opt[0]);
374 else if(composite_opt[0]==
"mean")
375 outputData[irow][icol]=stat.mean(inputData[irow][icol]);
376 else if(composite_opt[0]==
"sum")
377 outputData[irow][icol]=stat.sum(inputData[irow][icol]);
378 else if(composite_opt[0]==
"first")
379 outputData[irow][icol]=inputData[irow][icol][0];
380 else if(composite_opt[0]==
"last")
381 outputData[irow][icol]=inputData[irow][icol].back();
382 else if(composite_opt[0]==
"profile"){
383 if(inputData[irow][icol].size()<2){
384 for(
int iband=0;iband<nband;++iband)
385 outputProfile[iband][icol]=static_cast<double>(nodata_opt[0]);
390 stat.minmax(inputData[irow][icol],inputData[irow][icol].begin(),inputData[irow][icol].end(),min,max);
392 std::cout <<
"min,max: " << min <<
"," << max << std::endl;
394 stat.percentiles(inputData[irow][icol],inputData[irow][icol].begin(),inputData[irow][icol].end(),profile,nband,min,max);
395 assert(profile.size()==nband);
396 for(
int iband=0;iband<nband;++iband)
397 outputProfile[iband][icol]=profile[iband];
400 for(
int iband=0;iband<nband;++iband)
401 outputProfile[iband][icol]=max;
405 std::cout <<
"Error: composite_opt " << composite_opt[0] <<
" not supported" << std::endl;
410 if(composite_opt[0]==
"profile"){
411 for(
int iband=0;iband<nband;++iband){
413 assert(outputProfile[iband].size()==outputWriter.nrOfCol());
415 outputWriter.writeData(outputProfile[iband],GDT_Float64,irow,iband);
417 catch(std::string errorString){
418 cout << errorString << endl;
423 progress=
static_cast<float>(irow)/outputWriter.nrOfRow();
424 pfnProgress(progress,pszMessage,pProgressArg);
427 pfnProgress(progress,pszMessage,pProgressArg);
526 if(composite_opt[0]!=
"profile"){
528 std::cout <<
"writing output raster file" << std::endl;
530 pfnProgress(progress,pszMessage,pProgressArg);
531 for(
int irow=0;irow<nrow;++irow){
533 assert(outputData.size()==outputWriter.nrOfRow());
534 assert(outputData[0].size()==outputWriter.nrOfCol());
535 outputWriter.writeData(outputData[irow],GDT_Float64,irow,0);
537 catch(std::string errorString){
538 cout << errorString << endl;
541 progress=
static_cast<float>(irow)/outputWriter.nrOfRow();
542 pfnProgress(progress,pszMessage,pProgressArg);
546 pfnProgress(progress,pszMessage,pProgressArg);
548 std::cout <<
"closing lasReader" << std::endl;
549 outputWriter.close();