latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 1999, 2000, 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 /*---------------------------------------------------------------- 00025 * project ....: LTI Digital Image/Signal Processing Library 00026 * file .......: ltiKMColorQuantization.h 00027 * authors ....: Pablo Alvarado 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 30.04.99 00030 * revisions ..: $Id: ltiKMColorQuantization.h,v 1.11 2007/01/10 02:25:58 alvarado Exp $ 00031 */ 00032 00033 #ifndef _LTI_KM_COLOR_QUANTIZATION_H_ 00034 #define _LTI_KM_COLOR_QUANTIZATION_H_ 00035 00036 #include "ltiFunctor.h" 00037 #include "ltiImage.h" 00038 #include "ltiTypes.h" 00039 #include "ltiVector.h" 00040 #include "ltiColorQuantization.h" 00041 #include "ltiUniformDist.h" 00042 #include <map> 00043 00044 namespace lti { 00045 /** 00046 * k-Means based color quantization. 00047 * 00048 * This functor calculates (using k-Means) an optimal color subpalette for 00049 * the input image. The maximal number of colors to be used is given 00050 * through the parameters (inherited from colorQuantization::parameters). 00051 * 00052 * If the real number of colors used in the image is less than the desired 00053 * number of quantized colors, no quantization is done and the output palette 00054 * will contain all image colors, i.e. it will be smaller that the expected 00055 * size of parameters::numberOfColors. 00056 */ 00057 class kMColorQuantization : public colorQuantization { 00058 public: 00059 00060 /** 00061 * the parameters for the class kMColorQuantization 00062 */ 00063 class parameters : public colorQuantization::parameters { 00064 public: 00065 /** 00066 * default constructor 00067 */ 00068 parameters(); 00069 00070 /** 00071 * copy constructor 00072 * @param other the parameters object to be copied 00073 */ 00074 parameters(const parameters& other); 00075 00076 /** 00077 * destructor 00078 */ 00079 ~parameters(); 00080 00081 /** 00082 * returns name of this type 00083 */ 00084 const char* getTypeName() const; 00085 00086 /** 00087 * copy the contents of a parameters object 00088 * @param other the parameters object to be copied 00089 * @return a reference to this parameters object 00090 */ 00091 parameters& copy(const parameters& other); 00092 00093 /** 00094 * copy the contents of a parameters object 00095 * @param other the parameters object to be copied 00096 * @return a reference to this parameters object 00097 */ 00098 parameters& operator=(const parameters& other); 00099 00100 00101 /** 00102 * returns a pointer to a clone of the parameters 00103 */ 00104 virtual functor::parameters* clone() const; 00105 00106 /** 00107 * write the parameters in the given ioHandler 00108 * @param handler the ioHandler to be used 00109 * @param complete if true (the default) the enclosing begin/end will 00110 * be also written, otherwise only the data block will be written. 00111 * @return true if write was successful 00112 */ 00113 virtual bool write(ioHandler& handler,const bool complete=true) const; 00114 00115 /** 00116 * write the parameters in the given ioHandler 00117 * @param handler the ioHandler to be used 00118 * @param complete if true (the default) the enclosing begin/end will 00119 * be also written, otherwise only the data block will be written. 00120 * @return true if write was successful 00121 */ 00122 virtual bool read(ioHandler& handler,const bool complete=true); 00123 00124 # ifdef _LTI_MSC_6 00125 /** 00126 * this function is required by MSVC only, as a workaround for a 00127 * very awful bug, which exists since MSVC V.4.0, and still by 00128 * V.6.0 with all bugfixes (so called "service packs") remains 00129 * there... This method is also public due to another bug, so please 00130 * NEVER EVER call this method directly: use read() instead 00131 */ 00132 bool readMS(ioHandler& handler,const bool complete=true); 00133 00134 /** 00135 * this function is required by MSVC only, as a workaround for a 00136 * very awful bug, which exists since MSVC V.4.0, and still by 00137 * V.6.0 with all bugfixes (so called "service packs") remains 00138 * there... This method is also public due to another bug, so please 00139 * NEVER EVER call this method directly: use write() instead 00140 */ 00141 bool writeMS(ioHandler& handler,const bool complete=true) const; 00142 # endif 00143 00144 // ------------------------------------------------ 00145 // the parameters 00146 // ------------------------------------------------ 00147 00148 /** 00149 * maximal number of iteration for the k-Means algorithm 00150 * (Default value: 50) 00151 */ 00152 int maximalNumberOfIterations; 00153 00154 /** 00155 * if "Palette-Changing" by iteration < thresholdDeltaPalette 00156 * than stop iterating 00157 * sum(distanceSqr(palNew-palOld)) 00158 * (Default value: 0.2) 00159 */ 00160 float thresholdDeltaPalette; 00161 00162 }; 00163 00164 /** 00165 * default constructor 00166 */ 00167 kMColorQuantization(); 00168 00169 /** 00170 * default constructor 00171 */ 00172 kMColorQuantization(const parameters& par); 00173 00174 /** 00175 * copy constructor 00176 */ 00177 kMColorQuantization(const kMColorQuantization& other); 00178 00179 /** 00180 * destructor 00181 */ 00182 virtual ~kMColorQuantization(); 00183 00184 /** 00185 * returns current parameters. 00186 */ 00187 const parameters& getParameters() const; 00188 00189 /** 00190 * copy data of "other" functor. 00191 */ 00192 kMColorQuantization& copy(const kMColorQuantization& other); 00193 00194 /** 00195 * returns a pointer to a clone of the functor. 00196 */ 00197 virtual functor* clone() const; 00198 00199 /** 00200 * returns the name of this type 00201 */ 00202 virtual const char* getTypeName() const; 00203 00204 /** 00205 * Apply 00206 * 00207 * @param src original image with the true-color data 00208 * @param dest matrix<int> where the indexes of the calculated palette 00209 * will be. 00210 * @param thePalette the color palette used by the matrix. If it is not 00211 * empty, it will be taken as a InitPalette for 00212 * the computation of the new one. 00213 * @return true if apply successful or false otherwise. 00214 */ 00215 bool apply(const image& src,matrix<int>& dest,palette& thePalette) const; 00216 00217 /** 00218 * Apply 00219 * 00220 * Operates on a copy of the given %parameters. 00221 * @param src original image with the true-color data 00222 * @param dest channel8 where the indexes of the also calculated palette 00223 * will be. 00224 * @param thePalette the color palette used by the channel. If it is not 00225 * empty, it will be taken as a InitPalette for 00226 * the computation of the new one. 00227 * @return true if apply successful or false otherwise. 00228 */ 00229 bool apply(const image& src,channel8& dest,palette& thePalette) const; 00230 00231 /** 00232 * Operates on the given %parameter. 00233 * 00234 * @param srcdest image with the source data. The result 00235 * will be left here too. 00236 * @return true if apply successful or false otherwise. 00237 */ 00238 bool apply(image& srcdest) const; 00239 00240 /** 00241 * Operates on the given %parameter. 00242 * 00243 * @param src image with the source data. 00244 * @param dest image with only the number of colors specified in 00245 * the parameters 00246 * @return true if apply successful or false otherwise. 00247 */ 00248 bool apply(const image& src,image& dest) const; 00249 00250 private: 00251 /** 00252 * functor to calculate the kMeans 00253 */ 00254 class kMeanColor { 00255 public: 00256 /** 00257 * constructor 00258 */ 00259 kMeanColor(const int& maxNumOfClasses, 00260 const int& maxIterations, 00261 const float& thresdDeltaPal); 00262 00263 /** 00264 * destructor 00265 */ 00266 virtual ~kMeanColor(); 00267 00268 /** 00269 * calculate palette and colorMap using k-Means. 00270 * img is the input image, and it will be modified to use 00271 * the quantized colors! 00272 */ 00273 bool operator() (const image& src,matrix<int>& dest,palette& thePalette); 00274 00275 protected: 00276 /** 00277 * an entry of the hash table contains the number of pixels in 00278 * the image that have the color corresponding to this entry (counter) 00279 * and the index of this color in the cetroid-vector; 00280 */ 00281 struct hashEntry { 00282 hashEntry(const int& idx=0,const int& cnt=0) 00283 : index(idx),counter(cnt) {}; 00284 int index; 00285 int counter; 00286 }; 00287 00288 /** 00289 * each entry of the hash has this type 00290 */ 00291 typedef std::map<int,hashEntry> hashMapType; 00292 00293 /** 00294 * hash table type (see theHash for more details). 00295 */ 00296 typedef hashMapType* hashType; 00297 00298 /** 00299 * the centroids 00300 */ 00301 vector<trgbPixel<float> > centroids; 00302 00303 /** 00304 * centroid elements 00305 */ 00306 vector<int> centerElems; 00307 00308 /** 00309 * The hash table. 00310 * 00311 * The hash table contains all relevant information of the image to be 00312 * quantized, necessary for the k-Mean algorithms. 00313 * 00314 * It is organized as an array of 4096 (12 bits) hashMapType elements. 00315 * 00316 * This array is then accessed with the lower 12 bits of the color 00317 * value. The upper 12 bits of the color are used to index the 00318 * proper map, that returns a hashEntry structure, with the correponding 00319 * centroid index for this color and the number of pixels assigned 00320 * to the centroid until now. 00321 * 00322 * In real world images, there will be an average between 5 and 10 00323 * elements per map. 00324 * 00325 * To access theHash directly, you can use the method at(), or put() 00326 */ 00327 hashType theHash; 00328 00329 /** 00330 * the maximal number of classes 00331 */ 00332 const int maxNumberOfClasses; 00333 00334 /** 00335 * the number of classes really used in the image 00336 */ 00337 int realNumberOfClasses; 00338 00339 /** 00340 * maximum number of iterations for the k-Means 00341 */ 00342 const int maxNumberOfIterations; 00343 00344 /** 00345 * if "Palette-Changing" by iteration < thresholdDeltaPalette 00346 * than stop iterating 00347 * sum(distanceSqr(palNew-palOld)) 00348 */ 00349 const float thresholdDeltaPalette; 00350 00351 /** 00352 * returns a reference to the hash entry for the given pixel 00353 */ 00354 inline hashEntry& at(const rgbPixel& px); 00355 00356 /** 00357 * put the given pixel in the hash table (increments the counter if 00358 * already exists). 00359 * @return true if the pixel is new added, false otherwise. 00360 */ 00361 inline bool put(const rgbPixel& px); 00362 00363 /** 00364 * create and initialize the hash table with the image values 00365 */ 00366 void initialize(const image& src); 00367 00368 /** 00369 * get initial palette from hash 00370 */ 00371 void getInitialPalette(const lti::palette& thePalette); 00372 00373 /** 00374 * iterate to find the clusters 00375 */ 00376 void iterate(); 00377 00378 /** 00379 * get a random color from the color hash 00380 */ 00381 rgbPixel getAnImageColor(); 00382 00383 /** 00384 * size of the maps array 00385 */ 00386 static const int firstKeySize; 00387 00388 /** 00389 * a counter to generate the random colors 00390 */ 00391 int lastHashPosition; 00392 00393 /** 00394 * Random number generator 00395 */ 00396 uniformDistribution uni; 00397 }; 00398 00399 }; 00400 00401 } 00402 00403 #endif