/** * @file Operation.h * @brief abstract class for any kind of feature extraction from images * @author Björn Fröhlich * @date 24.04.2012 */ #include "core/image/MultiChannelImageT.h" #define BOUND(x,min,max) (((x)<(min))?(min):((x)>(max)?(max):(x))) namespace OBJREC { class Operation; /** * @brief methods for value access **/ enum ValueTypes { RAWFEAT, CONTEXT, SPARSE, NBVALUETYPES }; /** * @brief feature extraction methods **/ enum OperationTypes { MINUS, MINUSABS, ADDITION, ONLY1, INTEGRAL, INTEGRALCENT, BIINTEGRALCENT, HAARHORIZ, HAARVERT, HAARDIAG, HAAR3HORIZ, HAAR3VERT, RELATIVEXPOSITION, RELATIVEYPOSITION, GLOBALFEATS, EQUALITY, NBOPERATIONS }; /** * @brief node class for context tree **/ class TreeNode { public: /** left child node */ int left; /** right child node */ int right; /** position of feat for decision */ Operation *feat; /** decision stamp */ double decision; /** is the node a leaf or not */ bool isleaf; /** distribution in current node */ std::vector dist; /** depth of the node in the tree */ int depth; /** how many pixels are in this node */ int featcounter; /** unique number */ int nodeNumber; /** simple constructor */ TreeNode() : left ( -1 ), right ( -1 ), feat ( NULL ), decision ( -1.0 ), isleaf ( false ) {} /** standard constructor */ TreeNode ( int _left, int _right, Operation *_feat, double _decision ) : left ( _left ), right ( _right ), feat ( _feat ), decision ( _decision ), isleaf ( false ) {} }; /** * @brief holds all necessary information for feature extraction **/ struct Features { /** simple features like RGB values */ NICE::MultiChannelImageT *feats; /** current leaf position for each pixel and each tree */ NICE::MultiChannelImageT *cfeats; /** amount of trees */ int cTree; /** tree nodes */ std::vector *tree; /** probabilities for each region */ std::vector > *rProbs; }; /** * @brief abstract values access class **/ class ValueAccess { public: /** * @brief extract value on specific position x,y and channel; * * @param feats see struct Features * @param x position of feature * @param y position of feature * @param channel position of feature * @return double value **/ virtual double getVal ( const Features &feats, const int &x, const int &y, const int &channel ) = 0; /** * @brief print some infos about feature type * * @return string feature type **/ virtual std::string writeInfos() = 0; /** * @brief get feature type * * @return feature type **/ virtual ValueTypes getType() = 0; }; /** * @brief simple MultiChannelImageT access **/ class MCImageAccess: public ValueAccess { public: /** * @brief extract value on specific position x,y and channel; * * @param feats see struct Features * @param x position of feature * @param y position of feature * @param channel position of feature * @return double value **/ virtual double getVal ( const Features &feats, const int &x, const int &y, const int &channel ) { return feats.feats->get ( x, y, channel ); } /** * @brief print some infos about feature type * * @return string feature type **/ virtual std::string writeInfos() { return "raw"; } /** * @brief get feature type * * @return feature type **/ virtual ValueTypes getType() { return RAWFEAT; } }; class ClassificationResultAccess: public ValueAccess { public: /** * @brief extract value on specific position x,y and channel; * * @param feats see struct Features * @param x position of feature * @param y position of feature * @param channel position of feature * @return double value **/ virtual double getVal ( const Features &feats, const int &x, const int &y, const int &channel ) { return ( *feats.tree ) [feats.cfeats->get ( x,y,feats.cTree ) ].dist[channel]; } /** * @brief print some infos about feature type * * @return string feature type **/ virtual std::string writeInfos() { return "context"; } /** * @brief get feature type * * @return feature type **/ virtual ValueTypes getType() { return CONTEXT; } }; #if 0 /** * @brief not finished yet, do we really need sparse feature representation or ClassificationResultAccess sufficient **/ class SparseImageAccess: public ValueAccess { private: double scale; public: /** * @brief extract value on specific position x,y and channel; * * @param feats see struct Features * @param x position of feature * @param y position of feature * @param channel position of feature * @return double value **/ virtual double getVal ( const Features &feats, const int &x, const int &y, const int &channel ) { //MultiChannelImageT textonMap; //TODO: implement access return -1.0; } /** * @brief print some infos about feature type * * @return string feature type **/ virtual std::string writeInfos() { return "context"; } /** * @brief get feature type * * @return feature type **/ virtual ValueTypes getType() { return CONTEXT; } }; #endif /** * @brief abstract operation class **/ class Operation { protected: /** two different points (e.g. for an rectangle or two positions), channels and size */ int x1, y1, x2, y2, channel1, channel2, maxtypes; /** type of feature */ int featType; ValueAccess *values; bool context; public: /** simple constructor */ Operation(); /** * @brief set all parameters * @param _x1 position 1 * @param _y1 position 1 * @param _x2 position 2 * @param _y2 position 2 * @param _channel1 channel 1 * @param _channel2 channel 2 * @param _values value extraction method * @return void nothing **/ virtual void set ( int _x1, int _y1, int _x2, int _y2, int _channel1, int _channel2, ValueAccess *_values ); /** * @brief set whether it is a context feature or not * @param _context context boolean * @return void nothing **/ void setContext ( bool _context ); /** * @brief return context information (set by setContext(bool) * * @return bool whether context is used or not **/ bool getContext(); /** * @brief set type of feature * @param _featType type of feature * @return void nothing **/ void setFeatType ( int _featType ); /** * @brief return context information (set by setContext(bool) * * @return int get feature type **/ int getFeatType(); /** * @brief abstract interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ) = 0; /** * @brief virtual clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() = 0; /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos(); /** * @brief exctract current image boarders * @param feats image information * @param xsize width * @param ysize height * @return void **/ inline void getXY ( const Features &feats, int &xsize, int &ysize ); /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() = 0; /** * @brief store all information for current operation in stream * @param os out stream * @return void **/ virtual void store ( std::ostream & os ); /** * @brief restore all information for current operation from stream * @param is in stream * @return void **/ virtual void restore ( std::istream & is ); }; /** * @brief simple equality check ?(A==B) **/ class RegionFeat: public Operation { public: /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new RegionFeat(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { std::string out = "RegionFeat"; if ( values != NULL ) out += values->writeInfos(); return out + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return EQUALITY; } }; /** * @brief simple difference operation A-B **/ class Minus: public Operation { public: /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new Minus(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { std::string out = "Minus"; if ( values != NULL ) out += values->writeInfos(); return out + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return MINUS; } }; /** * @brief simple absolute difference operation |A-B| **/ class MinusAbs: public Operation { public: /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new MinusAbs(); }; /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { std::string out = "MinusAbs"; if ( values != NULL ) out += values->writeInfos(); return out; } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return MINUSABS; } }; /** * @brief simple addition operation A+B **/ class Addition: public Operation { public: /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new Addition(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { std::string out = "Addition"; if ( values != NULL ) out += values->writeInfos(); return out + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return ADDITION; } }; /** * @brief simple single element access operation **/ class Only1: public Operation { public: /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new Only1(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { std::string out = "Only1"; if ( values != NULL ) out += values->writeInfos(); return out + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return ONLY1; } }; /** * @brief get current relative x position **/ class RelativeXPosition: public Operation { public: /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new RelativeXPosition(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { return "RelativeXPosition" + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return RELATIVEXPOSITION; } }; /** * @brief get current relative y position **/ class RelativeYPosition: public Operation { public: /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new RelativeYPosition(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { return "RelativeYPosition" + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return RELATIVEYPOSITION; } }; /** * @brief uses mean in a window given by (x1,y1) (x2,y2) **/ class IntegralOps: public Operation { public: /** * @brief set all parameters * @param _x1 position 1 * @param _y1 position 1 * @param _x2 position 2 * @param _y2 position 2 * @param _channel1 channel 1 * @param _channel2 channel 2 * @param _values value extraction method * @return void nothing **/ virtual void set ( int _x1, int _y1, int _x2, int _y2, int _channel1, int _channel2, ValueAccess *_values ); /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new IntegralOps(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { return "IntegralOps" + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return INTEGRAL; } }; /** * @brief like a global bag of words to model the current appearance of classes in an image without local context **/ class GlobalFeats: public IntegralOps { public: /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new GlobalFeats(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { return "GlobalFeats" + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return GLOBALFEATS; } }; /** * @brief uses mean of Integral image given by x1, y1 with current pixel as center **/ class IntegralCenteredOps: public IntegralOps { public: /** * @brief set all parameters * @param _x1 position 1 * @param _y1 position 1 * @param _x2 position 2 * @param _y2 position 2 * @param _channel1 channel 1 * @param _channel2 channel 2 * @param _values value extraction method * @return void nothing **/ virtual void set ( int _x1, int _y1, int _x2, int _y2, int _channel1, int _channel2, ValueAccess *_values ); /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new IntegralCenteredOps(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { return "IntegralCenteredOps" + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return INTEGRALCENT; } }; /** * @brief uses different of mean of Integral image given by two windows, where (x1,y1) is the width and height of window1 and (x2,y2) of window 2 **/ class BiIntegralCenteredOps: public IntegralCenteredOps { public: /** * @brief set all parameters * @param _x1 position 1 * @param _y1 position 1 * @param _x2 position 2 * @param _y2 position 2 * @param _channel1 channel 1 * @param _channel2 channel 2 * @param _values value extraction method * @return void nothing **/ virtual void set ( int _x1, int _y1, int _x2, int _y2, int _channel1, int _channel2, ValueAccess *_values ); /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new BiIntegralCenteredOps(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { return "BiIntegralCenteredOps" + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return BIINTEGRALCENT; } }; /** * @brief horizontal Haar features * ++ * -- **/ class HaarHorizontal: public IntegralCenteredOps { public: /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new HaarHorizontal(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { return "HaarHorizontal" + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return HAARHORIZ; } }; /** * @brief vertical Haar features * +- * +- **/ class HaarVertical: public IntegralCenteredOps { public: /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new HaarVertical(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { return "HaarVertical" + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return HAARVERT; } }; /** * @brief diagonal Haar features * +- * -+ **/ class HaarDiag: public IntegralCenteredOps { public: /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new HaarDiag(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { return "HaarDiag" + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return HAARDIAG; } }; /** * @brief horizontal Haar features * +++ * --- * +++ */ class Haar3Horiz: public BiIntegralCenteredOps { public: /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new Haar3Horiz(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { return "Haar3Horiz" + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return HAAR3HORIZ; } }; /** * @brief vertical Haar features * +-+ * +-+ * +-+ */ class Haar3Vert: public BiIntegralCenteredOps { public: /** * @brief interface for feature computation * @param feats features * @param cfeats number of tree node for each pixel * @param tree current tree * @param x current x position * @param y current y position * @return double distance **/ virtual double getVal ( const Features &feats, const int &x, const int &y ); /** * @brief clone operation instead of copy constructor (copy constructor does not work) **/ virtual Operation* clone() { return new Haar3Vert(); } /** * @brief print some infos about operation extraction type * @return string feature type **/ virtual std::string writeInfos() { return "Haar3Vert" + Operation::writeInfos(); } /** * @brief return operation type (for store and restor) * @return OperationTypes **/ virtual OperationTypes getOps() { return HAAR3VERT; } }; } //end namespace