21 #include "imageclasses/ImgReaderGdal.h"
22 #include "imageclasses/ImgWriterGdal.h"
23 #include "imageclasses/ImgReaderOgr.h"
24 #include "imageclasses/ImgWriterOgr.h"
25 #include "base/Optionpk.h"
26 #include "algorithms/ConfusionMatrix.h"
30 int main(
int argc,
char *argv[])
33 Optionpk<string> reference_opt(
"ref",
"reference",
"Reference (raster or vector) dataset");
34 Optionpk<string> layer_opt(
"ln",
"ln",
"Layer name(s) in sample. Leave empty to select all (for vector reference datasets only)");
35 Optionpk<string> mask_opt(
"m",
"mask",
"Use the first band of the specified file as a validity mask. Nodata values can be set with the option msknodata.");
36 Optionpk<double> msknodata_opt(
"msknodata",
"msknodata",
"Mask value(s) where image is invalid. Use negative value for valid data (example: use -t -1: if only -1 is valid value)", 0);
37 Optionpk<double> nodata_opt(
"nodata",
"nodata",
"No data value(s) in input or reference dataset are ignored");
38 Optionpk<short> band_opt(
"b",
"band",
"Input (reference) raster band. Optionally, you can define different bands for input and reference bands respectively: -b 1 -b 0.", 0);
39 Optionpk<bool> rmse_opt(
"rmse",
"rmse",
"Report root mean squared error",
false);
40 Optionpk<bool> regression_opt(
"reg",
"reg",
"Report linear regression (Input = c0+c1*Reference)",
false);
41 Optionpk<bool> confusion_opt(
"cm",
"confusion",
"Create confusion matrix (to std out)",
false);
42 Optionpk<string> labelref_opt(
"lr",
"lref",
"Attribute name of the reference label (for vector reference datasets only)",
"label");
44 Optionpk<short> classvalue_opt(
"r",
"reclass",
"List of class values (use same order as in classname option).");
46 Optionpk<string> ogrformat_opt(
"f",
"f",
"OGR format for output vector (for vector reference datasets only)",
"SQLite");
47 Optionpk<string> labelclass_opt(
"lc",
"lclass",
"Attribute name of the classified label (for vector reference datasets only)",
"class");
48 Optionpk<short> boundary_opt(
"bnd",
"boundary",
"Boundary for selecting the sample (for vector reference datasets only)", 1,1);
49 Optionpk<bool> homogeneous_opt(
"hom",
"homogeneous",
"Only take regions with homogeneous boundary into account (for reference datasets only)",
false,1);
50 Optionpk<bool> disc_opt(
"circ",
"circular",
"Use circular boundary (for vector reference datasets only)",
false,1);
51 Optionpk<string> colorTable_opt(
"ct",
"ct",
"Color table in ASCII format having 5 columns: id R G B ALFA (0: transparent, 255: solid).");
52 Optionpk<string> option_opt(
"co",
"co",
"Creation option for output file. Multiple options can be specified.");
53 Optionpk<short> valueE_opt(
"\0",
"correct",
"Value for correct pixels", 0,2);
54 Optionpk<short> valueO_opt(
"\0",
"omission",
"Value for omission errors: input label > reference label", 1,2);
55 Optionpk<short> valueC_opt(
"\0",
"commission",
"Value for commission errors: input label < reference label", 2,1);
58 output_opt.setHide(1);
59 ogrformat_opt.setHide(1);
60 labelclass_opt.setHide(1);
61 boundary_opt.setHide(1);
62 homogeneous_opt.setHide(1);
64 colorTable_opt.setHide(1);
65 option_opt.setHide(1);
69 doProcess=input_opt.retrieveOption(argc,argv);
70 reference_opt.retrieveOption(argc,argv);
71 layer_opt.retrieveOption(argc,argv);
72 band_opt.retrieveOption(argc,argv);
73 rmse_opt.retrieveOption(argc,argv);
74 regression_opt.retrieveOption(argc,argv);
75 confusion_opt.retrieveOption(argc,argv);
76 labelref_opt.retrieveOption(argc,argv);
77 classname_opt.retrieveOption(argc,argv);
78 classvalue_opt.retrieveOption(argc,argv);
79 nodata_opt.retrieveOption(argc,argv);
80 mask_opt.retrieveOption(argc,argv);
81 msknodata_opt.retrieveOption(argc,argv);
82 output_opt.retrieveOption(argc,argv);
83 ogrformat_opt.retrieveOption(argc,argv);
84 labelclass_opt.retrieveOption(argc,argv);
85 boundary_opt.retrieveOption(argc,argv);
86 homogeneous_opt.retrieveOption(argc,argv);
87 disc_opt.retrieveOption(argc,argv);
88 colorTable_opt.retrieveOption(argc,argv);
89 option_opt.retrieveOption(argc,argv);
91 valueE_opt.retrieveOption(argc,argv);
92 valueO_opt.retrieveOption(argc,argv);
93 valueC_opt.retrieveOption(argc,argv);
94 verbose_opt.retrieveOption(argc,argv);
96 catch(
string predefinedString){
97 std::cout << predefinedString << std::endl;
102 cout <<
"Usage: pkdiff -i input -ref reference" << endl;
104 std::cout <<
"short option -h shows basic options only, use long option --help to show all options" << std::endl;
112 cout <<
"flag(s) set to";
113 for(
int iflag=0;iflag<nodata_opt.size();++iflag)
114 cout <<
" " << nodata_opt[iflag];
118 if(input_opt.empty()){
119 std::cerr <<
"No input file provided (use option -i). Use --help for help information" << std::endl;
122 if(reference_opt.empty()){
123 std::cerr <<
"No reference file provided (use option -ref). Use --help for help information" << std::endl;
129 if(band_opt.size()<2)
130 band_opt.push_back(band_opt[0]);
133 while(mask_opt.size()<input_opt.size())
134 mask_opt.push_back(mask_opt[0]);
135 vector<short> inputRange;
136 vector<short> referenceRange;
139 map<string,short> classValueMap;
140 vector<std::string> nameVector(255);
141 vector<string> classNames;
143 unsigned int ntotalValidation=0;
144 unsigned int nflagged=0;
147 vector<float> producer;
148 vector<unsigned int> nvalidation;
150 if(confusion_opt[0]){
158 cout <<
"opening input image file " << input_opt[0] << endl;
159 inputReader.open(input_opt[0]);
162 cerr << error << endl;
165 inputReader.getRange(inputRange,band_opt[0]);
169 for(
int iflag=0;iflag<nodata_opt.size();++iflag){
170 vector<short>::iterator fit;
171 fit=find(inputRange.begin(),inputRange.end(),
static_cast<short>(nodata_opt[iflag]));
172 if(fit!=inputRange.end())
173 inputRange.erase(fit);
175 nclass=inputRange.size();
177 cout <<
"nclass (inputRange.size()): " << nclass << endl;
178 cout <<
"input range: " << endl;
180 if(classname_opt.size()){
181 assert(classname_opt.size()==classvalue_opt.size());
182 for(
int iclass=0;iclass<classname_opt.size();++iclass){
183 classValueMap[classname_opt[iclass]]=classvalue_opt[iclass];
184 assert(classvalue_opt[iclass]<nameVector.size());
185 nameVector[classvalue_opt[iclass]]=classname_opt[iclass];
189 for(
int rc=0;rc<inputRange.size();++rc){
190 classNames.push_back(type2string(inputRange[rc]));
192 cout << inputRange[rc] << endl;
194 cm.setClassNames(classNames);
196 cout <<
"class names: " << endl;
197 for(
int iclass=0;iclass<cm.nClasses();++iclass)
198 cout << iclass <<
" " << cm.getClass(iclass) << endl;
200 resultClass.resize(nclass,nclass);
202 producer.resize(nclass);
203 nvalidation.resize(nclass);
205 for(
int rc=0;rc<nclass;++rc){
206 for(
int ic=0;ic<nclass;++ic)
207 resultClass[rc][ic]=0;
212 bool isDifferent=
false;
213 bool refIsRaster=
false;
217 referenceReaderOgr.open(reference_opt[0]);
218 referenceReaderOgr.close();
220 catch(
string errorString){
223 const char* pszMessage;
224 void* pProgressArg=NULL;
225 GDALProgressFunc pfnProgress=GDALTermProgress;
229 for(
int iinput=0;iinput<input_opt.size();++iinput){
231 cout <<
"Processing input " << input_opt[iinput] << endl;
232 if(output_opt.size())
233 assert(reference_opt.size()==output_opt.size());
234 for(
int iref=0;iref<reference_opt.size();++iref){
235 cout <<
"reference " << reference_opt[iref] << endl;
238 inputReader.open(input_opt[iinput]);
240 maskReader.open(mask_opt[iinput]);
241 assert(inputReader.nrOfCol()==maskReader.nrOfCol());
242 assert(inputReader.nrOfRow()==maskReader.nrOfRow());
244 referenceReaderOgr.open(reference_opt[iref]);
247 cerr << error << endl;
251 referenceRange=inputRange;
254 if(output_opt.size()){
256 ogrWriter.open(output_opt[iref],ogrformat_opt[0]);
259 cerr << error << endl;
263 int nlayer=referenceReaderOgr.getDataSource()->GetLayerCount();
264 for(
int ilayer=0;ilayer<nlayer;++ilayer){
266 OGRLayer *readLayer=referenceReaderOgr.getLayer(ilayer);
268 string currentLayername=readLayer->GetName();
270 if(find(layer_opt.begin(),layer_opt.end(),currentLayername)==layer_opt.end())
273 pfnProgress(progress,pszMessage,pProgressArg);
275 cout <<
"processing layer " << readLayer->GetName() << endl;
277 readLayer->ResetReading();
278 OGRLayer *writeLayer;
279 if(output_opt.size()){
281 cout <<
"creating output vector file " << output_opt[0] << endl;
283 char **papszOptions=NULL;
285 cout <<
"creating layer: " << readLayer->GetName() << endl;
287 writeLayer=ogrWriter.createLayer(readLayer->GetName(), referenceReaderOgr.getProjection(ilayer), wkbPoint, papszOptions);
290 cout <<
"created layer" << endl;
291 cout <<
"copy fields from " << reference_opt[iref] << endl;
293 ogrWriter.copyFields(referenceReaderOgr,ilayer,ilayer);
295 short theDim=boundary_opt[0];
296 for(
int windowJ=-theDim/2;windowJ<(theDim+1)/2;++windowJ){
297 for(
int windowI=-theDim/2;windowI<(theDim+1)/2;++windowI){
298 if(disc_opt[0]&&(windowI*windowI+windowJ*windowJ>(theDim/2)*(theDim/2)))
302 fs << labelclass_opt[0] <<
"_" << windowJ <<
"_" << windowI;
304 fs << labelclass_opt[0];
306 cout <<
"creating field " << fs.str() << endl;
307 ogrWriter.createField(fs.str(),OFTInteger,ilayer);
311 OGRFeature *readFeature;
312 OGRFeature *writeFeature;
314 unsigned int nfeatureInLayer=readLayer->GetFeatureCount();
315 unsigned int ifeature=0;
316 while( (readFeature = readLayer->GetNextFeature()) != NULL ){
318 cout <<
"sample " << ++isample << endl;
321 OGRGeometry *poGeometry;
322 OGRPoint centroidPoint;
324 poGeometry = readFeature->GetGeometryRef();
328 else if(wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon){
329 OGRMultiPolygon readPolygon = *((OGRMultiPolygon *) poGeometry);
330 readPolygon = *((OGRMultiPolygon *) poGeometry);
331 readPolygon.Centroid(¢roidPoint);
332 poPoint=¢roidPoint;
334 else if(wkbFlatten(poGeometry->getGeometryType()) == wkbPolygon){
335 OGRPolygon readPolygon=*((OGRPolygon *) poGeometry);
336 readPolygon.Centroid(¢roidPoint);
337 poPoint=¢roidPoint;
339 else if(wkbFlatten(poGeometry->getGeometryType()) == wkbPoint )
340 poPoint = (OGRPoint *) poGeometry;
342 std::cerr <<
"Warning: skipping feature (not of type point or polygon)" << std::endl;
348 vector<double> inputValues;
349 bool isHomogeneous=
true;
353 unsigned short referenceValue;
354 string referenceClassName;
355 if(classValueMap.size()){
356 referenceClassName=readFeature->GetFieldAsString(readFeature->GetFieldIndex(labelref_opt[0].c_str()));
357 referenceValue=classValueMap[referenceClassName];
360 referenceValue=readFeature->GetFieldAsInteger(readFeature->GetFieldIndex(labelref_opt[0].c_str()));
362 cout <<
"reference value: " << referenceValue << endl;
364 bool pixelFlagged=
false;
365 bool maskFlagged=
false;
366 for(
int iflag=0;iflag<nodata_opt.size();++iflag){
367 if(referenceValue==nodata_opt[iflag])
372 double i_centre,j_centre;
374 inputReader.geo2image(x,y,i_centre,j_centre);
380 j_centre=
static_cast<int>(j_centre);
381 i_centre=
static_cast<int>(i_centre);
383 if(static_cast<int>(j_centre)<0||
static_cast<int>(j_centre)>=inputReader.nrOfRow())
386 if(static_cast<int>(i_centre)<0||
static_cast<int>(i_centre)>=inputReader.nrOfCol())
389 if(output_opt.size()){
390 writeFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
392 int nfield=readFeature->GetFieldCount();
393 writeFeature->SetGeometry(poPoint);
395 cout <<
"copying fields from " << reference_opt[0] << endl;
397 assert(writeFeature);
398 vector<int> panMap(nfield);
399 vector<int>::iterator panit=panMap.begin();
400 for(
int ifield=0;ifield<nfield;++ifield)
401 panMap[ifield]=ifield;
402 writeFeature->SetFieldsFrom(readFeature,&(panMap[0]));
408 bool windowAllFlagged=
true;
409 bool windowHasFlag=
false;
410 short theDim=boundary_opt[0];
411 for(
int windowJ=-theDim/2;windowJ<(theDim+1)/2;++windowJ){
412 for(
int windowI=-theDim/2;windowI<(theDim+1)/2;++windowI){
413 if(disc_opt[0]&&(windowI*windowI+windowJ*windowJ>(theDim/2)*(theDim/2)))
415 int j=j_centre+windowJ;
417 if(static_cast<int>(j)<0||
static_cast<int>(j)>=inputReader.nrOfRow())
419 int i=i_centre+windowI;
421 if(static_cast<int>(i)<0||
static_cast<int>(i)>=inputReader.nrOfCol())
424 cout << setprecision(12) <<
"reading image value at x,y " << x <<
"," << y <<
" (" << i <<
"," << j <<
"), ";
425 inputReader.readData(inputValue,GDT_Float64,i,j,band_opt[0]);
426 inputValues.push_back(inputValue);
427 if(inputValues.back()!=*(inputValues.begin()))
430 cout <<
"input value: " << inputValue << endl;
432 for(
int iflag=0;iflag<nodata_opt.size();++iflag){
433 if(inputValue==nodata_opt[iflag]){
440 maskReader.readData(maskValue,GDT_Float64,i,j,0);
441 for(
int ivalue=0;ivalue<msknodata_opt.size();++ivalue){
442 if(msknodata_opt[ivalue]>=0){
443 if(maskValue==msknodata_opt[ivalue]){
449 if(maskValue!=-msknodata_opt[ivalue])
458 pixelFlagged=pixelFlagged||maskFlagged;
462 windowAllFlagged=
false;
467 if(homogeneous_opt[0]){
472 if(!windowHasFlag&&isHomogeneous){
473 if(output_opt.size())
474 writeFeature->SetField(labelclass_opt[0].c_str(),
static_cast<int>(inputValue));
475 if(confusion_opt[0]){
477 if(classValueMap.size()){
478 assert(inputValue<nameVector.size());
479 string className=nameVector[
static_cast<unsigned short>(inputValue)];
480 cm.incrementResult(type2string<short>(classValueMap[referenceClassName]),type2string<short>(classValueMap[className]),1);
483 int rc=distance(referenceRange.begin(),find(referenceRange.begin(),referenceRange.end(),
static_cast<unsigned short>(referenceValue)));
484 int ic=distance(inputRange.begin(),find(inputRange.begin(),inputRange.end(),
static_cast<unsigned short>(inputValue)));
488 ++resultClass[rc][ic];
490 cout <<
"increment: " << rc <<
" " << referenceRange[rc] <<
" " << ic <<
" " << inputRange[ic] << endl;
491 cm.incrementResult(cm.getClass(rc),cm.getClass(ic),1);
494 if(inputValue==referenceValue){
495 outputValue=valueE_opt[0];
496 if(nodata_opt.size()){
497 if(valueE_opt[0]==nodata_opt[0])
498 outputValue=inputValue;
501 else if(inputValue>referenceValue)
502 outputValue=valueO_opt[0];
504 outputValue=valueC_opt[0];
508 for(
int windowJ=-theDim/2;windowJ<(theDim+1)/2;++windowJ){
509 for(
int windowI=-theDim/2;windowI<(theDim+1)/2;++windowI){
510 if(disc_opt[0]&&(windowI*windowI+windowJ*windowJ>(theDim/2)*(theDim/2)))
512 int j=j_centre+windowJ;
514 if(static_cast<int>(j)<0||
static_cast<int>(j)>=inputReader.nrOfRow())
516 int i=i_centre+windowI;
518 if(static_cast<int>(i)<0||
static_cast<int>(i)>=inputReader.nrOfCol())
520 if(!windowAllFlagged){
523 fs << labelclass_opt[0] <<
"_" << windowJ <<
"_" << windowI;
525 fs << labelclass_opt[0];
526 if(output_opt.size())
527 writeFeature->SetField(fs.str().c_str(),inputValue);
528 if(!windowJ&&!windowI){
529 if(confusion_opt[0]){
531 if(classValueMap.size()){
532 assert(inputValue<nameVector.size());
533 string className=nameVector[
static_cast<unsigned short>(inputValue)];
534 cm.incrementResult(type2string<short>(classValueMap[referenceClassName]),type2string<short>(classValueMap[className]),1);
537 int rc=distance(referenceRange.begin(),find(referenceRange.begin(),referenceRange.end(),
static_cast<unsigned short>(referenceValue)));
538 int ic=distance(inputRange.begin(),find(inputRange.begin(),inputRange.end(),
static_cast<unsigned short>(inputValue)));
546 ++resultClass[rc][ic];
548 cout <<
"increment: " << rc <<
" " << referenceRange[rc] <<
" " << ic <<
" " << inputRange[ic] << endl;
549 cm.incrementResult(cm.getClass(rc),cm.getClass(ic),1);
552 if(inputValue==referenceValue){
553 outputValue=valueE_opt[0];
554 if(nodata_opt.size()){
555 if(valueE_opt[0]==nodata_opt[0])
556 outputValue=inputValue;
559 else if(inputValue>referenceValue)
560 outputValue=valueO_opt[0];
562 outputValue=valueC_opt[0];
568 if(output_opt.size()){
569 if(!windowAllFlagged){
571 cout <<
"creating feature" << endl;
572 if(writeLayer->CreateFeature( writeFeature ) != OGRERR_NONE ){
573 string errorString=
"Failed to create feature in OGR vector file";
577 OGRFeature::DestroyFeature( writeFeature );
580 progress=
static_cast<float>(ifeature+1)/nfeatureInLayer;
581 pfnProgress(progress,pszMessage,pProgressArg);
584 if(output_opt.size())
586 referenceReaderOgr.close();
592 pfnProgress(1.0,pszMessage,pProgressArg);
597 inputReader.open(input_opt[0]);
599 maskReader.open(mask_opt[0]);
600 if(output_opt.size()){
602 cout <<
"opening output image " << output_opt[0] << endl;
603 if(option_opt.findSubstring(
"INTERLEAVE=")==option_opt.end()){
604 string theInterleave=
"INTERLEAVE=";
605 theInterleave+=inputReader.getInterleave();
606 option_opt.push_back(theInterleave);
608 gdalWriter.open(output_opt[0],inputReader.nrOfCol(),inputReader.nrOfRow(),1,inputReader.getDataType(),inputReader.getImageType(),option_opt);
609 if(nodata_opt.size())
610 gdalWriter.GDALSetNoDataValue(nodata_opt[0]);
611 gdalWriter.copyGeoTransform(inputReader);
612 if(colorTable_opt.size())
613 gdalWriter.setColorTable(colorTable_opt[0]);
614 else if(inputReader.getColorTable()!=NULL){
616 cout <<
"set colortable from input image" << endl;
617 gdalWriter.setColorTable(inputReader.getColorTable());
620 else if(verbose_opt[0])
621 cout <<
"no output image defined" << endl;
625 cout << error << endl;
629 vector<double> lineInput(inputReader.nrOfCol());
630 vector<double> lineMask(maskReader.nrOfCol());
631 vector<double> lineOutput;
632 vector<double> bufferInput;
633 vector<double> bufferReference;
634 if(output_opt.size())
635 lineOutput.resize(inputReader.nrOfCol());
639 double oldreferencerow=-1;
640 double oldmaskrow=-1;
643 referenceReaderGdal.open(reference_opt[0]);
646 cerr << error << endl;
649 if(inputReader.isGeoRef()){
650 assert(referenceReaderGdal.isGeoRef());
651 if(inputReader.getProjection()!=referenceReaderGdal.getProjection())
652 cerr <<
"Warning: projection of input image and reference image are different" << endl;
654 vector<double> lineReference(referenceReaderGdal.nrOfCol());
655 if(confusion_opt[0]){
656 referenceReaderGdal.getRange(referenceRange,band_opt[1]);
657 for(
int iflag=0;iflag<nodata_opt.size();++iflag){
658 vector<short>::iterator fit;
659 fit=find(referenceRange.begin(),referenceRange.end(),
static_cast<unsigned short>(nodata_opt[iflag]));
660 if(fit!=referenceRange.end())
661 referenceRange.erase(fit);
664 cout <<
"reference range: " << endl;
665 for(
int rc=0;rc<referenceRange.size();++rc)
666 cout << referenceRange[rc] << endl;
668 if(referenceRange.size()!=inputRange.size()){
669 if(confusion_opt[0]||output_opt.size()){
670 cout <<
"reference range is not equal to input range!" << endl;
671 cout <<
"Kappa: " << 0 << endl;
672 cout <<
"total weighted: " << 0 << endl;
675 cout <<
"reference range is not equal to input range!" << endl;
676 cout << input_opt[0] <<
" and " << reference_opt[0] <<
" are different" << endl;
682 for(irow=0;irow<inputReader.nrOfRow();++irow){
684 inputReader.readData(lineInput,GDT_Float64,irow,band_opt[0]);
686 double ireference,jreference;
688 for(icol=0;icol<inputReader.nrOfCol();++icol){
690 inputReader.image2geo(icol,irow,x,y);
691 referenceReaderGdal.geo2image(x,y,ireference,jreference);
692 if(ireference<0||ireference>=referenceReaderGdal.nrOfCol()){
693 if(rmse_opt[0]||regression_opt[0])
696 cerr << ireference <<
" out of reference range!" << endl;
697 cerr << x <<
" " << y <<
" " << icol <<
" " << irow << endl;
698 cerr << x <<
" " << y <<
" " << ireference <<
" " << jreference << endl;
702 if(jreference!=oldreferencerow){
703 if(jreference<0||jreference>=referenceReaderGdal.nrOfRow()){
704 if(rmse_opt[0]||regression_opt[0])
707 cerr << jreference <<
" out of reference range!" << endl;
708 cerr << x <<
" " << y <<
" " << icol <<
" " << irow << endl;
709 cerr << x <<
" " << y <<
" " << ireference <<
" " << jreference << endl;
714 referenceReaderGdal.readData(lineReference,GDT_Float64,static_cast<int>(jreference),band_opt[1]);
715 oldreferencerow=jreference;
719 for(
int iflag=0;iflag<nodata_opt.size();++iflag){
720 if((lineInput[icol]==nodata_opt[iflag])||(lineReference[ireference]==nodata_opt[iflag])){
721 if(output_opt.size())
722 lineOutput[icol]=nodata_opt[iflag];
728 maskReader.geo2image(x,y,imask,jmask);
729 if(jmask>=0&&jmask<maskReader.nrOfRow()){
730 if(jmask!=oldmaskrow)
731 maskReader.readData(lineMask,GDT_Float64,jmask);
732 for(
int ivalue=0;ivalue<msknodata_opt.size();++ivalue){
733 if(lineMask[icol]==msknodata_opt[ivalue]){
742 rmse+=
static_cast<double>(lineInput[icol]-lineReference[ireference])*(lineInput[icol]-lineReference[ireference])/inputReader.nrOfCol()/inputReader.nrOfRow();
744 else if(regression_opt[0]){
745 bufferInput.push_back(lineInput[icol]);
746 bufferReference.push_back(lineReference[ireference]);
749 if(confusion_opt[0]){
751 int rc=distance(referenceRange.begin(),find(referenceRange.begin(),referenceRange.end(),lineReference[ireference]));
752 int ic=distance(inputRange.begin(),find(inputRange.begin(),inputRange.end(),lineInput[icol]));
756 ++resultClass[rc][ic];
758 cout <<
"increment: " << rc <<
" " << referenceRange[rc] <<
" " << ic <<
" " << inputRange[ic] << endl;
759 cm.incrementResult(cm.getClass(rc),cm.getClass(ic),1);
761 if(lineInput[icol]==lineReference[ireference]){
762 if(output_opt.size()){
763 lineOutput[icol]=valueE_opt[0];
764 if(nodata_opt.size()){
765 if(valueE_opt[0]==nodata_opt[0])
766 lineOutput[icol]=lineInput[icol];
771 if(output_opt.empty()&&!confusion_opt[0]&&!rmse_opt[0]&&!regression_opt[0]){
775 if(output_opt.size()){
776 if(lineInput[icol]>lineReference[ireference])
777 lineOutput[icol]=valueO_opt[0];
779 lineOutput[icol]=valueC_opt[0];
785 if(output_opt.size()){
786 if(nodata_opt.size())
787 lineOutput[icol]=nodata_opt[0];
793 if(output_opt.size()){
795 gdalWriter.writeData(lineOutput,GDT_Float64,irow);
797 catch(
string errorstring){
798 cerr <<
"lineOutput.size(): " << lineOutput.size() << endl;
799 cerr <<
"gdalWriter.nrOfCol(): " << gdalWriter.nrOfCol() << endl;
800 cerr << errorstring << endl;
804 else if(isDifferent&&!confusion_opt[0]&&!rmse_opt[0]&&!regression_opt[0]){
806 pfnProgress(1.0,pszMessage,pProgressArg);
809 progress=
static_cast<float>(irow+1.0)/inputReader.nrOfRow();
811 pfnProgress(progress,pszMessage,pProgressArg);
813 if(output_opt.size())
815 else if(!confusion_opt[0]){
817 double normalization=1.0*inputReader.nrOfCol()*inputReader.nrOfRow()/(inputReader.nrOfCol()*inputReader.nrOfRow()-nflagged);
819 cout <<
"normalization: " << normalization << endl;
820 cout <<
"rmse before sqrt and normalization: " << rmse << endl;
822 cout <<
"--rmse " << sqrt(rmse/normalization) << endl;
824 else if(regression_opt[0]){
829 if(bufferInput.size()&&bufferReference.size()){
830 err=stat.linear_regression_err(bufferInput,bufferReference,c0,c1);
833 cout <<
"bufferInput.size(): " << bufferInput.size() << endl;
834 cout <<
"bufferReference.size(): " << bufferReference.size() << endl;
837 stat.minmax(bufferInput,bufferInput.begin(),bufferInput.end(),theMin,theMax);
838 cout <<
"min, max input: " << theMin <<
", " << theMax << endl;
841 stat.minmax(bufferReference,bufferReference.begin(),bufferReference.end(),theMin,theMax);
842 cout <<
"min, max reference: " << theMin <<
", " << theMax << endl;
844 cout <<
"--c0 " << c0 <<
"--c1 " << c1 <<
" --rmse: " << err << endl;
848 cout << input_opt[0] <<
" and " << reference_opt[0] <<
" are different" << endl;
850 cout << input_opt[0] <<
" and " << reference_opt[0] <<
" are identical" << endl;
852 referenceReaderGdal.close();
858 if(confusion_opt[0]){
862 cout <<
"class #samples userAcc prodAcc" << endl;
869 for(
int iclass=0;iclass<cm.nClasses();++iclass){
870 dua=cm.ua_pct(classNames[iclass],&se95_ua);
871 dpa=cm.pa_pct(classNames[iclass],&se95_pa);
872 cout << cm.getClass(iclass) <<
" " << cm.nReference(cm.getClass(iclass)) <<
" " << dua <<
" (" << se95_ua <<
")" <<
" " << dpa <<
" (" << se95_pa <<
")" << endl;
875 cout <<
"Kappa: " << cm.kappa() << endl;
876 cout <<
"Overall Accuracy: " << 100*doa <<
" (" << 100*se95_oa <<
")" << endl;