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 "algorithms/svm.h" 115 enum SVM_TYPE {C_SVC=0, nu_SVC=1,one_class=2, epsilon_SVR=3, nu_SVR=4};
116 enum KERNEL_TYPE {linear=0,polynomial=1,radial=2,sigmoid=3};
119 #define Malloc(type,n) (type *)malloc((n)*sizeof(type)) 123 int main(
int argc,
char *argv[])
125 vector<double> priors;
129 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)");
131 Optionpk<string> label_opt(
"label",
"label",
"Attribute name for class label in training vector file.",
"label");
132 Optionpk<unsigned int> balance_opt(
"bal",
"balance",
"Balance the input data to this number of samples for each class", 0);
133 Optionpk<bool> random_opt(
"random",
"random",
"Randomize training data for balancing and bagging",
true, 2);
134 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);
135 Optionpk<unsigned short> band_opt(
"b",
"band",
"Band index (starting from 0, either use band option or use start to end)");
138 Optionpk<double> offset_opt(
"offset",
"offset",
"Offset value for each spectral band input features: refl[band]=(DN[band]-offset[band])/scale[band]", 0.0);
139 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);
140 Optionpk<double> priors_opt(
"prior",
"prior",
"Prior probabilities for each class (e.g., -p 0.3 -p 0.3 -p 0.2 ). Used for input only (ignored for cross validation)", 0.0);
141 Optionpk<string> priorimg_opt(
"pim",
"priorimg",
"Prior probability image (multi-band img with band for each class",
"",2);
143 Optionpk<string> cmformat_opt(
"cmf",
"cmf",
"Format for confusion matrix (ascii or latex)",
"ascii");
144 Optionpk<std::string> svm_type_opt(
"svmt",
"svmtype",
"Type of SVM (C_SVC, nu_SVC,one_class, epsilon_SVR, nu_SVR)",
"C_SVC");
145 Optionpk<std::string> kernel_type_opt(
"kt",
"kerneltype",
"Type of kernel function (linear,polynomial,radial,sigmoid) ",
"radial");
147 Optionpk<float> gamma_opt(
"g",
"gamma",
"Gamma in kernel function",1.0);
148 Optionpk<float> coef0_opt(
"c0",
"coef0",
"Coef0 in kernel function",0);
149 Optionpk<float> ccost_opt(
"cc",
"ccost",
"The parameter C of C_SVC, epsilon_SVR, and nu_SVR",1000);
150 Optionpk<float> nu_opt(
"nu",
"nu",
"The parameter nu of nu_SVC, one_class SVM, and nu_SVR",0.5);
151 Optionpk<float> epsilon_loss_opt(
"eloss",
"eloss",
"The epsilon in loss function of epsilon_SVR",0.1);
152 Optionpk<int> cache_opt(
"cache",
"cache",
"Cache memory size in MB",100);
153 Optionpk<float> epsilon_tol_opt(
"etol",
"etol",
"The tolerance of termination criterion",0.001);
154 Optionpk<bool> shrinking_opt(
"shrink",
"shrink",
"Whether to use the shrinking heuristics",
false);
155 Optionpk<bool> prob_est_opt(
"pe",
"probest",
"Whether to train a SVC or SVR model for probability estimates",
true,2);
157 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.",0);
159 Optionpk<int> bagSize_opt(
"bagsize",
"bagsize",
"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);
160 Optionpk<string> classBag_opt(
"cb",
"classbag",
"Output for each individual bootstrap aggregation");
161 Optionpk<string> mask_opt(
"m",
"mask",
"Only classify within specified mask (vector or raster).");
162 Optionpk<unsigned short> nodata_opt(
"nodata",
"nodata",
"Nodata value to put where vector dataset is masked as nodata", 0);
164 Optionpk<string> option_opt(
"co",
"co",
"Creation option for output file. Multiple options can be specified.");
165 Optionpk<string> colorTable_opt(
"ct",
"ct",
"Color table in ASCII format having 5 columns: id R G B ALFA (0: transparent, 255: solid)");
166 Optionpk<string> entropy_opt(
"entropy",
"entropy",
"Entropy image (measure for uncertainty of classifier output",
"",2);
167 Optionpk<string> active_opt(
"active",
"active",
"Ogr output for active training sample.",
"",2);
168 Optionpk<string> ogrformat_opt(
"f",
"f",
"Output ogr format for active training sample",
"SQLite");
171 Optionpk<short> classvalue_opt(
"r",
"reclass",
"List of class values (use same order as in class opt).");
174 option_opt.setHide(1);
176 bstart_opt.setHide(1);
178 balance_opt.setHide(1);
179 minSize_opt.setHide(1);
181 bagSize_opt.setHide(1);
183 classBag_opt.setHide(1);
184 priorimg_opt.setHide(1);
185 offset_opt.setHide(1);
186 scale_opt.setHide(1);
187 svm_type_opt.setHide(1);
188 kernel_type_opt.setHide(1);
189 kernel_degree_opt.setHide(1);
190 coef0_opt.setHide(1);
192 epsilon_loss_opt.setHide(1);
193 cache_opt.setHide(1);
194 epsilon_tol_opt.setHide(1);
195 shrinking_opt.setHide(1);
196 prob_est_opt.setHide(1);
197 entropy_opt.setHide(1);
198 active_opt.setHide(1);
199 nactive_opt.setHide(1);
200 random_opt.setHide(1);
202 verbose_opt.setHide(2);
206 doProcess=training_opt.retrieveOption(argc,argv);
207 input_opt.retrieveOption(argc,argv);
208 output_opt.retrieveOption(argc,argv);
209 cv_opt.retrieveOption(argc,argv);
210 cmformat_opt.retrieveOption(argc,argv);
211 tlayer_opt.retrieveOption(argc,argv);
212 classname_opt.retrieveOption(argc,argv);
213 classvalue_opt.retrieveOption(argc,argv);
214 ogrformat_opt.retrieveOption(argc,argv);
215 option_opt.retrieveOption(argc,argv);
216 colorTable_opt.retrieveOption(argc,argv);
217 label_opt.retrieveOption(argc,argv);
218 priors_opt.retrieveOption(argc,argv);
219 gamma_opt.retrieveOption(argc,argv);
220 ccost_opt.retrieveOption(argc,argv);
221 mask_opt.retrieveOption(argc,argv);
222 nodata_opt.retrieveOption(argc,argv);
224 band_opt.retrieveOption(argc,argv);
225 bstart_opt.retrieveOption(argc,argv);
226 bend_opt.retrieveOption(argc,argv);
227 balance_opt.retrieveOption(argc,argv);
228 minSize_opt.retrieveOption(argc,argv);
229 bag_opt.retrieveOption(argc,argv);
230 bagSize_opt.retrieveOption(argc,argv);
231 comb_opt.retrieveOption(argc,argv);
232 classBag_opt.retrieveOption(argc,argv);
233 priorimg_opt.retrieveOption(argc,argv);
234 offset_opt.retrieveOption(argc,argv);
235 scale_opt.retrieveOption(argc,argv);
236 svm_type_opt.retrieveOption(argc,argv);
237 kernel_type_opt.retrieveOption(argc,argv);
238 kernel_degree_opt.retrieveOption(argc,argv);
239 coef0_opt.retrieveOption(argc,argv);
240 nu_opt.retrieveOption(argc,argv);
241 epsilon_loss_opt.retrieveOption(argc,argv);
242 cache_opt.retrieveOption(argc,argv);
243 epsilon_tol_opt.retrieveOption(argc,argv);
244 shrinking_opt.retrieveOption(argc,argv);
245 prob_est_opt.retrieveOption(argc,argv);
246 entropy_opt.retrieveOption(argc,argv);
247 active_opt.retrieveOption(argc,argv);
248 nactive_opt.retrieveOption(argc,argv);
249 verbose_opt.retrieveOption(argc,argv);
250 random_opt.retrieveOption(argc,argv);
252 catch(
string predefinedString){
253 std::cout << predefinedString << std::endl;
258 cout <<
"Usage: pksvmogr -t training [-i input -o output] [-cv value]" << endl;
260 std::cout <<
"short option -h shows basic options only, use long option --help to show all options" << std::endl;
264 if(entropy_opt[0]==
"")
266 if(active_opt[0]==
"")
268 if(priorimg_opt[0]==
"")
269 priorimg_opt.clear();
272 std::map<std::string, svm::SVM_TYPE> svmMap;
274 svmMap[
"C_SVC"]=svm::C_SVC;
275 svmMap[
"nu_SVC"]=svm::nu_SVC;
276 svmMap[
"one_class"]=svm::one_class;
277 svmMap[
"epsilon_SVR"]=svm::epsilon_SVR;
278 svmMap[
"nu_SVR"]=svm::nu_SVR;
280 std::map<std::string, svm::KERNEL_TYPE> kernelMap;
282 kernelMap[
"linear"]=svm::linear;
283 kernelMap[
"polynomial"]=svm::polynomial;
284 kernelMap[
"radial"]=svm::radial;
285 kernelMap[
"sigmoid;"]=svm::sigmoid;
287 assert(training_opt.size());
289 if(verbose_opt[0]>=1){
291 std::cout <<
"input filename: " << input_opt[0] << std::endl;
293 std::cout <<
"mask filename: " << mask_opt[0] << std::endl;
294 std::cout <<
"training vector file: " << std::endl;
295 for(
int ifile=0;ifile<training_opt.size();++ifile)
296 std::cout << training_opt[ifile] << std::endl;
297 std::cout <<
"verbose: " << verbose_opt[0] << std::endl;
299 unsigned short nbag=(training_opt.size()>1)?training_opt.size():bag_opt[0];
300 if(verbose_opt[0]>=1)
301 std::cout <<
"number of bootstrap aggregations: " << nbag << std::endl;
311 bool maskIsVector=
false;
314 extentReader.open(mask_opt[0]);
316 readLayer = extentReader.getDataSource()->GetLayer(0);
317 if(!(extentReader.getExtent(ulx,uly,lrx,lry))){
318 cerr <<
"Error: could not get extent from " << mask_opt[0] << endl;
322 catch(
string errorString){
328 if(active_opt.size()){
329 prob_est_opt[0]=
true;
331 activeWriter.open(active_opt[0],ogrformat_opt[0]);
332 activeWriter.createLayer(active_opt[0],trainingReader.getProjection(),wkbPoint,NULL);
333 activeWriter.copyFields(trainingReader);
335 vector<PosValue> activePoints(nactive_opt[0]);
336 for(
int iactive=0;iactive<activePoints.size();++iactive){
337 activePoints[iactive].value=1.0;
338 activePoints[iactive].posx=0.0;
339 activePoints[iactive].posy=0.0;
342 unsigned int totalSamples=0;
343 unsigned int nactive=0;
344 vector<struct svm_model*>
svm(nbag);
345 vector<struct svm_parameter> param(nbag);
352 if(priors_opt.size()>1){
353 priors.resize(priors_opt.size());
355 for(
short iclass=0;iclass<priors_opt.size();++iclass){
356 priors[iclass]=priors_opt[iclass];
357 normPrior+=priors[iclass];
360 for(
short iclass=0;iclass<priors_opt.size();++iclass)
361 priors[iclass]/=normPrior;
366 if(bstart_opt.size()){
367 if(bend_opt.size()!=bstart_opt.size()){
368 string errorstring=
"Error: options for start and end band indexes must be provided as pairs, missing end band";
372 for(
int ipair=0;ipair<bstart_opt.size();++ipair){
373 if(bend_opt[ipair]<=bstart_opt[ipair]){
374 string errorstring=
"Error: index for end band must be smaller then start band";
377 for(
int iband=bstart_opt[ipair];iband<=bend_opt[ipair];++iband)
378 band_opt.push_back(iband);
383 cerr << error << std::endl;
388 std::sort(band_opt.begin(),band_opt.end());
390 map<string,short> classValueMap;
391 vector<std::string> nameVector;
392 if(classname_opt.size()){
393 assert(classname_opt.size()==classvalue_opt.size());
394 for(
int iclass=0;iclass<classname_opt.size();++iclass)
395 classValueMap[classname_opt[iclass]]=classvalue_opt[iclass];
400 vector< vector<double> > offset(nbag);
401 vector< vector<double> > scale(nbag);
402 map<string,Vector2d<float> > trainingMap;
403 vector< Vector2d<float> > trainingPixels;
404 vector<string> fields;
406 vector<struct svm_problem> prob(nbag);
407 vector<struct svm_node *> x_space(nbag);
409 for(
int ibag=0;ibag<nbag;++ibag){
411 if(ibag<training_opt.size()){
413 trainingPixels.clear();
414 if(verbose_opt[0]>=1)
415 std::cout <<
"reading imageVector file " << training_opt[0] << std::endl;
420 totalSamples=trainingReaderBag.readDataImageOgr(trainingMap,fields,band_opt,label_opt[0],tlayer_opt,verbose_opt[0]);
422 totalSamples=trainingReaderBag.readDataImageOgr(trainingMap,fields,0,0,label_opt[0],tlayer_opt,verbose_opt[0]);
423 if(trainingMap.size()<2){
424 string errorstring=
"Error: could not read at least two classes from training file, did you provide class labels in training sample (see option label)?";
427 trainingReaderBag.close();
430 cerr << error << std::endl;
433 catch(std::exception& e){
434 std::cerr <<
"Error: ";
435 std::cerr << e.what() << std::endl;
436 std::cerr << CPLGetLastErrorMsg() << std::endl;
440 cerr <<
"error caught" << std::endl;
447 std::cout <<
"training pixels: " << std::endl;
448 map<string,Vector2d<float> >::iterator mapit=trainingMap.begin();
449 while(mapit!=trainingMap.end()){
451 if((mapit->second).size()<minSize_opt[0]){
452 trainingMap.erase(mapit);
455 trainingPixels.push_back(mapit->second);
457 std::cout << mapit->first <<
": " << (mapit->second).size() <<
" samples" << std::endl;
461 nclass=trainingPixels.size();
462 if(classname_opt.size())
463 assert(nclass==classname_opt.size());
464 nband=trainingPixels[0][0].size()-2;
467 assert(nclass==trainingPixels.size());
468 assert(nband==trainingPixels[0][0].size()-2);
473 if(balance_opt[0]>0){
474 while(balance_opt.size()<nclass)
475 balance_opt.push_back(balance_opt.back());
479 for(
short iclass=0;iclass<nclass;++iclass){
480 if(trainingPixels[iclass].size()>balance_opt[iclass]){
481 while(trainingPixels[iclass].size()>balance_opt[iclass]){
482 int index=rand()%trainingPixels[iclass].size();
483 trainingPixels[iclass].erase(trainingPixels[iclass].begin()+index);
487 int oldsize=trainingPixels[iclass].size();
488 for(
int isample=trainingPixels[iclass].size();isample<balance_opt[iclass];++isample){
489 int index = rand()%oldsize;
490 trainingPixels[iclass].push_back(trainingPixels[iclass][index]);
493 totalSamples+=trainingPixels[iclass].size();
498 offset[ibag].resize(nband);
499 scale[ibag].resize(nband);
500 if(offset_opt.size()>1)
501 assert(offset_opt.size()==nband);
502 if(scale_opt.size()>1)
503 assert(scale_opt.size()==nband);
504 for(
int iband=0;iband<nband;++iband){
505 if(verbose_opt[0]>=1)
506 std::cout <<
"scaling for band" << iband << std::endl;
507 offset[ibag][iband]=(offset_opt.size()==1)?offset_opt[0]:offset_opt[iband];
508 scale[ibag][iband]=(scale_opt.size()==1)?scale_opt[0]:scale_opt[iband];
510 if(scale[ibag][iband]<=0){
511 float theMin=trainingPixels[0][0][iband+startBand];
512 float theMax=trainingPixels[0][0][iband+startBand];
513 for(
short iclass=0;iclass<nclass;++iclass){
514 for(
int isample=0;isample<trainingPixels[iclass].size();++isample){
515 if(theMin>trainingPixels[iclass][isample][iband+startBand])
516 theMin=trainingPixels[iclass][isample][iband+startBand];
517 if(theMax<trainingPixels[iclass][isample][iband+startBand])
518 theMax=trainingPixels[iclass][isample][iband+startBand];
521 offset[ibag][iband]=theMin+(theMax-theMin)/2.0;
522 scale[ibag][iband]=(theMax-theMin)/2.0;
523 if(verbose_opt[0]>=1){
524 std::cout <<
"Extreme image values for band " << iband <<
": [" << theMin <<
"," << theMax <<
"]" << std::endl;
525 std::cout <<
"Using offset, scale: " << offset[ibag][iband] <<
", " << scale[ibag][iband] << std::endl;
526 std::cout <<
"scaled values for band " << iband <<
": [" << (theMin-offset[ibag][iband])/scale[ibag][iband] <<
"," << (theMax-offset[ibag][iband])/scale[ibag][iband] <<
"]" << std::endl;
532 offset[ibag].resize(nband);
533 scale[ibag].resize(nband);
534 for(
int iband=0;iband<nband;++iband){
535 offset[ibag][iband]=offset[0][iband];
536 scale[ibag][iband]=scale[0][iband];
541 if(priors_opt.size()==1){
542 priors.resize(nclass);
543 for(
short iclass=0;iclass<nclass;++iclass)
544 priors[iclass]=1.0/nclass;
546 assert(priors_opt.size()==1||priors_opt.size()==nclass);
549 while(bagSize_opt.size()<nclass)
550 bagSize_opt.push_back(bagSize_opt.back());
552 if(verbose_opt[0]>=1){
553 std::cout <<
"number of bands: " << nband << std::endl;
554 std::cout <<
"number of classes: " << nclass << std::endl;
555 if(priorimg_opt.empty()){
556 std::cout <<
"priors:";
557 for(
short iclass=0;iclass<nclass;++iclass)
558 std::cout <<
" " << priors[iclass];
559 std::cout << std::endl;
562 map<string,Vector2d<float> >::iterator mapit=trainingMap.begin();
565 while(mapit!=trainingMap.end()){
566 nameVector.push_back(mapit->first);
567 if(classValueMap.size()){
569 if(classValueMap[mapit->first]>0){
570 if(cm.getClassIndex(type2string<short>(classValueMap[mapit->first]))<0){
571 cm.pushBackClassName(type2string<short>(classValueMap[mapit->first]),doSort);
575 std::cerr <<
"Error: names in classname option are not complete, please check names in training vector and make sure classvalue is > 0" << std::endl;
580 cm.pushBackClassName(mapit->first,doSort);
585 std::cerr <<
"Error: did you provide class pairs names (-c) and integer values (-r) for each class in training vector?" << std::endl;
588 if(classname_opt.empty()){
590 for(
int iclass=0;iclass<nclass;++iclass){
592 std::cout << iclass <<
" " << cm.getClass(iclass) <<
" -> " << string2type<short>(cm.getClass(iclass)) << std::endl;
593 classValueMap[cm.getClass(iclass)]=string2type<short>(cm.getClass(iclass));
605 vector< Vector2d<float> > trainingFeatures(nclass);
606 for(
short iclass=0;iclass<nclass;++iclass){
608 if(verbose_opt[0]>=1)
609 std::cout <<
"calculating features for class " << iclass << std::endl;
612 nctraining=(bagSize_opt[iclass]<100)? trainingPixels[iclass].size()/100.0*bagSize_opt[iclass] : trainingPixels[iclass].size();
615 assert(nctraining<=trainingPixels[iclass].size());
617 if(bagSize_opt[iclass]<100)
618 random_shuffle(trainingPixels[iclass].begin(),trainingPixels[iclass].end());
620 std::cout <<
"nctraining (class " << iclass <<
"): " << nctraining << std::endl;
621 trainingFeatures[iclass].resize(nctraining);
622 for(
int isample=0;isample<nctraining;++isample){
624 for(
int iband=0;iband<nband;++iband){
625 float value=trainingPixels[iclass][isample][iband+startBand];
626 trainingFeatures[iclass][isample].push_back((value-offset[ibag][iband])/scale[ibag][iband]);
629 assert(trainingFeatures[iclass].size()==nctraining);
632 unsigned int nFeatures=trainingFeatures[0][0].size();
633 if(verbose_opt[0]>=1)
634 std::cout <<
"number of features: " << nFeatures << std::endl;
635 unsigned int ntraining=0;
636 for(
short iclass=0;iclass<nclass;++iclass)
637 ntraining+=trainingFeatures[iclass].size();
638 if(verbose_opt[0]>=1)
639 std::cout <<
"training size over all classes: " << ntraining << std::endl;
641 prob[ibag].l=ntraining;
642 prob[ibag].y = Malloc(
double,prob[ibag].l);
643 prob[ibag].x = Malloc(
struct svm_node *,prob[ibag].l);
644 x_space[ibag] = Malloc(
struct svm_node,(nFeatures+1)*ntraining);
645 unsigned long int spaceIndex=0;
647 for(
short iclass=0;iclass<nclass;++iclass){
648 for(
int isample=0;isample<trainingFeatures[iclass].size();++isample){
649 prob[ibag].x[lIndex]=&(x_space[ibag][spaceIndex]);
650 for(
int ifeature=0;ifeature<nFeatures;++ifeature){
651 x_space[ibag][spaceIndex].index=ifeature+1;
652 x_space[ibag][spaceIndex].value=trainingFeatures[iclass][isample][ifeature];
655 x_space[ibag][spaceIndex++].index=-1;
656 prob[ibag].y[lIndex]=iclass;
660 assert(lIndex==prob[ibag].l);
663 param[ibag].svm_type = svmMap[svm_type_opt[0]];
664 param[ibag].kernel_type = kernelMap[kernel_type_opt[0]];
665 param[ibag].degree = kernel_degree_opt[0];
666 param[ibag].gamma = (gamma_opt[0]>0)? gamma_opt[0] : 1.0/nFeatures;
667 param[ibag].coef0 = coef0_opt[0];
668 param[ibag].nu = nu_opt[0];
669 param[ibag].cache_size = cache_opt[0];
670 param[ibag].C = ccost_opt[0];
671 param[ibag].eps = epsilon_tol_opt[0];
672 param[ibag].p = epsilon_loss_opt[0];
673 param[ibag].shrinking = (shrinking_opt[0])? 1 : 0;
674 param[ibag].probability = (prob_est_opt[0])? 1 : 0;
675 param[ibag].nr_weight = 0;
676 param[ibag].weight_label = NULL;
677 param[ibag].weight = NULL;
678 param[ibag].verbose=(verbose_opt[0]>1)?
true:
false;
681 std::cout <<
"checking parameters" << std::endl;
682 svm_check_parameter(&prob[ibag],¶m[ibag]);
684 std::cout <<
"parameters ok, training" << std::endl;
685 svm[ibag]=svm_train(&prob[ibag],¶m[ibag]);
687 std::cout <<
"SVM is now trained" << std::endl;
690 std::cout <<
"Cross validating" << std::endl;
691 double *target = Malloc(
double,prob[ibag].l);
692 svm_cross_validation(&prob[ibag],¶m[ibag],cv_opt[0],target);
693 assert(param[ibag].svm_type != EPSILON_SVR&¶m[ibag].svm_type != NU_SVR);
695 for(
int i=0;i<prob[ibag].l;i++){
696 string refClassName=nameVector[prob[ibag].y[i]];
697 string className=nameVector[target[i]];
698 if(classValueMap.size())
699 cm.incrementResult(type2string<short>(classValueMap[refClassName]),type2string<short>(classValueMap[className]),1.0/nbag);
701 cm.incrementResult(cm.getClass(prob[ibag].y[i]),cm.getClass(target[i]),1.0/nbag);
710 assert(cm.nReference());
711 cm.setFormat(cmformat_opt[0]);
712 cm.reportSE95(
false);
713 std::cout << cm << std::endl;
732 if(input_opt.empty())
735 const char* pszMessage;
736 void* pProgressArg=NULL;
737 GDALProgressFunc pfnProgress=GDALTermProgress;
740 pfnProgress(progress,pszMessage,pProgressArg);
742 bool inputIsRaster=
false;
745 imgReaderOgr.open(input_opt[0]);
746 imgReaderOgr.close();
748 catch(
string errorString){
754 for(
int ivalidation=0;ivalidation<input_opt.size();++ivalidation){
755 if(output_opt.size())
756 assert(output_opt.size()==input_opt.size());
758 std::cout <<
"opening img reader " << input_opt[ivalidation] << std::endl;
759 imgReaderOgr.open(input_opt[ivalidation]);
762 if(output_opt.size()){
764 std::cout <<
"opening img writer and copying fields from img reader" << output_opt[ivalidation] << std::endl;
765 imgWriterOgr.open(output_opt[ivalidation],imgReaderOgr);
768 cout <<
"number of layers in input ogr file: " << imgReaderOgr.getLayerCount() << endl;
769 for(
int ilayer=0;ilayer<imgReaderOgr.getLayerCount();++ilayer){
771 cout <<
"processing input layer " << ilayer << endl;
772 if(output_opt.size()){
774 std::cout <<
"creating field class" << std::endl;
775 if(classValueMap.size())
776 imgWriterOgr.createField(
"class",OFTInteger,ilayer);
778 imgWriterOgr.createField(
"class",OFTString,ilayer);
780 unsigned int nFeatures=imgReaderOgr.getFeatureCount(ilayer);
781 unsigned int ifeature=0;
783 pfnProgress(progress,pszMessage,pProgressArg);
784 OGRFeature *poFeature;
785 while( (poFeature = imgReaderOgr.getLayer(ilayer)->GetNextFeature()) != NULL ){
787 std::cout <<
"feature " << ifeature << std::endl;
788 if( poFeature == NULL ){
789 cout <<
"Warning: could not read feature " << ifeature <<
" in layer " << imgReaderOgr.getLayerName(ilayer) << endl;
792 OGRFeature *poDstFeature = NULL;
793 if(output_opt.size()){
794 poDstFeature=imgWriterOgr.createFeature(ilayer);
795 if( poDstFeature->SetFrom( poFeature, TRUE ) != OGRERR_NONE ){
796 CPLError( CE_Failure, CPLE_AppDefined,
797 "Unable to translate feature %d from layer %s.\n",
798 poFeature->GetFID(), imgWriterOgr.getLayerName(ilayer).c_str() );
799 OGRFeature::DestroyFeature( poFeature );
800 OGRFeature::DestroyFeature( poDstFeature );
803 vector<float> validationPixel;
804 vector<float> validationFeature;
806 imgReaderOgr.readData(validationPixel,OFTReal,fields,poFeature,ilayer);
807 assert(validationPixel.size()==nband);
808 vector<float> probOut(nclass);
809 for(
short iclass=0;iclass<nclass;++iclass)
811 for(
int ibag=0;ibag<nbag;++ibag){
812 for(
int iband=0;iband<nband;++iband){
813 validationFeature.push_back((validationPixel[iband]-offset[ibag][iband])/scale[ibag][iband]);
814 if(verbose_opt[0]==2)
815 std::cout <<
" " << validationFeature.back();
817 if(verbose_opt[0]==2)
818 std::cout << std::endl;
819 vector<double> result(nclass);
821 x = (
struct svm_node *) malloc((validationFeature.size()+1)*
sizeof(
struct svm_node));
822 for(
int i=0;i<validationFeature.size();++i){
824 x[i].value=validationFeature[i];
827 x[validationFeature.size()].index=-1;
828 double predict_label=0;
829 if(!prob_est_opt[0]){
830 predict_label = svm_predict(
svm[ibag],x);
831 for(
short iclass=0;iclass<nclass;++iclass){
832 if(iclass==static_cast<short>(predict_label))
839 assert(svm_check_probability_model(
svm[ibag]));
840 predict_label = svm_predict_probability(
svm[ibag],x,&(result[0]));
842 if(verbose_opt[0]>1){
843 std::cout <<
"predict_label: " << predict_label << std::endl;
844 for(
int iclass=0;iclass<result.size();++iclass)
845 std::cout << result[iclass] <<
" ";
846 std::cout << std::endl;
850 for(
short iclass=0;iclass<nclass;++iclass){
854 probOut[iclass]+=result[iclass]*priors[iclass];
857 probOut[iclass]*=pow(static_cast<float>(priors[iclass]),static_cast<float>(1.0-nbag)/nbag)*result[iclass];
860 if(priors[iclass]*result[iclass]>probOut[iclass])
861 probOut[iclass]=priors[iclass]*result[iclass];
871 string classOut=
"Unclassified";
872 for(
short iclass=0;iclass<nclass;++iclass){
874 std::cout << probOut[iclass] <<
" ";
875 if(probOut[iclass]>maxBag){
876 maxBag=probOut[iclass];
877 classOut=nameVector[iclass];
881 if(verbose_opt[0]>1){
882 if(classValueMap.size())
883 std::cout <<
"->" << classValueMap[classOut] << std::endl;
885 std::cout <<
"->" << classOut << std::endl;
887 if(output_opt.size()){
888 if(classValueMap.size())
889 poDstFeature->SetField(
"class",classValueMap[classOut]);
891 poDstFeature->SetField(
"class",classOut.c_str());
892 poDstFeature->SetFID( poFeature->GetFID() );
894 int labelIndex=poFeature->GetFieldIndex(label_opt[0].c_str());
896 string classRef=poFeature->GetFieldAsString(labelIndex);
898 if(classValueMap.size())
899 cm.incrementResult(type2string<short>(classValueMap[classRef]),type2string<short>(classValueMap[classOut]),1);
901 cm.incrementResult(classRef,classOut,1);
905 if(output_opt.size()){
906 if(imgWriterOgr.createFeature(poDstFeature,ilayer) != OGRERR_NONE){
907 CPLError( CE_Failure, CPLE_AppDefined,
908 "Unable to translate feature %d from layer %s.\n",
909 poFeature->GetFID(), imgWriterOgr.getLayerName(ilayer).c_str() );
910 OGRFeature::DestroyFeature( poDstFeature );
911 OGRFeature::DestroyFeature( poDstFeature );
916 progress=
static_cast<float>(ifeature+1.0)/nFeatures;
917 pfnProgress(progress,pszMessage,pProgressArg);
919 OGRFeature::DestroyFeature( poFeature );
920 OGRFeature::DestroyFeature( poDstFeature );
923 imgReaderOgr.close();
924 if(output_opt.size())
925 imgWriterOgr.close();
928 std::cout << cm << std::endl;
929 cout <<
"class #samples userAcc prodAcc" << endl;
936 for(
short iclass=0;iclass<cm.nClasses();++iclass){
937 dua=cm.ua_pct(cm.getClass(iclass),&se95_ua);
938 dpa=cm.pa_pct(cm.getClass(iclass),&se95_pa);
939 cout << cm.getClass(iclass) <<
" " << cm.nReference(cm.getClass(iclass)) <<
" " << dua <<
" (" << se95_ua <<
")" <<
" " << dpa <<
" (" << se95_pa <<
")" << endl;
941 std::cout <<
"Kappa: " << cm.kappa() << std::endl;
943 std::cout <<
"Overall Accuracy: " << 100*doa <<
" (" << 100*se95_oa <<
")" << std::endl;
947 if(active_opt.size())
948 activeWriter.close();
950 catch(
string errorString){
951 std::cerr <<
"Error: errorString" << std::endl;
954 for(
int ibag=0;ibag<nbag;++ibag){
956 svm_destroy_param(¶m[ibag]);
960 svm_free_and_destroy_model(&(
svm[ibag]));
throw this class when syntax error in command line option