latest version v1.9 - last update 10 Apr 2010 |
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