24 #include "imageclasses/ImgReaderGdal.h" 25 #include "imageclasses/ImgWriterGdal.h" 26 #include "imageclasses/ImgReaderOgr.h" 27 #include "imageclasses/ImgWriterOgr.h" 28 #include "base/Optionpk.h" 29 #include "base/PosValue.h" 30 #include "algorithms/ConfusionMatrix.h" 31 #include "floatfann.h" 32 #include "algorithms/myfann_cpp.h" 106 int main(
int argc,
char *argv[])
108 vector<double> priors;
112 Optionpk<string> training_opt(
"t",
"training",
"training vector file. A single vector file contains all training features (must be set as: B0, B1, B2,...) for all classes (class numbers identified by label option). Use multiple training files for bootstrap aggregation (alternative to the bag and bsize options, where a random subset is taken from a single training file)");
114 Optionpk<string> label_opt(
"label",
"label",
"identifier for class label in training vector file.",
"label");
115 Optionpk<unsigned int> balance_opt(
"bal",
"balance",
"balance the input data to this number of samples for each class", 0);
116 Optionpk<bool> random_opt(
"random",
"random",
"in case of balance, randomize input data",
true,2);
117 Optionpk<int> minSize_opt(
"min",
"min",
"if number of training pixels is less then min, do not take this class into account (0: consider all classes)", 0);
118 Optionpk<unsigned short> band_opt(
"b",
"band",
"band index (starting from 0, either use band option or use start to end)");
121 Optionpk<double> offset_opt(
"offset",
"offset",
"offset value for each spectral band input features: refl[band]=(DN[band]-offset[band])/scale[band]", 0.0);
122 Optionpk<double> scale_opt(
"scale",
"scale",
"scale value for each spectral band input features: refl=(DN[band]-offset[band])/scale[band] (use 0 if scale min and max in each band to -1.0 and 1.0)", 0.0);
123 Optionpk<unsigned short> aggreg_opt(
"a",
"aggreg",
"how to combine aggregated classifiers, see also rc option (1: sum rule, 2: max rule).",1);
124 Optionpk<double> priors_opt(
"prior",
"prior",
"prior probabilities for each class (e.g., -p 0.3 -p 0.3 -p 0.2 )", 0.0);
125 Optionpk<string> priorimg_opt(
"pim",
"priorimg",
"prior probability image (multi-band img with band for each class",
"",2);
127 Optionpk<string> cmformat_opt(
"cmf",
"cmf",
"Format for confusion matrix (ascii or latex)",
"ascii");
128 Optionpk<unsigned int> nneuron_opt(
"nn",
"nneuron",
"number of neurons in hidden layers in neural network (multiple hidden layers are set by defining multiple number of neurons: -n 15 -n 1, default is one hidden layer with 5 neurons)", 5);
129 Optionpk<float> connection_opt(
"\0",
"connection",
"connection reate (default: 1.0 for a fully connected network)", 1.0);
130 Optionpk<float> learning_opt(
"l",
"learning",
"learning rate (default: 0.7)", 0.7);
131 Optionpk<float> weights_opt(
"w",
"weights",
"weights for neural network. Apply to fully connected network only, starting from first input neuron to last output neuron, including the bias neurons (last neuron in each but last layer)", 0.0);
132 Optionpk<unsigned int> maxit_opt(
"\0",
"maxit",
"number of maximum iterations (epoch) (default: 500)", 500);
133 Optionpk<unsigned short> comb_opt(
"comb",
"comb",
"how to combine bootstrap aggregation classifiers (0: sum rule, 1: product rule, 2: max rule). Also used to aggregate classes with rc option. Default is sum rule (0)",0);
135 Optionpk<int> bagSize_opt(
"bs",
"bsize",
"Percentage of features used from available training features for each bootstrap aggregation (one size for all classes, or a different size for each class respectively", 100);
136 Optionpk<string> classBag_opt(
"cb",
"classbag",
"output for each individual bootstrap aggregation (default is blank)");
137 Optionpk<string> mask_opt(
"m",
"mask",
"Only classify within specified mask (vector or raster).");
140 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");
141 Optionpk<string> option_opt(
"co",
"co",
"Creation option for output file. Multiple options can be specified.");
142 Optionpk<string> colorTable_opt(
"ct",
"ct",
"colour table in ASCII format having 5 columns: id R G B ALFA (0: transparent, 255: solid)");
143 Optionpk<string> entropy_opt(
"entropy",
"entropy",
"entropy image (measure for uncertainty of classifier output",
"",2);
144 Optionpk<string> active_opt(
"active",
"active",
"ogr output for active training sample.",
"",2);
145 Optionpk<string> ogrformat_opt(
"f",
"f",
"Output ogr format for active training sample",
"SQLite");
148 Optionpk<short> classvalue_opt(
"r",
"reclass",
"list of class values (use same order as in class opt).");
149 Optionpk<short> verbose_opt(
"v",
"verbose",
"set to: 0 (results only), 1 (confusion matrix), 2 (debug)",0,2);
151 option_opt.setHide(1);
153 bstart_opt.setHide(1);
155 balance_opt.setHide(1);
156 minSize_opt.setHide(1);
158 bagSize_opt.setHide(1);
160 classBag_opt.setHide(1);
161 minSize_opt.setHide(1);
162 priorimg_opt.setHide(1);
163 minSize_opt.setHide(1);
164 offset_opt.setHide(1);
165 scale_opt.setHide(1);
166 connection_opt.setHide(1);
167 weights_opt.setHide(1);
168 maxit_opt.setHide(1);
169 learning_opt.setHide(1);
171 verbose_opt.setHide(2);
175 doProcess=input_opt.retrieveOption(argc,argv);
176 training_opt.retrieveOption(argc,argv);
177 tlayer_opt.retrieveOption(argc,argv);
178 label_opt.retrieveOption(argc,argv);
179 balance_opt.retrieveOption(argc,argv);
180 random_opt.retrieveOption(argc,argv);
181 minSize_opt.retrieveOption(argc,argv);
182 band_opt.retrieveOption(argc,argv);
183 bstart_opt.retrieveOption(argc,argv);
184 bend_opt.retrieveOption(argc,argv);
185 offset_opt.retrieveOption(argc,argv);
186 scale_opt.retrieveOption(argc,argv);
187 aggreg_opt.retrieveOption(argc,argv);
188 priors_opt.retrieveOption(argc,argv);
189 priorimg_opt.retrieveOption(argc,argv);
190 cv_opt.retrieveOption(argc,argv);
191 cmformat_opt.retrieveOption(argc,argv);
192 nneuron_opt.retrieveOption(argc,argv);
193 connection_opt.retrieveOption(argc,argv);
194 weights_opt.retrieveOption(argc,argv);
195 learning_opt.retrieveOption(argc,argv);
196 maxit_opt.retrieveOption(argc,argv);
197 comb_opt.retrieveOption(argc,argv);
198 bag_opt.retrieveOption(argc,argv);
199 bagSize_opt.retrieveOption(argc,argv);
200 classBag_opt.retrieveOption(argc,argv);
201 mask_opt.retrieveOption(argc,argv);
202 nodata_opt.retrieveOption(argc,argv);
203 output_opt.retrieveOption(argc,argv);
204 otype_opt.retrieveOption(argc,argv);
205 colorTable_opt.retrieveOption(argc,argv);
206 option_opt.retrieveOption(argc,argv);
207 entropy_opt.retrieveOption(argc,argv);
208 active_opt.retrieveOption(argc,argv);
209 ogrformat_opt.retrieveOption(argc,argv);
210 nactive_opt.retrieveOption(argc,argv);
211 classname_opt.retrieveOption(argc,argv);
212 classvalue_opt.retrieveOption(argc,argv);
213 verbose_opt.retrieveOption(argc,argv);
215 catch(
string predefinedString){
216 std::cout << predefinedString << std::endl;
221 cout <<
"Usage: pkannogr -t training [-i input -o output] [-cv value]" << endl;
223 cout <<
"short option -h shows basic options only, use long option --help to show all options" << endl;
227 if(entropy_opt[0]==
"")
229 if(active_opt[0]==
"")
231 if(priorimg_opt[0]==
"")
232 priorimg_opt.clear();
234 if(verbose_opt[0]>=1){
236 cout <<
"image filename: " << input_opt[0] << endl;
238 cout <<
"mask filename: " << mask_opt[0] << endl;
239 if(training_opt.size()){
240 cout <<
"training vector file: " << endl;
241 for(
int ifile=0;ifile<training_opt.size();++ifile)
242 cout << training_opt[ifile] << endl;
245 cerr <<
"no training file set!" << endl;
246 cout <<
"verbose: " << verbose_opt[0] << endl;
248 unsigned short nbag=(training_opt.size()>1)?training_opt.size():bag_opt[0];
249 if(verbose_opt[0]>=1)
250 cout <<
"number of bootstrap aggregations: " << nbag << endl;
260 bool maskIsVector=
false;
263 extentReader.open(mask_opt[0]);
265 readLayer = extentReader.getDataSource()->GetLayer(0);
266 if(!(extentReader.getExtent(ulx,uly,lrx,lry))){
267 cerr <<
"Error: could not get extent from " << mask_opt[0] << endl;
271 catch(
string errorString){
277 if(active_opt.size()){
279 activeWriter.open(active_opt[0],ogrformat_opt[0]);
280 activeWriter.createLayer(active_opt[0],trainingReader.getProjection(),wkbPoint,NULL);
281 activeWriter.copyFields(trainingReader);
283 vector<PosValue> activePoints(nactive_opt[0]);
284 for(
int iactive=0;iactive<activePoints.size();++iactive){
285 activePoints[iactive].value=1.0;
286 activePoints[iactive].posx=0.0;
287 activePoints[iactive].posy=0.0;
290 unsigned int totalSamples=0;
291 unsigned int nactive=0;
292 vector<FANN::neural_net> net(nbag);
294 unsigned int nclass=0;
298 if(priors_opt.size()>1){
299 priors.resize(priors_opt.size());
301 for(
int iclass=0;iclass<priors_opt.size();++iclass){
302 priors[iclass]=priors_opt[iclass];
303 normPrior+=priors[iclass];
306 for(
int iclass=0;iclass<priors_opt.size();++iclass)
307 priors[iclass]/=normPrior;
312 if(bstart_opt.size()){
313 if(bend_opt.size()!=bstart_opt.size()){
314 string errorstring=
"Error: options for start and end band indexes must be provided as pairs, missing end band";
318 for(
int ipair=0;ipair<bstart_opt.size();++ipair){
319 if(bend_opt[ipair]<=bstart_opt[ipair]){
320 string errorstring=
"Error: index for end band must be smaller then start band";
323 for(
int iband=bstart_opt[ipair];iband<=bend_opt[ipair];++iband)
324 band_opt.push_back(iband);
329 cerr << error << std::endl;
334 std::sort(band_opt.begin(),band_opt.end());
336 map<string,short> classValueMap;
337 vector<std::string> nameVector;
338 if(classname_opt.size()){
339 assert(classname_opt.size()==classvalue_opt.size());
340 for(
int iclass=0;iclass<classname_opt.size();++iclass)
341 classValueMap[classname_opt[iclass]]=classvalue_opt[iclass];
345 vector< vector<double> > offset(nbag);
346 vector< vector<double> > scale(nbag);
347 map<string,Vector2d<float> > trainingMap;
348 vector< Vector2d<float> > trainingPixels;
349 vector<string> fields;
350 for(
int ibag=0;ibag<nbag;++ibag){
352 if(ibag<training_opt.size()){
354 trainingPixels.clear();
355 if(verbose_opt[0]>=1)
356 cout <<
"reading imageVector file " << training_opt[0] << endl;
360 totalSamples=trainingReaderBag.readDataImageOgr(trainingMap,fields,band_opt,label_opt[0],tlayer_opt);
362 totalSamples=trainingReaderBag.readDataImageOgr(trainingMap,fields,0,0,label_opt[0],tlayer_opt);
363 if(trainingMap.size()<2){
364 string errorstring=
"Error: could not read at least two classes from training file, did you provide class labels in training sample (see option label)?";
367 trainingReaderBag.close();
370 cerr << error << std::endl;
374 cerr <<
"error caught" << std::endl;
384 std::cout <<
"training pixels: " << std::endl;
385 map<string,Vector2d<float> >::iterator mapit=trainingMap.begin();
386 while(mapit!=trainingMap.end()){
388 if((mapit->second).size()<minSize_opt[0]){
389 trainingMap.erase(mapit);
392 trainingPixels.push_back(mapit->second);
394 std::cout << mapit->first <<
": " << (mapit->second).size() <<
" samples" << std::endl;
398 nclass=trainingPixels.size();
399 if(classname_opt.size())
400 assert(nclass==classname_opt.size());
401 nband=(training_opt.size())?trainingPixels[0][0].size()-2:trainingPixels[0][0].size();
404 assert(nclass==trainingPixels.size());
405 assert(nband==(training_opt.size())?trainingPixels[0][0].size()-2:trainingPixels[0][0].size());
410 if(balance_opt[0]>0){
411 while(balance_opt.size()<nclass)
412 balance_opt.push_back(balance_opt.back());
416 for(
int iclass=0;iclass<nclass;++iclass){
417 if(trainingPixels[iclass].size()>balance_opt[iclass]){
418 while(trainingPixels[iclass].size()>balance_opt[iclass]){
419 int index=rand()%trainingPixels[iclass].size();
420 trainingPixels[iclass].erase(trainingPixels[iclass].begin()+index);
424 int oldsize=trainingPixels[iclass].size();
425 for(
int isample=trainingPixels[iclass].size();isample<balance_opt[iclass];++isample){
426 int index = rand()%oldsize;
427 trainingPixels[iclass].push_back(trainingPixels[iclass][index]);
430 totalSamples+=trainingPixels[iclass].size();
435 offset[ibag].resize(nband);
436 scale[ibag].resize(nband);
437 if(offset_opt.size()>1)
438 assert(offset_opt.size()==nband);
439 if(scale_opt.size()>1)
440 assert(scale_opt.size()==nband);
441 for(
int iband=0;iband<nband;++iband){
442 if(verbose_opt[0]>=1)
443 cout <<
"scaling for band" << iband << endl;
444 offset[ibag][iband]=(offset_opt.size()==1)?offset_opt[0]:offset_opt[iband];
445 scale[ibag][iband]=(scale_opt.size()==1)?scale_opt[0]:scale_opt[iband];
447 if(scale[ibag][iband]<=0){
448 float theMin=trainingPixels[0][0][iband+startBand];
449 float theMax=trainingPixels[0][0][iband+startBand];
450 for(
int iclass=0;iclass<nclass;++iclass){
451 for(
int isample=0;isample<trainingPixels[iclass].size();++isample){
452 if(theMin>trainingPixels[iclass][isample][iband+startBand])
453 theMin=trainingPixels[iclass][isample][iband+startBand];
454 if(theMax<trainingPixels[iclass][isample][iband+startBand])
455 theMax=trainingPixels[iclass][isample][iband+startBand];
458 offset[ibag][iband]=theMin+(theMax-theMin)/2.0;
459 scale[ibag][iband]=(theMax-theMin)/2.0;
460 if(verbose_opt[0]>=1){
461 std::cout <<
"Extreme image values for band " << iband <<
": [" << theMin <<
"," << theMax <<
"]" << std::endl;
462 std::cout <<
"Using offset, scale: " << offset[ibag][iband] <<
", " << scale[ibag][iband] << std::endl;
463 std::cout <<
"scaled values for band " << iband <<
": [" << (theMin-offset[ibag][iband])/scale[ibag][iband] <<
"," << (theMax-offset[ibag][iband])/scale[ibag][iband] <<
"]" << std::endl;
469 offset[ibag].resize(nband);
470 scale[ibag].resize(nband);
471 for(
int iband=0;iband<nband;++iband){
472 offset[ibag][iband]=offset[0][iband];
473 scale[ibag][iband]=scale[0][iband];
478 if(priors_opt.size()==1){
479 priors.resize(nclass);
480 for(
int iclass=0;iclass<nclass;++iclass)
481 priors[iclass]=1.0/nclass;
483 assert(priors_opt.size()==1||priors_opt.size()==nclass);
486 while(bagSize_opt.size()<nclass)
487 bagSize_opt.push_back(bagSize_opt.back());
489 if(verbose_opt[0]>=1){
490 std::cout <<
"number of bands: " << nband << std::endl;
491 std::cout <<
"number of classes: " << nclass << std::endl;
492 std::cout <<
"priors:";
493 if(priorimg_opt.empty()){
494 for(
int iclass=0;iclass<nclass;++iclass)
495 std::cout <<
" " << priors[iclass];
496 std::cout << std::endl;
499 map<string,Vector2d<float> >::iterator mapit=trainingMap.begin();
501 while(mapit!=trainingMap.end()){
502 nameVector.push_back(mapit->first);
503 if(classValueMap.size()){
505 if(classValueMap[mapit->first]>0){
506 if(cm.getClassIndex(type2string<short>(classValueMap[mapit->first]))<0)
507 cm.pushBackClassName(type2string<short>(classValueMap[mapit->first]),doSort);
510 std::cerr <<
"Error: names in classname option are not complete, please check names in training vector and make sure classvalue is > 0" << std::endl;
515 cm.pushBackClassName(mapit->first,doSort);
518 if(classname_opt.empty()){
520 for(
int iclass=0;iclass<nclass;++iclass){
522 std::cout << iclass <<
" " << cm.getClass(iclass) <<
" -> " << string2type<short>(cm.getClass(iclass)) << std::endl;
523 classValueMap[cm.getClass(iclass)]=string2type<short>(cm.getClass(iclass));
526 if(priors_opt.size()==nameVector.size()){
527 std::cerr <<
"Warning: please check if priors are provided in correct order!!!" << std::endl;
528 for(
int iclass=0;iclass<nameVector.size();++iclass)
529 std::cerr << nameVector[iclass] <<
" " << priors_opt[iclass] << std::endl;
534 vector< Vector2d<float> > trainingFeatures(nclass);
535 for(
int iclass=0;iclass<nclass;++iclass){
537 if(verbose_opt[0]>=1)
538 cout <<
"calculating features for class " << iclass << endl;
541 nctraining=(bagSize_opt[iclass]<100)? trainingPixels[iclass].size()/100.0*bagSize_opt[iclass] : trainingPixels[iclass].size();
544 assert(nctraining<=trainingPixels[iclass].size());
546 if(bagSize_opt[iclass]<100)
547 random_shuffle(trainingPixels[iclass].begin(),trainingPixels[iclass].end());
549 trainingFeatures[iclass].resize(nctraining);
550 for(
int isample=0;isample<nctraining;++isample){
552 for(
int iband=0;iband<nband;++iband){
553 float value=trainingPixels[iclass][isample][iband+startBand];
554 trainingFeatures[iclass][isample].push_back((value-offset[ibag][iband])/scale[ibag][iband]);
557 assert(trainingFeatures[iclass].size()==nctraining);
560 unsigned int nFeatures=trainingFeatures[0][0].size();
561 unsigned int ntraining=0;
562 for(
int iclass=0;iclass<nclass;++iclass)
563 ntraining+=trainingFeatures[iclass].size();
565 const unsigned int num_layers = nneuron_opt.size()+2;
566 const float desired_error = 0.0003;
567 const unsigned int iterations_between_reports = (verbose_opt[0])? maxit_opt[0]+1:0;
568 if(verbose_opt[0]>=1){
569 cout <<
"number of features: " << nFeatures << endl;
570 cout <<
"creating artificial neural network with " << nneuron_opt.size() <<
" hidden layer, having " << endl;
571 for(
int ilayer=0;ilayer<nneuron_opt.size();++ilayer)
572 cout << nneuron_opt[ilayer] <<
" ";
573 cout <<
"neurons" << endl;
574 cout <<
"connection_opt[0]: " << connection_opt[0] << std::endl;
575 cout <<
"num_layers: " << num_layers << std::endl;
576 cout <<
"nFeatures: " << nFeatures << std::endl;
577 cout <<
"nneuron_opt[0]: " << nneuron_opt[0] << std::endl;
578 cout <<
"number of classes (nclass): " << nclass << std::endl;
583 unsigned int layers[3];
585 layers[1]=nneuron_opt[0];
587 net[ibag].create_sparse_array(connection_opt[0],num_layers,layers);
591 unsigned int layers[4];
593 layers[1]=nneuron_opt[0];
594 layers[2]=nneuron_opt[1];
600 net[ibag].create_sparse_array(connection_opt[0],num_layers,layers);
604 cerr <<
"Only 1 or 2 hidden layers are supported!" << endl;
608 if(verbose_opt[0]>=1)
609 cout <<
"network created" << endl;
611 net[ibag].set_learning_rate(learning_opt[0]);
616 net[ibag].set_activation_function_hidden(FANN::SIGMOID_SYMMETRIC_STEPWISE);
617 net[ibag].set_activation_function_output(FANN::SIGMOID_SYMMETRIC_STEPWISE);
623 if(verbose_opt[0]>=1){
624 cout << endl <<
"Network Type : ";
625 switch (net[ibag].get_network_type())
628 cout <<
"LAYER" << endl;
631 cout <<
"SHORTCUT" << endl;
634 cout <<
"UNKNOWN" << endl;
637 net[ibag].print_parameters();
642 std::cout <<
"cross validation" << std::endl;
643 vector<unsigned short> referenceVector;
644 vector<unsigned short> outputVector;
645 float rmse=net[ibag].cross_validation(trainingFeatures,
653 map<string,Vector2d<float> >::iterator mapit=trainingMap.begin();
654 for(
int isample=0;isample<referenceVector.size();++isample){
655 string refClassName=nameVector[referenceVector[isample]];
656 string className=nameVector[outputVector[isample]];
657 if(classValueMap.size())
658 cm.incrementResult(type2string<short>(classValueMap[refClassName]),type2string<short>(classValueMap[className]),1.0/nbag);
660 cm.incrementResult(cm.getClass(referenceVector[isample]),cm.getClass(outputVector[isample]),1.0/nbag);
664 if(verbose_opt[0]>=1)
665 cout << endl <<
"Set training data" << endl;
667 if(verbose_opt[0]>=1)
668 cout << endl <<
"Training network" << endl;
670 if(verbose_opt[0]>=1){
671 cout <<
"Max Epochs " << setw(8) << maxit_opt[0] <<
". " 672 <<
"Desired Error: " << left << desired_error << right << endl;
674 if(weights_opt.size()==net[ibag].get_total_connections()){
675 vector<fann_connection> convector;
676 net[ibag].get_connection_array(convector);
677 for(
int i_connection=0;i_connection<net[ibag].get_total_connections();++i_connection)
678 convector[i_connection].weight=weights_opt[i_connection];
679 net[ibag].set_weight_array(convector);
682 bool initWeights=
true;
683 net[ibag].train_on_data(trainingFeatures,ntraining,initWeights, maxit_opt[0],
684 iterations_between_reports, desired_error);
688 if(verbose_opt[0]>=2){
689 net[ibag].print_connections();
690 vector<fann_connection> convector;
691 net[ibag].get_connection_array(convector);
692 for(
int i_connection=0;i_connection<net[ibag].get_total_connections();++i_connection)
693 cout <<
"connection " << i_connection <<
": " << convector[i_connection].weight << endl;
698 assert(cm.nReference());
699 cm.setFormat(cmformat_opt[0]);
700 cm.reportSE95(
false);
701 std::cout << cm << std::endl;
702 cout <<
"class #samples userAcc prodAcc" << endl;
709 for(
int iclass=0;iclass<cm.nClasses();++iclass){
710 dua=cm.ua_pct(cm.getClass(iclass),&se95_ua);
711 dpa=cm.pa_pct(cm.getClass(iclass),&se95_pa);
712 cout << cm.getClass(iclass) <<
" " << cm.nReference(cm.getClass(iclass)) <<
" " << dua <<
" (" << se95_ua <<
")" <<
" " << dpa <<
" (" << se95_pa <<
")" << endl;
714 std::cout <<
"Kappa: " << cm.kappa() << std::endl;
715 doa=cm.oa_pct(&se95_oa);
716 std::cout <<
"Overall Accuracy: " << doa <<
" (" << se95_oa <<
")" << std::endl;
719 if(input_opt.empty())
722 const char* pszMessage;
723 void* pProgressArg=NULL;
724 GDALProgressFunc pfnProgress=GDALTermProgress;
727 bool inputIsRaster=
false;
730 imgReaderOgr.open(input_opt[0]);
731 imgReaderOgr.close();
733 catch(
string errorString){
739 for(
int ivalidation=0;ivalidation<input_opt.size();++ivalidation){
740 if(output_opt.size())
741 assert(output_opt.size()==input_opt.size());
743 cout <<
"opening img reader " << input_opt[ivalidation] << endl;
744 imgReaderOgr.open(input_opt[ivalidation]);
747 if(output_opt.size()){
749 std::cout <<
"opening img writer and copying fields from img reader" << output_opt[ivalidation] << std::endl;
750 imgWriterOgr.open(output_opt[ivalidation],imgReaderOgr);
753 cout <<
"number of layers in input ogr file: " << imgReaderOgr.getLayerCount() << endl;
754 for(
int ilayer=0;ilayer<imgReaderOgr.getLayerCount();++ilayer){
756 cout <<
"processing input layer " << ilayer << endl;
757 if(output_opt.size()){
759 std::cout <<
"creating field class" << std::endl;
760 if(classValueMap.size())
761 imgWriterOgr.createField(
"class",OFTInteger,ilayer);
763 imgWriterOgr.createField(
"class",OFTString,ilayer);
765 unsigned int nFeatures=imgReaderOgr.getFeatureCount(ilayer);
766 unsigned int ifeature=0;
768 pfnProgress(progress,pszMessage,pProgressArg);
769 OGRFeature *poFeature;
770 while( (poFeature = imgReaderOgr.getLayer(ilayer)->GetNextFeature()) != NULL ){
772 cout <<
"feature " << ifeature << endl;
773 if( poFeature == NULL ){
774 cout <<
"Warning: could not read feature " << ifeature <<
" in layer " << imgReaderOgr.getLayerName(ilayer) << endl;
777 OGRFeature *poDstFeature = NULL;
778 if(output_opt.size()){
779 poDstFeature=imgWriterOgr.createFeature(ilayer);
780 if( poDstFeature->SetFrom( poFeature, TRUE ) != OGRERR_NONE ){
781 CPLError( CE_Failure, CPLE_AppDefined,
782 "Unable to translate feature %d from layer %s.\n",
783 poFeature->GetFID(), imgWriterOgr.getLayerName(ilayer).c_str() );
784 OGRFeature::DestroyFeature( poFeature );
785 OGRFeature::DestroyFeature( poDstFeature );
788 vector<float> validationPixel;
789 vector<float> validationFeature;
791 imgReaderOgr.readData(validationPixel,OFTReal,fields,poFeature,ilayer);
792 assert(validationPixel.size()==nband);
793 vector<float> probOut(nclass);
794 for(
int iclass=0;iclass<nclass;++iclass)
796 for(
int ibag=0;ibag<nbag;++ibag){
797 for(
int iband=0;iband<nband;++iband){
798 validationFeature.push_back((validationPixel[iband]-offset[ibag][iband])/scale[ibag][iband]);
799 if(verbose_opt[0]==2)
800 std:: cout <<
" " << validationFeature.back();
802 if(verbose_opt[0]==2)
803 std::cout << std:: endl;
804 vector<float> result(nclass);
805 result=net[ibag].run(validationFeature);
807 if(verbose_opt[0]>1){
808 for(
int iclass=0;iclass<result.size();++iclass)
809 std::cout << result[iclass] <<
" ";
810 std::cout << std::endl;
813 for(
int iclass=0;iclass<nclass;++iclass){
814 result[iclass]=(result[iclass]+1.0)/2.0;
818 probOut[iclass]+=result[iclass]*priors[iclass];
821 probOut[iclass]*=pow(static_cast<float>(priors[iclass]),static_cast<float>(1.0-nbag)/nbag)*result[iclass];
824 if(priors[iclass]*result[iclass]>probOut[iclass])
825 probOut[iclass]=priors[iclass]*result[iclass];
833 string classOut=
"Unclassified";
834 for(
int iclass=0;iclass<nclass;++iclass){
836 std::cout << probOut[iclass] <<
" ";
837 if(probOut[iclass]>maxBag){
838 maxBag=probOut[iclass];
839 classOut=nameVector[iclass];
843 if(verbose_opt[0]>1){
844 if(classValueMap.size())
845 std::cout <<
"->" << classValueMap[classOut] << std::endl;
847 std::cout <<
"->" << classOut << std::endl;
849 if(output_opt.size()){
850 if(classValueMap.size())
851 poDstFeature->SetField(
"class",classValueMap[classOut]);
853 poDstFeature->SetField(
"class",classOut.c_str());
854 poDstFeature->SetFID( poFeature->GetFID() );
856 int labelIndex=poFeature->GetFieldIndex(label_opt[0].c_str());
858 string classRef=poFeature->GetFieldAsString(labelIndex);
860 if(classValueMap.size())
861 cm.incrementResult(type2string<short>(classValueMap[classRef]),type2string<short>(classValueMap[classOut]),1);
863 cm.incrementResult(classRef,classOut,1);
867 if(output_opt.size()){
868 if(imgWriterOgr.createFeature(poDstFeature,ilayer) != OGRERR_NONE){
869 CPLError( CE_Failure, CPLE_AppDefined,
870 "Unable to translate feature %d from layer %s.\n",
871 poFeature->GetFID(), imgWriterOgr.getLayerName(ilayer).c_str() );
872 OGRFeature::DestroyFeature( poDstFeature );
873 OGRFeature::DestroyFeature( poDstFeature );
878 progress=
static_cast<float>(ifeature+1.0)/nFeatures;
879 pfnProgress(progress,pszMessage,pProgressArg);
881 OGRFeature::DestroyFeature( poFeature );
882 OGRFeature::DestroyFeature( poDstFeature );
885 imgReaderOgr.close();
886 if(output_opt.size())
887 imgWriterOgr.close();
890 std::cout << cm << std::endl;
909 if(active_opt.size())
910 activeWriter.close();
912 catch(
string errorString){
913 std::cerr <<
"Error: errorString" << std::endl;