/** * @file LFonHSG.cpp * @brief Implementation of the LocalFeatureHSG.h. See description there. * @author Eric Bach, Alexander Freytag * @date 26.10.2011 */ /* LocalFeatureHSG Include */ #include "vislearning/features/localfeatures/LFonHSG.h" using namespace std; using namespace NICE; using namespace OBJREC; #ifdef NICE_USELIB_BOOST using namespace boost; #endif ///////////////////// ///////////////////// ///////////////////// // PROTECTED METHODS ///////////////////// ///////////////////// ///////////////// void LFonHSG::convertScalesStringToScaleList ( ) { if ( this->debug ) { clog << "[log] LocalFeatureHSG::LocalFeatureHSG" << std::endl; clog << "[log] try to parse the 'scales-string': " << this->scales << " -> "; } // the scales are seperated by '+', like in the Van de Sande implementation char separator = '+'; #ifdef NICE_USELIB_BOOST typedef tokenizer > tokenizer; char_separator sep (&separator); tokenizer tokens (scales, sep); // parse the string into tokens for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) { if ( this->debug ) clog << *tok_iter << " "; this->scalesV.push_back(StringTools::convert(*tok_iter)); } #else // standard std::vector temp; StringTools::split (scales, separator, temp); for ( std::vector::const_iterator it = temp.begin(); it != temp.end(); ++it) { if ( this->debug ) clog << *it << " "; this->scalesV.push_back(StringTools::convert(*it)); } #endif if ( this->debug ) { clog << std::endl; } } ///////////////////// ///////////////////// ///////////////////// // CONSTRUCTORS / DESTRUCTORS ///////////////////// ///////////////////// ///////////////// LFonHSG::LFonHSG () : LocalFeatureRepresentation () { this->debug = false; this->sampleScaling = 50; this->scales = "1"; /** parse scales string **/ this->convertScalesStringToScaleList(); this->lf = NULL; } LFonHSG::LFonHSG ( const NICE::Config * _conf, const std::string _confSection) { this->initFromConfig( _conf, _confSection ); } LFonHSG::~LFonHSG() { /** free memory of descriptors **/ // don't waste memory if ( this->lf != NULL ) { delete this->lf; this->lf = NULL; } } void OBJREC::LFonHSG::initFromConfig(const NICE::Config * _conf, const std::string & _confSection) { this->debug = _conf->gB (_confSection, "debug", false); this->sampleScaling = _conf->gI (_confSection, "sample_scaling", 50); this->scales = _conf->gS (_confSection, "scales" , "1"); this->lf = NULL; this->lf = OBJREC::GenericLocalFeatureSelection::selectLocalFeature (_conf, _confSection /*TODO check whether it is useful to hand over the confSection string here*/); /** parse scales string **/ this->convertScalesStringToScaleList(); } ///////////////////// ///////////////////// ///////////////////// // FEATURE STUFF ///////////////////// ///////////////////// ///////////////// int LFonHSG::getDescSize() const { return lf->getDescSize(); } void LFonHSG::getPositionsOnHSG (const unsigned int imageWidth, const unsigned int imageHeight, VVector& positions) const { if (sampleScaling < 1) { std::cerr << "[err] sample-scaling (" << sampleScaling << ") musst be larger the 0!" << std::endl; return; } if ( this->debug ) clog << "[log] LocalFeatureHSG::getPositionsOnHSG calculate "; bool oddRow = true; NICE::Vector pos (4); /** we have to calculate the koo. for every different scale **/ for ( std::vector::const_iterator it = this->scalesV.begin(); it != this->scalesV.end(); ++it) { oddRow = true; for (unsigned int j = sampleScaling; j <= (imageHeight - sampleScaling); j += sampleScaling) { for ( unsigned int i = (oddRow ? sampleScaling + sampleScaling / 2 : sampleScaling); i <= (imageWidth - sampleScaling); i += sampleScaling ) { pos[ 0 ] = i; pos[ 1 ] = j; pos[ 2 ] = *it; pos[ 3 ] = 0; positions.push_back (pos); } oddRow = !oddRow; } } } int LFonHSG::extractFeatures (const NICE::ColorImage & cimg, VVector & features, VVector & positions) const { /** To get the keypoint descriptor, we need the positions of the keypoints. **/ this->getPositionsOnHSG (cimg.width(), cimg.height(), positions); /** calulate the descriptor-values **/ return lf->getDescriptors (cimg, positions, features); } int LFonHSG::extractFeatures (const NICE::Image & img, VVector & features, VVector & positions) const { /** To get the keypoint descriptor, we need the positions of the keypoints. **/ this->getPositionsOnHSG (img.width(), img.height(), positions); /** calculate the descriptor-values **/ return lf->getDescriptors (img, positions, features); } void LFonHSG::visualizeFeatures (NICE::Image & mark, const VVector & positions, size_t color) const { // TODO: Implementierung des gewaehlten Descriptortyps aufrufen. throw NICE::Exception( "LFonHSG::visualizeFeatures currently not implemented." ); } ///////////////////// INTERFACE PERSISTENT ///////////////////// // interface specific methods for store and restore ///////////////////// INTERFACE PERSISTENT ///////////////////// void LFonHSG::restore ( std::istream & is, int format ) { //delete everything we knew so far... this->clear(); if ( is.good() ) { std::string tmp; is >> tmp; //class name if ( ! this->isStartTag( tmp, "LFonHSG" ) ) { std::cerr << " WARNING - attempt to restore LFonHSG, but start flag " << tmp << " does not match! Aborting... " << std::endl; throw; } bool b_endOfBlock ( false ) ; while ( !b_endOfBlock ) { is >> tmp; // start of block if ( this->isEndTag( tmp, "LFonHSG" ) ) { b_endOfBlock = true; continue; } tmp = this->removeStartTag ( tmp ); if ( tmp.compare("debug") == 0 ) { is >> this->debug; is >> tmp; // end of block tmp = this->removeEndTag ( tmp ); } else if ( tmp.compare("sampleScaling") == 0 ) { is >> this->sampleScaling; is >> tmp; // end of block tmp = this->removeEndTag ( tmp ); } else if ( tmp.compare("scales") == 0 ) { is >> this->scales; is >> tmp; // end of block tmp = this->removeEndTag ( tmp ); } else if ( tmp.compare("scalesV") == 0 ) { is >> tmp; //size: unsigned int ui_scalesVSize; is >> ui_scalesVSize; this->scalesV.clear(); //allocate enough memory this->scalesV.resize( ui_scalesVSize ); std::vector< float >::iterator itScalesV = this->scalesV.begin(); for ( uint tmpIdx = 0; tmpIdx < ui_scalesVSize; tmpIdx++, itScalesV++ ) { is >> *itScalesV; } is >> tmp; // end of block tmp = this->removeEndTag ( tmp ); } else if ( tmp.compare("lf") == 0 ) { OBJREC::GenericLocalFeatureSelection::restoreLocalFeature( this->lf, is ); is >> tmp; // end of block tmp = this->removeEndTag ( tmp ); } else { std::cerr << "WARNING -- unexpected LFonHSG object -- " << tmp << " -- for restoration... aborting" << std::endl; throw; } } } else { std::cerr << "LFonHSG::restore -- InStream not initialized - restoring not possible!" << std::endl; throw; } } void LFonHSG::store ( std::ostream & os, int format ) const { if (os.good()) { // show starting point os << this->createStartTag( "LFonHSG" ) << std::endl; os << this->createStartTag( "debug" ) << std::endl; os << this->debug << std::endl; os << this->createEndTag( "debug" ) << std::endl; os << this->createStartTag( "sampleScaling" ) << std::endl; os << this->sampleScaling << std::endl; os << this->createEndTag( "sampleScaling" ) << std::endl; os << this->createStartTag( "scalesV" ) << std::endl; os << "size: " << this->scalesV.size() << std::endl; for ( std::vector< float >::const_iterator itScalesV = this->scalesV.begin(); itScalesV != this->scalesV.end(); itScalesV++ ) { os << *itScalesV << " "; } os << std::endl; os << this->createEndTag( "scalesV" ) << std::endl; os << this->createStartTag( "lf" ) << std::endl; if ( this->lf != NULL ) { //TODO this might be tricky if lf was not intantiated properly. this->lf->store ( os ); } os << this->createEndTag( "lf" ) << std::endl; // done os << this->createEndTag( "LFonHSG" ) << std::endl; } else { std::cerr << "OutStream not initialized - storing not possible!" << std::endl; } } void LFonHSG::clear () { if ( this->lf != NULL ) { delete this->lf; this->lf = NULL; } }