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 .......: ltiLkTracker.h 00027 * authors ....: Frederik Lange 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 26.4.2001 00030 * revisions ..: $Id: ltiLkTracker.h,v 1.8 2006/02/08 11:23:21 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_LK_TRACKER_H_ 00034 #define _LTI_LK_TRACKER_H_ 00035 00036 #include "ltiImage.h" 00037 #include "ltiModifier.h" 00038 #include "ltiPointList.h" 00039 #include "ltiGaussianPyramid.h" 00040 #include "ltiCornerDetector.h" 00041 00042 namespace lti { 00043 00044 /** 00045 * This functor implements a hierachical Lucas Kanade optical flow. 00046 * It is used for feature tracking through a image sequence. 00047 * Therefore it uses a corner detector to find the initial features 00048 * 00049 * For more details please look at Jean-Yves Bouguet's paper "Pyramidal 00050 * Implementation of the Lucas Kanade Feature Tracker. Description of the 00051 * algorithm" 00052 * 00053 */ 00054 class lkTracker : public modifier { 00055 public: 00056 00057 /** 00058 * constant which describes a point outOfRange. In general, a point 00059 * with negative coordinates can be considered out of range 00060 */ 00061 static const tpoint<float> outOfRange; 00062 00063 /** 00064 * the parameters for the class lkTracker 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 * returns name of this type 00086 */ 00087 const char* getTypeName() const; 00088 00089 /** 00090 * copy the contents of a parameters object 00091 * @param other the parameters object to be copied 00092 * @return a reference to this parameters object 00093 */ 00094 parameters& copy(const parameters& other); 00095 00096 /** 00097 * copy the contents of a parameters object 00098 * @param other the parameters object to be copied 00099 * @return a reference to this parameters object 00100 */ 00101 parameters& operator=(const parameters& other); 00102 00103 00104 /** 00105 * returns a pointer to a clone of the parameters 00106 */ 00107 virtual functor::parameters* clone() const; 00108 00109 /** 00110 * write the parameters in the given ioHandler 00111 * @param handler the ioHandler to be used 00112 * @param complete if true (the default) the enclosing begin/end will 00113 * be also written, otherwise only the data block will be written. 00114 * @return true if write was successful 00115 */ 00116 virtual bool write(ioHandler& handler,const bool complete=true) const; 00117 00118 /** 00119 * write the parameters in the given ioHandler 00120 * @param handler the ioHandler to be used 00121 * @param complete if true (the default) the enclosing begin/end will 00122 * be also written, otherwise only the data block will be written. 00123 * @return true if write was successful 00124 */ 00125 virtual bool read(ioHandler& handler,const bool complete=true); 00126 00127 # ifdef _LTI_MSC_6 00128 /** 00129 * this function is required by MSVC only, as a workaround for a 00130 * very awful bug, which exists since MSVC V.4.0, and still by 00131 * V.6.0 with all bugfixes (so called "service packs") remains 00132 * there... This method is also public due to another bug, so please 00133 * NEVER EVER call this method directly: use read() instead 00134 */ 00135 bool readMS(ioHandler& handler,const bool complete=true); 00136 00137 /** 00138 * this function is required by MSVC only, as a workaround for a 00139 * very awful bug, which exists since MSVC V.4.0, and still by 00140 * V.6.0 with all bugfixes (so called "service packs") remains 00141 * there... This method is also public due to another bug, so please 00142 * NEVER EVER call this method directly: use write() instead 00143 */ 00144 bool writeMS(ioHandler& handler,const bool complete=true) const; 00145 # endif 00146 00147 // ------------------------------------------------ 00148 // the parameters 00149 // ------------------------------------------------ 00150 00151 /** 00152 * WindowSize gives the size of the window used for comparsion 00153 * of the features. 00154 * 00155 * Default value is 4 00156 */ 00157 int windowSize; 00158 00159 /** 00160 * NumLevels gives the number of levels in the Pyramid. 00161 * 00162 * Default value is 4 00163 */ 00164 int numLevels; 00165 00166 /** 00167 * maximal number of iteration steps per pyramid level. 00168 * Default value: 10 00169 */ 00170 int maxStepsPerLevel; 00171 00172 /** 00173 * This is the square of the computed pixel residual which must be 00174 * reached before the algorithm stops. 00175 * Default value: 0.0009f (0.03*0.03); 00176 */ 00177 float eta2Threshold; 00178 00179 /** 00180 * if the difference between both matched windows is greater 00181 * than this threshold, the point will be marked as invalid, and it 00182 * will not be tracked any more. 00183 * Default value: 0.99f 00184 */ 00185 float errorThreshold; 00186 00187 /** 00188 * @name Corner Extraction 00189 * The following parameters controls the internal corner detection 00190 * algorithms. 00191 */ 00192 //@{ 00193 /** 00194 * if true, a corner detector is used. 00195 * 00196 * Default is true 00197 */ 00198 bool autoCorners; 00199 00200 /** 00201 * set the corner detector to be used. A copy of the given 00202 * functor will be made. 00203 */ 00204 bool setCornerDetector(const cornerDetector& cdet); 00205 00206 /** 00207 * get a reference to the corner detector functor being used 00208 */ 00209 cornerDetector& getCornerDetector(); 00210 00211 /** 00212 * get a read only reference to the corner detector object being used 00213 */ 00214 const cornerDetector& getCornerDetector() const; 00215 //@} 00216 00217 protected: 00218 /** 00219 * cornerDetector used to generate the corners. 00220 * 00221 * Default value: 00222 */ 00223 cornerDetector* cornerFinder; 00224 }; 00225 00226 /** 00227 * default constructor 00228 */ 00229 lkTracker(); 00230 00231 /** 00232 * copy constructor 00233 * @param other the object to be copied 00234 */ 00235 lkTracker(const lkTracker& other); 00236 00237 /** 00238 * destructor 00239 */ 00240 virtual ~lkTracker(); 00241 00242 /** 00243 * returns the name of this type ("lkTracker") 00244 */ 00245 virtual const char* getTypeName() const; 00246 00247 /** 00248 * Track the points in the src channel and return the new positions in 00249 * the given point list. 00250 * Please note that internally the pointList contains points with 00251 * <code>float</code> precision, and to return an <code>pointList</code> 00252 * they need to be casted. Is faster if you try to use directly the 00253 * other apply member, which works directly with the float-points. 00254 * 00255 * @param src the channel with the points being tracked. 00256 * The first presentation (or the next presentation after a 00257 * reset() ) is used for initialization only. The 00258 * next ones are used to track the first given point set, and 00259 * the results will be left in <code>featurePoints</code>. 00260 * 00261 * @param featurePoints the first time the apply is called (or after a 00262 * reset() ), this list contain the positions of the points to 00263 * track. If the attribute <code>autoCorners</code> of the 00264 * parameters is true, the content of this list will be 00265 * discarded and the positions of the automatic detected 00266 * corners will be left here. Points getting 00267 * invalid during tracking are marked by negative values in the 00268 * point list. 00269 * 00270 * @return true if apply successful or false otherwise. 00271 */ 00272 bool apply(const channel& src, pointList& featurePoints); 00273 00274 /** 00275 * Track the points in the src channel and return the new positions in 00276 * the given point list. 00277 * Please note that internally the pointList contains points with 00278 * <code>float</code> precision, and to return an <code>pointList</code> 00279 * they need to be casted. Is faster if you try to use directly the 00280 * other apply member, which works directly with the float-points. 00281 * 00282 * @param src the channel with the points being tracked. 00283 * The first presentation (or the next presentation after a 00284 * reset() ) is used for initialization only. The 00285 * next ones are used to track the first given point set, and 00286 * the results will be left in <code>featurePoints</code>. 00287 * 00288 * @param featurePoints the first time the apply is called (or after a 00289 * reset() ), this list contain the positions of the points to 00290 * track. If the attribute <code>autoCorners</code> of the 00291 * parameters is true, the content of this list will be 00292 * discarded and the positions of the automatic detected 00293 * corners will be left here. Points getting 00294 * invalid during tracking are marked by negative values in the 00295 * point list. 00296 * @param validPoints returns the number of valid points in the list 00297 * feature points. 00298 * @return true if apply successful or false otherwise. 00299 */ 00300 bool apply(const channel& src, pointList& featurePoints,int& validPoints); 00301 00302 /** 00303 * Track the points in the src channel and return the new positions in 00304 * the given point list. 00305 * 00306 * @param src the channel with the points being tracked. 00307 * The first presentation (or the next presentation after a 00308 * reset() ) is used for initialization only. The 00309 * next ones are used to track the first given point set, and 00310 * the results will be left in <code>featurePoints</code>. 00311 * 00312 * @param featurePoints the first time the apply is called (or after a 00313 * reset() ), this list contain the positions of the points to 00314 * track. If the attribute <code>autoCorners</code> of the 00315 * parameters is true, the content of this list will be 00316 * discarded and the positions of the automatic detected 00317 * corners will be left here. Points getting 00318 * invalid during tracking are marked by negative values in the 00319 * point list. 00320 * 00321 * @return true if apply successful or false otherwise. 00322 */ 00323 bool apply(const channel& src, tpointList<float>& featurePoints); 00324 00325 /** 00326 * Track the points in the src channel and return the new positions in 00327 * the given point list. 00328 * 00329 * @param src the channel with the points being tracked. 00330 * The first presentation (or the next presentation after a 00331 * reset() ) is used for initialization only. The 00332 * next ones are used to track the first given point set, and 00333 * the results will be left in <code>featurePoints</code>. 00334 * 00335 * @param featurePoints the first time the apply is called (or after a 00336 * reset() ), this list contain the positions of the points to 00337 * track. If the attribute <code>autoCorners</code> of the 00338 * parameters is true, the content of this list will be 00339 * discarded and the positions of the automatic detected 00340 * corners will be left here. Points getting 00341 * invalid during tracking are marked by negative values in the 00342 * point list. 00343 * @param validPoints returns the number of valid points in the list 00344 * featurePoints 00345 * 00346 * @return true if apply successful or false otherwise. 00347 */ 00348 bool apply(const channel& src, tpointList<float>& featurePoints, 00349 int& validPoints); 00350 00351 /** 00352 * Resets the internal state but not the parameters 00353 */ 00354 bool reset(); 00355 00356 /** 00357 * Reset some points in the tracking list. 00358 * 00359 * Please note that this reset takes effect only if there is already 00360 * a tracking point list in the functor, i.e. if a "total" reset was 00361 * already done followed by an apply. 00362 * 00363 * @param whichPoints Only those points in the list with valid 00364 * values (coordinates > 0) will be reset: they will get this 00365 * valid value. All invalid points in the list, i.e. with 00366 * coordinates lower than zero will be keped as they are. 00367 * Please note that point sequence in this list must correspond to 00368 * the sequence of the tracking list! 00369 */ 00370 bool reset(const tpointList<float>& whichPoints); 00371 00372 /** 00373 * Reset some points in the tracking list. 00374 * 00375 * Please note that this reset takes effect only if there is already 00376 * a tracking point list in the functor, i.e. if a "total" reset was 00377 * already done followed by an apply. 00378 * 00379 * @param whichPoints Only those points in the list with valid 00380 * values (coordinates > 0) will be reset: they will get this 00381 * valid value. All invalid points in the list, i.e. with 00382 * coordinates lower than zero will be keped as they are. 00383 * Please note that point sequence in this list must correspond to 00384 * the sequence of the tracking list! 00385 */ 00386 bool reset(const pointList& whichPoints); 00387 00388 /** 00389 * copy data of "other" functor. 00390 * @param other the functor to be copied 00391 * @return a reference to this functor object 00392 */ 00393 lkTracker& copy(const lkTracker& other); 00394 00395 /** 00396 * returns a pointer to a clone of this functor. 00397 */ 00398 virtual functor* clone() const; 00399 00400 /** 00401 * returns used parameters 00402 */ 00403 const parameters& getParameters() const; 00404 00405 protected: 00406 /** 00407 * a position/direction vector type 00408 */ 00409 class vec2d { 00410 public: 00411 /** 00412 * Default constructor. Intialize all members with 0.0f 00413 */ 00414 vec2d() : error(0.0f) {}; 00415 00416 /** 00417 * default destructor 00418 */ 00419 ~vec2d(){}; 00420 00421 /** 00422 * position of the origin of the vector 00423 */ 00424 tpoint<float> p; 00425 00426 /** 00427 * direction of the vector 00428 */ 00429 tpoint<float> d; 00430 00431 /** 00432 * error term 00433 */ 00434 float error; 00435 }; 00436 00437 private: 00438 /** 00439 * automatic detection of corners 00440 */ 00441 void findInitialPoints(const channel& img,pointList& initialPoints); 00442 00443 /** 00444 * exchange both pyramids and generate the new gassian pyramid for 00445 * the given channel in the pyramid B. 00446 */ 00447 void buildPyramid(const channel& img); 00448 00449 /** 00450 * generate the gradient of the given channel 00451 */ 00452 void buildGradientMaps(const gaussianPyramid<channel>& src, 00453 channel*& gradX, 00454 channel*& gradY); 00455 00456 /** 00457 * return the result of a bilinear interpolation for the value at(y,x) 00458 */ 00459 inline float getBilinear(const float x, const float y, const channel& map); 00460 00461 /** 00462 * indicates if the tracker is initialised 00463 */ 00464 bool initialised; 00465 00466 /** 00467 * the two pyramids for the downsampled images 00468 * These are pointers to allow efficient exchange from B to A without 00469 * copying anything. 00470 */ 00471 gaussianPyramid<channel> 00472 *pyramidA, 00473 *pyramidB; 00474 00475 /** 00476 * the flow vectors between the images 00477 */ 00478 std::list<vec2d> flowVectors; 00479 00480 }; 00481 } 00482 00483 #endif