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 /*---------------------------------------------------------------- 00025 * project ....: LTI Digital Image/Signal Processing Library 00026 * file .......: ltiMeanshiftTracker.h 00027 * authors ....: Torsten Kämper 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 24.9.2001 00030 * revisions ..: $Id: ltiMeanshiftTracker.h,v 1.8 2006/02/08 11:27:18 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_MEANSHIFT_TRACKER_H_ 00034 #define _LTI_MEANSHIFT_TRACKER_H_ 00035 00036 // include files which are needed in this header 00037 #include "ltiHistogram.h" 00038 00039 // include parent class: 00040 00041 #include "ltiModifier.h" 00042 namespace lti { 00043 /** 00044 * This is the implementation of the MEANSHIFT 00045 * Tracking algorithm as described in: 00046 * Comaniciu, Ramesh and Meer, "Real-Time Tracking of 00047 * Non-Rigid Objects using the Mean Shift", IEEE Workshop 00048 * on Applic.Comp.Vis.,2000. 00049 * 00050 * It tracks a rectangular search window (the target) 00051 * in an image by its color distribution. Therefore 00052 * it uses an iterative gradient ascent algorithm, known as 00053 * mean shift, that finds a similarity peak between target 00054 * and candidate positions. The similarity is measured with 00055 * a distance metric, which can be obtained after each apply(). 00056 * 00057 * Use this by calling an apply on subsequent images and thereby 00058 * passing the last returned search rectangle. Initialization is 00059 * done with first use or after a call of the reset() method. 00060 */ 00061 class meanshiftTracker : public modifier { 00062 public: 00063 /** 00064 * the parameters for the class meanshiftTracker 00065 */ 00066 class parameters : public modifier::parameters { 00067 public: 00068 /** 00069 * default constructor 00070 */ 00071 parameters(); 00072 00073 /** 00074 * copy constructor 00075 * @param other the parameters object to be copied 00076 */ 00077 parameters(const parameters& other); 00078 00079 /** 00080 * destructor 00081 */ 00082 ~parameters(); 00083 00084 00085 /** 00086 * Kernel Type. 00087 */ 00088 enum eKernelType { 00089 Normal, /**< Normal Kernel (default)*/ 00090 Epanechnikov /**< Epanechnikov Kernel */ 00091 }; 00092 00093 00094 /** 00095 * returns name of this type 00096 */ 00097 const char* getTypeName() const; 00098 00099 /** 00100 * copy the contents of a parameters object 00101 * @param other the parameters object to be copied 00102 * @return a reference to this parameters object 00103 */ 00104 parameters& copy(const parameters& other); 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& operator=(const parameters& other); 00112 00113 00114 /** 00115 * returns a pointer to a clone of the parameters 00116 */ 00117 virtual functor::parameters* clone() const; 00118 00119 /** 00120 * write the parameters in the given ioHandler 00121 * @param handler the ioHandler to be used 00122 * @param complete if true (the default) the enclosing begin/end will 00123 * be also written, otherwise only the data block will be written. 00124 * @return true if write was successful 00125 */ 00126 virtual bool write(ioHandler& handler,const bool complete=true) const; 00127 00128 /** 00129 * read the parameters from the given ioHandler 00130 * @param handler the ioHandler to be used 00131 * @param complete if true (the default) the enclosing begin/end will 00132 * be also written, otherwise only the data block will be written. 00133 * @return true if write was successful 00134 */ 00135 virtual bool read(ioHandler& handler,const bool complete=true); 00136 00137 # ifdef _LTI_MSC_6 00138 /** 00139 * this function is required by MSVC only, as a workaround for a 00140 * very awful bug, which exists since MSVC V.4.0, and still by 00141 * V.6.0 with all bugfixes (so called "service packs") remains 00142 * there... This method is also public due to another bug, so please 00143 * NEVER EVER call this method directly: use read() instead 00144 */ 00145 bool readMS(ioHandler& handler,const bool complete=true); 00146 00147 /** 00148 * this function is required by MSVC only, as a workaround for a 00149 * very awful bug, which exists since MSVC V.4.0, and still by 00150 * V.6.0 with all bugfixes (so called "service packs") remains 00151 * there... This method is also public due to another bug, so please 00152 * NEVER EVER call this method directly: use write() instead 00153 */ 00154 bool writeMS(ioHandler& handler,const bool complete=true) const; 00155 # endif 00156 00157 // ------------------------------------------------ 00158 // the parameters 00159 // ------------------------------------------------ 00160 00161 // If you add more parameters manually, do not forget to do following: 00162 // 1. indicate in the default constructor the default values 00163 // 2. make sure that the copy member also copy your new parameters 00164 // 3. make sure that the read and write members also read and 00165 // write your parameters 00166 00167 /** 00168 * precision for iterations: 00169 * 0.1 for deep iteration , 10.0 for fast runtime 00170 * default is 2. allowed range is [0.1 ... ] 00171 */ 00172 float precision; 00173 00174 /** 00175 * Threshold for tracker validity. Range is from 0.0 to 1.0. 00176 * If color distribution distance after apply is below this 00177 * threshold, then the tracker simply doesn't react. Default is 0.8 00178 */ 00179 float threshold; 00180 00181 /** 00182 * Kerneltypes are Normal or Epanechnikov-Kernel 00183 * Default is Normal 00184 */ 00185 eKernelType kernelType; 00186 00187 /** 00188 * The size adaption ratio tells how strong the size adaptation 00189 * may be with one call of an apply() method. 00190 * Range is 0.0 to 1.0 (reasonable values lie between 0.0 and 0.5). 00191 * Default is 0.1 00192 */ 00193 float sizeAdaptRatio; 00194 }; 00195 00196 /** 00197 * default constructor 00198 */ 00199 meanshiftTracker(); 00200 00201 /** 00202 * copy constructor 00203 * @param other the object to be copied 00204 */ 00205 meanshiftTracker(const meanshiftTracker& other); 00206 00207 /** 00208 * destructor 00209 */ 00210 virtual ~meanshiftTracker(); 00211 00212 /** 00213 * returns the name of this type ("meanshiftTracker") 00214 */ 00215 virtual const char* getTypeName() const; 00216 00217 /** 00218 * Tracks a target color distribution. The initial target is 00219 * specified by "window" on first usage or after a reset() 00220 * (i.e. tracker is not initialized). 00221 * Subsequent calls of this method perform tracking by translating 00222 * and scaling the "window" to optimally fit the target color 00223 * distribution. 00224 */ 00225 bool apply(const image& src,trectangle<int>& window); 00226 00227 /** 00228 * Tells, if the tracker has already been initialized with a 00229 * target color distribution. 00230 */ 00231 bool isInitialized() const; 00232 00233 /** 00234 * Explicitly initialize tracker with given region in image. 00235 * This is called automatically when an apply is used while 00236 * tracker is not initialised. I.e. calling initialize() is 00237 * the same as subsequently calling reset() and apply(). 00238 */ 00239 void initialize(const image& src,trectangle<int>& window); 00240 00241 /** 00242 * Explicitly initialize tracker with given region in image. 00243 * Additionally weight all pixels with the value in mask. 00244 * You must call this explicitly, if you want to initialize 00245 * with a weighting mask. 00246 */ 00247 void initialize(const image& src,trectangle<int>& window, const channel8& mask); 00248 00249 /** 00250 * Explicitly initialize tracker with given region in image. 00251 * Additionally weight all pixels with the value in mask. 00252 * You must call this explicitly, if you want to initialize 00253 * with a weighting mask. 00254 */ 00255 void initialize(const image& src,trectangle<int>& window, const channel& mask); 00256 00257 /** 00258 * Resets the tracker. Next call of apply initializes it again. 00259 */ 00260 void reset(); 00261 00262 /** 00263 * Tells if returned window is valid. This depends on the threshold 00264 * parameter. If the color distribution distance between target and 00265 * candidate window is above threshold, then this method returns 00266 * false. 00267 */ 00268 bool isValid() const; 00269 00270 /** 00271 * returns the distance between the color distribution of the 00272 * initial target and the last returned window. 00273 */ 00274 float getDistance() const; 00275 00276 /** 00277 * returns the center of the tracked candidate distribution. 00278 * In general, this is the returned search windows center, 00279 * except that the winwod is at the fringe of the image. 00280 */ 00281 tpoint<float> getCenter() const; 00282 00283 /** 00284 * returns a const reference to the histogram of the target. 00285 * The histogram only changes on initialization. 00286 */ 00287 const thistogram<float>& getTargetHist() const; 00288 00289 /** 00290 * returns a const reference to the histogram of the tracked candidate. 00291 * The histogram changes after each call of an apply method. 00292 */ 00293 const thistogram<float>& getCandidateHist() const; 00294 00295 /** 00296 * copy data of "other" functor. 00297 * @param other the functor to be copied 00298 * @return a reference to this functor object 00299 */ 00300 meanshiftTracker& copy(const meanshiftTracker& other); 00301 00302 /** 00303 * alias for copy member 00304 * @param other the functor to be copied 00305 * @return a reference to this functor object 00306 */ 00307 meanshiftTracker& operator=(const meanshiftTracker& other); 00308 00309 /** 00310 * returns a pointer to a clone of this functor. 00311 */ 00312 virtual functor* clone() const; 00313 00314 /** 00315 * returns used parameters 00316 */ 00317 const parameters& getParameters() const; 00318 00319 // If you add more attributes manually, do not forget to do following: 00320 // 1. indicate in the default constructor the default values 00321 // 2. make sure that the copy member also copy your new attributes, or 00322 // to ensure there, that these attributes are properly initialized. 00323 00324 private: 00325 /** 00326 * Struct for storing the tracker data after call of any apply method 00327 */ 00328 class trackerState { 00329 public: 00330 trackerState(); 00331 ~trackerState(); 00332 00333 // methods 00334 void clear(); 00335 trackerState& copy(const trackerState& other); 00336 trackerState& operator=(const trackerState& other); 00337 00338 // final center position y1 (after iterations) 00339 tpoint<float> y1; 00340 // final Bhattacharyya coefficient for position y1 00341 float bhat1; 00342 // target color probability 00343 thistogram<float> targetProb; 00344 // candidate color probability for pos y1 00345 thistogram<float> candProb; 00346 // distance and height to width ratio of tracking box 00347 float distance, hwRatio; 00348 }; 00349 00350 /** 00351 * calculates the bhattacharyya metric for measuring 00352 * similarity of two color distributions 00353 */ 00354 float calcBhatCoef(const thistogram<float>& targetProb, 00355 const thistogram<float>& candProb) const; 00356 00357 /** 00358 * fills the histogram "prob" with the colors inside the 00359 * rectangle "canvas" in the image. Each color is weighted 00360 * with a kernel function. Note: the histogramm is not 00361 * normalized to 1, thus use prob.getProbability() to obtain 00362 * probabilities. 00363 */ 00364 void calcProb(thistogram<float>& prob, 00365 const trectangle<int>& canvas, 00366 const image& src) const; 00367 00368 /** 00369 * fills the histogram "prob" with the colors inside the 00370 * rectangle "canvas" in the image. Each color is weighted 00371 * with a kernel function AND the weight given in mask. 00372 * Note: the histogramm is not normalized to 1, thus use 00373 * prob.getProbability() to obtain probabilities. 00374 */ 00375 void calcProb(thistogram<float>& prob, 00376 const trectangle<int>& canvas, 00377 const image& src, 00378 const channel8& mask) const; 00379 00380 /** 00381 * fills the histogram "prob" with the colors inside the 00382 * rectangle "canvas" in the image. Each color is weighted 00383 * with a kernel function AND the weight given in mask. 00384 * Note: the histogramm is not normalized to 1, thus use 00385 * prob.getProbability() to obtain probabilities. 00386 */ 00387 void calcProb(thistogram<float>& prob, 00388 const trectangle<int>& canvas, 00389 const image& src, 00390 const channel& mask) const; 00391 00392 00393 /** 00394 * returns the Normal or Epanechikov kernel for the given position 00395 */ 00396 float kernel(const tpoint<int>& cen, 00397 const tpoint<int>& pos, 00398 const tpoint<int>& h) const; 00399 00400 /** 00401 * calculates the color distribution distance between two histogramms 00402 */ 00403 float calcDistance(const thistogram<float>& targetProb, 00404 const thistogram<float>& candProb) const; 00405 00406 /** 00407 * shifts and clips rect to fit into given canvas 00408 */ 00409 void correctRect(trectangle<int>& rect, 00410 const trectangle<int>& canvas) const; 00411 00412 /** 00413 * returns the derivate of the Epanechikov kernel 00414 */ 00415 float derivateKernel(const tpoint<int>& cen, 00416 const tpoint<int>& pos, 00417 const tpoint<int>& h) const; 00418 00419 /** 00420 * stores results of last call of one apply method (the state of the tracker) 00421 */ 00422 trackerState td; 00423 00424 /** 00425 * indicates if the tracker is initialized 00426 */ 00427 bool initialized; 00428 00429 /** 00430 * indicates if the last apply was a valid tracking step 00431 */ 00432 bool valid; 00433 00434 }; 00435 } 00436 00437 #endif