LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiSparseHistogram.h

00001 /*
00002  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 /*----------------------------------------------------------------
00024  * project ....: LTI Digital Image/Signal Processing Library
00025  * file .......: ltiSparseHistogram.h
00026  * authors ....: Jochen Wickel
00027  * organization: LTI, RWTH Aachen
00028  * creation ...: 30.10.2001
00029  * revisions ..: $Id: ltiSparseHistogram.h,v 1.6 2006/02/08 12:45:34 ltilib Exp $
00030  */
00031 
00032 #ifndef _LTI_SPARSE_HISTOGRAM_H_
00033 #define _LTI_SPARSE_HISTOGRAM_H_
00034 
00035 #include "ltiBoundsFunctor.h"
00036 #include <map>
00037 
00038 namespace lti {
00039 
00040   /**
00041    * Simple sparse multidimensional histogram. It can be indexed via
00042    * int and double vectors.  It can handle index spaces of
00043    * arbitrary dimensions.
00044    *
00045    * The maximum number of bins per dimension is limited to 64.
00046    *
00047    * The accumulated type is always float.
00048    *
00049    * @see sparseMatrix
00050    *
00051    * @ingroup gAggregate
00052    */
00053   class sparseHistogram: public mathObject {
00054   protected:
00055 
00056     /**
00057      * Comparator for C-strings (null-terminated char array)
00058      */
00059     struct cless {
00060       bool operator()(const char* x, const char* y) const {
00061         return strcmp(x,y) < 0;
00062       }
00063     };
00064 
00065     /**
00066      * index map type
00067      */
00068     typedef std::map<const char*,float,cless> mapType;
00069 
00070 
00071   public:
00072 
00073     typedef float value_type;
00074 
00075     class const_iterator;
00076 
00077     /**
00078      * Similar to the iterators of the sparse matrix, these iterators
00079      * allow to access the non-sparse cells of the histogram.  This way
00080      * all data of the histogram can be efficiently accessed without loosing
00081      * time with the sparse valued cells.
00082      *
00083      * Note that the access sequence is not defined, so this is usually
00084      * required when ALL the data of the histogram needs to be changed.
00085      */
00086     class iterator {
00087       friend class sparseHistogram;
00088 #     ifdef _LTI_MSC_6
00089       friend class const_iterator;
00090 #     else
00091       friend class sparseHistogram::const_iterator;
00092 #     endif
00093     private:
00094       /**
00095        * actual vector index
00096        */
00097       mapType::iterator it;
00098 
00099     public:
00100       /**
00101        * Default constructor
00102        */
00103       iterator() : it() {};
00104 
00105       /**
00106        * copy constructor
00107        */
00108       iterator(const iterator& other) : it(other.it) {};
00109 
00110       /**
00111        * advance to next item
00112        */
00113       inline iterator& operator++() {++it; return *this;};   // prefix
00114 
00115       /**
00116        * advance to next item
00117        */
00118       inline iterator operator++(int) {
00119         iterator tmp(*this);
00120         it++; return tmp;
00121       }; // postfix
00122 
00123       /**
00124        * recede to previous item
00125        */
00126       inline iterator& operator--() {--it; return *this;};   // prefix
00127 
00128       /**
00129        * recede to previous item
00130        */
00131       inline iterator operator--(int) {
00132         iterator tmp(*this);
00133         it--; return tmp;
00134       }; // postfix
00135 
00136       /**
00137        * compare if both pointed positions are the same
00138        */
00139       inline bool operator==(const iterator& other) const {
00140         return (it == other.it);
00141       };
00142 
00143       /**
00144        * compare if both pointed positions are different
00145        */
00146       inline bool operator!=(const iterator& other) const {
00147         return (it != other.it);
00148       };
00149 
00150       /**
00151        * get pointed data
00152        */
00153       inline float& operator*() {return (*it).second;};
00154 
00155       /**
00156        * copy member
00157        */
00158       inline iterator& operator=(const iterator& other) {
00159         it = other.it;
00160         return *this;
00161       };
00162 
00163     protected:
00164       /**
00165        * protected constructor (for internal use only)
00166        */
00167       explicit iterator(const mapType::iterator& iter)
00168         : it(iter) {};
00169 
00170       /**
00171        *
00172        */
00173       const char* getKey() const {
00174         return (*it).first;
00175       }
00176 
00177     };
00178 
00179     /**
00180      * Similar to the const_iterators of the sparse matrix, these iterators
00181      * allow read-only access the non-sparse cells of the histogram.  This way
00182      * all data of the histogram can be efficiently accessed without loosing
00183      * time with the sparse valued cells.
00184      *
00185      * Note that the access sequence is not defined, so this is usually
00186      * required when ALL the data of the histogram needs to be changed.
00187      */
00188     class const_iterator {
00189       friend class sparseHistogram;
00190     private:
00191       /**
00192        * actual vector index
00193        */
00194       mapType::const_iterator it;
00195 
00196     public:
00197       /**
00198        * Default constructor
00199        */
00200       const_iterator() : it() {};
00201 
00202       /**
00203        * copy constructor
00204        */
00205       const_iterator(const const_iterator& other) : it(other.it) {};
00206 
00207       /**
00208        * advance to next item
00209        */
00210       inline const_iterator& operator++() {++it; return *this;};   // prefix
00211 
00212       /**
00213        * advance to next item
00214        */
00215       inline const_iterator operator++(int) {
00216         const_iterator tmp(*this);
00217         it++; return tmp;
00218       }; // postfix
00219 
00220       /**
00221        * recede to previous item
00222        */
00223       inline const_iterator& operator--() {--it; return *this;};   // prefix
00224 
00225       /**
00226        * recede to previous item
00227        */
00228       inline const_iterator operator--(int) {
00229         const_iterator tmp(*this);
00230         it--; return tmp;
00231       }; // postfix
00232 
00233       /**
00234        * compare if both pointed positions are the same
00235        */
00236       inline bool operator==(const const_iterator& other) const {
00237         return (it == other.it);
00238       };
00239 
00240       /**
00241        * compare if both pointed positions are different
00242        */
00243       inline bool operator!=(const const_iterator& other) const {
00244         return (it != other.it);
00245       };
00246 
00247       /**
00248        * get pointed data
00249        */
00250       inline const float& operator*() const {return (*it).second;};
00251 
00252       /**
00253        * copy member
00254        */
00255       inline const_iterator& operator=(const const_iterator& other) {
00256         it = other.it;
00257         return *this;
00258       };
00259 
00260     protected:
00261       /**
00262        * protected constructor (for internal use only)
00263        */
00264       explicit const_iterator(const mapType::const_iterator& iter)
00265         : it(iter) {};
00266 
00267       /**
00268        *
00269        */
00270       const char* getKey() const {
00271         return (*it).first;
00272       }
00273     };
00274 
00275 
00276     /**
00277      * Default constructor
00278      *
00279      * Creates an empty histogram.  You need to resize it before using it
00280      */
00281     sparseHistogram();
00282 
00283     /**
00284      * Constructor.
00285      *
00286      * Required parameters are the number of bins per dimension and
00287      * the number of dimensions.
00288      *
00289      * The maximum number of bins per dimension is limited to 64.
00290      *
00291      * @param dim number of dimensions
00292      * @param numberOfBins number of bins per dimension
00293      */
00294     sparseHistogram(const int dim, const int numberOfBins);
00295 
00296     /**
00297      * Constructor. The vector gives the number of bins for
00298      * each dimension.
00299      */
00300     sparseHistogram(const ivector& bins);
00301 
00302     /**
00303      * Constructor.
00304      *
00305      * Required parameters are the number of bins per dimension.
00306      * Furthermore, you must give the lower and upper bounds of the
00307      * hyperbox which is supposed to be occupied by the histogram.
00308      * This will be used to access the histogram by vectors with
00309      * double elements.
00310      *
00311      * The maximum number of bins per dimension is limited to 64.
00312      */
00313     sparseHistogram(const int numberOfBins,
00314                     const dvector& min,
00315                     const dvector& max);
00316 
00317     /**
00318      * Constructor.
00319      *
00320      * The first vector gives the number of bins for each dimension.
00321      * The second and third vector give the lower and upper bounds of
00322      * the hyperbox which is supposed to be occupied by the histogram.
00323      *
00324      * The maximum number of bins per dimension is limited to 64.
00325      */
00326     sparseHistogram(const ivector& numberOfBins,
00327                     const dvector& min,
00328                     const dvector& max);
00329 
00330     /**
00331      * copy constructor
00332      */
00333     sparseHistogram(const sparseHistogram& other);
00334 
00335     /**
00336      * destructor
00337      */
00338     virtual ~sparseHistogram();
00339 
00340     /**
00341      * copy data of "other" histogram.
00342      * @param other the clustering to be copied
00343      * @return a reference to this clustering object
00344      */
00345     sparseHistogram& copy(const sparseHistogram& other);
00346 
00347     /**
00348      * Clear the previous content of the histogram and resize it
00349      * to the given dimensions and bins per dimensions.
00350      *
00351      * The maximum number of bins per dimension is limited to 64.
00352      *
00353      * @param dim number of dimensions
00354      * @param numberOfBins number of bins per dimension
00355      */
00356     void resize(const int dim, const int numberOfBins);
00357 
00358     /**
00359      * Clear and resize the histogram to the number of dimensions equal to
00360      * the size of the vector bins, and having at each dimension the number
00361      * of bins given at each component of bins vector.
00362      *
00363      * The maximum number of bins per dimension is limited to 64.
00364      */
00365     void resize(const ivector& bins);
00366 
00367     /**
00368      * Clear and resize the histogram.
00369      *
00370      * The new histogram will have the given numbers of bins per dimension, for
00371      * a number of dimensions equal min.size() or max.size() (which must have
00372      * the same number of elements).
00373      * Furthermore, you must give the lower and upper bounds
00374      * of the hyperbox which is supposed to be occupied by the
00375      * histogram.
00376      * This will be used to access the histogram by vectors with
00377      * double elements.
00378      *
00379      * The maximum number of bins per dimension is limited to 64.
00380      */
00381     void resize(const int numberOfBins,
00382                 const dvector& min,
00383                 const dvector& max);
00384 
00385     /**
00386      * Clear and resize the histogram
00387      *
00388      * The first vector gives the number of bins for each dimension.
00389      * The second and third vector give the lower and upper bounds of
00390      * the hyperbox which is supposed to be occupied by the histogram.
00391      * This will be used to access the histogram by vectors with
00392      * double elements.
00393      *
00394      * The maximum number of bins per dimension is limited to 64.
00395      */
00396     void resize(const ivector& numberOfBins,
00397                 const dvector& min,
00398                 const dvector& max);
00399 
00400     /**
00401      * Returns the value stored at the given index.
00402      */
00403     float get(const ivector& index) const;
00404 
00405     /**
00406      * Sets the value at the given index.
00407      *
00408      * Note that put(index,0.0f) inserts a "non-sparse" cell with the
00409      * value zero.  If you really want to delete the cell, you need to
00410      * clear it explicitelly with the method clear(const ivector&).
00411      */
00412     void put(const ivector& index, float value=0.0f);
00413 
00414     /**
00415      * Set the entry value at the given index to the sparse value.
00416      * Note that the put(index,0.0f) inserts a "non-sparse" cell with the
00417      * value zero.  If you really want to delete the cell, you need to
00418      * clear it explicitelly.
00419      */
00420     void clear(const ivector& index);
00421 
00422     /**
00423      * Adds the value to the value at the given index.
00424      */
00425     void add(const ivector& index, float value=1.0);
00426 
00427     /**
00428      * Multiplies the value with the value at the given index.
00429      */
00430     void multiply(const ivector& index, const float& value);
00431 
00432     /**
00433      * Divides the value with the value at the given index.
00434      */
00435     void divide(const ivector& index, const float& value);
00436 
00437     /**
00438      * Divides all entries by the given value.
00439      */
00440     void divide(const float& sum);
00441 
00442     /**
00443      * returns the name of this class: "sparseHistogram"
00444      */
00445     const char* getTypeName() const {
00446       return "sparseHistogram";
00447     };
00448 
00449     /**
00450      * read-only access to the element x of the histogram
00451      * @param x index of the histogram element to be accessed.  It should
00452      *          be between getFirstCell() and getLastCell()
00453      * @return the number of entries in the given cell
00454      */
00455     const float& at(const ivector& x) const;
00456 
00457     /**
00458      * access element x of the histogram
00459      * @param x index of the histogram element to be accessed.  It should
00460      *          be between getFirstCell() and getLastCell()
00461      * @return the number of entries in the given cell
00462      */
00463     float& at(const ivector& x);
00464 
00465     /**
00466      * read-only access to the element x of the histogram
00467      * @param x index of the histogram element to be accessed.  It should
00468      *          be between getFirstCell() and getLastCell()
00469      * @return the number of entries in the given cell
00470      */
00471     inline const float& at(const dvector& x) const {
00472       return at(makeTmpIndex(x));
00473     }
00474 
00475     /**
00476      * access element x of the histogram
00477      * @param x index of the histogram element to be accessed.  It should
00478      *          be between getFirstCell() and getLastCell()
00479      * @return the number of entries in the given cell
00480      */
00481     inline float& at(const dvector& x) {
00482       return at(makeTmpIndex(x));
00483     }
00484 
00485     /**
00486      * returns the number of dimensions of this histogram
00487      */
00488     inline int dimensions() const {
00489       return bins.size();
00490     }
00491 
00492     /**
00493      * returns first element as a const_iterator.
00494      * Note that you can not change the values of the vector
00495      * elements when you use a const_iterator. See also begin()
00496      */
00497     inline const_iterator begin() const {
00498       return const_iterator(core.begin());
00499     };
00500 
00501     /**
00502      * returns first element as an iterator
00503      * The use of the interators is similar to the iterators of the
00504      * Standard Template Library (STL).
00505      * If you need to iterate on all non-sparse elements of the histogram
00506      * use following code:
00507      *
00508      * \code
00509      *   float tmp,accu;                   // temporal variables
00510      *   lti::sparseHistogram myHist(3,6); // a 3D Histogram with 6 bins
00511      *                                     // per dimension (216 cells)
00512      *   // fill the histogram
00513      *   ivector idx(3,1);
00514      *   myHist.put(idx,5); // at (1,1,1) set 5
00515      *   ...
00516      *
00517      *   lti::sparseHistogram::iterator it;  // an iterator
00518      *   accu = 0;
00519      *   for (it=myVct.begin();it!=myVct.end();it++) {
00520      *     tmp = *it;                    // tmp has value of element pointed
00521      *                                   // by the iterator.
00522      *     accu += tmp;
00523      *     (*it) *= 5                    // change the value in the vector.
00524 
00525      *    }
00526      * \endcode
00527      *
00528      * Please note that if you define <code>it</code> as a const_iterator,
00529      * you can not make something like <code>(*it)*=5</code>.
00530      */
00531     inline iterator begin() {
00532       return iterator(core.begin());
00533     };
00534 
00535     /**
00536      * returns last index as a const iterator.
00537      * For an example see begin()
00538      */
00539     inline const_iterator end() const {
00540       return const_iterator(core.end());
00541     }
00542 
00543     /**
00544      * returns last index as an iterator
00545      * For an example see begin()
00546      */
00547     inline iterator end() {
00548       return iterator(core.end());
00549     }
00550 
00551     /**
00552      * Returns the value stored at the given index.
00553      */
00554     inline float get(const dvector& index) const {
00555       return get(makeTmpIndex(index));
00556     };
00557 
00558     /**
00559      * Sets the value at the given index.
00560      */
00561     inline void put(const dvector& index, float value=0.0) {
00562       put(makeTmpIndex(index),value);
00563     };
00564 
00565     /**
00566      * Adds the value to the value at the given index.
00567      */
00568     inline void add(const dvector& index, float value=1.0) {
00569       add(makeTmpIndex(index),value);
00570     };
00571 
00572     /**
00573      * Multiplies the value with the value at the given index.
00574      */
00575     inline void multiply(const dvector& index, const float& value) {
00576       multiply(makeTmpIndex(index),value);
00577     };
00578 
00579     /**
00580      * Erases all elements from the histogram.
00581      */
00582     void clear();
00583 
00584     /**
00585      * Returns an identical copy of this histogram.
00586      */
00587     virtual mathObject* clone() const;
00588 
00589 
00590     /**
00591      * write the histogram in the given ioHandler
00592      * @param handler the ioHandler to be used
00593      * @param complete if true (the default) the enclosing begin/end will
00594      *        be also written, otherwise only the data block will be written.
00595      * @return true if write was successful
00596      */
00597     virtual bool write(ioHandler& handler,const bool complete=true) const;
00598 
00599     /**
00600      * read the histogram from the given ioHandler
00601      * @param handler the ioHandler to be used
00602      * @param complete if true (the default) the enclosing begin/end will
00603      *        be also written, otherwise only the data block will be written.
00604      * @return true if write was successful
00605      */
00606     virtual bool read(ioHandler& handler,const bool complete=true);
00607 
00608 
00609   private:
00610 
00611     /**
00612      * Creates a new char array key from an index vector.
00613      */
00614     inline const char* makeNewKey(const ivector& index) const {
00615       char* buf=new char[index.size()+1];
00616       char* c=buf;
00617       for (int i=0; i<index.size(); i++) {
00618         assert(index[i] < bins[i]);
00619         *c++=codeChars[index[i]];
00620       }
00621       *c='\0';
00622       return buf;
00623     };
00624 
00625     inline void makeKey(const ivector& index, char *buf) const {
00626       assert(index.size()==tmpBufSize);
00627       char* c=buf;
00628       for (int i=0; i<index.size(); i++) {
00629         assert(index[i] < bins[i]);
00630         *c++=codeChars[index[i]];
00631       }
00632       *c='\0';
00633     };
00634 
00635     /**
00636      * Creates a new string buffer to the generation of hash-keys.
00637      * This method ensures the deletion of the previous buffer
00638      */
00639     inline void checkTmpBuffer(const ivector& index) const;
00640 
00641     /**
00642      * Convert the given dvector into an ivector.  The attribute
00643      * tmpIndex is used for this task, and a reference to it is
00644      * returned.
00645      */
00646     inline const ivector& makeTmpIndex(const dvector& d) const;
00647 
00648     /**
00649      * conversion from the integer value to the corresponding string
00650      * entry for the hash-key creation.
00651      */
00652     static const char* codeChars;
00653 
00654     /**
00655      * Maximal number of bins per dimension is determined by the length of
00656      * the codeChar symbols.
00657      */
00658     static const int maxN;
00659 
00660     /**
00661      * number of bins per axis
00662      */
00663     ivector bins;
00664 
00665     /**
00666      * The data ist stored in this map.
00667      */
00668     mapType core;
00669 
00670     /**
00671      * transform for the index computation
00672      */
00673     dvector offset;
00674 
00675     /**
00676      * slope for the linear transformation from dvectors to the index ivectors
00677      */
00678     dvector scale;
00679 
00680     /**
00681      * lower bound of the bounding hyper-box of the histogram
00682      */
00683     ivector minIndex;
00684 
00685     /**
00686      * higher bound of the bounding hyper-box of the histogram
00687      */
00688     ivector maxIndex;
00689 
00690     /**
00691      *
00692      */
00693     boundsFunctor<int> indexClipper;
00694 
00695     /**
00696      * sparse valued returned when an element is not in the core data.
00697      */
00698     static const float zero;
00699 
00700     /**
00701      * temporary buffers for the conversion of double index
00702      * to integer index
00703      */
00704     mutable dvector tmp;
00705 
00706     /**
00707      * temporal index vector usually constructed through makeTmpIndex from
00708      * a double vector.
00709      */
00710     mutable ivector tmpIndex;
00711 
00712     /**
00713      * temporary buffer for the conversion of index vector
00714      * to index string
00715      */
00716     mutable char *tmpBuffer;
00717 
00718     /**
00719      * Size of the tmpBuffer string
00720      */
00721     mutable int tmpBufSize;
00722   };
00723 
00724   // inline methods implementation
00725   inline const ivector& sparseHistogram::makeTmpIndex(const dvector& d) const {
00726     tmp=d;
00727     tmp.subtract(offset);
00728     tmp.emultiply(scale);
00729     tmpIndex.castFrom(tmp);
00730     indexClipper.clip(tmpIndex,minIndex,maxIndex);
00731     return tmpIndex;
00732   }
00733 
00734 
00735 }
00736 
00737 #endif

Generated on Sat Apr 10 15:26:14 2010 for LTI-Lib by Doxygen 1.6.1