/** * @file NegativeFactory.cpp * @brief obtain negative examples from some images * @author Erik Rodner * @date 11/13/2008 */ #include #include "NegativeFactory.h" using namespace OBJREC; using namespace std; using namespace NICE; NegativeFactory::NegativeFactory() { } NegativeFactory::~NegativeFactory() { } void NegativeFactory::createNegativesFromText ( Examples & examples, vector & cexamples, const std::string & filename, ImageFeatures & imgf, int negativeClassDST ) { ifstream ifs ( filename.c_str(), ios::in ); if ( ! ifs.good() ) { fprintf (stderr, "Error reading %s\n", filename.c_str() ); exit(-1); } long int count = 0; // refactor-nice.pl: check this substitution // old: string imgfn; std::string imgfn; int xi, yi, xa, ya; map cexamples_map; double confidence = 1.0; while ( ! ifs.eof() ) { if ( !(ifs >> imgfn) ) break; if ( !(ifs >> confidence) ) break; if ( !(ifs >> xi) ) break; if ( !(ifs >> yi) ) break; if ( !(ifs >> xa) ) break; if ( !(ifs >> ya) ) break; map::const_iterator i = cexamples_map.find ( imgfn ); CachedExample *ce = NULL; if ( i == cexamples_map.end() ) { fprintf (stderr, "Loading negative image: %s\n", imgfn.c_str() ); ce = new CachedExample ( imgfn ); imgf.fillExample ( ce ); cexamples.push_back ( ce ); cexamples_map.insert ( pair ( imgfn, ce ) ); } else { ce = i->second; } int xsize; int ysize; ce->getImageSize ( xsize, ysize ); int x = (xi+xa) / 2; int y = (yi+ya) / 2; int width = xa - xi; int height = ya - yi; Example pce ( ce, x, y, width, height ); examples.push_back ( pair ( negativeClassDST, pce ) ); count++; } ifs.close (); fprintf (stderr, "%ld negative examples loaded..\n", count ); } void NegativeFactory::createNegativesExhaustiveSearch ( Examples & examples, vector & cexamples, const LabeledSet *ls, ImageFeatures & imgf, int examplesPerImage, int negativeClassSRC, int negativeClassDST, FeaturePoolClassifier *fpc, double & falsePositiveEstimate, const VVector & bb, int subsample ) { falsePositiveEstimate = 0.0; int noImages = 0; LOOP_ALL_S ( (*ls) ) { EACH_S ( classno, filename ); if ( classno != negativeClassSRC ) continue; long rejected = 0; fprintf (stderr, "Loading negative image: %s\n", filename.c_str() ); CachedExample *ce = new CachedExample ( filename ); cexamples.push_back ( ce ); imgf.fillExample ( ce ); int xsize; int ysize; ce->getImageSize ( xsize, ysize ); long k = 0; assert ( bb.size() > 0 ); assert ( fpc != NULL ); for ( int i = 0 ; i < (int)bb.size() ; i++ ) { // refactor-nice.pl: check this substitution // old: const Vector & box = bb[i]; const NICE::Vector & box = bb[i]; int width = (int)box[0]; int height = (int)box[1]; assert ( width > 0.0 ); assert ( height > 0.0 ); if ( width >= xsize ) width = xsize - 3; if ( height >= ysize ) height = ysize - 3; for ( int y = height/2 ; y < ysize - height/2 ; y+=subsample ) { for ( int x = width/2 ; x < xsize - width/2 ; x+=subsample ) { Example pce ( ce, x, y, width, height ); ClassificationResult r = fpc->classify(pce); if ( r.classno == negativeClassDST ) { rejected++; continue; // already correctly classified } examples.push_back ( pair ( negativeClassDST, pce ) ); k++; } } } fprintf (stderr, "Image processed: %s (rejected %ld/obtained %ld/%f)\n", filename.c_str(), rejected, k, k/(double)(rejected+k)); falsePositiveEstimate += k / (double)(rejected+k); noImages++; } falsePositiveEstimate /= noImages; } void NegativeFactory::createNegatives ( Examples & examples, vector & cexamples, const LabeledSet *ls, ImageFeatures & imgf, int noImages, int examplesPerImage, int negativeClassSRC, int negativeClassDST, FeaturePoolClassifier *fpc, double & falsePositiveEstimate, const VVector & bb ) { int maxRejected = 1000*examplesPerImage; srand(time(NULL)); LabeledSet randSel (true); LabeledSet dummy (true); map selection; assert ( ls->count(negativeClassSRC) >= noImages ); selection[negativeClassSRC] = noImages; LabeledSetSelection::selectRandom ( selection, *ls, randSel, dummy ); falsePositiveEstimate = 0.0; #define SAVE_RANDOM_POSITIONS #ifdef SAVE_RANDOM_POSITIONS ofstream ofs ( "/tmp/randomlocations.txt", ios::out ); if ( ! ofs.good() ) { fprintf (stderr, "Error writing to /tmp/randomlocations.txt.\n" ); exit(-1); } #endif LOOP_ALL_S ( randSel ) { EACH_S ( classno, filename ); long rejected = 0; fprintf (stderr, "Loading negative image: %s\n", filename.c_str() ); CachedExample *ce = new CachedExample ( filename ); cexamples.push_back ( ce ); imgf.fillExample ( ce ); int xsize; int ysize; ce->getImageSize ( xsize, ysize ); long k = 0; bool usebb = (bb.size() > 0); #ifdef CSFPNegatives_DISTRIBUTION_ANALYSIS NICE::Image img (xsize, ysize); img.set(0); #endif while( (k < examplesPerImage) && (rejected < maxRejected) ) { int width, height; if ( ! usebb ) { width = rand() % (xsize/3) + 20; height = rand() % (ysize/3) + 20; } else { const NICE::Vector & x = bb[ rand() % bb.size() ]; width = (int)x[0]; height = (int)x[1]; assert ( width > 0.0 ); assert ( height > 0.0 ); if ( width >= xsize ) width = xsize - 3; if ( height >= ysize ) height = ysize - 3; } int x = rand() % (xsize-width) + width/2; int y = rand() % (ysize-height) + height/2; Example pce ( ce, x, y, width, height ); if ( fpc != NULL ) { ClassificationResult r = fpc->classify(pce); if ( r.classno == negativeClassDST ) { rejected++; continue; // already correctly classified } } #ifdef SAVE_RANDOM_POSITIONS ofs << filename << " 1.0 "; int xi = x - width/2; int xa = x + width/2; int yi = y - height/2; int ya = y + height/2; ofs << xi << " " << yi << " " << xa << " " << ya << endl; #endif examples.push_back ( pair ( negativeClassDST, pce ) ); k++; } fprintf (stderr, "Image processed: %s (rejected %ld/obtained %ld/%f)\n", filename.c_str(), rejected, k, k/(double)(rejected+k)); falsePositiveEstimate += k / (double)(rejected+k); } #ifdef SAVE_RANDOM_POSITIONS ofs.close(); #endif falsePositiveEstimate /= noImages; }