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"
94 int main(
int argc,
char *argv[])
97 Optionpk<string> reference_opt(
"ref",
"reference",
"Reference (raster or vector) dataset");
98 Optionpk<string> layer_opt(
"ln",
"ln",
"Layer name(s) in sample. Leave empty to select all (for vector reference datasets only)");
99 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.");
100 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);
101 Optionpk<double> nodata_opt(
"nodata",
"nodata",
"No data value(s) in input or reference dataset are ignored");
102 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);
103 Optionpk<bool> rmse_opt(
"rmse",
"rmse",
"Report root mean squared error",
false);
104 Optionpk<bool> regression_opt(
"reg",
"reg",
"Report linear regression (Input = c0+c1*Reference)",
false);
105 Optionpk<bool> confusion_opt(
"cm",
"confusion",
"Create confusion matrix (to std out)",
false);
106 Optionpk<string> cmformat_opt(
"cmf",
"cmf",
"Format for confusion matrix (ascii or latex)",
"ascii");
107 Optionpk<string> cmoutput_opt(
"cmo",
"cmo",
"Output file for confusion matrix");
108 Optionpk<bool> se95_opt(
"se95",
"se95",
"Report standard error for 95 confidence interval",
false);
109 Optionpk<string> labelref_opt(
"lr",
"lref",
"Attribute name of the reference label (for vector reference datasets only)",
"label");
111 Optionpk<short> classvalue_opt(
"r",
"reclass",
"List of class values (use same order as in classname option).");
113 Optionpk<string> ogrformat_opt(
"f",
"f",
"OGR format for output vector (for vector reference datasets only)",
"SQLite");
114 Optionpk<string> labelclass_opt(
"lc",
"lclass",
"Attribute name of the classified label (for vector reference datasets only)",
"class");
115 Optionpk<short> boundary_opt(
"bnd",
"boundary",
"Boundary for selecting the sample (for vector reference datasets only)", 1,1);
116 Optionpk<bool> homogeneous_opt(
"hom",
"homogeneous",
"Only take regions with homogeneous boundary into account (for reference datasets only)",
false,1);
117 Optionpk<bool> disc_opt(
"circ",
"circular",
"Use circular boundary (for vector reference datasets only)",
false,1);
118 Optionpk<string> colorTable_opt(
"ct",
"ct",
"Color table in ASCII format having 5 columns: id R G B ALFA (0: transparent, 255: solid).");
119 Optionpk<string> option_opt(
"co",
"co",
"Creation option for output file. Multiple options can be specified.");
120 Optionpk<short> valueE_opt(
"\0",
"correct",
"Value for correct pixels", 0,2);
121 Optionpk<short> valueO_opt(
"\0",
"omission",
"Value for omission errors: input label > reference label", 1,2);
122 Optionpk<short> valueC_opt(
"\0",
"commission",
"Value for commission errors: input label < reference label", 2,1);
125 output_opt.setHide(1);
126 ogrformat_opt.setHide(1);
127 labelclass_opt.setHide(1);
128 boundary_opt.setHide(1);
129 homogeneous_opt.setHide(1);
131 colorTable_opt.setHide(1);
132 option_opt.setHide(1);
136 doProcess=input_opt.retrieveOption(argc,argv);
137 reference_opt.retrieveOption(argc,argv);
138 layer_opt.retrieveOption(argc,argv);
139 band_opt.retrieveOption(argc,argv);
140 rmse_opt.retrieveOption(argc,argv);
141 regression_opt.retrieveOption(argc,argv);
142 confusion_opt.retrieveOption(argc,argv);
143 labelref_opt.retrieveOption(argc,argv);
144 classname_opt.retrieveOption(argc,argv);
145 classvalue_opt.retrieveOption(argc,argv);
146 nodata_opt.retrieveOption(argc,argv);
147 mask_opt.retrieveOption(argc,argv);
148 msknodata_opt.retrieveOption(argc,argv);
149 output_opt.retrieveOption(argc,argv);
150 ogrformat_opt.retrieveOption(argc,argv);
151 labelclass_opt.retrieveOption(argc,argv);
152 cmformat_opt.retrieveOption(argc,argv);
153 cmoutput_opt.retrieveOption(argc,argv);
154 se95_opt.retrieveOption(argc,argv);
155 boundary_opt.retrieveOption(argc,argv);
156 homogeneous_opt.retrieveOption(argc,argv);
157 disc_opt.retrieveOption(argc,argv);
158 colorTable_opt.retrieveOption(argc,argv);
159 option_opt.retrieveOption(argc,argv);
161 valueE_opt.retrieveOption(argc,argv);
162 valueO_opt.retrieveOption(argc,argv);
163 valueC_opt.retrieveOption(argc,argv);
164 verbose_opt.retrieveOption(argc,argv);
166 catch(
string predefinedString){
167 std::cout << predefinedString << std::endl;
172 cout <<
"Usage: pkdiff -i input -ref reference" << endl;
174 std::cout <<
"short option -h shows basic options only, use long option --help to show all options" << std::endl;
182 cout <<
"flag(s) set to";
183 for(
int iflag=0;iflag<nodata_opt.size();++iflag)
184 cout <<
" " << nodata_opt[iflag];
188 if(input_opt.empty()){
189 std::cerr <<
"No input file provided (use option -i). Use --help for help information" << std::endl;
192 if(reference_opt.empty()){
193 std::cerr <<
"No reference file provided (use option -ref). Use --help for help information" << std::endl;
199 if(band_opt.size()<2)
200 band_opt.push_back(band_opt[0]);
203 while(mask_opt.size()<input_opt.size())
204 mask_opt.push_back(mask_opt[0]);
205 vector<short> inputRange;
206 vector<short> referenceRange;
209 map<string,short> classValueMap;
210 vector<std::string> nameVector(255);
211 vector<string> classNames;
213 unsigned int ntotalValidation=0;
214 unsigned int nflagged=0;
217 vector<float> producer;
218 vector<unsigned int> nvalidation;
220 if(confusion_opt[0]){
228 cout <<
"opening input image file " << input_opt[0] << endl;
229 inputReader.open(input_opt[0]);
232 cerr << error << endl;
235 inputReader.getRange(inputRange,band_opt[0]);
239 for(
int iflag=0;iflag<nodata_opt.size();++iflag){
240 vector<short>::iterator fit;
241 fit=find(inputRange.begin(),inputRange.end(),
static_cast<short>(nodata_opt[iflag]));
242 if(fit!=inputRange.end())
243 inputRange.erase(fit);
245 nclass=inputRange.size();
247 cout <<
"nclass (inputRange.size()): " << nclass << endl;
248 cout <<
"input range: " << endl;
250 if(classname_opt.size()){
251 assert(classname_opt.size()==classvalue_opt.size());
252 for(
int iclass=0;iclass<classname_opt.size();++iclass){
253 classValueMap[classname_opt[iclass]]=classvalue_opt[iclass];
254 assert(classvalue_opt[iclass]<nameVector.size());
255 nameVector[classvalue_opt[iclass]]=classname_opt[iclass];
259 for(
int rc=0;rc<inputRange.size();++rc){
260 classNames.push_back(type2string(inputRange[rc]));
262 cout << inputRange[rc] << endl;
264 cm.setClassNames(classNames);
266 cout <<
"class names: " << endl;
267 for(
int iclass=0;iclass<cm.nClasses();++iclass)
268 cout << iclass <<
" " << cm.getClass(iclass) << endl;
270 resultClass.resize(nclass,nclass);
272 producer.resize(nclass);
273 nvalidation.resize(nclass);
275 for(
int rc=0;rc<nclass;++rc){
276 for(
int ic=0;ic<nclass;++ic)
277 resultClass[rc][ic]=0;
282 bool isDifferent=
false;
283 bool refIsRaster=
false;
287 referenceReaderOgr.open(reference_opt[0]);
288 referenceReaderOgr.close();
290 catch(
string errorString){
293 const char* pszMessage;
294 void* pProgressArg=NULL;
295 GDALProgressFunc pfnProgress=GDALTermProgress;
299 for(
int iinput=0;iinput<input_opt.size();++iinput){
301 cout <<
"Processing input " << input_opt[iinput] << endl;
302 if(output_opt.size())
303 assert(reference_opt.size()==output_opt.size());
304 for(
int iref=0;iref<reference_opt.size();++iref){
305 cout <<
"reference " << reference_opt[iref] << endl;
308 inputReader.open(input_opt[iinput]);
310 maskReader.open(mask_opt[iinput]);
311 assert(inputReader.nrOfCol()==maskReader.nrOfCol());
312 assert(inputReader.nrOfRow()==maskReader.nrOfRow());
314 referenceReaderOgr.open(reference_opt[iref]);
317 cerr << error << endl;
321 referenceRange=inputRange;
324 if(output_opt.size()){
326 ogrWriter.open(output_opt[iref],ogrformat_opt[0]);
329 cerr << error << endl;
333 int nlayer=referenceReaderOgr.getDataSource()->GetLayerCount();
334 for(
int ilayer=0;ilayer<nlayer;++ilayer){
336 OGRLayer *readLayer=referenceReaderOgr.getLayer(ilayer);
338 string currentLayername=readLayer->GetName();
340 if(find(layer_opt.begin(),layer_opt.end(),currentLayername)==layer_opt.end())
343 pfnProgress(progress,pszMessage,pProgressArg);
345 cout <<
"processing layer " << readLayer->GetName() << endl;
347 readLayer->ResetReading();
348 OGRLayer *writeLayer;
349 if(output_opt.size()){
351 cout <<
"creating output vector file " << output_opt[0] << endl;
353 char **papszOptions=NULL;
355 cout <<
"creating layer: " << readLayer->GetName() << endl;
357 writeLayer=ogrWriter.createLayer(readLayer->GetName(), referenceReaderOgr.getProjection(ilayer), wkbPoint, papszOptions);
360 cout <<
"created layer" << endl;
361 cout <<
"copy fields from " << reference_opt[iref] << endl;
363 ogrWriter.copyFields(referenceReaderOgr,ilayer,ilayer);
365 short theDim=boundary_opt[0];
366 for(
int windowJ=-theDim/2;windowJ<(theDim+1)/2;++windowJ){
367 for(
int windowI=-theDim/2;windowI<(theDim+1)/2;++windowI){
368 if(disc_opt[0]&&(windowI*windowI+windowJ*windowJ>(theDim/2)*(theDim/2)))
372 fs << labelclass_opt[0] <<
"_" << windowJ <<
"_" << windowI;
374 fs << labelclass_opt[0];
376 cout <<
"creating field " << fs.str() << endl;
377 ogrWriter.createField(fs.str(),OFTInteger,ilayer);
381 OGRFeature *readFeature;
382 OGRFeature *writeFeature;
384 unsigned int nfeatureInLayer=readLayer->GetFeatureCount();
385 unsigned int ifeature=0;
386 while( (readFeature = readLayer->GetNextFeature()) != NULL ){
388 cout <<
"sample " << ++isample << endl;
391 OGRGeometry *poGeometry;
392 OGRPoint centroidPoint;
394 poGeometry = readFeature->GetGeometryRef();
398 else if(wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon){
399 OGRMultiPolygon readPolygon = *((OGRMultiPolygon *) poGeometry);
400 readPolygon = *((OGRMultiPolygon *) poGeometry);
401 readPolygon.Centroid(¢roidPoint);
402 poPoint=¢roidPoint;
404 else if(wkbFlatten(poGeometry->getGeometryType()) == wkbPolygon){
405 OGRPolygon readPolygon=*((OGRPolygon *) poGeometry);
406 readPolygon.Centroid(¢roidPoint);
407 poPoint=¢roidPoint;
409 else if(wkbFlatten(poGeometry->getGeometryType()) == wkbPoint )
410 poPoint = (OGRPoint *) poGeometry;
412 std::cerr <<
"Warning: skipping feature (not of type point or polygon)" << std::endl;
418 vector<double> inputValues;
419 bool isHomogeneous=
true;
423 unsigned short referenceValue;
424 string referenceClassName;
425 if(classValueMap.size()){
426 referenceClassName=readFeature->GetFieldAsString(readFeature->GetFieldIndex(labelref_opt[0].c_str()));
427 referenceValue=classValueMap[referenceClassName];
430 referenceValue=readFeature->GetFieldAsInteger(readFeature->GetFieldIndex(labelref_opt[0].c_str()));
432 cout <<
"reference value: " << referenceValue << endl;
434 bool pixelFlagged=
false;
435 bool maskFlagged=
false;
436 for(
int iflag=0;iflag<nodata_opt.size();++iflag){
437 if(referenceValue==nodata_opt[iflag])
442 double i_centre,j_centre;
444 inputReader.geo2image(x,y,i_centre,j_centre);
450 j_centre=
static_cast<int>(j_centre);
451 i_centre=
static_cast<int>(i_centre);
453 if(static_cast<int>(j_centre)<0||
static_cast<int>(j_centre)>=inputReader.nrOfRow())
456 if(static_cast<int>(i_centre)<0||
static_cast<int>(i_centre)>=inputReader.nrOfCol())
459 if(output_opt.size()){
460 writeFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
462 int nfield=readFeature->GetFieldCount();
463 writeFeature->SetGeometry(poPoint);
465 cout <<
"copying fields from " << reference_opt[0] << endl;
467 assert(writeFeature);
468 vector<int> panMap(nfield);
469 vector<int>::iterator panit=panMap.begin();
470 for(
int ifield=0;ifield<nfield;++ifield)
471 panMap[ifield]=ifield;
472 writeFeature->SetFieldsFrom(readFeature,&(panMap[0]));
478 bool windowAllFlagged=
true;
479 bool windowHasFlag=
false;
480 short theDim=boundary_opt[0];
481 for(
int windowJ=-theDim/2;windowJ<(theDim+1)/2;++windowJ){
482 for(
int windowI=-theDim/2;windowI<(theDim+1)/2;++windowI){
483 if(disc_opt[0]&&(windowI*windowI+windowJ*windowJ>(theDim/2)*(theDim/2)))
485 int j=j_centre+windowJ;
487 if(static_cast<int>(j)<0||
static_cast<int>(j)>=inputReader.nrOfRow())
489 int i=i_centre+windowI;
491 if(static_cast<int>(i)<0||
static_cast<int>(i)>=inputReader.nrOfCol())
494 cout << setprecision(12) <<
"reading image value at x,y " << x <<
"," << y <<
" (" << i <<
"," << j <<
"), ";
495 inputReader.readData(inputValue,GDT_Float64,i,j,band_opt[0]);
496 inputValues.push_back(inputValue);
497 if(inputValues.back()!=*(inputValues.begin()))
500 cout <<
"input value: " << inputValue << endl;
502 for(
int iflag=0;iflag<nodata_opt.size();++iflag){
503 if(inputValue==nodata_opt[iflag]){
510 maskReader.readData(maskValue,GDT_Float64,i,j,0);
511 for(
int ivalue=0;ivalue<msknodata_opt.size();++ivalue){
512 if(msknodata_opt[ivalue]>=0){
513 if(maskValue==msknodata_opt[ivalue]){
519 if(maskValue!=-msknodata_opt[ivalue])
528 pixelFlagged=pixelFlagged||maskFlagged;
532 windowAllFlagged=
false;
537 if(homogeneous_opt[0]){
542 if(!windowHasFlag&&isHomogeneous){
543 if(output_opt.size())
544 writeFeature->SetField(labelclass_opt[0].c_str(),
static_cast<int>(inputValue));
545 if(confusion_opt[0]){
547 if(classValueMap.size()){
548 assert(inputValue<nameVector.size());
549 string className=nameVector[
static_cast<unsigned short>(inputValue)];
550 cm.incrementResult(type2string<short>(classValueMap[referenceClassName]),type2string<short>(classValueMap[className]),1);
553 int rc=distance(referenceRange.begin(),find(referenceRange.begin(),referenceRange.end(),
static_cast<unsigned short>(referenceValue)));
554 int ic=distance(inputRange.begin(),find(inputRange.begin(),inputRange.end(),
static_cast<unsigned short>(inputValue)));
558 ++resultClass[rc][ic];
560 cout <<
"increment: " << rc <<
" " << referenceRange[rc] <<
" " << ic <<
" " << inputRange[ic] << endl;
561 cm.incrementResult(cm.getClass(rc),cm.getClass(ic),1);
564 if(inputValue==referenceValue){
565 outputValue=valueE_opt[0];
566 if(nodata_opt.size()){
567 if(valueE_opt[0]==nodata_opt[0])
568 outputValue=inputValue;
571 else if(inputValue>referenceValue)
572 outputValue=valueO_opt[0];
574 outputValue=valueC_opt[0];
578 for(
int windowJ=-theDim/2;windowJ<(theDim+1)/2;++windowJ){
579 for(
int windowI=-theDim/2;windowI<(theDim+1)/2;++windowI){
580 if(disc_opt[0]&&(windowI*windowI+windowJ*windowJ>(theDim/2)*(theDim/2)))
582 int j=j_centre+windowJ;
584 if(static_cast<int>(j)<0||
static_cast<int>(j)>=inputReader.nrOfRow())
586 int i=i_centre+windowI;
588 if(static_cast<int>(i)<0||
static_cast<int>(i)>=inputReader.nrOfCol())
590 if(!windowAllFlagged){
593 fs << labelclass_opt[0] <<
"_" << windowJ <<
"_" << windowI;
595 fs << labelclass_opt[0];
596 if(output_opt.size())
597 writeFeature->SetField(fs.str().c_str(),inputValue);
598 if(!windowJ&&!windowI){
599 if(confusion_opt[0]){
601 if(classValueMap.size()){
602 assert(inputValue<nameVector.size());
603 string className=nameVector[
static_cast<unsigned short>(inputValue)];
604 cm.incrementResult(type2string<short>(classValueMap[referenceClassName]),type2string<short>(classValueMap[className]),1);
607 int rc=distance(referenceRange.begin(),find(referenceRange.begin(),referenceRange.end(),
static_cast<unsigned short>(referenceValue)));
608 int ic=distance(inputRange.begin(),find(inputRange.begin(),inputRange.end(),
static_cast<unsigned short>(inputValue)));
616 ++resultClass[rc][ic];
618 cout <<
"increment: " << rc <<
" " << referenceRange[rc] <<
" " << ic <<
" " << inputRange[ic] << endl;
619 cm.incrementResult(cm.getClass(rc),cm.getClass(ic),1);
622 if(inputValue==referenceValue){
623 outputValue=valueE_opt[0];
624 if(nodata_opt.size()){
625 if(valueE_opt[0]==nodata_opt[0])
626 outputValue=inputValue;
629 else if(inputValue>referenceValue)
630 outputValue=valueO_opt[0];
632 outputValue=valueC_opt[0];
638 if(output_opt.size()){
639 if(!windowAllFlagged){
641 cout <<
"creating feature" << endl;
642 if(writeLayer->CreateFeature( writeFeature ) != OGRERR_NONE ){
643 string errorString=
"Failed to create feature in OGR vector file";
647 OGRFeature::DestroyFeature( writeFeature );
650 progress=
static_cast<float>(ifeature+1)/nfeatureInLayer;
651 pfnProgress(progress,pszMessage,pProgressArg);
654 if(output_opt.size())
656 referenceReaderOgr.close();
662 pfnProgress(1.0,pszMessage,pProgressArg);
667 inputReader.open(input_opt[0]);
669 maskReader.open(mask_opt[0]);
670 if(output_opt.size()){
672 cout <<
"opening output image " << output_opt[0] << endl;
673 if(option_opt.findSubstring(
"INTERLEAVE=")==option_opt.end()){
674 string theInterleave=
"INTERLEAVE=";
675 theInterleave+=inputReader.getInterleave();
676 option_opt.push_back(theInterleave);
678 gdalWriter.open(output_opt[0],inputReader.nrOfCol(),inputReader.nrOfRow(),1,inputReader.getDataType(),inputReader.getImageType(),option_opt);
679 if(nodata_opt.size())
680 gdalWriter.GDALSetNoDataValue(nodata_opt[0]);
681 gdalWriter.copyGeoTransform(inputReader);
682 if(colorTable_opt.size())
683 gdalWriter.setColorTable(colorTable_opt[0]);
684 else if(inputReader.getColorTable()!=NULL){
686 cout <<
"set colortable from input image" << endl;
687 gdalWriter.setColorTable(inputReader.getColorTable());
690 else if(verbose_opt[0])
691 cout <<
"no output image defined" << endl;
695 cout << error << endl;
699 vector<double> lineInput(inputReader.nrOfCol());
700 vector<double> lineMask(maskReader.nrOfCol());
701 vector<double> lineOutput;
702 vector<double> bufferInput;
703 vector<double> bufferReference;
704 if(output_opt.size())
705 lineOutput.resize(inputReader.nrOfCol());
709 double oldreferencerow=-1;
710 double oldmaskrow=-1;
713 referenceReaderGdal.open(reference_opt[0]);
716 cerr << error << endl;
719 if(inputReader.isGeoRef()){
720 assert(referenceReaderGdal.isGeoRef());
721 if(inputReader.getProjection()!=referenceReaderGdal.getProjection())
722 cerr <<
"Warning: projection of input image and reference image are different" << endl;
724 vector<double> lineReference(referenceReaderGdal.nrOfCol());
725 if(confusion_opt[0]){
726 referenceReaderGdal.getRange(referenceRange,band_opt[1]);
727 for(
int iflag=0;iflag<nodata_opt.size();++iflag){
728 vector<short>::iterator fit;
729 fit=find(referenceRange.begin(),referenceRange.end(),
static_cast<unsigned short>(nodata_opt[iflag]));
730 if(fit!=referenceRange.end())
731 referenceRange.erase(fit);
734 cout <<
"reference range: " << endl;
735 for(
int rc=0;rc<referenceRange.size();++rc)
736 cout << referenceRange[rc] << endl;
738 if(referenceRange.size()!=inputRange.size()){
739 if(confusion_opt[0]||output_opt.size()){
740 cout <<
"reference range is not equal to input range!" << endl;
741 cout <<
"Kappa: " << 0 << endl;
742 cout <<
"total weighted: " << 0 << endl;
745 cout <<
"reference range is not equal to input range!" << endl;
746 cout << input_opt[0] <<
" and " << reference_opt[0] <<
" are different" << endl;
752 for(irow=0;irow<inputReader.nrOfRow();++irow){
754 inputReader.readData(lineInput,GDT_Float64,irow,band_opt[0]);
756 double ireference,jreference;
758 for(icol=0;icol<inputReader.nrOfCol();++icol){
760 inputReader.image2geo(icol,irow,x,y);
761 referenceReaderGdal.geo2image(x,y,ireference,jreference);
762 if(ireference<0||ireference>=referenceReaderGdal.nrOfCol()){
763 if(rmse_opt[0]||regression_opt[0])
766 cerr << ireference <<
" out of reference range!" << endl;
767 cerr << x <<
" " << y <<
" " << icol <<
" " << irow << endl;
768 cerr << x <<
" " << y <<
" " << ireference <<
" " << jreference << endl;
772 if(jreference!=oldreferencerow){
773 if(jreference<0||jreference>=referenceReaderGdal.nrOfRow()){
774 if(rmse_opt[0]||regression_opt[0])
777 cerr << jreference <<
" out of reference range!" << endl;
778 cerr << x <<
" " << y <<
" " << icol <<
" " << irow << endl;
779 cerr << x <<
" " << y <<
" " << ireference <<
" " << jreference << endl;
784 referenceReaderGdal.readData(lineReference,GDT_Float64,static_cast<int>(jreference),band_opt[1]);
785 oldreferencerow=jreference;
789 for(
int iflag=0;iflag<nodata_opt.size();++iflag){
790 if((lineInput[icol]==nodata_opt[iflag])||(lineReference[ireference]==nodata_opt[iflag])){
791 if(output_opt.size())
792 lineOutput[icol]=nodata_opt[iflag];
798 maskReader.geo2image(x,y,imask,jmask);
799 if(jmask>=0&&jmask<maskReader.nrOfRow()){
800 if(jmask!=oldmaskrow)
801 maskReader.readData(lineMask,GDT_Float64,jmask);
802 for(
int ivalue=0;ivalue<msknodata_opt.size();++ivalue){
803 if(lineMask[icol]==msknodata_opt[ivalue]){
812 rmse+=
static_cast<double>(lineInput[icol]-lineReference[ireference])*(lineInput[icol]-lineReference[ireference])/inputReader.nrOfCol()/inputReader.nrOfRow();
814 else if(regression_opt[0]){
815 bufferInput.push_back(lineInput[icol]);
816 bufferReference.push_back(lineReference[ireference]);
819 if(confusion_opt[0]){
821 int rc=distance(referenceRange.begin(),find(referenceRange.begin(),referenceRange.end(),lineReference[ireference]));
822 int ic=distance(inputRange.begin(),find(inputRange.begin(),inputRange.end(),lineInput[icol]));
826 ++resultClass[rc][ic];
828 cout <<
"increment: " << rc <<
" " << referenceRange[rc] <<
" " << ic <<
" " << inputRange[ic] << endl;
829 cm.incrementResult(cm.getClass(rc),cm.getClass(ic),1);
831 if(lineInput[icol]==lineReference[ireference]){
832 if(output_opt.size()){
833 lineOutput[icol]=valueE_opt[0];
834 if(nodata_opt.size()){
835 if(valueE_opt[0]==nodata_opt[0])
836 lineOutput[icol]=lineInput[icol];
841 if(output_opt.empty()&&!confusion_opt[0]&&!rmse_opt[0]&&!regression_opt[0]){
845 if(output_opt.size()){
846 if(lineInput[icol]>lineReference[ireference])
847 lineOutput[icol]=valueO_opt[0];
849 lineOutput[icol]=valueC_opt[0];
855 if(output_opt.size()){
856 if(nodata_opt.size())
857 lineOutput[icol]=nodata_opt[0];
863 if(output_opt.size()){
865 gdalWriter.writeData(lineOutput,GDT_Float64,irow);
867 catch(
string errorstring){
868 cerr <<
"lineOutput.size(): " << lineOutput.size() << endl;
869 cerr <<
"gdalWriter.nrOfCol(): " << gdalWriter.nrOfCol() << endl;
870 cerr << errorstring << endl;
874 else if(isDifferent&&!confusion_opt[0]&&!rmse_opt[0]&&!regression_opt[0]){
876 pfnProgress(1.0,pszMessage,pProgressArg);
879 progress=
static_cast<float>(irow+1.0)/inputReader.nrOfRow();
881 pfnProgress(progress,pszMessage,pProgressArg);
883 if(output_opt.size())
885 else if(!confusion_opt[0]){
887 double normalization=1.0*inputReader.nrOfCol()*inputReader.nrOfRow()/(inputReader.nrOfCol()*inputReader.nrOfRow()-nflagged);
889 cout <<
"normalization: " << normalization << endl;
890 cout <<
"rmse before sqrt and normalization: " << rmse << endl;
892 cout <<
"--rmse " << sqrt(rmse/normalization) << endl;
894 else if(regression_opt[0]){
899 if(bufferInput.size()&&bufferReference.size()){
900 err=stat.linear_regression_err(bufferInput,bufferReference,c0,c1);
903 cout <<
"bufferInput.size(): " << bufferInput.size() << endl;
904 cout <<
"bufferReference.size(): " << bufferReference.size() << endl;
907 stat.minmax(bufferInput,bufferInput.begin(),bufferInput.end(),theMin,theMax);
908 cout <<
"min, max input: " << theMin <<
", " << theMax << endl;
911 stat.minmax(bufferReference,bufferReference.begin(),bufferReference.end(),theMin,theMax);
912 cout <<
"min, max reference: " << theMin <<
", " << theMax << endl;
914 cout <<
"--c0 " << c0 <<
"--c1 " << c1 <<
" --rmse: " << err << endl;
918 cout << input_opt[0] <<
" and " << reference_opt[0] <<
" are different" << endl;
920 cout << input_opt[0] <<
" and " << reference_opt[0] <<
" are identical" << endl;
922 referenceReaderGdal.close();
928 if(confusion_opt[0]){
929 cm.setFormat(cmformat_opt[0]);
930 cm.reportSE95(se95_opt[0]);
932 if(cmoutput_opt.size()){
933 outputFile.open(cmoutput_opt[0].c_str(),ios::out);
934 outputFile << cm << endl;