latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 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 .......: ltiRegionGrowing.h 00027 * authors ....: Pablo Alvarado 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 28.9.2000 00030 * revisions ..: $Id: ltiRegionGrowing.h,v 1.10 2006/02/08 11:45:11 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_REGION_GROWING_H_ 00034 #define _LTI_REGION_GROWING_H_ 00035 00036 #include "ltiObject.h" 00037 #include "ltiTypes.h" 00038 #include "ltiSegmentation.h" 00039 #include "ltiVector.h" 00040 #include "ltiMatrix.h" 00041 #include "ltiImage.h" 00042 #include "ltiMath.h" 00043 00044 namespace lti { 00045 /** 00046 * This class is used to segmentate an image with a regular 00047 * background. It uses a set of seed pixels (given in the 00048 * parameters) to start the region growing. To check the 00049 * similarity, a comparition is done between the pixel value at the 00050 * candidate position and the average value at the 00051 * seed position. If the difference of these values is lower than a given 00052 * threshold, the pixel will be considered as part of the growing 00053 * region. It is possible to get automatically values for these thresholds 00054 * if a known background region is given in the parameters. 00055 * 00056 * Example: 00057 * 00058 * \code 00059 * lti::loadBMP loader; 00060 * 00061 * lti::image img; // the color image to be segmented 00062 * lti::channel8 chnl; // the segmentation mask will be left here 00063 * 00064 * loader.load("img/leo040801_00_019.bmp",img); // read an image 00065 * 00066 * lti::regionGrowing segmenter; // segmentation functor and 00067 * lti::regionGrowing::parameters param; // its parameters 00068 * 00069 * param.useGaussKernel = true; // use a gaussian kernel 5x5 00070 * param.localStatisticsKernelSize = 5; 00071 * param.localStatisticsKernelVariance = -1; 00072 * 00073 * param.mode = lti::regionGrowing::parameters::UseGivenThresholds; 00074 * param.averageThresholds = trgbPixel<float>(0.05,0.05,0.05); 00075 * param.edgesThreshold = 0.04; 00076 * 00077 * // do not use all corners as seed-points, just the three following... 00078 * param.seedPoints.resize(3,tpoint<float>(0,0)); 00079 * param.seedPoints.at(1).y = 1.0f; 00080 * param.seedPoints.at(2).x = 1.0f; 00081 * param.seedPoints.at(2).y = 1.0f; 00082 * 00083 * // indicate the segmentation functor the user-parameters 00084 * segmenter.setParameters(param); 00085 * 00086 * // segmentate the image and leave the segmentation in the channel 00087 * segmenter.apply(img,chnl); 00088 * 00089 * view1.show(img); // show original image 00090 * view2.show(chnl); // show the segmentation mask 00091 * 00092 * \endcode 00093 * 00094 * @ingroup gSegmentation 00095 */ 00096 class regionGrowing : public segmentation { 00097 public: 00098 /** 00099 * The parameters for the class regionGrowing 00100 */ 00101 class parameters : public segmentation::parameters { 00102 public: 00103 /** 00104 * Default constructor 00105 */ 00106 parameters(); 00107 00108 /** 00109 * Copy constructor 00110 * @param other the parameters object to be copied 00111 */ 00112 parameters(const parameters& other); 00113 00114 /** 00115 * Destructor 00116 */ 00117 ~parameters(); 00118 00119 /** 00120 * Returns name of this type 00121 */ 00122 const char* getTypeName() const; 00123 00124 /** 00125 * Copy the contents of a parameters object 00126 * @param other the parameters object to be copied 00127 * @return a reference to this parameters object 00128 */ 00129 parameters& copy(const parameters& other); 00130 00131 /** 00132 * Returns a pointer to a clone of the parameters 00133 */ 00134 virtual functor::parameters* clone() const; 00135 00136 // ----------------------------------------------------------------- 00137 00138 /** 00139 * Write the parameters in the given ioHandler 00140 * @param handler the ioHandler to be used 00141 * @param complete if true (the default) the enclosing begin/end will 00142 * be also written, otherwise only the data block will be written. 00143 * @return true if write was successful 00144 */ 00145 virtual bool write(ioHandler& handler, 00146 const bool complete=true) const; 00147 00148 /** 00149 * Write the parameters in the given ioHandler 00150 * @param handler the ioHandler to be used 00151 * @param complete if true (the default) the enclosing begin/end will 00152 * be also written, otherwise only the data block will be written. 00153 * @return true if write was successful 00154 */ 00155 virtual bool read(ioHandler& handler,const bool complete=true); 00156 00157 # ifdef _LTI_MSC_6 00158 /** 00159 * This function is required by MSVC only, as a workaround for a 00160 * very awful bug, which exists since MSVC V.4.0, and still by 00161 * V.6.0 with all bugfixes (so called "service packs") remains 00162 * there... This method is public due to another bug!, so please 00163 * NEVER EVER call this method directly 00164 */ 00165 bool readMS(ioHandler& handler,const bool complete=true); 00166 00167 /** 00168 * This function is required by MSVC only, as a workaround for a 00169 * very awful bug, which exists since MSVC V.4.0, and still by 00170 * V.6.0 with all bugfixes (so called "service packs") remains 00171 * there... This method is public due to another bug!, so please 00172 * NEVER EVER call this method directly 00173 */ 00174 bool writeMS(ioHandler& handler,const bool complete=true) const; 00175 # endif 00176 00177 /** 00178 * Types for the region growing modi 00179 */ 00180 enum eMode { 00181 UseGivenThresholds, /*!< Use the thresholds specified in the 00182 parameters */ 00183 GetThresholdsRelative, /*!< Use the relative patchPosition to obtain 00184 the threshold values */ 00185 GetThresholdsAbsolute /*!< Use the absolute patchPosition to obtain 00186 the threshold values */ 00187 }; 00188 00189 /** 00190 * Types of "lightness" for the background 00191 */ 00192 enum eBackgroundType { 00193 Dark, /*!< The background has only dark colors */ 00194 Medium, /*!< The background has colors with medium intensity */ 00195 Light /*!< The background is white */ 00196 }; 00197 00198 /** 00199 * Type (brightness) of the background. The default value is "Dark". 00200 */ 00201 eBackgroundType backgroundType; 00202 00203 /** 00204 * If this variable is "true", the local region will be specified 00205 * by a gassian filter with the given (local region) size and variance. 00206 * If "false", a rectangular filter will be used. The default value is 00207 * "false" 00208 */ 00209 bool useGaussKernel; 00210 00211 /** 00212 * Size of the filter kernel used to specify a local region. 00213 * The default value is 5 00214 */ 00215 int localStatisticsKernelSize; 00216 00217 /** 00218 * Variance of the filter kernel used to specify a local region 00219 * (used only if useGaussKernel is true). The default value is 00220 * "-1", which meaning is described in gaussKernel 00221 */ 00222 double localStatisticsKernelVariance; 00223 00224 /** 00225 * Size of a gaussian kernel used to low-pass-filter the final 00226 * segmentated mask. 00227 */ 00228 int smoothingKernelSize; 00229 00230 /** 00231 * Smoothing threshold. After the first segmentation, all pixels 00232 * will be assigned to the background or the object. The smoothing 00233 * filter will generate at the borders of the objects values between 00234 * 0 (background) and 1 (object). This value will determine which values 00235 * will be considered as object. 00236 * 00237 * The default value is 0.6 00238 */ 00239 float smoothingThreshold; 00240 00241 /** 00242 * Specify the position in the image or channel, where the 00243 * values for the "background" can be taken. 00244 * 00245 * If the mode is GetThresholdsRelative, the values of the 00246 * coordinates must be between 0.0 and 1.0. The absolute 00247 * coordinates will be calculated multiplying this values with 00248 * the size of the image to be segmented. 00249 * 00250 * If the mode is GetThresholdsAbsolute, this parameters should 00251 * contain the absolute coordinates for the background patch. 00252 */ 00253 trectangle<float> patchPosition; 00254 00255 /** 00256 * Specify how to obtain the threshold values to considered a pixel 00257 * similar to the seed or not. 00258 */ 00259 eMode mode; 00260 00261 /** 00262 * The scale factor allows a faster calculation for the segmentation 00263 * mask, but with a lower boundary detection accuracy. 00264 */ 00265 int scaleFactor; 00266 00267 /** 00268 * Used by the UseGivenThresholds-mode for the segmentation of a 00269 * channel or channel8. This value MUST be between 0.0 and 1.0 00270 * (The channel8 values will be divided by 255 before the comparitions) 00271 */ 00272 float averageThreshold; 00273 00274 /** 00275 * Used by the UseGivenThresholds-mode for the segmentation of a 00276 * color image. Each component value must be between 0.0 and 1.0 00277 * 00278 */ 00279 trgbPixel<float> averageThresholds; 00280 00281 /** 00282 * Used by the UseGivenThresholds-mode for the segmentation of a 00283 * channel or channel8. This value must be between 0.0 and 1.0. 00284 * (The channel8 values will be divided by 255 before the comparitions) 00285 * 00286 */ 00287 float edgesThreshold; 00288 00289 /** 00290 * A list with the relative positions for the starting seed points 00291 * can be specified here. The valid values for each coordinate are 00292 * between 0.0f and 1.0f. The default values are the four corners 00293 * (i.e. (0,0),(0,1),(1,0),(1,1) ) 00294 */ 00295 vector< tpoint<float> > seedPoints; 00296 }; 00297 00298 /** 00299 * Default constructor 00300 */ 00301 regionGrowing(); 00302 00303 /** 00304 * Default constructor with parameters 00305 */ 00306 regionGrowing(const parameters& par); 00307 00308 /** 00309 * Copy constructor 00310 * @param other the object to be copied 00311 */ 00312 regionGrowing(const regionGrowing& other); 00313 00314 /** 00315 * Destructor 00316 */ 00317 virtual ~regionGrowing(); 00318 00319 /** 00320 * Returns the name of this type ("regionGrowing") 00321 */ 00322 virtual const char* getTypeName() const; 00323 00324 /** 00325 * Operates on the given parameter. 00326 * 00327 * The background-pixels will be set to 0,128 or 255 depending on 00328 * the parameter "backgroundType". 00329 * 00330 * @param srcdest channel8 with the source data. The result 00331 * will be left here too. 00332 * @return a reference to the <code>srcdest</code>. 00333 */ 00334 channel8& apply(channel8& srcdest) const; 00335 00336 /** 00337 * Operates on the given parameter. 00338 * 00339 * The background-pixels will be set to 0, 0.5 or 1.0 depending on 00340 * the parameter "backgroundType". 00341 * 00342 * @param srcdest channel with the source data. The result 00343 * will be left here too. 00344 * @return a reference to the <code>srcdest</code>. 00345 */ 00346 channel& apply(channel& srcdest) const; 00347 00348 /** 00349 * Operates on the given parameter. 00350 * 00351 * The background-pixels will be set to black, grey or white depending on 00352 * the parameter "backgroundType". 00353 * 00354 * @param srcdest image with the source data. The result 00355 * will be left here too. 00356 * @return a reference to the <code>srcdest</code>. 00357 */ 00358 image& apply(image& srcdest) const; 00359 00360 /** 00361 * Operates on a copy of the given %parameters. 00362 * 00363 * @param src channel8 with the source data. 00364 * @param dest channel8 where the segmentation mask will be left. 00365 * This mask contains 0 for a background point and 00366 * (usually) 255 for an object point. 00367 * @return a reference to the <code>dest</code>. 00368 */ 00369 channel8& apply(const channel8& src,channel8& dest) const; 00370 00371 /** 00372 * Operates on a copy of the given %parameters. 00373 * @param src channel with the source data. 00374 * @param dest channel8 where the segmentation mask will be left. 00375 * This mask contains 0 for a background point and 00376 * (usually) 255 for an object point. 00377 * @return a reference to the <code>dest</code>. 00378 */ 00379 channel8& apply(const channel& src,channel8& dest) const; 00380 00381 /** 00382 * Operates on a copy of the given %parameters. 00383 * @param src image with the source data. 00384 * @param dest channel8 where the segmentation mask will be left. 00385 * This mask contains 0 for a background point and 00386 * (usually) 255 for an object point. 00387 * @return a reference to the <code>dest</code>. 00388 */ 00389 channel8& apply(const image& src,channel8& dest) const; 00390 00391 /** 00392 * Copy data of "other" functor. 00393 * @param other the functor to be copied 00394 * @return a reference to this functor object 00395 */ 00396 regionGrowing& copy(const regionGrowing& other); 00397 00398 /** 00399 * Returns a pointer to a clone of this functor. 00400 */ 00401 virtual functor* clone() const; 00402 00403 /** 00404 * Returns used parameters 00405 */ 00406 const parameters& getParameters() const; 00407 00408 00409 protected: 00410 static float sqroot(const float& x) { 00411 return static_cast<float>(sqrt(x)); 00412 }; 00413 00414 static int sqroot(const int& x) { 00415 return static_cast<int>(sqrt(x)); 00416 }; 00417 00418 /** 00419 * The pixel at position "neighbour" will be compared with the average 00420 * value corresponding to the position "seed". 00421 * 00422 * The Codition for similarity proof if the absolute value of 00423 * the difference between the channel value at "neighbour" and the 00424 * local average on the "seed"-position is lower than the given 00425 * avrgThreshold 00426 * 00427 */ 00428 inline bool similar(const ubyte& neighbour, 00429 const ubyte& avrgAtSeed, 00430 const int& avrgThreshold) const { 00431 return (abs(int(neighbour)-int(avrgAtSeed))<=avrgThreshold); 00432 } 00433 00434 /** 00435 * The pixel at position "neighbour" will be compared with the average 00436 * value corresponding to the position "seed". 00437 * 00438 * The Codition for similarity proof if the absolute value of 00439 * the difference between the channel value at "neighbour" and the 00440 * local average on the "seed"-position is lower than the given 00441 * avrgThreshold 00442 * 00443 */ 00444 inline bool similar(const float& neighbour, 00445 const float& avrgAtSeed, 00446 const float& avrgThreshold) const { 00447 return (fabs(neighbour - avrgAtSeed)<=avrgThreshold); 00448 } 00449 00450 /** 00451 * All pixels at img for which the mask is 0 will be set to the given 00452 * value. The mask and img MUST have the same size! 00453 */ 00454 template <class T> 00455 void mask(matrix<T>& img,const channel8& msk,const T& background) const { 00456 channel8::const_iterator cit,ce; 00457 typename matrix<T>::iterator it; 00458 for (cit=msk.begin(),ce=msk.end(),it=img.begin(); 00459 cit!=ce; 00460 cit++,it++) { 00461 if ((*cit) == 0) { 00462 (*it)=background; 00463 } 00464 } 00465 } 00466 00467 /** 00468 * Operates on a copy of the given %parameters. 00469 * @param src image with the source data. 00470 * @param dest the mask will be 0 for background pixels 00471 * @return a reference to the <code>dest</code>. 00472 */ 00473 channel8& segmentate(const image& src,channel8& dest) const; 00474 00475 /** 00476 * Operates on a copy of the given %parameters. 00477 * @param src image with the source data. 00478 * @param dest the mask will be 0 for background pixels 00479 * @return a reference to the <code>dest</code>. 00480 */ 00481 channel8& segmentate(const channel& src,channel8& dest) const; 00482 }; 00483 } 00484 00485 #endif