last update 20 Sep 2009 |
00001 /* 00002 * Copyright (C) 1998-2006 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * 00006 * This file is part of the Computer Vision and Robotics Library (CVR-Lib) 00007 * 00008 * The CVR-Lib is free software; you can redistribute it and/or 00009 * modify it under the terms of the BSD License. 00010 * 00011 * All rights reserved. 00012 * 00013 * Redistribution and use in source and binary forms, with or without 00014 * modification, are permitted provided that the following conditions are met: 00015 * 00016 * 1. Redistributions of source code must retain the above copyright notice, 00017 * this list of conditions and the following disclaimer. 00018 * 00019 * 2. Redistributions in binary form must reproduce the above copyright notice, 00020 * this list of conditions and the following disclaimer in the documentation 00021 * and/or other materials provided with the distribution. 00022 * 00023 * 3. Neither the name of the authors nor the names of its contributors may be 00024 * used to endorse or promote products derived from this software without 00025 * specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00028 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00029 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00030 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00031 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00032 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00033 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00034 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00035 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00036 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00037 * POSSIBILITY OF SUCH DAMAGE. 00038 */ 00039 00040 00041 /** 00042 * \file cvrKMColorQuantization.h 00043 * Contains a class for color quantization using the k-Means algorithm. 00044 * \author Pablo Alvarado 00045 * \date 30.04.1999 (CVR-Lib 1) 00046 * \date 12.01.2006 (CVR-Lib ) 00047 * 00048 * $Id: cvrKMColorQuantization.h,v 1.2 2006/01/15 22:15:27 alvarado Exp $ 00049 */ 00050 00051 00052 #ifndef _CVR_KM_COLOR_QUANTIZATION_H_ 00053 #define _CVR_KM_COLOR_QUANTIZATION_H_ 00054 00055 #include "cvrFunctor.h" 00056 #include "cvrImage.h" 00057 #include "cvrTypes.h" 00058 #include "cvrVector.h" 00059 #include "cvrColorQuantization.h" 00060 #include "cvrRGBPixel.h" 00061 #include <map> 00062 00063 namespace cvr { 00064 /** 00065 * k-Means based color quantization. 00066 * 00067 * This functor calculates (using k-Means) an optimal color subpalette for 00068 * the input image. The maximal number of colors to be used is given 00069 * through the parameters (inherited from colorQuantization::parameters). 00070 * 00071 * If the real number of colors used in the image is less than the desired 00072 * number of quantized colors, no quantization is done and the output palette 00073 * will contain all image colors, i.e. it will be smaller that the expected 00074 * size of parameters::numberOfColors. 00075 * 00076 * @ingroup gColorQuantization 00077 */ 00078 class kMColorQuantization : public colorQuantization { 00079 public: 00080 00081 /** 00082 * the parameters for the class kMColorQuantization 00083 */ 00084 class parameters : public colorQuantization::parameters { 00085 public: 00086 /** 00087 * default constructor 00088 */ 00089 parameters(); 00090 00091 /** 00092 * copy constructor 00093 * @param other the parameters object to be copied 00094 */ 00095 parameters(const parameters& other); 00096 00097 /** 00098 * destructor 00099 */ 00100 ~parameters(); 00101 00102 00103 /** 00104 * Returns the name of this type 00105 */ 00106 virtual const std::string& name() const; 00107 00108 /** 00109 * Returns a pointer to a clone of the parameters 00110 */ 00111 virtual parameters* clone() const; 00112 00113 /** 00114 * Returns a pointer to a new instance of the parameters 00115 */ 00116 virtual parameters* newInstance() const; 00117 00118 /** 00119 * Copy the other instance.here. 00120 */ 00121 parameters& copy(const parameters& other); 00122 00123 /** 00124 * Copy the contents of a parameters object. 00125 * 00126 * @param other the parameters object to be copied 00127 * @return a reference to this parameters object 00128 */ 00129 parameters& operator=(const parameters& other); 00130 00131 /** 00132 * write the parameters in the given ioHandler 00133 * @param handler the ioHandler to be used 00134 * @param complete if true (the default) the enclosing begin/end will 00135 * be also written, otherwise only the data block will be written. 00136 * @return true if write was successful 00137 */ 00138 virtual bool write(ioHandler& handler,const bool complete=true) const; 00139 00140 /** 00141 * write the parameters in the given ioHandler 00142 * @param handler the ioHandler to be used 00143 * @param complete if true (the default) the enclosing begin/end will 00144 * be also written, otherwise only the data block will be written. 00145 * @return true if write was successful 00146 */ 00147 virtual bool read(ioHandler& handler,const bool complete=true); 00148 00149 // ------------------------------------------------ 00150 // the parameters 00151 // ------------------------------------------------ 00152 00153 /** 00154 * Maximal number of iterations taken for the k-Means algorithm to 00155 * converge. 00156 * 00157 * Default value: 50 00158 */ 00159 int maximalNumberOfIterations; 00160 00161 /** 00162 * Smallest change of palette. 00163 * 00164 * If the difference between the palette in the previous iteration 00165 * and the palette in the current iteration is smaller than this value 00166 * then it will be assumed that the algorithm has converged. 00167 * 00168 * The difference is computed as the sum of the distances between 00169 * corresponding entries of the palette, taken in the RGB color space, 00170 * with an L2 distance, i.e. sum(distanceSqr(palNew-palOld)). 00171 * 00172 * Note that the axes of the RGB space are dimensioned from 0 to 255. 00173 * 00174 * Default value: 0.2 00175 */ 00176 float thresholdDeltaPalette; 00177 00178 }; 00179 00180 /** 00181 * Default constructor 00182 */ 00183 kMColorQuantization(); 00184 00185 /** 00186 * Constructor with parameters 00187 */ 00188 kMColorQuantization(const parameters& par); 00189 00190 /** 00191 * Copy constructor 00192 */ 00193 kMColorQuantization(const kMColorQuantization& other); 00194 00195 /** 00196 * Destructor 00197 */ 00198 virtual ~kMColorQuantization(); 00199 00200 /** 00201 * Returns current parameters. 00202 */ 00203 const parameters& getParameters() const; 00204 00205 /** 00206 * Returns the name of this type. 00207 */ 00208 virtual const std::string& name() const; 00209 00210 /** 00211 * Copy data of "other" functor. 00212 * 00213 * @param other the functor to be copied 00214 * @return a reference to this functor object 00215 */ 00216 kMColorQuantization& copy(const kMColorQuantization& other); 00217 00218 /** 00219 * Returns a pointer to a clone of this functor. 00220 */ 00221 virtual kMColorQuantization* clone() const; 00222 00223 /** 00224 * Returns a pointer to a clone of this functor. 00225 */ 00226 virtual kMColorQuantization* newInstance() const; 00227 00228 00229 /** 00230 * Quantize the colors of src and leave the labels for the quantized colors 00231 * in dest, and in the palette entries corresponding to the labels the 00232 * mean colors for each label. 00233 * 00234 * @param src Original image with the true-color data 00235 * @param dest channel8 where the indexes of the also calculated palette 00236 * will be. 00237 * @param thePalette the color palette used by the channel. If it is not 00238 * empty, it will be taken as a InitPalette for 00239 * the computation of the new one. 00240 * @return true if apply successful or false otherwise. 00241 */ 00242 virtual bool apply(const image& src, 00243 matrix<ubyte>& dest, 00244 palette& thePalette) const; 00245 00246 00247 /** 00248 * Quantize the colors of src and leave the labels for the quantized colors 00249 * in dest, and in the palette entries corresponding to the labels the 00250 * mean colors for each label. 00251 * 00252 * @param src Original image with the true-color data 00253 * @param dest matrix<int> where the indexes of the calculated palette 00254 * will be. 00255 * @param thePalette The color palette used by the matrix. If it is not 00256 * empty, it will be taken as a InitPalette for 00257 * the computation of the new one. 00258 * @return true if apply successful or false otherwise. 00259 */ 00260 virtual bool apply(const image& src, 00261 matrix<int>& dest, 00262 palette& thePalette) const; 00263 00264 00265 /** 00266 * Quantize the colors of the given image. 00267 * 00268 * @param srcdest image with the source data. The result 00269 * will be left here too. 00270 * @return true if apply successful or false otherwise. 00271 */ 00272 virtual bool apply(image& srcdest) const; 00273 00274 /** 00275 * Quantize the colors of the given src image and leave the result in dest. 00276 * 00277 * @param src image with the source data. 00278 * @param dest image with only the number of colors specified in 00279 * the parameters 00280 * @return true if apply successful or false otherwise. 00281 */ 00282 virtual bool apply(const image& src,image& dest) const; 00283 00284 private: 00285 /** 00286 * functor to calculate the kMeans 00287 */ 00288 class kMeanColor { 00289 public: 00290 /** 00291 * constructor 00292 */ 00293 kMeanColor(const int& maxNumOfClasses, 00294 const int& maxIterations, 00295 const float& thresdDeltaPal); 00296 00297 /** 00298 * destructor 00299 */ 00300 virtual ~kMeanColor(); 00301 00302 /** 00303 * calculate palette and colorMap using k-Means. 00304 * img is the input image, and it will be modified to use 00305 * the quantized colors! 00306 */ 00307 bool operator()(const image& src,matrix<int>& dest,palette& thePalette); 00308 00309 protected: 00310 /** 00311 * An entry of the hash table contains the number of pixels in 00312 * the image that have the color corresponding to this entry (counter) 00313 * and the index of this color in the cetroid-vector; 00314 */ 00315 struct hashEntry { 00316 hashEntry(const int& idx=0,const int& cnt=0) 00317 : index(idx),counter(cnt) {}; 00318 int index; 00319 int counter; 00320 }; 00321 00322 /** 00323 * Each entry of the hash has this type 00324 */ 00325 typedef std::map<int,hashEntry> hashMapType; 00326 00327 /** 00328 * Hash table type (see theHash for more details). 00329 */ 00330 typedef hashMapType* hashType; 00331 00332 /** 00333 * the centroids 00334 */ 00335 vector< frgbPixel > centroids_; 00336 00337 /** 00338 * centroid elements 00339 */ 00340 vector<int> centerElems_; 00341 00342 /** 00343 * The hash table. 00344 * 00345 * The hash table contains all relevant information of the image to be 00346 * quantized, necessary for the k-Mean algorithms. 00347 * 00348 * It is organized as an array of 4096 (12 bits) hashMapType elements. 00349 * 00350 * This array is then accessed with the lower 12 bits of the color 00351 * value. The upper 12 bits of the color are used to index the 00352 * proper map, that returns a hashEntry structure, with the correponding 00353 * centroid index for this color and the number of pixels assigned 00354 * to the centroid until now. 00355 * 00356 * In real world images, there will be an average between 5 and 10 00357 * elements per map. 00358 * 00359 * To access theHash directly, you can use the method at(), or put() 00360 */ 00361 hashType theHash_; 00362 00363 /** 00364 * the maximal number of classes 00365 */ 00366 const int maxNumberOfClasses_; 00367 00368 /** 00369 * the number of classes really used in the image 00370 */ 00371 int realNumberOfClasses_; 00372 00373 /** 00374 * maximum number of iterations for the k-Means 00375 */ 00376 const int maxNumberOfIterations_; 00377 00378 /** 00379 * if "Palette-Changing" by iteration < thresholdDeltaPalette 00380 * than stop iterating 00381 * sum(distanceSqr(palNew-palOld)) 00382 */ 00383 const float thresholdDeltaPalette_; 00384 00385 /** 00386 * returns a reference to the hash entry for the given pixel 00387 */ 00388 inline hashEntry& at(const rgbaPixel& px); 00389 00390 /** 00391 * put the given pixel in the hash table (increments the counter if 00392 * already exists). 00393 * @return true if the pixel is new added, false otherwise. 00394 */ 00395 inline bool put(const rgbaPixel& px); 00396 00397 /** 00398 * create and initialize the hash table with the image values 00399 */ 00400 void initialize(const image& src); 00401 00402 /** 00403 * get initial palette from hash 00404 */ 00405 void getInitialPalette(const cvr::palette& thePalette); 00406 00407 /** 00408 * iterate to find the clusters 00409 */ 00410 void iterate(); 00411 00412 /** 00413 * get a random color from the color hash 00414 */ 00415 rgbaPixel getAnImageColor(); 00416 00417 /** 00418 * size of the maps array 00419 */ 00420 static const int firstKeySize_; 00421 00422 /** 00423 * a counter to generate the random colors 00424 */ 00425 int lastHashPosition_; 00426 00427 /** 00428 * Random number generator from 0.0 to 1.0 00429 */ 00430 double random() const; 00431 }; 00432 00433 }; 00434 00435 } 00436 00437 #endif