/** * @file ConvolutionFeature.cpp * @brief convolutional feature * @author Sven Sickert * @date 10/13/2008 */ #include #include "ConvolutionFeature.h" #include "vislearning/cbaselib/FeaturePool.h" using namespace OBJREC; using namespace NICE; /* Convolutional feature consists of shift parameter beta[0] and the convolutional mask, which is stored in the rest of the parameter vector beta */ /** simple constructor */ ConvolutionFeature::ConvolutionFeature ( ) { window_size_x = 15; window_size_y = 15; isColor = false; initializeParameterVector(); } /** alternative constructor */ ConvolutionFeature::ConvolutionFeature ( const int wsize_x, const int wsize_y, const bool color ) { window_size_x = wsize_x; window_size_y = wsize_y; isColor = color; initializeParameterVector(); } /** default constructor */ ConvolutionFeature::ConvolutionFeature ( const Config *conf ) { std::string section = "ConvolutionFeature"; window_size_x = conf->gI ( section, "window_size_x", 15 ); window_size_y = conf->gI ( section, "window_size_y", 15 ); isColor = conf->gB ( section, "is_color", false ); initializeParameterVector(); } /** copy constructor */ ConvolutionFeature::ConvolutionFeature ( const ConvolutionFeature *confFeat ) { window_size_x = confFeat->window_size_x; window_size_y = confFeat->window_size_y; betaLength = confFeat->betaLength; isColor = confFeat->isColor; beta = new NICE::Vector( betaLength, 0.0 ); int i = 0; for ( NICE::Vector::iterator it = confFeat->beta->begin(); it != confFeat->beta->end(); ++it, i++ ) { beta[i] = *it; } } /** simple destructor */ ConvolutionFeature::~ConvolutionFeature ( ) { } /** (re)initialize parameter vector */ void ConvolutionFeature::initializeParameterVector() { if (window_size_x > 0 && window_size_y > 0) { if (isColor) betaLength = 3*window_size_x*window_size_y + 1; else betaLength = window_size_x*window_size_y + 1; beta = new NICE::Vector( betaLength, (1.0/(double)(betaLength-1) ) ); beta[0] = 1; } else std::cerr << "ConvolutionFeature::initializeVector: Size of window is Zero! Could not initialize..." << std::endl; } /** return parameter vector */ NICE::Vector ConvolutionFeature::getParameterVector() const { NICE::Vector res = (*this->beta); return res; } /** return feature vector */ NICE::Vector ConvolutionFeature::getFeatureVector( const Example *example ) const { NICE::Vector vec(betaLength, 1.0); NICE::MultiChannelImageT * img = NULL; if (isColor) img = & example->ce->getIChannel( CachedExample::I_COLOR ); else img = & example->ce->getIChannel( CachedExample::I_GRAYVALUES ); int xsize, ysize, x, y; example->ce->getImageSize( xsize, ysize ); x = example->x; y = example->y; int halfwsx = std::floor ( window_size_x / 2 ); int halfwsy = std::floor ( window_size_y / 2 ); int numChannels = img->channels(); int k = 1; for ( int c = 0; c < numChannels; c++ ) for ( int v = -halfwsy; v <= halfwsy; v++ ) for ( int u = -halfwsx; u <= halfwsx; u++, k++ ) { int uu = u; int vv = v; if (x+u < 0 || x+u >= xsize) uu=-u; if (y+v < 0 || y+v >= ysize) vv=-v; if ( x+uu > 0 && x+uu < xsize && y+vv > 0 && y+vv < ysize && k < vec.size() ) { vec[k] = img->get(x+uu,y+vv,c); } } return vec; } /** return length of parameter vector */ int ConvolutionFeature::getParameterLength() const { return betaLength; } /** set parameter vector */ void ConvolutionFeature::setParameterVector( const Vector & vec ) { if ( beta->size() == vec.size() ) { int i = 0; for ( NICE::Vector::iterator it = beta->begin(); it != beta->end(); ++it, i++ ) { *it = vec[i]; } beta->normalizeL2(); } else std::cerr << "ConvolutionFeature::setParameterVector: Vector sizes do not match!" << " expected: " << beta->size() << ", got: " << vec.size() << std::endl; } /** return feature value */ double ConvolutionFeature::val ( const Example *example ) const { double val1 = 0.0; // is parameter vector and image data available? if (beta == NULL) { std::cerr << "ConvolutionalFeature::val: Missing parameter vector!" << std::endl; return val1; } NICE::MultiChannelImageT * img = NULL; if (isColor) img = & example->ce->getIChannel( CachedExample::I_COLOR ); else img = & example->ce->getIChannel( CachedExample::I_GRAYVALUES ); int xsize, ysize, x, y; example->ce->getImageSize( xsize, ysize ); x = example->x; y = example->y; int halfwsx = std::floor ( window_size_x / 2 ); int halfwsy = std::floor ( window_size_y / 2 ); int numChannels = img->channels(); int k = 1; for ( int c = 0; c < numChannels; c++ ) for ( int v = -halfwsy; v <= halfwsy; v++ ) for ( int u = -halfwsx; u <= halfwsx; u++, k++ ) { int uu = u; int vv = v; if (x+u < 0 || x+u >= xsize) uu=-u; if (y+v < 0 || y+v >= ysize) vv=-v; if ( x+uu > 0 && x+uu < xsize && y+vv > 0 && y+vv < ysize && k < beta->size() ) { val1 += (double)img->get(x+uu,y+vv,c) * beta->operator [](k); } } return val1; } /** creature feature pool */ void ConvolutionFeature::explode ( FeaturePool &featurePool, bool variableWindow ) const { ConvolutionFeature *f = new ConvolutionFeature ( this->window_size_x, this->window_size_y, this->isColor ); featurePool.addFeature(f); } /** clone current feature */ Feature *ConvolutionFeature::clone ( ) const { ConvolutionFeature *f = new ConvolutionFeature ( this->window_size_x, this->window_size_y, this->isColor ); f->setParameterVector( *beta ); return f; } Feature *ConvolutionFeature::generateFirstParameter () const { return clone(); } void ConvolutionFeature::restore ( std::istream & is, int format ) { is >> window_size_x; is >> window_size_y; is >> betaLength; isColor = false; if ( betaLength > (window_size_x*window_size_y+1) ) isColor = true; beta = new NICE::Vector( betaLength, 1.0 ); for ( NICE::Vector::iterator it = beta->begin(); it != beta->end(); ++it ) is >> *it; } void ConvolutionFeature::store ( std::ostream & os, int format ) const { os << "ConvolutionFeature " << window_size_x << " " << window_size_y << " " << betaLength; for ( NICE::Vector::const_iterator it = beta->begin(); it != beta->end(); ++it ) os << ' ' << *it; } void ConvolutionFeature::clear () { beta->clear(); }