latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 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-Lib: Image Processing and Computer Vision Library 00026 * file .......: ltiColorACASegmentation.h 00027 * authors ....: Pablo Alvarado 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 6.1.2004 00030 * revisions ..: $Id: ltiColorACASegmentation.h,v 1.4 2006/02/07 18:37:27 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_COLOR_A_C_A_SEGMENTATION_H_ 00034 #define _LTI_COLOR_A_C_A_SEGMENTATION_H_ 00035 00036 #include "ltiImage.h" 00037 #include "ltiSegmentation.h" 00038 #include "ltiKMColorQuantization.h" 00039 00040 #include <vector> 00041 00042 namespace lti { 00043 /** 00044 * Color Adaptive Clustering Algorithm. 00045 * 00046 * This functor provides a segmentation algorithm based on the Adaptive 00047 * Clustering Algorithm (ACA) proposed by Thrasyvoulos N. Pappas in 00048 * his paper "An adaptive clustering algorithm for image segmentation", 00049 * IEEE Transactions on signal processing, vol. 40, No. 4, april 1992. 00050 * 00051 * Even if in the original version the algorithm has been applied to 00052 * gray valued images, the current implementation has been adapted for the 00053 * segmentation of color images. 00054 * 00055 * The algorithm first generates an image pyramid for the input. For the 00056 * smallest image a k-Means color clustering is done, and a labeling 00057 * procedure assigns to each pixel the corresponding label. 00058 * 00059 * Using this first segmentation proposal and the current window 00060 * size (initially the whole image) it generates a new estimation of the 00061 * expected mean values for each pixel. With the new mean values compute the 00062 * a-posteriori probabilities for each pixel to belong to any of the classes 00063 * and compute with them a new segmentation hypothesis. 00064 * 00065 * Repeat the estimation of the expected values and the new 00066 * segmentation until the algorithm converges or only a small number 00067 * of changes has been done in the last iteration. 00068 * 00069 * Reduce the window size and begin the iterations again, until the minimum 00070 * window size is reached. 00071 * 00072 * Now duplicate the size of the segmentation result and use it as 00073 * initialization for the next iteration using the next pyramid 00074 * level. 00075 * 00076 * The whole process is repeated until the highest resolution level has 00077 * been analyzed. 00078 * 00079 * Note that this algorithm is very slow. It is implemented to 00080 * provide a comparison possibility with your own algorithms. 00081 * 00082 */ 00083 class colorACASegmentation : public segmentation { 00084 public: 00085 /** 00086 * The parameters for the class colorACASegmentation 00087 */ 00088 class parameters : public segmentation::parameters { 00089 public: 00090 /** 00091 * Default constructor 00092 */ 00093 parameters(); 00094 00095 /** 00096 * Copy constructor 00097 * @param other the parameters object to be copied 00098 */ 00099 parameters(const parameters& other); 00100 00101 /** 00102 * Destructor 00103 */ 00104 ~parameters(); 00105 00106 /** 00107 * Returns name of this type 00108 */ 00109 const char* getTypeName() const; 00110 00111 /** 00112 * Copy the contents of a parameters object 00113 * @param other the parameters object to be copied 00114 * @return a reference to this parameters object 00115 */ 00116 parameters& copy(const parameters& other); 00117 00118 /** 00119 * Copy the contents of a parameters object 00120 * @param other the parameters object to be copied 00121 * @return a reference to this parameters object 00122 */ 00123 parameters& operator=(const parameters& other); 00124 00125 00126 /** 00127 * Returns a pointer to a clone of the parameters 00128 */ 00129 virtual functor::parameters* clone() const; 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 * Read the parameters from 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 # ifdef _LTI_MSC_6 00150 /** 00151 * This function is required by MSVC only, as a workaround for a 00152 * very awful bug, which exists since MSVC V.4.0, and still by 00153 * V.6.0 with all bugfixes (so called "service packs") remains 00154 * there... This method is also public due to another bug, so please 00155 * NEVER EVER call this method directly: use read() instead 00156 */ 00157 bool readMS(ioHandler& handler,const bool complete=true); 00158 00159 /** 00160 * This function is required by MSVC only, as a workaround for a 00161 * very awful bug, which exists since MSVC V.4.0, and still by 00162 * V.6.0 with all bugfixes (so called "service packs") remains 00163 * there... This method is also public due to another bug, so please 00164 * NEVER EVER call this method directly: use write() instead 00165 */ 00166 bool writeMS(ioHandler& handler,const bool complete=true) const; 00167 # endif 00168 00169 // ------------------------------------------------ 00170 // the parameters 00171 // ------------------------------------------------ 00172 00173 /** 00174 * Number of levels in the pyramid. 00175 * 00176 * This value \b must be greater or equal one. 00177 * 00178 * Default value: 4 00179 */ 00180 int levels; 00181 00182 /** 00183 * Parameters for the kMeans quantization. 00184 * 00185 * The number of means used in the whole algorithm will be given by 00186 * the attribute kMColorQuantization::parameters::numberOfColors. 00187 * 00188 * Default value: all default values except numberOfColors, which is set 00189 * to 16. 00190 */ 00191 kMColorQuantization::parameters kMeansParam; 00192 00193 /** 00194 * Beta factor used in the Gibbs distribution model for the spatial 00195 * consideration. 00196 * 00197 * Default value: 0.5 00198 */ 00199 float beta; 00200 00201 /** 00202 * A-Priori label membership. 00203 * 00204 * If empty, all labels are equiprobable. If not empty, for those labels 00205 * with an entry, this corresponds to the one-pixel clique potentials. 00206 * 00207 * Default value: empty vector 00208 */ 00209 fvector alpha; 00210 00211 /** 00212 * Standard deviation of Gaussian white distribution assumed for the 00213 * region noise. 00214 * 00215 * Since the value range of the data is between 0 and 255, you can 00216 * consider this value as the deviation brightness expected in each 00217 * of the R,G and B color channels. 00218 * 00219 * Default value: 5 00220 */ 00221 float sigma; 00222 00223 /** 00224 * Convergence criterion for a \e cycle. 00225 * 00226 * After the mean values has been estimated, the new segmentation has 00227 * to be computed using an iterative procedure that uses the previous 00228 * segmentation as suggestion and continues until less than the given 00229 * percentage of totall image pixels change. 00230 * 00231 * Note that this value is usually much smaller than one. 00232 * 00233 * Default value: 0.0004f 00234 */ 00235 float convergenceCriterion; 00236 00237 /** 00238 * Threshold minimum. 00239 * 00240 * The real threshold is computed multiplying this value by the current 00241 * window width. 00242 * 00243 * If the number of pixels in a window that belong to the current label 00244 * is less than the computed threshold, the current pixel is marked as 00245 * undefined and the desition to which level it will belong will be made 00246 * according to spatial conditiions only (based on a MRF). 00247 * 00248 * Default value: 1.0 00249 */ 00250 float tMin; 00251 00252 /** 00253 * Maximum number of iterations with the same window size 00254 * 00255 * This parameter controls how much iteration will be done with the 00256 * same window size of mean-estimation + segmentation-estimation steps. 00257 * 00258 * Default value: 20 00259 */ 00260 int nMax; 00261 00262 /** 00263 * The positioning of the window centroids will be computing 00264 * using this overlap factor. If zero is given, the windows 00265 * will be place side by side. If one is given the windows will be 00266 * computed for each pixel in the image, which is very expensive. 00267 * 00268 * Pappas suggests the use of 0.5f. 00269 * 00270 * Default value: 0.5f 00271 */ 00272 float windowOverlap; 00273 00274 /** 00275 * Initial window size as percentage of the minimum of the image 00276 * dimensions. 00277 * 00278 * Default value: 1.0f 00279 */ 00280 float firstWindowSize; 00281 00282 /** 00283 * Absolute minimum window size. 00284 * 00285 * The window size will be reduce until it is smaller that this size. 00286 * 00287 * Default value: 7 00288 */ 00289 int lastWindowSize; 00290 00291 /** 00292 * Multiplicative window size step change. 00293 * 00294 * This values must be possitive and strictly smaller than one. 00295 * 00296 * If you set the value outsize this range, no window iteration sizes 00297 * will be done, and the algorithm will behave like a k-Means clustering 00298 * (but very slow). 00299 * 00300 * Default value 0.5 00301 */ 00302 float windowSizeStep; 00303 00304 }; 00305 00306 /** 00307 * Default constructor 00308 */ 00309 colorACASegmentation(); 00310 00311 /** 00312 * Construct a functor using the given parameters 00313 */ 00314 colorACASegmentation(const parameters& par); 00315 00316 /** 00317 * Copy constructor 00318 * @param other the object to be copied 00319 */ 00320 colorACASegmentation(const colorACASegmentation& other); 00321 00322 /** 00323 * Destructor 00324 */ 00325 virtual ~colorACASegmentation(); 00326 00327 /** 00328 * Returns the name of this type ("colorACASegmentation") 00329 */ 00330 virtual const char* getTypeName() const; 00331 00332 /** 00333 * Segmentates the \a srcdest image and replaces it with the 00334 * estimated mean values. 00335 * 00336 * @param srcdest image with the source data. The result 00337 * will be left here too. 00338 * @return true if apply successful or false otherwise. 00339 */ 00340 bool apply(image& srcdest) const; 00341 00342 /** 00343 * Segmentates the image \a src and compute the estimated mean 00344 * values. 00345 * 00346 * @param src image with the source data. 00347 * @param dest image with the smooth changing means per region. 00348 * @return true if apply successful or false otherwise. 00349 */ 00350 bool apply(const image& src,image& dest) const; 00351 00352 /** 00353 * Segmentates the image and computes the labeled mask, with labels between 00354 * 0 and parameters::kMeansParam::numberOfColors - 1. Additionally, the 00355 * estimated mean values will be computed. 00356 * 00357 * Note that the result differs from other segmentation approaches in the 00358 * fact that the functor doesn't compute a palette, since the values within 00359 * a region are allowed to slowly change. 00360 * 00361 * @param src image with the source data 00362 * @param mask imatrix with the labels for each region 00363 * @param means image with the estimated mean values per pixel. 00364 */ 00365 bool apply(const image& src,imatrix& mask,image& means) const; 00366 00367 /** 00368 * Segmentates the image and computes the labeled mask, with labels between 00369 * 0 and parameters::kMeansParam::numberOfColors - 1. Additionally, the 00370 * estimated mean values will be computed. 00371 * 00372 * Note that the result differs from other segmentation approaches in the 00373 * fact that the functor doesn't compute a palette, since the values within 00374 * a region are allowed to slowly change. 00375 * 00376 * @param src image with the source data 00377 * @param mask imatrix with the labels for each region 00378 */ 00379 bool apply(const image& src,imatrix& mask) const; 00380 00381 /** 00382 * Copy data of "other" functor. 00383 * @param other the functor to be copied 00384 * @return a reference to this functor object 00385 */ 00386 colorACASegmentation& copy(const colorACASegmentation& other); 00387 00388 /** 00389 * Alias for copy member 00390 * @param other the functor to be copied 00391 * @return a reference to this functor object 00392 */ 00393 colorACASegmentation& operator=(const colorACASegmentation& other); 00394 00395 /** 00396 * Returns a pointer to a clone of this functor. 00397 */ 00398 virtual functor* clone() const; 00399 00400 /** 00401 * Returns used parameters 00402 */ 00403 const parameters& getParameters() const; 00404 00405 /** 00406 * Set the parameters 00407 */ 00408 bool setParameters(const functor::parameters& param); 00409 00410 protected: 00411 /** 00412 * Segmentates the image and computes the labeled mask, with labels between 00413 * 0 and parameters::kMeansParam::numberOfColors - 1. Additionally, the 00414 * estimated mean values will be computed. 00415 * 00416 * Note that the result differs from other segmentation approaches in the 00417 * fact that the functor doesn't compute a palette, since the values within 00418 * a region are allowed to slowly change. 00419 * 00420 * @param src image with the source data 00421 * @param mask imatrix with the labels for each region 00422 * @param means image with the estimated mean values per pixel. 00423 * @param computeMeans compute image with means 00424 * @return true if successful, false otherwise. 00425 */ 00426 bool aca(const image& src,imatrix& mask,image& means, 00427 const bool computeMeans) const; 00428 00429 /** 00430 * Initialize the segmentation using k-Means. 00431 * 00432 * The argument \a mask represents the variable \a x in the original paper 00433 */ 00434 bool kMeansInit(const image& src, imatrix& mask) const; 00435 00436 /** 00437 * Estimates the means channel using linear interpolation of the support 00438 * points at the grid, using a window of the given size. 00439 * 00440 * The means image vector must have the proper size when initialized: 00441 * parameters::kMeansParam::numberOfColors 00442 */ 00443 bool estimateMeans(const image& src, 00444 const imatrix& mask, 00445 std::vector<image>& means, 00446 const int windowSize, 00447 const int gridSize, 00448 const int tMin) const; 00449 00450 /** 00451 * Interpolate all pixels not at the grid points using bilinear 00452 * interpolation. 00453 */ 00454 bool interpolate(image& src, 00455 const int gridSize) const; 00456 00457 /** 00458 * Estimate segmentation given the means 00459 */ 00460 bool estimateSegmentation(const image& src, 00461 const std::vector<image>& means, 00462 const float gfactor, 00463 imatrix& mask, 00464 int& cycles) const; 00465 00466 /** 00467 * Compute label. 00468 * 00469 * @param src original image 00470 * @param means the mean values for each label 00471 * @param mask initial segmentation 00472 * @param p point to be evaluated 00473 * @param from which neighbor should be considered first 00474 * @param to which neighbor should be considered last 00475 * @param gfactor must be -1/2*sigma^2 00476 * @param numChanges number of changes taken in the iteration. 00477 * @return label that maximizes the a posteriori probability 00478 */ 00479 inline int computeLabel(const image& src, 00480 const std::vector<image>& means, 00481 const imatrix& mask, 00482 const point& p, 00483 const int from, 00484 const int to, 00485 const float gfactor, 00486 int& numChanges) const; 00487 /** 00488 * Estimate segmentation given the means 00489 */ 00490 bool estimateSegmentationStep(const image& src, 00491 const std::vector<image>& means, 00492 const float gfactor, 00493 imatrix& mask, 00494 imatrix& nmask, 00495 int& numChanges) const; 00496 00497 /** 00498 * Create an image containing the appropriate mean values 00499 */ 00500 bool createMeanImage(const std::vector<image>& lmeans, 00501 const imatrix mask, 00502 image& means) const; 00503 00504 private: 00505 /** 00506 * Constants 00507 * 00508 * One point clique constants. This has always a length numberOfColors 00509 */ 00510 fvector alpha; 00511 00512 /** 00513 * Constant 00514 * 00515 * Potential for the two-point cliques. 00516 */ 00517 float beta; 00518 00519 }; 00520 } 00521 00522 #endif