latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 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 .......: ltiCoilBackgroundSegmentation.h 00027 * authors ....: Helmuth Euler 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 29.4.2003 00030 * revisions ..: $Id: ltiCoilBackgroundSegmentation.h,v 1.9 2006/02/07 18:37:08 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_COILBACKGROUND_SEGMENTATION_H_ 00034 #define _LTI_COILBACKGROUND_SEGMENTATION_H_ 00035 00036 #include "ltiImage.h" 00037 #include "ltiSegmentation.h" 00038 #include "ltiKMColorQuantization.h" 00039 #include "ltiSparseMatrix.h" 00040 00041 namespace lti { 00042 /** 00043 * The coilBackgroundSegmentation functor tries to detect which pixels 00044 * belong to the background and which not. It is quite slow, so it should be 00045 * used mainly for static applications where the mask has to be generated 00046 * only once and without any matter of time. 00047 * 00048 * For proper functionality there are some assumtions/requirements: 00049 * 00050 * - The background has to be almost homogeneous. (The functor works best 00051 * with black background, but this is not necessary.) 00052 * - There is a high probability that the border of the image 00053 * contains only background pixels and the object overlaps the middle 00054 * of the image. 00055 * 00056 * 00057 * The algorithm works as follows: 00058 * 00059 * At first the colors are quantized into regions using the k-means 00060 * algorithm. Then two masks are generated, one representing the 00061 * object, the other one the background. These masks serve as a 00062 * basis for a probability estimation which region belongs to object 00063 * or background. After that the masks grow considering these 00064 * results, neighbourhoods and covariance matrices. This iteration 00065 * is repeated "iteration"-times and finally generates a channel 00066 * containing 0 for background and 255 for the object. 00067 * 00068 * At last some after-treatment is done: Pixels constituting weak 00069 * links are deleted and if there is more than one object estimated, 00070 * only the largest one is kept. In order to improve results, the 00071 * whole algorithm is reiterated up to "maxNumberBestOfN"-times, 00072 * erasing pixels in the final mask which are not estimated as 00073 * object every time. In the best case these shrinking lasts until 00074 * the final mask doesn´t change any more. 00075 * 00076 * See the lti::coilBackgroundSegmentation::parameters for more information. 00077 */ 00078 class coilBackgroundSegmentation : public segmentation { 00079 public: 00080 /** 00081 * the parameters for the class coilBackgroundSegmentation 00082 */ 00083 class parameters : public segmentation::parameters { 00084 public: 00085 /** 00086 * default constructor 00087 */ 00088 parameters(); 00089 00090 /** 00091 * copy constructor 00092 * @param other the parameters object to be copied 00093 */ 00094 parameters(const parameters& other); 00095 00096 /** 00097 * destructor 00098 */ 00099 ~parameters(); 00100 00101 /** 00102 * returns name of this type 00103 */ 00104 const char* getTypeName() const; 00105 00106 /** 00107 * copy the contents of a parameters object 00108 * @param other the parameters object to be copied 00109 * @return a reference to this parameters object 00110 */ 00111 parameters& copy(const parameters& other); 00112 00113 /** 00114 * copy the contents of a parameters object 00115 * @param other the parameters object to be copied 00116 * @return a reference to this parameters object 00117 */ 00118 parameters& operator=(const parameters& other); 00119 00120 00121 /** 00122 * returns a pointer to a clone of the parameters 00123 */ 00124 virtual functor::parameters* clone() const; 00125 00126 /** 00127 * write the parameters in the given ioHandler 00128 * @param handler the ioHandler to be used 00129 * @param complete if true (the default) the enclosing begin/end will 00130 * be also written, otherwise only the data block will be written. 00131 * @return true if write was successful 00132 */ 00133 virtual bool write(ioHandler& handler,const bool complete=true) const; 00134 00135 /** 00136 * read the parameters from the given ioHandler 00137 * @param handler the ioHandler to be used 00138 * @param complete if true (the default) the enclosing begin/end will 00139 * be also written, otherwise only the data block will be written. 00140 * @return true if write was successful 00141 */ 00142 virtual bool read(ioHandler& handler,const bool complete=true); 00143 00144 # ifdef _LTI_MSC_6 00145 /** 00146 * this function is required by MSVC only, as a workaround for a 00147 * very awful bug, which exists since MSVC V.4.0, and still by 00148 * V.6.0 with all bugfixes (so called "service packs") remains 00149 * there... This method is also public due to another bug, so please 00150 * NEVER EVER call this method directly: use read() instead 00151 */ 00152 bool readMS(ioHandler& handler,const bool complete=true); 00153 00154 /** 00155 * this function is required by MSVC only, as a workaround for a 00156 * very awful bug, which exists since MSVC V.4.0, and still by 00157 * V.6.0 with all bugfixes (so called "service packs") remains 00158 * there... This method is also public due to another bug, so please 00159 * NEVER EVER call this method directly: use write() instead 00160 */ 00161 bool writeMS(ioHandler& handler,const bool complete=true) const; 00162 # endif 00163 00164 // ------------------------------------------------ 00165 // the parameters 00166 // ------------------------------------------------ 00167 00168 /** 00169 * The number of iterations the object- and background-masks take to grow 00170 * outside and inside the object. 00171 * 00172 * Default value: 10 00173 */ 00174 int iterations; 00175 00176 /** 00177 * The number of masks created. From them the final mask will be 00178 * generated with the value zero where not all masks were nonzero. 00179 * 4 is enough for a good result, but values >= 100 will generate 00180 * the best possible solution (high values will cause a long time 00181 * to do the segmentation). 00182 * 00183 * Minimum value: 2 00184 * Default value: 100 00185 */ 00186 int maxNumberBestOfN; 00187 00188 /** 00189 * The factor the first object- and background-mask is stretchend. 00190 * Values > 1 should be used if the image is larger than 128*128 00191 * pixels in order to get a sharper segmentation around the object. 00192 * 00193 * Minimum value: 1 00194 * Default value: 1 00195 */ 00196 float maskFactor; 00197 00198 /** 00199 * The factor the threshold decinding between object and 00200 * background is stretched. Lower values will cause better 00201 * results with objects containing many dark spots. Higher 00202 * values prevent 'noise' outside the object. 00203 * 00204 * Default value: 1.30 00205 */ 00206 double thresholdFactor; 00207 00208 /** 00209 * The mean background color to be expected in order to improve 00210 * results by estimating with another covariance matrix. If the 00211 * backgroundcolor is unknown use meanBackgroundColor = -1 to 00212 * disable. Otherwise use only values between 0 and 255. (See 00213 * also: covarMatrixBackground.) 00214 * 00215 * Default value: 0 (black) 00216 */ 00217 int meanBackgroundColor; 00218 00219 /** 00220 * The size and shape of the additional covariace matrix. 00221 * Only affecting the result if meanBackgroundColor >= 0. 00222 * (See also: meanBackgroundColor) 00223 * 00224 * Default value: 100 on the main diagonal, 0 otherwise 00225 */ 00226 dmatrix covarMatrixBackground; 00227 }; 00228 00229 /** 00230 * default constructor 00231 */ 00232 coilBackgroundSegmentation(); 00233 00234 /** 00235 * copy constructor 00236 * @param other the object to be copied 00237 */ 00238 coilBackgroundSegmentation(const coilBackgroundSegmentation& other); 00239 00240 /** 00241 * destructor 00242 */ 00243 virtual ~coilBackgroundSegmentation(); 00244 00245 /** 00246 * returns the name of this type ("coilBackgroundSegmentation") 00247 */ 00248 virtual const char* getTypeName() const; 00249 00250 /** 00251 * generates a mask with the value 255 where the object is estimated 00252 * and 0 for the background. 00253 * 00254 * @param src image with the source data 00255 * @param result the resulting mask 00256 * @return true if apply successful or false otherwise 00257 */ 00258 bool apply(const image& src,channel8& result); 00259 00260 /** 00261 * copy data of "other" functor. 00262 * @param other the functor to be copied 00263 * @return a reference to this functor object 00264 */ 00265 coilBackgroundSegmentation& copy(const coilBackgroundSegmentation& other); 00266 00267 /** 00268 * alias for copy member 00269 * @param other the functor to be copied 00270 * @return a reference to this functor object 00271 */ 00272 coilBackgroundSegmentation& 00273 operator=(const coilBackgroundSegmentation& other); 00274 00275 /** 00276 * returns a pointer to a clone of this functor. 00277 */ 00278 virtual functor* clone() const; 00279 00280 /** 00281 * returns used parameters 00282 */ 00283 const parameters& getParameters() const; 00284 00285 protected: 00286 00287 /** 00288 * type combining the region with its mean color, probability 00289 * and relation to background and object 00290 */ 00291 struct TmeanProbability { 00292 float sumProbability; /// sum of the regionwide probability 00293 int appearanceCounter; /// number of pixels in this region 00294 float meanProbability; /// mean probability for the region 00295 int sumColorRed; /// sum of the regionwide red-value 00296 int sumColorGreen; /// sum of the regionwide green-value 00297 int sumColorBlue; /// sum of the regionwide blue-value 00298 rgbPixel meanColor; /// mean color for the region 00299 bool labelToObjectVector; /// true if region belongs to object 00300 bool labelToBackgroundVector; /// true if region belongs to background 00301 }; 00302 00303 /** 00304 * delete such positions in the mask 00305 * \code 00306 * ** ** ***** 00307 * ** ** ***** 00308 * **x** x 00309 * ** ** ***** 00310 * ** ** ***** 00311 * \endcode 00312 * @param ch8 the channel8 to be optimized 00313 */ 00314 void deleteWeakLinks(channel8& ch8) const; 00315 00316 /** 00317 * calculating the inverted covariance matrix under consideration of 00318 * the object/background mask 00319 * @param img the image to be considered 00320 * @param mask the mask which pixels from img should be used 00321 * @param mean the meanvalue (center) of the covarianve matrix is returned 00322 * here 00323 * @param covarMatrix the resulting matrix is returned here 00324 * @return true if succesfull 00325 */ 00326 bool getInvertedCovarMatrixForMask(const image& img, 00327 channel8& mask, 00328 trgbPixel<double>& mean, 00329 dmatrix& covarMatrix) const; 00330 00331 /** 00332 * checking if a given color is close enough to the covariance matrix 00333 * @param mean the center of the covarianve matrix is considered here 00334 * @param covarMatrix the covariance matrix to be considered 00335 * @param xMinusM pixel with the color to be checked 00336 * @return true if succesfull 00337 */ 00338 bool checkColorReasonable(const trgbPixel<double>& mean, 00339 const dmatrix& covarMatrix, 00340 const rgbPixel& xMinusM) const; 00341 00342 /** 00343 * building the background mask under consideration of 00344 * neighbourhoods, covariance matrix and probabilities 00345 * 00346 * @param img the image to be considered 00347 * @param ch8MaskChannel the mask estimating the background 00348 * @param intSparseMat matix containing which regions are neighbours 00349 * @param meanProbabilityList a list containing mean probability, color and 00350 * relation towards background and object for each region 00351 * @param newLabelsMatrix matrix containing the labelnumber for each pixel 00352 * @param converged true if no change took place 00353 * @return true if succesfull 00354 */ 00355 bool growOutsideObject(const image& img, 00356 channel8& ch8MaskChannel, 00357 sparseMatrix<int>& intSparseMat, 00358 std::vector<TmeanProbability>& meanProbabilityList, 00359 matrix<int>& newLabelsMatrix, 00360 bool& converged) const; 00361 00362 /** 00363 * building the object mask under consideration of neighbourhoods, 00364 * covariance matrix and probabilities 00365 * 00366 * @param img the image to be considered 00367 * @param ch8MaskChannel the mask estimating the object 00368 * @param intSparseMat matix containing which labels are related 00369 * @param meanProbabilityList a list containing mean probability, color and 00370 * relation towards background and object for each region 00371 * @param newLabelsMatrix matrix containing the labelnumber for each pixel 00372 * @param converged true if no change took place 00373 * @return true if succesfull 00374 */ 00375 bool growInsideObject(const image& img, 00376 channel8& ch8MaskChannel, 00377 sparseMatrix<int>& intSparseMat, 00378 std::vector<TmeanProbability>& meanProbabilityList, 00379 matrix<int>& newLabelsMatrix, 00380 bool& converged) const; 00381 }; 00382 } 00383 00384 #endif