latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 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 * project ....: LTI Digital Image/Signal Processing Library 00025 * file .......: ltiMeanShiftSegmentation.h 00026 * authors ....: Axel Berner 00027 * organization: LTI, RWTH Aachen 00028 * creation ...: 22.6.2001 00029 * revisions ..: $Id: ltiMeanShiftSegmentation.h,v 1.14 2006/02/08 11:27:00 ltilib Exp $ 00030 */ 00031 00032 #ifndef _LTI_MEAN_SHIFT_SEGMENTATION_H_ 00033 #define _LTI_MEAN_SHIFT_SEGMENTATION_H_ 00034 00035 #include "ltiSegmentation.h" 00036 #include "ltiImage.h" 00037 #include "ltiTimer.h" 00038 00039 namespace lti { 00040 /** 00041 * This is the implementation of the mean shift segmentation algorithm. 00042 * It is described in 00043 * 00044 * D. Comaniciu, P. Meer, 00045 * "Mean Shift: A Robust Approach toward Feature Space Analysis" 00046 * appeared in IEEE Trans. Pattern Analysis Machine Intell. Vol. 24, No. 5, 00047 * 603-619, 2002 00048 * (original link <a href="http://www.caip.rutgers.edu/~comanici/"> 00049 * here </a>) 00050 * 00051 * http://www.caip.rutgers.edu/~comanici/Papers/MsRobustApproach.pdf 00052 * 00053 * The code here is based on the code of the original authors, modified 00054 * extensively for the use with the LTI-Lib. It has changed a lot since 00055 * then to provide more functionality and configuration options. 00056 * 00057 * There are two implementations available: 00058 * 00059 * The classic implementation is selected setting the parameter 00060 * parameters::classicAlgorithm to \c true. It is based on an old code 00061 * example published by Comaniciu and colleagues a few years ago. This 00062 * implementation was not as good as the newer version, but was already 00063 * available in the LTI-Lib. Since several applications were adapted to use 00064 * that mean-shift version, the default behaviour of this functors has not 00065 * been changed. 00066 * 00067 * The new implementation is an adaption of Comaniciu and Meer's EDISON code 00068 * (http://www.caip.rutgers.edu/riul/research/robust.html). It can be 00069 * selected setting parameters::classicAlgorithm to \c false. Decisive for 00070 * the result of the new implementation is the choice of the parameters 00071 * parameters::sigmaR, parameters::sigmaS, 00072 * parameters::maxNeighbourColorDistance, and the parameters::speedup. 00073 * 00074 * \warning This functor will be completely reviewed soon. Its interface 00075 * may change a little bit to improve its usability. 00076 * It has now the problem that the parameters for 00077 * the classic version and the ones for the new algorithmic 00078 * implementation are different and they shouldn't. 00079 * 00080 * \todo The interface for classic and new algorithms has to be unified and 00081 * simplified. There are also several efficiency aspects to be 00082 * reviewed. 00083 */ 00084 class meanShiftSegmentation : public segmentation { 00085 public: 00086 /** 00087 * the parameters for the class meanShiftSegmentation 00088 */ 00089 class parameters : public segmentation::parameters { 00090 public: 00091 /** 00092 * default constructor 00093 */ 00094 parameters(); 00095 00096 /** 00097 * copy constructor 00098 * @param other the parameters object to be copied 00099 */ 00100 parameters(const parameters& other); 00101 00102 /** 00103 * destructor 00104 */ 00105 ~parameters(); 00106 00107 /** 00108 * returns name of this type 00109 */ 00110 const char* getTypeName() const; 00111 00112 /** 00113 * copy the contents of a parameters object 00114 * @param other the parameters object to be copied 00115 * @return a reference to this parameters object 00116 */ 00117 parameters& copy(const parameters& other); 00118 00119 /** 00120 * copy the contents of a parameters object 00121 * @param other the parameters object to be copied 00122 * @return a reference to this parameters object 00123 */ 00124 parameters& operator=(const parameters& other); 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 * 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 # 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 * @name Parameters for the old algorithm 00175 */ 00176 //@{ 00177 /** 00178 * Constants to specify degree of segmentation 00179 */ 00180 enum { 00181 /** 00182 * Constant value to specify the quantization option. 00183 */ 00184 Quantization = 0, 00185 00186 /** 00187 * constant value to specify the oversegmentation option. 00188 */ 00189 Oversegmentation = 1, 00190 00191 /** 00192 * constant value to specify the undersegmentation option. 00193 */ 00194 Undersegmentation = 2 00195 }; 00196 00197 /** 00198 * Option: 0 Quantization 00199 * 1 Oversegmentation 00200 * 2 Undersegmentation 00201 * 00202 * You should use the given constants instead of the magic numbers... 00203 * 00204 * Default: Undersegmentation 00205 */ 00206 int option; 00207 00208 /** 00209 * Number of rectangles, in which the segmenter looks for a color 00210 * 00211 * If the first rectangle is (0,0,0,0) then an \e auto-segmentation 00212 * mode is activated and colors are taken from the whole image. 00213 * Otherwise the colors will be taken from the given image region. 00214 * 00215 * The number of rectangles specifies the maximal possible number of 00216 * colors for the segmented/quantized image. 00217 * 00218 * If you give only one rectangle with (0,0,0,0) or an empty vector, 00219 * then 50 elements will be assumed. 00220 * 00221 * Default value: vector with 1 element (0,0,0,0) 00222 */ 00223 std::vector<rectangle> rects; 00224 00225 /** 00226 * Maximal number of trials for choosing a valid representing color. 00227 * 00228 * Default: 10 00229 */ 00230 int maxTrial; 00231 00232 /** 00233 * Number of trials for the representing color to converge 00234 * 00235 * Default: 15 trials 00236 */ 00237 int trial2converge; 00238 00239 /** 00240 * How many pixel in promille of the image must have a colorClass. 00241 * 00242 * Each element of the array corresponds to one of the possible options 00243 * (see <code>option</code> parameter) 00244 * 00245 * Default value: {2.5, 5.0, 10.0} for Quantization, Over- and 00246 * Undersegmentation respectively. 00247 */ 00248 double classThreshold[3]; 00249 00250 /** 00251 * Number of trials to pick up randomly a suitable color in the 00252 * image(rect). 00253 * 00254 * Default: 25 00255 */ 00256 int maxTrialRandomColor; 00257 00258 00259 /** 00260 * Set the minSize (in Pixel) a region must have. 00261 * default: 15 00262 */ 00263 int minRegionSize; 00264 00265 /** 00266 * Multiplication factor for the colorRadius (variance in image) 00267 * 00268 * Only used in auto-segmentation mode (see rects). 00269 * 00270 * Each element of the array corresponds to one of the possible options 00271 * (see <code>option</code> parameter); 00272 * 00273 * Default value: {8.0, 6.0, 4.0} for Quantization, Over- and 00274 * Undersegmentation respectively. 00275 */ 00276 float rectRadius[3]; 00277 00278 /** 00279 * Multiplication factor for the colorRadius(option) 00280 * 00281 * Use in auto-segmentation mode (see rects). 00282 * 00283 * Increase value if too many colors are found, because of a low 00284 * variance(image) 00285 * 00286 * Each element of the array corresponds to one of the possible options 00287 * (see \c option parameter); 00288 * 00289 * Default value: {2.0, 3.0, 4.0} for Quantization, Over- and 00290 * Undersegmentation respectively. 00291 */ 00292 float autoRadius[3]; 00293 00294 /** 00295 * Set the lower limit of a multiplication factor \e v for the 00296 * colorRadius. max( minVar , \e v ) 00297 * 00298 * The factor \e v = sqrt((var.l+var.u+var.v)/100) 00299 * depends on the variance of the image in luv. 00300 * 00301 * For images with an homogeneous background and a small object, this 00302 * value could be increased to get better results (for example with 1.0). 00303 * 00304 * Default value: 0.0 (no influence on factor v) 00305 */ 00306 float minVar; 00307 //@} 00308 00309 /** 00310 * @name Parameters for the new algorithm 00311 */ 00312 //@{ 00313 00314 /* 00315 * Using the multivariate normal kernel yields better results 00316 * but is more computational intensive 00317 * 00318 * Default: false 00319 * not yet implemented! 00320 */ 00321 bool multivariateNormalKernel; 00322 00323 /** 00324 * Three types of speed-up techniques 00325 */ 00326 enum eSpeedUpType{ 00327 NoSpeedup, /**< Filters the image applying mean shift to each 00328 * point. 00329 * 00330 * Advantage: most accurate 00331 * 00332 * Disadvantage : time expensive 00333 */ 00334 MediumSpeedup, /**< Filters the image using previous mode information 00335 * to avoid re-applying mean shift to some data 00336 * points (is default) 00337 * 00338 * Advantage: maintains high level of accuracy, 00339 * large speed up compared to 00340 * non-optimized version 00341 * 00342 * Disadvantage: possibly not as accurate as 00343 * non-optimized version 00344 */ 00345 HighSpeedup /**< filters the image using previous mode information 00346 * and window traversals to avoid re-applying mean 00347 * shift to some data points 00348 * 00349 * advantage: huge speed up maintains accuracy good 00350 * enough for segmentation 00351 * disadvantage: not as accurate as previous filters 00352 */ 00353 }; 00354 00355 /** 00356 * Higher speedup level causes loss of acuracy 00357 * 00358 * Default: MediumSpeedup 00359 */ 00360 eSpeedUpType speedup; 00361 00362 /** 00363 * The spatial radius of the mean shift sphere. 00364 * (the radius in grid space) 00365 * 00366 * Higher values cause longer computation times, and smoother region 00367 * boundaries. 00368 * 00369 * Default value: 5 00370 */ 00371 double sigmaS; 00372 00373 /** 00374 * The range radius of the mean shift sphere. 00375 * (the radius in color space) 00376 * 00377 * Higher values result in less regions 00378 * 00379 * Default value: 5 00380 */ 00381 double sigmaR; 00382 00383 /** 00384 * Regions having a color difference less than this parameter are joined 00385 * together (by the method fuseRegions()). 00386 * 00387 * It should be smaller than sigmaR. 00388 * 00389 * Default value: 3 00390 */ 00391 double maxNeighbourColorDistance; 00392 00393 /** 00394 * If the magnitude of the mean-shift vector is under this 00395 * threshold, it is considered as converged. 00396 * 00397 * Default value: 0.1 00398 */ 00399 double thresholdConverged; 00400 00401 /** 00402 * Choose algorithm by this parameter. 00403 * 00404 * - \c true: the old algorithm (for compatibility reasons still 00405 * provided) 00406 * - \c false: the new implementation, like in EDISON. 00407 * 00408 * The classic algorithm uses the following parameters: 00409 * - option 00410 * - rects 00411 * - maxTrial 00412 * - trial2converge 00413 * - classThreshold 00414 * - maxTrialRandomColor 00415 * - minRegionSize 00416 * - rectRadius 00417 * - autoRadius 00418 * - minVar 00419 * 00420 * The new algorithm considers the following parameters; 00421 * - maxTrial 00422 * - speedup 00423 * - sigmaS 00424 * - sigmaR 00425 * - maxNeighbourColorDistance 00426 * - thresholdConverged 00427 * 00428 * Default value: true (classic algorithm is used) 00429 */ 00430 bool classicAlgorithm; 00431 00432 }; 00433 00434 /** 00435 * default constructor 00436 */ 00437 meanShiftSegmentation(); 00438 00439 /** 00440 * default constructor 00441 */ 00442 meanShiftSegmentation(const parameters& par); 00443 00444 /** 00445 * copy constructor 00446 * @param other the object to be copied 00447 */ 00448 meanShiftSegmentation(const meanShiftSegmentation& other); 00449 00450 /** 00451 * destructor 00452 */ 00453 virtual ~meanShiftSegmentation(); 00454 00455 /** 00456 * returns the name of this type ("meanShiftSegmentation") 00457 */ 00458 virtual const char* getTypeName() const; 00459 00460 /** 00461 * Apply the mean shift segmentation algorithm to the given image. 00462 * 00463 * This image will be internally transformed into the Luv color space, as 00464 * proposed by Comaniciu et.al. in their original paper. 00465 * 00466 * @param src image with the source data. 00467 * @param dest image where the result (segmented image) will be left. 00468 * @return true if apply successful or false otherwise. 00469 */ 00470 bool apply(const lti::image& src, lti::image& dest); 00471 00472 /** 00473 * Apply the mean shift segmentation algorithm to the given image. 00474 * 00475 * This image will be internally transformed into the Luv color space, as 00476 * proposed by Comaniciu et.al. in their original paper. 00477 * 00478 * @param src image with the source data. 00479 * @param dest imatrix where the result (region-labels) will be left. 00480 * @return true if apply successful or false otherwise. 00481 */ 00482 bool apply(const lti::image& src, 00483 lti::imatrix& dest); 00484 00485 /** 00486 * Apply the mean shift segmentation algorithm to the given image. 00487 * 00488 * This image will be internally transformed into the Luv color space, as 00489 * proposed by Comaniciu et.al. in their original paper. 00490 * 00491 * @param src image with the source data. 00492 * @param labels imatrix where the result (region-labels) will be left. 00493 * @param colorMap the color palette used 00494 * @return true if apply successful or false otherwise. 00495 */ 00496 bool apply(const lti::image& src, 00497 lti::imatrix& labels, 00498 lti::palette& colorMap); 00499 00500 /** 00501 * Apply the mean shift segmentation algorithm to a color image, which 00502 * has been already split into three channels. The algorithm will work 00503 * with these channels without converting them into the Luv color space. 00504 * This allows the use of the mean shift segmentation in other color 00505 * spaces than Luv. 00506 * 00507 * @param chnl1 first channel of the source color image. 00508 * @param chnl2 second channel of the source color image. 00509 * @param chnl3 third channel of the source color image. 00510 * @param dest imatrix where the result (region-labels) will be left. 00511 * @return true if apply successful or false otherwise. 00512 */ 00513 bool apply(const lti::channel8& chnl1, 00514 const lti::channel8& chnl2, 00515 const lti::channel8& chnl3, 00516 lti::imatrix& dest); 00517 00518 00519 /** 00520 * Apply the mean shift segmentation algorithm to the given image. 00521 * 00522 * This image will be internally transformed into the Luv color space, as 00523 * proposed by Comaniciu et.al. in their original paper. 00524 * 00525 * @param src image with the source data. 00526 * @param destFiltered the meanshift filtered image (not 00527 * available for classic algorithm) 00528 * @param destSegmented the segmented image 00529 * @param destLabels label associating each pixel to a 00530 * mode and thus a color to each pixel 00531 * @param destColorMap the colors of the found modes 00532 * @return true if apply successful or false otherwise. 00533 */ 00534 bool apply(const lti::image& src, 00535 lti::image& destFiltered, 00536 lti::image& destSegmented, 00537 lti::imatrix& destLabels, 00538 lti::palette& destColorMap); 00539 00540 /** 00541 * filter the image with meanshift algorithm 00542 * 00543 * @param src the image to be filtered 00544 * @param dest the result will be left here 00545 * @return true if apply successful or false otherwise. 00546 */ 00547 bool filter(const lti::image& src, lti::image& dest); 00548 00549 /** 00550 * filter the image with meanshift algorithm 00551 * 00552 * @param srcdest the image to be filtered 00553 * @return true if apply successful or false otherwise. 00554 */ 00555 bool filter(lti::image& srcdest); 00556 00557 /** 00558 * copy data of "other" functor. 00559 * @param other the functor to be copied 00560 * @return a reference to this functor object 00561 */ 00562 meanShiftSegmentation& copy(const meanShiftSegmentation& other); 00563 00564 /** 00565 * returns a pointer to a clone of this functor. 00566 */ 00567 virtual functor* clone() const; 00568 00569 /** 00570 * returns used parameters 00571 */ 00572 const parameters& getParameters() const; 00573 00574 protected: 00575 00576 /** 00577 * like rgbPixel for RGB-ColorSpace, 00578 * is luvPixel for LUV-ColorSpace 00579 */ 00580 struct luvPixel { 00581 float l,u,v; 00582 }; 00583 00584 private: 00585 00586 //----------------------------------------------------------------------- 00587 // members used for classic algorithm - not used in new implementation 00588 //----------------------------------------------------------------------- 00589 /** 00590 * @name Classic implementation 00591 */ 00592 //@{ 00593 00594 /** 00595 * internal structure to administrate a region list. 00596 */ 00597 struct region { 00598 int my_contor; 00599 int my_class; 00600 int my_label; 00601 int *my_region; 00602 region* next_region_str; 00603 }; 00604 00605 /** 00606 * def. number for nonColor in palette(colorMap) 00607 */ 00608 static const int nonColor; // set to 255 00609 00610 static const int FIRST_SIZE; // = 262144 = 2^18 00611 static const int SEC_SIZE; // = 64 = 2^6 00612 00613 /** 00614 * radius for searching of similar colors 00615 * depend from variance of image and parms(autoRadius,rectRadius) 00616 */ 00617 std::vector<float> fixRadius; 00618 00619 /** 00620 * color-search-radius 00621 */ 00622 float RADIUS; 00623 float RADIUS2; // RADIUS^2 00624 00625 /** 00626 * actual number of image pixels that must have a color class 00627 */ 00628 int act_threshold; 00629 00630 /** 00631 * neighbour for images, which are stored in a vector (not matrix) 00632 * for whole image 00633 */ 00634 int neigh[8]; 00635 00636 /** 00637 * neighbour for images, which are stored in a vector (not matrix) 00638 * for subImage 00639 */ 00640 int neigh_sub[8]; 00641 00642 /** 00643 * image and subimage(rect) splitted in L,U,V - components 00644 */ 00645 matrix<int> chL,chU,chV; 00646 matrix<int> chLcurr,chUcurr,chVcurr; // current subImage (def by rect) 00647 00648 bool auto_segm; // true for autosegmentation 00649 00650 int numImgPxl; //number of pixel of the original image 00651 int numSubimgPxl; //number of pixel of subimage 00652 int numRemPxl; //number of remaining pixels 00653 int numOrgColors; //number of colors in the original image 00654 int numRemColors; //number of remaining colors 00655 00656 00657 int*_col0,*_col1,*_col2; // LUV color representation of org image 00658 00659 /** 00660 * map of assigned labels for segmented image 00661 * value = index in colorPalette luvPalSegm[](LUV) and colorMap[](RGB) 00662 */ 00663 ubyte* mapAssignedLabels; 00664 00665 /* 00666 * map of the pixels colors 00667 * value = index of color palette _col0[],_col1[],_col2[] 00668 * mapPxlToColor[0...numSubimgPxl] 00669 */ 00670 int* mapPxlToColor; 00671 00672 /** 00673 * map of remaining pixels 00674 * value = index of original pixel 00675 * mapRemPxl[0...numRemPxl] 00676 */ 00677 int* mapRemPxl; 00678 00679 /** 00680 * map of remaining colors 00681 * value = index of color palette _col0[], col1[], _col2[] 00682 * mapRemColors[0...numRemColors] 00683 */ 00684 int* mapRemColors; 00685 00686 /** 00687 * how many occurences of each remaining color 00688 * value = number of occurences of this color 00689 * howManyEachRemColor[0...numRemColors] 00690 */ 00691 int* howManyEachRemColor; 00692 00693 00694 /* 00695 * 00696 */ 00697 void setRadius(const double r); 00698 00699 /* 00700 * For non auto segmentation 00701 * Test if the clusters have the same mean, that is return true 00702 * if found color T[rect] is too near to previously found color 00703 * from T[0...rect] 00704 */ 00705 bool testSameCluster(int rect, luvPixel T[]); 00706 00707 /* 00708 * 00709 */ 00710 void luv2rgb( luvPixel& final_T, lti::rgbPixel& TI); 00711 00712 /* 00713 * 00714 */ 00715 void convert_RGB_LUV( const lti::image signal, 00716 const int _col_RGB[], const int _col_misc[] ); 00717 00718 /** 00719 * Method that copies the three channels as Luv channels into 00720 * the internal structures. 00721 */ 00722 void convert_RGB_LUV( const lti::channel8& chnl1, 00723 const lti::channel8& chnl2, 00724 const lti::channel8& chnl3, 00725 const int _col_RGB[], const int _col_misc[] ); 00726 /* 00727 * copy a rectangle from the original image into the subimage 00728 * by filling current channels chLcurr,chUcurr, chVcurr and 00729 * determine neighbourhood vector neigh_r 00730 */ 00731 void cutRectangle(const rectangle& rect ); 00732 00733 /* 00734 * 00735 */ 00736 void init_matr(int _m_colors[]); 00737 00738 /* 00739 * compute the mean color of N points given by J[] and return it by T 00740 */ 00741 void meanColor(const int N, int J[], luvPixel& T); 00742 00743 /* 00744 * get the color of a pixel within the subimage which 00745 * is located in a high density region in color space 00746 * by calling N times subsample() and keep the color 00747 * with the highest density 00748 */ 00749 bool my_sampling(luvPixel& T, int N); 00750 00751 /* 00752 * take randomly one of the remaining pixels and call meanColor() 00753 * to compute the mean color of a neighbourhood of 8 pixels 00754 */ 00755 void subsample(luvPixel& Xmean); 00756 00757 /* 00758 * check all remaining points which were not yet selected. If they 00759 * have enough neighbours(1,2,3) converging to T[rect] they are 00760 * also selected for getting T[rect] assigned 00761 * @param my_class[] true if point should get color assigned 00762 * @param selected[] indices of points that get color T[rect] assigned 00763 * @param numSelectedPxl total number of points changing color (directly 00764 * selected ones and as neighbours selected points) 00765 */ 00766 void add_neigh(bool my_class[], int selected[], int& numSelectedPxl); 00767 00768 /* 00769 * Update numRemPxl, mapRemPxl[], numRemColors, mapRemColors[] 00770 * and howManyEachRemColor[] 00771 */ 00772 void updateTables(const bool my_class[]); 00773 00774 /* 00775 * 00776 */ 00777 void covariance_w(int _m_colors[], luvPixel& m, luvPixel& v); 00778 00779 /* 00780 * 00781 */ 00782 void find_other_neigh(int k, int *my_ptr_tab, region *current_region, 00783 int conn_selected[], bool taken[]); 00784 00785 /* 00786 * the actual meanshift algorithm: compute median color of the colors 00787 * within a sphere of RADIUS and center final_T in color space 00788 * @param final_T input: center of sphere output: median color 00789 * @param sel_col[] true if this color is inside the sphere 00790 */ 00791 void new_auto_loop(luvPixel& final_T, bool sel_col[] ); 00792 00793 /* 00794 * 00795 */ 00796 void nauto_loop(luvPixel& final_T, int selected[], 00797 bool my_class[], int& numSelectedPxl); 00798 00799 /* 00800 * call new_auto_loop() until color T is converged to local maximum 00801 * and return all points touched by moving sphere 00802 * @param selected[] indices of points that change color to T (all points 00803 * that have their color touched by the sphere) 00804 * @param my_class[] true if point should get new color T assigned 00805 * @param numSelectedPxl number of points that should get new color T 00806 * assigned 00807 */ 00808 void calcRepresColorAuto (int selected[], bool my_class[], 00809 luvPixel& T, int& numSelectedPxl); 00810 00811 /* 00812 * 00813 */ 00814 void calcRepresColorNAuto(int selected[], bool my_class[], 00815 luvPixel& T, int& numSelectedPxl); 00816 00817 /* 00818 * 00819 */ 00820 void getBestPalEntry(const luvPixel T[], const int n_rects); 00821 00822 /* 00823 * 00824 */ 00825 void try2getPalEntry(const luvPixel T[], const int n_rects); 00826 00827 /* 00828 * 00829 */ 00830 void newPalette(luvPixel T[], int n_rects); 00831 00832 /* 00833 * 00834 */ 00835 void buildHistogram(const lti::image& signal, int* _col_RGB[], 00836 int* _m_colors[], int* _col_misc[]); 00837 00838 /** 00839 * build the histogram for a split image. 00840 */ 00841 void buildHistogram(const lti::channel8& chnl1, 00842 const lti::channel8& chnl2, 00843 const lti::channel8& chnl3, 00844 int* _col_RGB[], 00845 int* _m_colors[], 00846 int* _col_misc[]); 00847 00848 void updateGenclass( int& n_rects, 00849 const genericVector<bool>& valid_class, luvPixel T[]); 00850 00851 /* 00852 * 00853 */ 00854 void eliminateSmallClasses( int& n_rects, luvPixel T[]); 00855 00856 /* 00857 * 00858 */ 00859 void eliminateRegions(const luvPixel T[], const int my_lim); 00860 00861 /* 00862 * 00863 */ 00864 void destroyRegionList(region *); 00865 00866 /* 00867 * 00868 */ 00869 region* createRegionList(int *my_max_region); 00870 00871 /* 00872 * 00873 */ 00874 void initializations(const lti::image& src, std::vector<rectangle>& rects); 00875 00876 /** 00877 * initialization for the case when the user gives directly the 00878 * color space (giving three channels) 00879 */ 00880 void initializations(const lti::channel8& chnl1, 00881 const lti::channel8& chnl2, 00882 const lti::channel8& chnl3, 00883 std::vector<rectangle>& rects); 00884 00885 //@} 00886 00887 //----------------------------------------------------------------------- 00888 // members used for new imlementation - not used in classic algorithm 00889 //----------------------------------------------------------------------- 00890 00891 /** 00892 * @name new implementation 00893 */ 00894 //@{ 00895 00896 /// width and height of original image 00897 int width, height; 00898 00899 ///number of pixel of original image 00900 int imageSize; 00901 00902 ///The range dimension is the number of dimensions of color space 00903 int dimensionRange; 00904 00905 ///The spatial dimension is the number of dimensions of the image lattice 00906 int dimensionSpace; 00907 00908 ///The dimension of the feature space = dimensionRange + dimensionSpace 00909 int dimensionFeatureSpace; 00910 00911 ///represents the original image in luv space 00912 float* imageLuvOrgF; 00913 00914 ///represents the meanshift filtered image in luv space 00915 float* imageLuvFilteredF; 00916 00917 ///represents the meanshift filtered image in luv space (rounded integers) 00918 int* imageLuvFilteredI; 00919 00920 /// contains for each pixel a weight factor 00921 float* weightMap; 00922 00923 ///assigns a label to each data point associating it to a mode in modes 00924 ///e.g. a data point having label i has mode modes[i] 00925 int * labels; 00926 00927 ///containes all found modes as luv values (l1,u1,v1,l2,u2,v2,l3,u3,v3,...) 00928 float *modes; 00929 00930 ///counts the points associated to each mode 00931 vector<int> modePointCounts; 00932 00933 ///number of found regions 00934 int regionCount; 00935 00936 ///for debug and analysis information only: counts how many pixels converged in 00937 ///one step, two steps etc... 00938 vector<int> vecTrialsToConverge; 00939 00940 /** 00941 * initialize members and allocate memory 00942 */ 00943 void initialize(); 00944 00945 00946 /** 00947 * filters the image applying mean shift to each point 00948 * advantage: most accurate 00949 * disadvantage : time expensive 00950 */ 00951 void nonOptimizedFilter(); 00952 00953 00954 /** 00955 * filters the image using previous mode information 00956 * to avoid re-applying mean shift to some data points 00957 * speedup depends on parameter speed 00958 */ 00959 void optimizedFilter(); 00960 00961 00962 /** 00963 * connect neighbouring pixels having the same color values to a region 00964 * by giving them the same label in labels[] 00965 * input: imageLuvFilteredI 00966 * output: labels, modes, regionCount, modePointCounts 00967 */ 00968 void connect(); 00969 00970 00971 /** 00972 * fuse regions with similar color (modes within sphere) 00973 * input: labels, modes, regionCount, modePointCounts 00974 * output: labels, modes, regionCount, modePointCounts 00975 */ 00976 void fuseRegions(); 00977 00978 /** 00979 * prune regions that have less than minRegionSize pixels 00980 * input: labels, modes, regionCount, modePointCounts 00981 * output: labels, modes, regionCount, modePointCounts 00982 */ 00983 void pruneRegions(); 00984 00985 /** 00986 * build an array of regionAdjacencyLists (raMatrix) containing all 00987 * neighbour regions for each region (used in fuseRegions()) 00988 * input: labels, regionCount 00989 * output: raMatrix 00990 */ 00991 void buildRegionAdjacencyMatrix(); 00992 00993 00994 /** 00995 * convert image from rgb (src) to luv (imageLuvOrgF) 00996 */ 00997 void rgbToLuv(const image& src); 00998 00999 /** 01000 * convert image from luv (src) to rgb (dest) 01001 */ 01002 void luvToRgb(float* src, image& dest); 01003 01004 01005 /** 01006 * convert one luv pixel(src) to one rgb pixel(dest) 01007 */ 01008 void luvToRgb(luvPixel src, rgbPixel& dest); 01009 01010 /** 01011 * free memory allocated by initialize() 01012 */ 01013 void freeMemory(); 01014 01015 01016 /** 01017 * define region adjacency list class 01018 * which has one entry for each neighbour region of this (one) region 01019 * the first entry represents the region itself and not a neighbour 01020 */ 01021 class regionAdjacencyList { 01022 01023 public: 01024 01025 /** 01026 * the labels of this region 01027 */ 01028 int label; 01029 01030 /** 01031 * the next neighbour of the considered region 01032 */ 01033 regionAdjacencyList* next; 01034 01035 regionAdjacencyList(); 01036 01037 /** insert a region node into the region adjecency list 01038 * return true indicates that the node was inserted 01039 * return false indicates that the node was not inserted 01040 * because this neighbour region is already in the list 01041 */ 01042 bool insert(regionAdjacencyList* entry); 01043 01044 private: 01045 01046 // pointer to current and previous entry 01047 regionAdjacencyList *cur, *prev; 01048 }; 01049 01050 //used in fuseRegions() 01051 regionAdjacencyList* raMatrix, *raPool; 01052 01053 //@} 01054 }; 01055 } 01056 01057 #endif