Browse Source

restructured Codebook and CodebookPrototypes

Alexander Freytag 12 years ago
parent
commit
07268175da

+ 106 - 28
features/simplefeatures/Codebook.cpp

@@ -1,9 +1,8 @@
 /** 
 * @file Codebook.cpp
 * @brief feature codebook
-* @author Erik Rodner
-* @date 02/15/2008
-
+* @author Erik Rodner, Alexander Freytag
+* @date 05-06-2013 (dd-mm-yyyy ) (original: 02/15/2008)
 */
 #include <iostream>
 
@@ -14,33 +13,71 @@ using namespace OBJREC;
 using namespace std;
 using namespace NICE;
 
-void Codebook::vote ( const NICE::Vector & feature, 
-			NICE::Vector & histogram, 
-			int & codebookEntry,
-			double & weight,
-			double & distance ) const
+Codebook::Codebook ( )
+{
+  this->i_noOfNearestClustersToConsidere = 1;
+}
+
+Codebook::Codebook ( const int & _noOfNearestClustersToConsidere )
+{
+  this->i_noOfNearestClustersToConsidere = _noOfNearestClustersToConsidere;
+}
+
+Codebook::Codebook( NICE::Config * _conf, const std::string & _section)
+{
+  this->p_conf = _conf;
+  this->s_section = _section;
+  
+  this->i_noOfNearestClustersToConsidere = this->p_conf->gI( _section, "noOfNearestClustersToConsidere", 1);
+}
+
+
+Codebook::~Codebook ( )
+{
+  //NOTE the config does not need to be deleted, it is just a pointer to an external data structure  
+}
+
+void Codebook::voteVQ (const NICE::Vector &feature, NICE::Vector &histogram, int &codebookEntry, double &weight, double &distance) const
+{
+    this->voteVQ ( feature, codebookEntry, weight, distance );
+    //VQ, but we directly increase the corresponding entry without setting histogram to zero before (useful if we work on multiple images)
+    histogram[codebookEntry] += weight;  
+}
+
+void Codebook::voteVQ ( const NICE::Vector & feature, NICE::SparseVector & histogram, int &codebookEntry, double &weight, double &distance ) const
 {
-    vote ( feature, codebookEntry, weight, distance );
-    histogram[codebookEntry] += weight;
+    this->voteVQ ( feature, codebookEntry, weight, distance );
+    
+    //is this cluster already non-zero in the histogram?
+    NICE::SparseVector::iterator entryIt = histogram.find( codebookEntry ) ;
+    if ( entryIt  == histogram.end() )
+    {
+      //entry does not exist
+      histogram.insert ( histogram.begin(), pair<int, double> ( codebookEntry, weight ) );
+    }
+    else
+    {
+      //entry already exists, so we increase the weight
+      entryIt->second += weight;
+    }
 }
 
-void Codebook::vote ( const NICE::Vector & feature, SparseVector & votes ) const
+bool Codebook::allowsMultipleVoting () const
 {
-    int codebookEntry;
-    double weight;
-    double distance;
-    vote ( feature, codebookEntry, weight, distance );
-    votes.insert ( votes.begin(), pair<int, double> ( codebookEntry, weight ) );
+  if ( this->i_noOfNearestClustersToConsidere > 1 )
+    return true;
+  else
+    return false;
 }
-	
+
 void Codebook::reinit ( int numCodebookEntries )
 {
-    thresholds.resize ( numCodebookEntries );
-	thresholds.set(0.0);
-    informativeMeasure.resize ( numCodebookEntries );
-	informativeMeasure.set(0.0);
-    classnos.resize ( numCodebookEntries );
-	classnos.resize(0);
+  thresholds.resize ( numCodebookEntries );
+  thresholds.set(0.0);
+  informativeMeasure.resize ( numCodebookEntries );
+  informativeMeasure.set(0.0);
+  classnos.resize ( numCodebookEntries );
+  classnos.resize(0);
 }
 
 void Codebook::clear ()
@@ -54,20 +91,61 @@ void Codebook::restore ( istream & is, int format )
 {
    is >> thresholds;
    is >> informativeMeasure;
-   is >> classnos;
+//    is >> classnos;
+   
+   //TODO use a flag for compatibility with old systems?
+/*   try
+   {
+     
+     is >> i_noOfNearestClustersToConsidere;
+     is >> s_section;
+
+     this->p_conf->restore( is, format );
+   }
+   catch( ... )
+   {
+     std::cerr << "something went wrong while Loading the codebook - use default values instead" << std::endl;
+     //TODO use suitable default values
+   }  */ 
 }
 
 void Codebook::store ( ostream & os, int format ) const
 {
-    os << thresholds << endl;
-    os << informativeMeasure << endl;
-    os << classnos << endl;
+    os << this->thresholds << endl;
+    os << this->informativeMeasure << endl;
+    os << this->classnos << endl;
+//     os << this->i_noOfNearestClustersToConsidere << endl;
+//     os << this->s_section << endl;
+//     
+//     this->p_conf->store( os, format );
 }
 
 void Codebook::copy ( const Codebook *codebook )
 {
-    reinit ( codebook->thresholds.size() );
+    this->reinit ( codebook->thresholds.size() );
     thresholds = codebook->thresholds;
     informativeMeasure = codebook->informativeMeasure;
     classnos = codebook->classnos;
+    this->p_conf = codebook->p_conf;
+    this->setNoOfNearestClustersToConsidere ( codebook->getNoOfNearestClustersToConsidere() );
 }
+
+void Codebook::setNoOfNearestClustersToConsidere ( const int & _noOfNearestClustersToConsidere )
+{
+  this->i_noOfNearestClustersToConsidere = _noOfNearestClustersToConsidere;
+}
+
+int Codebook::getNoOfNearestClustersToConsidere ( ) const
+{
+  return this->i_noOfNearestClustersToConsidere;
+}
+
+void Codebook::setHardAssignment( const bool & _hardAssignment )
+{
+  this->b_hardAssignment = _hardAssignment;
+}
+
+bool Codebook::getHardAssignment ( ) const
+{
+  return this->b_hardAssignment;
+}

+ 160 - 64
features/simplefeatures/Codebook.h

@@ -1,83 +1,179 @@
 /**
 * @file Codebook.h
 * @brief feature codebook
-* @author Erik Rodner
-* @date 02/15/2008
-
+* @author Erik Rodner, Alexander Freytag
+* @date 05-06-2013 (dd-mm-yyyy ) (original: 02/15/2008)
 */
 #ifndef CODEBOOKINCLUDE
 #define CODEBOOKINCLUDE
 
-#include "core/vector/VectorT.h"
-#include "core/vector/MatrixT.h"
-#include "core/image/ImageT.h"
-#include "core/imagedisplay/ImageDisplay.h"
 
 #include <string>
 
+#include <core/basics/Config.h>
 #include "core/basics/Persistent.h"
+//
+#include "core/image/ImageT.h"
+#include "core/imagedisplay/ImageDisplay.h"
+//
+#include "core/vector/VectorT.h"
+#include "core/vector/MatrixT.h"
 #include "core/vector/SparseVectorT.h"
 
 
 namespace OBJREC {
 
-/** feature codebook */
-class Codebook : public NICE::Persistent
-{
-protected:
-    NICE::Vector thresholds;
-    NICE::Vector informativeMeasure;
-    NICE::VectorT<int> classnos;
-
-public:
-
-    /** simple destructor */
-    virtual ~Codebook() {};
-
-    virtual void vote ( const NICE::Vector & feature, int & codebookEntry,
-                        double & weight, double & distance ) const = 0;
-
-    virtual void vote ( const NICE::Vector & feature, NICE::Vector & histogram, int & codebookEntry,
-                        double & weight, double & distance ) const;
-
-    virtual void vote ( const NICE::Vector & feature, NICE::SparseVector & votes ) const;
-
-    virtual bool allowsMultipleVoting () {
-        return false;
-    };
-    virtual void add ( const Codebook *codebook ) = 0;
-    virtual void copy ( const Codebook *codebook );
-    virtual Codebook *clone () const = 0;
-
-    size_t getCodebookSize() const {
-        return informativeMeasure.size();
-    };
-    void reinit ( int numCodebookEntries );
-
-    const NICE::Vector & getThresholds () const {
-        return thresholds;
-    };
-    const NICE::Vector & getInformativeMeasure () const {
-        return informativeMeasure;
-    };
-    const NICE::VectorT<int> & getClassNos () const {
-        return classnos;
-    };
-
-    void setThresholds ( const NICE::Vector & _thresholds ) {
-        thresholds = _thresholds;
-    };
-    void setInformativeMeasure ( const NICE::Vector & _informativeMeasure ) {
-        informativeMeasure = _informativeMeasure;
-    };
-    void setClassNos ( const NICE::VectorT<int> & _classnos ) {
-        classnos = _classnos;
-    };
-
-    virtual void clear ();
-    virtual void restore ( std::istream & is, int format );
-    virtual void store ( std::ostream & os, int format ) const;
-};
+  /** feature codebook */
+  class Codebook : virtual public NICE::Persistent
+  {
+    protected:
+        NICE::Vector thresholds;
+        NICE::Vector informativeMeasure;
+        NICE::VectorT<int> classnos;
+        
+        /** if Soft Assignment or Hard Assignment instead of Vector Quantization, how many entries are allowed to be non-zero?*/
+        int i_noOfNearestClustersToConsidere;
+        
+        NICE::Config * p_conf;
+        std::string s_section;
+        
+        /** hard or soft assignment? */
+        bool b_hardAssignment;
+
+    public:
+
+        /**
+         * @brief simple constructor
+         */
+        Codebook ( );      
+      
+        /**
+         * @brief standard constructor
+         */
+        Codebook ( const int & _noOfNearestClustersToConsidere);
+
+         /**
+         * @brief recommended constructor
+         */
+        Codebook( NICE::Config * _conf, const std::string & _section);
+
+        /** simple destructor */
+        virtual ~Codebook();
+        
+
+        //vote for a single feature vector
+        /**
+         * @brief Vector Quantization for a single vector
+         * @date 11-06-2013 (dd-mm-yyyy)
+         * @author Erik Rodner, Alexander Freytag
+         * @param feature the feature that shall be quantized
+         * @param codebookEntry the corresponding cluster index for the quantized feature
+         * @param weight the weight of the nearest cluster
+         * @param distance the distance to its nearest cluster
+         */        
+        virtual void voteVQ ( const NICE::Vector & feature, int & codebookEntry,
+                            double & weight, double & distance ) const = 0;
+                            
+        /**
+         * @brief Vector Quantization for a single vector, directly increases the corresponding entry in histogram 
+         * @date 11-06-2013 (dd-mm-yyyy)
+         * @author Erik Rodner, Alexander Freytag
+         * @param feature the feature that shall be quantized
+         * @param histogram a BoW-histogram already given (does not need to be empty before) - the corresponding entry for feature will be increased
+         * @param codebookEntry  the corresponding cluster index for the quantized feature
+         * @param weight the weight of the nearest cluster
+         * @param distance the distance to its nearest cluster
+         */        
+        virtual void voteVQ (const NICE::Vector &feature, NICE::Vector &histogram, int & codebookEntry, double & weight, double & distance ) const; 
+        
+        /**
+         * @brief Vector Quantization for a single vector, directly increases the corresponding entry in histogram 
+         * @date 11-06-2013 (dd-mm-yyyy)
+         * @author Erik Rodner, Alexander Freytag
+         * @param feature the feature that shall be quantized
+         * @param histogram a BoW-histogram already given (does not need to be empty before) - the corresponding entry for feature will be increased
+         * @param codebookEntry the corresponding cluster index for the quantized feature
+         * @param weight the weight of the nearest cluster
+         * @param distance the distance to its nearest cluster
+         */        
+        virtual void voteVQ (const NICE::Vector &feature, NICE::SparseVector &histogram, int &codebookEntry, double &weight, double &distance ) const;         
+
+        
+        /**
+         * @brief Hard or Soft Assignment into NICE::Vector for a single vector
+         * @date 11-06-2013 (dd-mm-yyyy)
+         * @author Alexander Freytag
+         * @param feature the feature that shall be quantized
+         * @param votes BoW histogram adding non-zero entries at the k nearest clusters (hard or soft),  (does not need to be empty before)
+         */    
+        virtual void voteVA ( const NICE::Vector & feature, NICE::Vector & votes ) const = 0;
+
+        /**
+         * @brief Hard or Soft Assignment into NICE::SparseVector for a single vector 
+         * @date 11-06-2013 (dd-mm-yyyy)
+         * @author Erik Rodner, Alexander Freytag
+         * @param feature the feature that shall be quantized
+         * @param votes BoW histogram adding non-zero entries for the k nearest clusters (hard or soft),  (does not need to be empty before)
+         */                              
+        virtual void voteVA ( const NICE::Vector & feature, NICE::SparseVector & votes ) const = 0;
+        
+        
+        //for backward-compatibility
+        virtual void   vote (const NICE::Vector &feature, NICE::Vector &histogram, int &codebookEntry , double &weight , double &distance ) const { this->voteVQ ( feature, histogram, codebookEntry, weight, distance ); };
+        
+        virtual void   vote (const NICE::Vector &feature, NICE::SparseVector &histogram ) const {
+          int codebookEntry;
+          double weight, distance;
+          this->voteVQ ( feature, histogram, codebookEntry, weight, distance );          
+        };        
+   
+        
+        
+       
+        virtual void add ( const Codebook *codebook ) = 0;
+        virtual void copy ( const Codebook *codebook );
+        virtual Codebook *clone () const = 0;
+
+        size_t getCodebookSize() const {
+            return informativeMeasure.size();
+        };
+        void reinit ( int numCodebookEntries );
+
+        const NICE::Vector & getThresholds () const {
+            return thresholds;
+        };
+        const NICE::Vector & getInformativeMeasure () const {
+            return informativeMeasure;
+        };
+        const NICE::VectorT<int> & getClassNos () const {
+            return classnos;
+        };
+
+        void setThresholds ( const NICE::Vector & _thresholds ) {
+            thresholds = _thresholds;
+        };
+        void setInformativeMeasure ( const NICE::Vector & _informativeMeasure ) {
+            informativeMeasure = _informativeMeasure;
+        };
+        void setClassNos ( const NICE::VectorT<int> & _classnos ) {
+            classnos = _classnos;
+        };
+        
+        void setHardAssignment( const bool & _hardAssignment );
+        bool getHardAssignment ( ) const ;
+        
+        /** 
+         * @brief false, if only a single entry for soft or hard assignment can be larger than zero (=> effectively vector quantization)
+         */
+        virtual bool allowsMultipleVoting () const ;
+        
+        void setNoOfNearestClustersToConsidere ( const int & _noOfNearestClustersToConsidere );
+        int getNoOfNearestClustersToConsidere ( ) const ;
+
+        virtual void clear ();
+        virtual void restore ( std::istream & is, int format );
+        virtual void store ( std::ostream & os, int format ) const;
+  };
 
 
 } // namespace

+ 110 - 68
features/simplefeatures/CodebookPrototypes.cpp

@@ -1,15 +1,16 @@
 /** 
 * @file CodebookPrototypes.cpp
 * @brief feature CodebookPrototypes
-* @author Erik Rodner
-* @date 02/15/2008
-
+* @author Erik Rodner, Alexander Freytag
+* @date 05-06-2013 (dd-mm-yyyy ) (original: 02/15/2008)
 */
-#include <core/image/Convert.h>
-
 #include <iostream>
 #include <assert.h>
 
+#include <core/image/Convert.h>
+
+#include "vislearning/math/distances/genericDistance.h"
+
 #include "CodebookPrototypes.h"
 
 using namespace OBJREC;
@@ -20,6 +21,7 @@ using namespace NICE;
 
 CodebookPrototypes::CodebookPrototypes()
 {
+  this->clear();
 }
 
 CodebookPrototypes::CodebookPrototypes( const std::string & filename )
@@ -27,15 +29,24 @@ CodebookPrototypes::CodebookPrototypes( const std::string & filename )
     Codebook::read(filename);
 }
 
-CodebookPrototypes::CodebookPrototypes( const VVector & vv )
+CodebookPrototypes::CodebookPrototypes( const NICE::VVector & vv )
 {
-    for ( const_iterator i = vv.begin(); i != vv.end(); i++ )
-	push_back (*i);
-    reinit ( vv.size() );
+  this->append ( vv, true /* _copyData*/ ); 
+
+  reinit ( vv.size() );
+}
+
+CodebookPrototypes::CodebookPrototypes( NICE::Config * _conf, const std::string & _section) : Codebook ( _conf, _section )
+{    
+  this->distanceType = _conf->gS( _section, "distanceType", "euclidean" );
+  this->distancefunction = GenericDistanceSelection::selectDistance(distanceType);  
+  
+  this->clear();
 }
 
 CodebookPrototypes::~CodebookPrototypes()
 {
+  //NOTE the config does not need to be deleted, it is just a pointer to an external data structure
 }
 
 void CodebookPrototypes::copy ( const Codebook *codebook )
@@ -45,9 +56,12 @@ void CodebookPrototypes::copy ( const Codebook *codebook )
     const CodebookPrototypes *codebookp = dynamic_cast<const CodebookPrototypes *> ( codebook );
     assert ( codebookp != NULL );
     insert ( begin(), codebookp->begin(), codebookp->end() );
+    
+  this->distanceType = this->p_conf->gS( this->s_section, "distanceType", "euclidean" );
+  this->distancefunction = GenericDistanceSelection::selectDistance(distanceType);      
 }
 
-void CodebookPrototypes::vote ( const NICE::Vector & feature, int & codebookEntry, double & weight, double & distance ) const
+void CodebookPrototypes::voteVQ ( const NICE::Vector & feature, int & codebookEntry, double & weight, double & distance ) const
 {
     const double *xp = feature.getDataPointer();
     size_t k = 0;
@@ -55,34 +69,50 @@ void CodebookPrototypes::vote ( const NICE::Vector & feature, int & codebookEntr
     size_t my_cluster = 0;
     
     int len = feature.size();
-    for ( vector<Vector>::const_iterator i = begin();
-					 i != end();
-					 i++,k++ )
+    // iterate over all cluster centers
+    for ( std::vector<NICE::Vector>::const_iterator i = this->begin();
+            i != this->end();
+            i++,k++ )
     {
 
-	const NICE::Vector & cluster = *i;
-	//slow ICE variant
-	//double distance = (x - cluster).Length();
-	double distance = 0.0;
-	const double *clusterp = cluster.getDataPointer();
-	for ( int i = 0 ; i < len ; i++ )
-	{
-	    double h = clusterp[i] - xp[i];
-	    distance += h*h;
-	}
-
-	if ( distance < mindist )
-	{
-	    my_cluster = k;
-	    mindist = distance;
-	}
+      const NICE::Vector & cluster = *i;
+      //slow ICE variant
+      //double distance = (x - cluster).Length();
+      
+//       const double *clusterp = cluster.getDataPointer();
+      double distance = this->distancefunction->calculate(*i, feature);
+      
+      //old version without distance function
+//       for ( int i = 0 ; i < len ; i++ )
+//       {
+//           double h = clusterp[i] - xp[i];
+//           distance += h*h;
+//       }
+
+      if ( distance < mindist )
+      {
+          my_cluster = k;
+          mindist = distance;
+      }
     }
 
     codebookEntry = my_cluster;
     weight = 1.0;
     distance = mindist;
 }
-	
+
+void CodebookPrototypes::voteVA ( const NICE::Vector & feature, NICE::Vector & votes ) const
+{
+  votes.set( 0.0 );
+  //TODO
+}
+
+void CodebookPrototypes::voteVA ( const NICE::Vector & feature, NICE::SparseVector & votes ) const
+{
+  votes.clear(); 
+  //TODO
+}
+
 void CodebookPrototypes::add ( const Codebook *codebook )
 {
     informativeMeasure.append ( codebook->getInformativeMeasure() );
@@ -93,7 +123,7 @@ void CodebookPrototypes::add ( const Codebook *codebook )
     assert ( codebookp != NULL );
     insert ( begin(), codebookp->begin(), codebookp->end() );
 }
-	
+
 Codebook *CodebookPrototypes::clone () const
 {
     return (new CodebookPrototypes());
@@ -109,6 +139,8 @@ void CodebookPrototypes::restore ( istream & is, int format )
 {
     Codebook::restore ( is, format );
     VVector::restore ( is, format );
+    
+    std::cerr << "initial Codebook : " << std::endl; VVector::print ( std::cerr );
 }
 
 void CodebookPrototypes::store ( ostream & os, int format ) const
@@ -119,47 +151,57 @@ void CodebookPrototypes::store ( ostream & os, int format ) const
 
 void CodebookPrototypes::displayCodebook ( int xsize, int ysize ) const
 {
-    NICE::Image bigimg ( xsize * 5 , ysize * size() );
+    NICE::Image bigimg ( xsize * 5 , ysize * this->size() );
     bigimg.set(0);
 
     NICE::Image img_s (xsize, ysize);
-    for ( int k = 0 ; k < (int)size() ; k++ )
+    for ( int k = 0 ; k < (int)this->size() ; k++ )
     {
-	NICE::Vector vimg = *(begin() + k);
-	NICE::Image img ((int)sqrt(vimg.size()), (int)sqrt(vimg.size()));
-	int i = 0;
-	double max = - numeric_limits<double>::max();
-	double min = numeric_limits<double>::min();
-	for ( int y = 0 ; y < img.height() ; y++ )
-	    for ( int x = 0 ; x < img.width() ; x++,i++ )
-	    {
-		if ( max < vimg[i] ) max = vimg[i];
-		if ( min > vimg[i] ) min = vimg[i];
-	    }
-
-	i = 0;
-	for ( int y = 0 ; y < img.height() ; y++ )
-	    for ( int x = 0 ; x < img.width() ; x++,i++ )
-	    {
-		img.setPixel( x, y, (int)((vimg[i] - min)*255/(max-min)) );
-	    }
-
-	
-	NICE::scale ( img, &img_s );
-
-	for ( int y = 0 ; y < ysize ; y++ )
-	    for ( int x = 0 ; x < xsize ; x++ )
-		bigimg.setPixel(x, y+k*ysize, img_s.getPixel(x,y) );
-
-	{
-	    std::ostringstream os;
-	    os << "no: " << k;
-	    if ( (int)informativeMeasure.size() > k ) 
-		os << " " << informativeMeasure[k];
-	    // refactor-nice.pl: check this substitution
-	    // old: Text ( os.str().c_str(), xsize+1, k*ysize + 1, 255, 0, bigimg );
-	    // REFACTOR-FIXME Unable to map this statement
-	}
+      NICE::Vector vimg = *(this->begin() + k);
+      NICE::Image img ((int)sqrt(vimg.size()), (int)sqrt(vimg.size()));
+      int i = 0;
+      double max = - numeric_limits<double>::max();
+      double min = numeric_limits<double>::min();
+      for ( int y = 0 ; y < img.height() ; y++ )
+      {
+          for ( int x = 0 ; x < img.width() ; x++,i++ )
+            {
+              if ( max < vimg[i] )
+                max = vimg[i];
+              if ( min > vimg[i] )
+                min = vimg[i];
+            }
+      }
+
+      i = 0;
+      for ( int y = 0 ; y < img.height() ; y++ )
+      {
+          for ( int x = 0 ; x < img.width() ; x++,i++ )
+          {
+            img.setPixel( x, y, (int)((vimg[i] - min)*255/(max-min)) );
+          }
+      }
+
+      
+      NICE::scale ( img, &img_s );
+
+      for ( int y = 0 ; y < ysize ; y++ )
+      {
+          for ( int x = 0 ; x < xsize ; x++ )
+          {
+            bigimg.setPixel(x, y+k*ysize, img_s.getPixel(x,y) );
+          }
+      }
+
+      {
+          std::ostringstream os;
+          os << "no: " << k;
+          if ( (int)informativeMeasure.size() > k ) 
+          os << " " << informativeMeasure[k];
+          // refactor-nice.pl: check this substitution
+          // old: Text ( os.str().c_str(), xsize+1, k*ysize + 1, 255, 0, bigimg );
+          // REFACTOR-FIXME Unable to map this statement
+      }
     }
 
     bigimg.write ("/tmp/display.bmp");

+ 60 - 31
features/simplefeatures/CodebookPrototypes.h

@@ -1,9 +1,8 @@
 /** 
 * @file CodebookPrototypes.h
 * @brief feature CodebookPrototypes
-* @author Erik Rodner
-* @date 02/15/2008
-
+* @author Erik Rodner, Alexander Freytag
+* @date 05-06-2013 (dd-mm-yyyy ) (original: 02/15/2008)
 */
 #ifndef CodebookPrototypesINCLUDE
 #define CodebookPrototypesINCLUDE
@@ -15,42 +14,72 @@
 #include <string>
 
 #include "core/vector/VVector.h"
+#include <core/vector/Distance.h>
+
 #include "Codebook.h"
 
 
 namespace OBJREC {
 
-/** feature CodebookPrototypes */
-class CodebookPrototypes : public Codebook, public NICE::VVector
-{
-
-    protected:
-
-    public:
-  
-	/** simple constructor */
-	CodebookPrototypes();
-	
-	CodebookPrototypes( const std::string & filename );
-	
-	CodebookPrototypes( const NICE::VVector & vv );
-	
-	CodebookPrototypes( const CodebookPrototypes *cs );
-      
-	/** simple destructor */
-	virtual ~CodebookPrototypes();
+  /** feature CodebookPrototypes */
+  class CodebookPrototypes : public Codebook, public NICE::VVector
+  {
+
+      protected:
+        
+        //! specify which distance to use for calculating assignments
+        std::string distanceType;
+        
+        //! the actual distance metric
+        NICE::VectorDistance<double> *distancefunction;         
+
+      public:
     
-	void vote ( const NICE::Vector & feature, int & codebookEntry, double & weight, double & distance ) const;
-	void add ( const Codebook *codebook );
-	void copy ( const Codebook *codebook );
-	Codebook *clone () const;
+        /** simple constructor */
+        CodebookPrototypes();
+        
+        /** constructor reading the codebook from a file*/
+        CodebookPrototypes( const std::string & filename );
+        
+        /** constructor taking the given VVector as new codebook prototypes*/
+        CodebookPrototypes( const NICE::VVector & vv );
+        
+        /** copy constructor*/
+        CodebookPrototypes( const CodebookPrototypes *cs );
+        
+        /** recommended constructor*/
+        CodebookPrototypes( NICE::Config * _conf, const std::string & _section);
+            
+        /** simple destructor */
+        virtual ~CodebookPrototypes();
+        
+        //vote for a single feature vector
+        /**
+         * @brief Vector Quantization for a single vector
+         */        
+        void voteVQ ( const NICE::Vector & feature, int & codebookEntry, double & weight, double & distance ) const;
+
+        /**
+         * @brief Hard or Soft Assignment into NICE::Vector for a single vector
+         */        
+        virtual void voteVA ( const NICE::Vector & feature, NICE::Vector & votes ) const;
+
+        /**
+         * @brief Hard or Soft Assignment into NICE::SparseVector for a single vector
+         */                            
+        virtual void voteVA ( const NICE::Vector & feature, NICE::SparseVector & votes ) const;        
+         
+        
+        void add ( const Codebook *codebook );
+        void copy ( const Codebook *codebook );
+        Codebook *clone () const;
 
-	void clear ();
-	void restore ( std::istream & is, int format );
-	void store ( std::ostream & os, int format ) const;
+        void clear ();
+        void restore ( std::istream & is, int format );
+        void store ( std::ostream & os, int format ) const;
 
-	void displayCodebook (int xsize, int ysize) const;
-};
+        void displayCodebook (int xsize, int ysize) const;
+  };
 
 
 } // namespace