// Beispielhafter Aufruf: BUILD_x86_64/progs/testActiveSemanticSegmentationBinary -config /** * @file testActiveSemanticSegmentationBinary.cpp * @brief test semantic segmentation routines with actively selecting regions for labeling * @author Alexander Freytag * @date 27-02-2013 */ #ifdef NICE_USELIB_OPENMP #include #endif #include "core/basics/Config.h" #include "core/basics/StringTools.h" #include #include #include #include #include #include #include #include "core/image/FilterT.h" #include #include using namespace OBJREC; using namespace NICE; using namespace std; /** test semantic segmentation routines */ int main( int argc, char **argv ) { std::set_terminate( __gnu_cxx::__verbose_terminate_handler ); Config conf( argc, argv ); ResourceStatistics rs; NICE::MatrixT matTemp; std::cerr << "foo " << std::endl; std::cerr << matTemp << std::endl; bool show_result = conf.gB( "debug", "show_results", false ); bool write_results = conf.gB( "debug", "write_results", false ); bool write_results_pascal = conf.gB( "debug", "write_results_pascal", false ); std::string resultdir = conf.gS( "debug", "resultdir", "." ); //how often do we want to iterate between sem-seg and active query? int activeIterations = conf.gI("main", "activeIterations", 1 ); if ( write_results ) { cerr << "Writing Results to " << resultdir << endl; } MultiDataset md( &conf ); const ClassNames & classNames = md.getClassNames( "train" ); string method = conf.gS( "main", "method", "SSCsurka" ); //currently, we only allow SemSegNoveltyBinary, because it implements addNovelExamples() SemSegNoveltyBinary *semseg = NULL; Timer timer; timer.start(); semseg = new SemSegNoveltyBinary( &conf, &md ); timer.stop(); std::cerr << "AL time for training: " << timer.getLast() << std::endl; const LabeledSet *testFiles = md["test"]; std::set forbidden_classes; std::string forbidden_classes_s = conf.gS( "analysis", "forbidden_classesTrain", "" ); classNames.getSelection( forbidden_classes_s, forbidden_classes ); std::set forbidden_classesForActiveLearning; std::string forbidden_classesForActiveLearning_s = conf.gS( "analysis", "forbidden_classesForActiveLearning", "" ); classNames.getSelection( forbidden_classesForActiveLearning_s, forbidden_classesForActiveLearning ); int positiveClass; //check whether we have a single positive class std::string positiveClass_s = conf.gS ( "SemSegNoveltyBinary", "positiveClass", "" ); std::set positiveClassNumberTmp; classNames.getSelection ( positiveClass_s, positiveClassNumberTmp ); switch ( positiveClassNumberTmp.size() ) { case 0: { positiveClass = 0; // std::cerr << "no positive class given, assume 0 as positive class" << std::endl; break; } case 1: { positiveClass = *(positiveClassNumberTmp.begin()); // std::cerr << "positive class will be number" << positiveClass << " with the name: " << positiveClass_s << std::endl; break; } default: { //we specified more than a single positive class. right now, this is not what we are interested in, but //in theory we could also accept this and convert positiveClass into a set of ints of possible positive classes positiveClass = 0; // std::cerr << "no positive class given, assume 0 as positive class" << std::endl; break; } } std::cerr << "number of AL iterations: " << activeIterations << std::endl; for (int iterationCount = 0; iterationCount < activeIterations; iterationCount++) { std::cerr << "SemSeg AL Iteration: " << iterationCount << std::endl; semseg->setIterationCountSuffix(iterationCount); int fileno = 0; std::cerr << "start looping over all files" << std::endl; LOOP_ALL_S( *testFiles ) { EACH_INFO( classno, info ); std::string file = info.img(); NICE::ImageT lm; NICE::MultiChannelImageT probabilities; if ( info.hasLocalizationInfo() ) { const LocalizationResult *l_gt = info.localization(); lm.resize( l_gt->xsize, l_gt->ysize ); //lm.set( 0 ); l_gt->calcLabeledImage( lm, classNames.getBackgroundClass() ); } ((SemanticSegmentation*)semseg)->semanticseg( file, lm, probabilities ); fprintf( stderr, "testSemanticSegmentation: Segmentation finished !\n" ); //ground truth image, needed for updating the confusion matrix //TODO check whether this is really needed, since we computed such a label image already within SemSegNovelty NICE::ImageT lm_gt; if ( info.hasLocalizationInfo() ) { const LocalizationResult *l_gt = info.localization(); lm_gt.resize( l_gt->xsize, l_gt->ysize ); lm_gt.set( 0 ); fprintf( stderr, "testSemanticSegmentation: Generating Labeled NICE::Image (Ground-Truth)\n" ); l_gt->calcLabeledImage( lm_gt, classNames.getBackgroundClass() ); } if ( show_result || write_results ) { NICE::ColorImage orig( file ); NICE::ColorImage rgb; NICE::ColorImage rgb_gt; classNames.labelToRGB( lm, rgb ); classNames.labelToRGB( lm_gt, rgb_gt ); if ( write_results ) { std::stringstream out; std::vector< std::string > myList; StringTools::split ( Globals::getCurrentImgFN (), '/', myList ); out << resultdir << "/" << myList.back(); cerr << "Writing to file " << resultdir << "/"<< myList.back() << endl; std::string noveltyMethodString = conf.gS( "SemSegNoveltyBinary", "noveltyMethod", "gp-variance"); orig.write ( out.str() + "_orig.ppm" ); rgb.write ( out.str() + "_" + noveltyMethodString + "_result_run_" + NICE::intToString(iterationCount) + ".ppm" ); rgb_gt.write ( out.str() + "_groundtruth.ppm" ); } if ( show_result ) { #ifndef NOVISUAL showImage( rgb, "Result" ); showImage( rgb_gt, "Groundtruth" ); showImage( orig, "Input" ); #endif } } fileno++; } //Loop over all test images //********************************************** // EVALUATION // COMPUTE CONFUSION MAT AND FINAL SCORES //********************************************** timer.start(); double score = semseg->getAUCPerformance(); std::cerr << "auc scores of run : " << iterationCount << " : " << score << std::endl; long maxMemory; rs.getMaximumMemory(maxMemory); cerr << "Maximum memory used: " << maxMemory << " KB" << endl; timer.stop(); std::cout << "AL time for evaluation: " << timer.getLastAbsolute() << std::endl; //********************************************** // INCLUDE THE NEW INFORMATION // AND UPDATE THE CLASSIFIER //********************************************** timer.start(); semseg->addNovelExamples(); timer.stop(); std::cout << "AL time for incremental update: " << timer.getLastAbsolute() << std::endl; //alternatively, we could call the destructor of semseg, and create it again, which does the same thing // (add new features, save the classifier, re-read it after initialization) //BUT this would not setup the forbidden and known classes properly!!! We should fix that! const Examples * novelExamples = semseg->getNovelExamples(); // std::cerr << " ==================================== " << std::endl; // std::cerr << "new examples to be added: " << std::endl; // for ( uint i = 0 ; i < novelExamples->size() ; i++ ) // { // std::cerr << (*novelExamples)[i].first << " "; (*novelExamples)[i].second.store(std::cerr); // } // std::cerr << " ==================================== " << std::endl; //check which classes will be added using the features from the novel region std::set newClassNumbers; newClassNumbers.clear(); //just to be sure for ( uint i = 0 ; i < novelExamples->size() ; i++ ) { if (newClassNumbers.find( (*novelExamples)[i].first /* classNumber*/) == newClassNumbers.end() ) { newClassNumbers.insert( (*novelExamples)[i].first ); } } //accept the new classes as valid information for (std::set::const_iterator clNoIt = newClassNumbers.begin(); clNoIt != newClassNumbers.end(); clNoIt++) { if ( forbidden_classes.find ( *clNoIt ) != forbidden_classes.end() ) { forbidden_classes.erase(*clNoIt); } } std::cerr << "iteration finished - start the next round" << std::endl; } //iterationCount delete semseg; return 0; }