latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 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 .......: ltiSegmentationEvaluation.h 00027 * authors ....: Pablo Alvarado 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 25.11.2003 00030 * revisions ..: $Id: ltiSegmentationEvaluation.h,v 1.1 2006/03/10 02:53:11 alvarado Exp $ 00031 */ 00032 00033 #ifndef _LTI_SEGMENTATION_EVALUATION_TESTER_H_ 00034 #define _LTI_SEGMENTATION_EVALUATION_TESTER_H_ 00035 00036 #include "ltiParetoFront.h" 00037 #include "ltiImage.h" 00038 00039 namespace lti { 00040 00041 /** 00042 * Pareto evaluation of segmentation functors. 00043 * 00044 * This abstract class provides a basic framework for the evaluation of 00045 * segmentation algorithms. The functor evaluates a result comparing it 00046 * with some ground truth data, but it does not know anything about the 00047 * parameterization of any algorithm, which should be done by derived 00048 * classes. 00049 * 00050 * Several measures are provided to evaluate the algorithms: 00051 * - numberOfRegions 00052 * - numRegionsReciprocal (1/number of regions) 00053 * - pixelWisePotentialAccuracy 00054 * - objectWisePotentialAccuracy 00055 * - regionWiseInformationContent 00056 * - throughput 00057 * - regionIntegrity 00058 * - pixelWiseCertainty 00059 * 00060 * For the evaluation of a parameterization the algorithm takes all 00061 * images stored in the file specified in parameters::images. 00062 * 00063 * Following five methods have to be reimplemented in derived classes: 00064 * 00065 * For the pareto front interface 00066 * - chromosomeToPhenotype() 00067 * - phenotypeToChromosome() 00068 * - getChromosomeSize() 00069 * 00070 * For the real segmentation task 00071 * - init() 00072 * - segment() 00073 * - getInstanceOfParam() 00074 * 00075 * In the parameters you should define two sets of values for minimum and 00076 * maximum tolerable values (usually called minValues and maxValues). The 00077 * chromosomeToPhenotype method has to take care that the values produced 00078 * lie in the corresponding intervals. 00079 * 00080 * The definition of the used fitness measures can be found in the paper: 00081 * 00082 * Mark Everingham, Henk Muller and Barry Thomas, 00083 * "Evaluating Image Segmentation Algoritnms using the Pareto Front". 00084 * Proceedings of the 7th European Conference on Computer Vision, 00085 * 2002. 00086 * 00087 * except the region integrity and pixel-wise certainty, which are described 00088 * in 00089 * 00090 * Pablo Alvarado, "Segmentation of color images for interactive 3D 00091 * object retrieval", Dissertation, Aachen, 2004. 00092 */ 00093 class segmentationEvaluation : public paretoFront { 00094 public: 00095 00096 /** 00097 * The parameters for the class segmentationEvaluation 00098 */ 00099 class parameters : public paretoFront::parameters { 00100 public: 00101 /** 00102 * Default constructor 00103 */ 00104 parameters(); 00105 00106 /** 00107 * Copy constructor 00108 * @param other the parameters object to be copied 00109 */ 00110 parameters(const parameters& other); 00111 00112 /** 00113 * Destructor 00114 */ 00115 ~parameters(); 00116 00117 /** 00118 * Returns name of this type 00119 */ 00120 const char* getTypeName() const; 00121 00122 /** 00123 * Copy the contents of a parameters object 00124 * @param other the parameters object to be copied 00125 * @return a reference to this parameters object 00126 */ 00127 parameters& copy(const parameters& other); 00128 00129 /** 00130 * Copy the contents of a parameters object 00131 * @param other the parameters object to be copied 00132 * @return a reference to this parameters object 00133 */ 00134 parameters& operator=(const parameters& other); 00135 00136 00137 /** 00138 * Returns a pointer to a clone of the parameters 00139 */ 00140 virtual functor::parameters* clone() const; 00141 00142 /** 00143 * Write the parameters in the given ioHandler 00144 * @param handler the ioHandler to be used 00145 * @param complete if true (the default) the enclosing begin/end will 00146 * be also written, otherwise only the data block will be written. 00147 * @return true if write was successful 00148 */ 00149 virtual bool write(ioHandler& handler,const bool& complete=true) const; 00150 00151 /** 00152 * Read the parameters from the given ioHandler 00153 * @param handler the ioHandler to be used 00154 * @param complete if true (the default) the enclosing begin/end will 00155 * be also written, otherwise only the data block will be written. 00156 * @return true if write was successful 00157 */ 00158 virtual bool read(ioHandler& handler,const bool& complete=true); 00159 00160 # ifdef _LTI_MSC_6 00161 /** 00162 * This function is required by MSVC only, as a workaround for a 00163 * very awful bug, which exists since MSVC V.4.0, and still by 00164 * V.6.0 with all bugfixes (so called "service packs") remains 00165 * there... This method is also public due to another bug, so please 00166 * NEVER EVER call this method directly: use read() instead 00167 */ 00168 bool readMS(ioHandler& handler,const bool& complete=true); 00169 00170 /** 00171 * This function is required by MSVC only, as a workaround for a 00172 * very awful bug, which exists since MSVC V.4.0, and still by 00173 * V.6.0 with all bugfixes (so called "service packs") remains 00174 * there... This method is also public due to another bug, so please 00175 * NEVER EVER call this method directly: use write() instead 00176 */ 00177 bool writeMS(ioHandler& handler,const bool& complete=true) const; 00178 # endif 00179 00180 // ------------------------------------------------ 00181 // the parameters 00182 // ------------------------------------------------ 00183 00184 /** 00185 * @name Fitness measures 00186 * 00187 * Value containing the 1D fitness measures to be computed. 00188 * The constants defined here are: 00189 * - numberOfRegions 00190 * - numRegionsReciprocal (1/number of regions) 00191 * - pixelWisePotentialAccuracy 00192 * - objectWisePotentialAccuracy 00193 * - regionWiseInformationContent 00194 * - throughput (1/time) 00195 * - region integrity 00196 * - pixelWiseCertainty 00197 * 00198 * This sequence is important, since it determines the positions of 00199 * the single measures in the fitness output vector. 00200 * 00201 * If more fitness measures are selected than the inherited parameter 00202 * fitnessSpaceDimensionality, then the first ones in this sequence 00203 * will be selected. 00204 * 00205 * If less fitness measure are selected than the inherited parameter 00206 * fitnessSpaceDimensionality, then the rest of the vector will be 00207 * filled with zeros. 00208 */ 00209 //@{ 00210 /** 00211 * Total number of regiong detected per image. 00212 * 00213 * This is usually a cost, and therefore you will never want to optimize 00214 * the number of regions as if it were a fitness, but, in some 00215 * applications, it may be necessary to search for the optimal 00216 * "over-segmentations", which will therefore use this as fitness. 00217 * 00218 * Default value: false 00219 */ 00220 bool numberOfRegions; 00221 00222 /** 00223 * Reciprocal for the number of regions 00224 * 00225 * This is the inverse of the number of regions (1/number of regions). 00226 * Usually you want the get the less possible number of regions that 00227 * still don't merge different objects while partitioning an image. 00228 * 00229 * This can be interpreted as the mean size of the regions normalized 00230 * to the size of the image. 00231 * 00232 * Default value: true 00233 */ 00234 bool numRegionsReciprocal; 00235 00236 /** 00237 * Pixel-wise potential accuracy. 00238 * 00239 * Describes the percentange of the image pixels than can be optimally 00240 * assigned to one of the ground-truth regions. 00241 * 00242 * This can be interpreted as a measure inversely proportional to the 00243 * degree of undersegmentation. 00244 * 00245 * Default value: true 00246 */ 00247 bool pixelWisePotentialAccuracy; 00248 00249 /** 00250 * Object-wise potential accuracy. 00251 * 00252 * Like pixel-wise potential accuracy but the contribution of each 00253 * reference region is normalized to its size so that all regions in 00254 * the reference segmentation are equally important. 00255 * 00256 * Default value: false 00257 */ 00258 bool objectWisePotentialAccuracy; 00259 00260 /** 00261 * Region-wise information content. 00262 * 00263 * Proportion of the reference region covered by each single region. 00264 * 00265 * Default value: false 00266 */ 00267 bool regionWiseInformationContent; 00268 00269 /** 00270 * Throughput 00271 * 00272 * Number of images segmented per second. 00273 * 00274 * Default value: false 00275 */ 00276 bool throughput; 00277 00278 /** 00279 * Region integrity 00280 * 00281 * Measures the number of regions mapped to a reference region. The 00282 * function used punishes over- and under-segmentation. 00283 * 00284 * Default value: false 00285 */ 00286 bool regionIntegrity; 00287 00288 /** 00289 * Pixel-wise certainty 00290 * 00291 * This makes only sense for some segmentation functors, that can deliver 00292 * the certainty with which a pixel was assigned to a label. 00293 * 00294 * Default value: false 00295 */ 00296 bool pixelWiseCertainty; 00297 //@} 00298 00299 /** 00300 * Name of a file containing all images to be analyzed. 00301 * 00302 * Default value: "images.txt" 00303 */ 00304 std::string images; 00305 00306 /** 00307 * Mask postfix 00308 * 00309 * For each image file in \a images, a manual segmented mask is required 00310 * as "ground truth". 00311 * 00312 * The filename of the masks will be assumed to be the same 00313 * image name with the given postfix. For example, if an image is 00314 * called "test.png" and the postfix is "-preseg", then the 00315 * mask will be assumed to be "test-preseg.png". 00316 * 00317 * Default value: "_premask" 00318 */ 00319 std::string goldenPostfix; 00320 00321 /** 00322 * Previous Mask Postfix. 00323 * 00324 * To save evaluation time, the test of higher-level algorithm can load 00325 * the lower-level segmentations of the images in a file with this 00326 * postfix and type lti (see lti::ltiFunctor), which is the only format 00327 * that can save imatrices. For example, if an image is called 00328 * "test.png" and the prevStagePostfix is "-ibs", then the mask will 00329 * be assumed to be in "test-ibs.lti". 00330 * 00331 * If no file is found with these names, then a low-level segmentation 00332 * will be assumed, which does not require any previous masks. 00333 * 00334 * Default value: "_ibs" 00335 */ 00336 std::string prevStagePostfix; 00337 00338 /** 00339 * @name Fitness parameterizations 00340 */ 00341 //@{ 00342 /** 00343 * Minimal size for valid region 00344 * 00345 * Percentage of the image size that defines the minimal size of a 00346 * region to be considered in the statistics for region-wise information 00347 * content and object-wise potential accuracy. 00348 * 00349 * This value must be between 0 and 1. 00350 * 00351 * Default: 0.0005 (i.e. 0.05%) 00352 */ 00353 float minValidRegionSize; 00354 //@} 00355 }; 00356 00357 /** 00358 * Default constructor 00359 */ 00360 segmentationEvaluation(); 00361 00362 /** 00363 * Construct a functor using the given parameters 00364 */ 00365 segmentationEvaluation(const parameters& par); 00366 00367 /** 00368 * Copy constructor 00369 * @param other the object to be copied 00370 */ 00371 segmentationEvaluation(const segmentationEvaluation& other); 00372 00373 /** 00374 * Destructor 00375 */ 00376 virtual ~segmentationEvaluation(); 00377 00378 /** 00379 * Returns the name of this type ("segmentationEvaluation") 00380 */ 00381 virtual const char* getTypeName() const; 00382 00383 /** 00384 * Returns used parameters 00385 */ 00386 const parameters& getParameters() const; 00387 00388 /** 00389 * Set the parameters 00390 */ 00391 bool setParameters(const functor::parameters& other); 00392 00393 /** 00394 * @name Public methods to be reimplemented 00395 */ 00396 //@{ 00397 00398 /** 00399 * Convert a binary-chain representation of a chromosome to a valid 00400 * parameter object. 00401 */ 00402 virtual bool chromosomeToPhenotype(const chromosome& genotype, 00403 functor::parameters& phenotype) const=0; 00404 00405 /** 00406 * Return a fresh allocated parameters for the evaluated functor, which is 00407 * equivalent to the given genotype. 00408 */ 00409 virtual functor::parameters* 00410 chromosomeToPhenotype(const chromosome& genotype) const; 00411 00412 /** 00413 * Evaluate Chromosome 00414 * 00415 * This method is one of the most important ones for the pareto evaluation. 00416 * Its task is to produce a multidimensional fitness measure for a given 00417 * chromosome. 00418 * 00419 * It returns true if the evaluation was successful, of false if the 00420 * phenotype represents some invalid parameterization. It is highly 00421 * recomended that the mutation and crossover methods are reimplemented to 00422 * avoid invalid parameterizations. 00423 */ 00424 virtual bool evaluateChromosome(const chromosome& individual, 00425 dvector& fitness); 00426 00427 //@} 00428 00429 /** 00430 * @name Evaluation Functions 00431 * 00432 * The real evaluation is provided here in order to compute measures 00433 * independently of the Pareto Front. 00434 */ 00435 //@{ 00436 /** 00437 * Index names for the complete multidimensional fitness measure 00438 */ 00439 enum { 00440 IdxNumRegions, /**< Mean number of regions. */ 00441 IdxNumRegionsRecip, /**< Reciprocal of the mean number of regions. */ 00442 IdxPixelAccuracy, /**< Pixel wise potential accuracy. */ 00443 IdxObjectAccuracy, /**< Object wise potential accuracy. */ 00444 IdxRegionWiseInfo, /**< Region wise information content. */ 00445 IdxThroughput, /**< 1.0/time in s^-1, meaning the number of 00446 * complete segmentations per second. 00447 */ 00448 IdxRegionIntegrity, /**< Region integrity */ 00449 IdxPixelCertainty /**< Pixel-wise certainty */ 00450 }; 00451 00452 /** 00453 * Evaluate the set of images (in the parameters) using the 00454 * given parameterization. 00455 * 00456 * @param param parameters for the segmentation functor to be used in the 00457 * evaluation. 00458 * @param fitness multidimensional fitness measures for all images 00459 */ 00460 bool evaluate(const functor::parameters& param,dvector& fitness); 00461 00462 /** 00463 * Evaluation of the segmentation with the given channel using 00464 * the given parameterization. 00465 * 00466 * The real measures for the single image are obtained with the 00467 * element-wise division between fitness and norm. But if several images 00468 * are used in the computations, the norms of each image have to be added 00469 * first. 00470 * 00471 * It is assumed that there is no previous stage (empty previous stage 00472 * mask). 00473 */ 00474 virtual bool evaluate(const image& img, 00475 const channel8& mask, 00476 const functor::parameters& param, 00477 dvector& fitness, 00478 dvector& norm); 00479 00480 /** 00481 * Evaluation of the segmentation with the given channel using 00482 * the given parameterization. 00483 * 00484 * The real measures for the single image are obtained with the 00485 * element-wise division between fitness and norm. But if several images 00486 * are used in the computations, the norms of each image have to be added 00487 * first. 00488 */ 00489 virtual bool evaluate(const image& img, 00490 const imatrix& prevStage, 00491 const channel8& mask, 00492 const functor::parameters& param, 00493 dvector& fitness, 00494 dvector& norm); 00495 00496 /** 00497 * Evaluation of the segmentation with the given channel using 00498 * a previously set parameterization. 00499 * 00500 * The real measures for the single image are obtained with the 00501 * element-wise division between fitness and norm. But if several images 00502 * are used in the computations, the norms of each image have to be added 00503 * first. 00504 */ 00505 virtual bool evaluate(const image& img, 00506 const imatrix& prevStage, 00507 const channel8& mask, 00508 dvector& fitness, 00509 dvector& norm); 00510 00511 /** 00512 * Evaluation of segmentation 00513 * 00514 * Since you give already the results in this method, it is not possible to 00515 * compute the throughput and certainty measures. 00516 */ 00517 virtual bool evaluate(const imatrix& result, 00518 const channel8& refMask, 00519 dvector& fitness, 00520 dvector& norm, 00521 const float minValidRegionSize=0.0005); 00522 00523 00524 //@} 00525 00526 protected: 00527 /** 00528 * Total number of fitness measures that will be computed 00529 * 00530 */ 00531 static const int totalFitnessDimensionality; 00532 00533 /** 00534 * Cache for the images 00535 */ 00536 std::vector<image> imageData; 00537 00538 /** 00539 * Cache for the presegmentation masks 00540 */ 00541 std::vector<channel8> maskData; 00542 00543 /** 00544 * Cache for the previous stage masks 00545 */ 00546 std::vector<imatrix> prevMaskData; 00547 00548 /** 00549 * File names of the reference data 00550 */ 00551 std::vector<std::string> goldenNames; 00552 00553 /** 00554 * Read images and masks 00555 */ 00556 bool readData(); 00557 00558 /** 00559 * Get the image name 00560 */ 00561 std::string getMaskName(const std::string& imgName, 00562 const std::string& postfix) const; 00563 00564 /** 00565 * Get the image name of the previous stage file 00566 */ 00567 std::string getPrevName(const std::string& imgName, 00568 const std::string& postfix) const; 00569 00570 /** 00571 * @name The segmentation evaluation methods 00572 */ 00573 //@{ 00574 /** 00575 * Initialize the segmentation functor 00576 */ 00577 virtual bool init(const functor::parameters& param) = 0; 00578 00579 /** 00580 * Segmentate an image using the parameterization set with init() 00581 * 00582 * @param img image to be segmented 00583 * @param prevStage segmentation mask from a previous stage. Image-based 00584 * segmentation algorithms ignore this argument (in a 00585 * strict sense they consider a mask in which each pixel 00586 * has its own label). 00587 * @param mask new segmentation labeled mask. 00588 * @param certainty the certainty, with which the algorithm assigns each 00589 * pixel to its label. If an algorithm does not provide 00590 * such measure (like almost all image-based algorithms) 00591 * this value will be empty, and for the computations 00592 * it will be assumed that all pixels have a certainty of 00593 * 1.0 to be what they are. 00594 * 00595 * @return true if successful, false otherwise. 00596 */ 00597 virtual bool segment(const image& img, 00598 const imatrix& prevStage, 00599 imatrix& mask, 00600 channel& certainty) = 0; 00601 00602 //@} 00603 00604 /** 00605 * Return a new object with the correct parameters' type 00606 */ 00607 virtual functor::parameters* getInstanceOfParam() const = 0; 00608 00609 /** 00610 * Empty matrix used everywhere. 00611 */ 00612 static const imatrix emptyMatrix; 00613 00614 00615 }; 00616 } 00617 00618 #endif 00619