/** * @file EOHFeature.cpp * @brief edge orientation histograms (Levi and Weiss 2004) * @author Erik Rodner * @date 05/07/2008 */ #include #include "EOHFeature.h" #include "vislearning/cbaselib/FeaturePool.h" using namespace OBJREC; const double epsilon = 10e-8; using namespace std; using namespace NICE; /** simple constructor */ EOHFeature::EOHFeature ( const Config *conf ) { window_size_x = conf->gI ( "EOHFeature", "window_size_x", 21 ); window_size_y = conf->gI ( "EOHFeature", "window_size_y", 21 ); scaleStep = conf->gD ( "EOHFeature", "scale_step", sqrt ( 2 ) ); numScales = conf->gI ( "EOHFeature", "num_scales", 5 ); numBins = conf->gI ( "EOHFeature", "num_bins", 9 ); bin = 0; bin2 = 0; type = EOH_VALUE; } /** simple destructor */ EOHFeature::~EOHFeature() { } double EOHFeature::val ( const Example *example ) const { const NICE::MultiChannelImageT & img = example->ce->getDChannel ( CachedExample::D_INTEGRALEOH ); int xsize; int ysize; example->ce->getImageSize ( xsize, ysize ); int tm_xsize = img.width(); int tm_ysize = img.height(); int wsx2, wsy2; int xx, yy; int exwidth = example->width; if ( exwidth == 0 ) { wsx2 = window_size_x * tm_xsize / ( 2 * xsize ); wsy2 = window_size_y * tm_ysize / ( 2 * ysize ); } else { int exheight = example->height; wsx2 = exwidth * tm_xsize / ( 2 * xsize ); wsy2 = exheight * tm_ysize / ( 2 * ysize ); } xx = ( example->x ) * tm_xsize / xsize; yy = ( example->y ) * tm_ysize / ysize; int xtl = xx - wsx2; int ytl = yy - wsy2; int xrb = xx + wsx2; int yrb = yy + wsy2; #define BOUND(x,min,max) (((x)<(min))?(min):((x)>(max)?(max):(x))) xtl = BOUND ( xtl, 0, tm_xsize - 1 ); ytl = BOUND ( ytl, 0, tm_ysize - 1 ); xrb = BOUND ( xrb, 0, tm_xsize - 1 ); yrb = BOUND ( yrb, 0, tm_ysize - 1 ); #undef BOUND double A, B, C, D; assert ( bin < ( int ) img.channels() ); A = img.get ( xtl, ytl, bin ); B = img.get ( xrb, ytl, bin ); C = img.get ( xtl, yrb, bin ); D = img.get ( xrb, yrb, bin ); if ( type == EOH_VALUE ) { int area = ( xrb - xtl ) * ( yrb - ytl ); if ( area == 0 ) return 0.0; else { /* A B C D */ double value = ( D - B - C + A ) / area; return value; } } else if ( type == EOH_RATIO ) { assert ( bin2 < ( int ) img.channels() ); double val1 = ( D - B - C + A ); A = img.get ( xtl, ytl, bin2 ); B = img.get ( xrb, ytl, bin2 ); C = img.get ( xtl, yrb, bin2 ); D = img.get ( xrb, yrb, bin2 ); double val2 = ( D - B - C + A ); return ( val1 + epsilon ) / ( val2 + epsilon ); } else if ( type == EOH_DOMINANT_ORIENTATION ) { double val1 = ( D - B - C + A ); double sum = val1; for ( int b = 0 ; b < ( int ) img.channels() ; b++ ) { if ( b == bin ) continue; A = img.get ( xtl, ytl, b ); B = img.get ( xrb, ytl, b ); C = img.get ( xtl, yrb, b ); D = img.get ( xrb, yrb, b ); sum += ( D - B - C + A ); } return ( val1 + epsilon ) / ( sum + epsilon ); } assert ( 1 == 0 ); } void EOHFeature::explode ( FeaturePool & featurePool, bool variableWindow ) const { int nScales = ( variableWindow ? numScales : 1 ); for ( int i = 0 ; i < nScales ; i++ ) { int wsy = window_size_y; int wsx = window_size_x; for ( int _type = 0 ; _type < EOH_NUMTYPES; _type++ ) { if ( ( _type == EOH_VALUE ) || ( _type == EOH_DOMINANT_ORIENTATION ) ) { for ( int _bin = 0 ; _bin < numBins ; _bin++ ) { EOHFeature *f = new EOHFeature(); f->window_size_x = wsx; f->window_size_y = wsy; f->bin = _bin; f->type = _type; featurePool.addFeature ( f, 1.0 / ( EOH_NUMTYPES * numBins * nScales ) ); } } if ( ( _type == EOH_RATIO ) ) { for ( int _bin = 0 ; _bin < numBins ; _bin++ ) { for ( int _bin2 = 0 ; _bin2 < numBins ; _bin2++ ) { if ( bin == bin2 ) continue; EOHFeature *f = new EOHFeature(); f->window_size_x = wsx; f->window_size_y = wsy; f->bin = _bin; f->bin2 = _bin2; f->type = _type; featurePool.addFeature ( f, 1.0 / ( EOH_NUMTYPES * ( numBins - 1 ) * numBins * nScales ) ); } } } } wsx = ( int ) ( scaleStep * wsx ); wsy = ( int ) ( scaleStep * wsy ); } } Feature *EOHFeature::clone() const { EOHFeature *f = new EOHFeature(); f->window_size_x = window_size_x; f->window_size_y = window_size_y; f->bin = bin; f->bin2 = bin2; f->type = type; return f; } Feature *EOHFeature::generateFirstParameter () const { return clone(); } void EOHFeature::restore ( istream & is, int format ) { is >> window_size_x; is >> window_size_y; is >> type; is >> bin; is >> bin2; } void EOHFeature::store ( ostream & os, int format ) const { os << "EOHFEATURE " << window_size_x << " " << window_size_y << " " << type << " " << bin << " " << bin2; } void EOHFeature::clear () { }