last update 20 Sep 2009 |
00001 /* 00002 * Copyright (C) 2007 00003 * Pablo Alvarado 00004 * 00005 * This file is part of the LTI-Computer Vision Library 2 (CVR-Lib ) 00006 * 00007 * The CVR-Lib is free software; you can redistribute it and/or 00008 * modify it under the terms of the BSD License. 00009 * 00010 * All rights reserved. 00011 * 00012 * Redistribution and use in source and binary forms, with or without 00013 * modification, are permitted provided that the following conditions are met: 00014 * 00015 * 1. Redistributions of source code must retain the above copyright notice, 00016 * this list of conditions and the following disclaimer. 00017 * 00018 * 2. Redistributions in binary form must reproduce the above copyright notice, 00019 * this list of conditions and the following disclaimer in the documentation 00020 * and/or other materials provided with the distribution. 00021 * 00022 * 3. Neither the name of the authors nor the names of its contributors may be 00023 * used to endorse or promote products derived from this software without 00024 * specific prior written permission. 00025 * 00026 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00027 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00029 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00030 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00031 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00032 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00033 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00034 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00035 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00036 * POSSIBILITY OF SUCH DAMAGE. 00037 */ 00038 00039 /** 00040 * \file cvrSurfLocalDescriptor.h 00041 * Contains the class cvr::surfLocalDescriptor, 00042 * which computes local descriptors with the SURF approach. 00043 * \author Pablo Alvarado 00044 * \date 12.11.2007 00045 * 00046 * revisions ..: $Id: cvrSurfLocalDescriptor.h,v 1.1 2007/11/24 16:46:25 alvarado Exp $ 00047 */ 00048 00049 #ifndef _CVR_SURF_LOCAL_DESCRIPTOR_H_ 00050 #define _CVR_SURF_LOCAL_DESCRIPTOR_H_ 00051 00052 #include "cvrChannel.h" 00053 #include "cvrLocation.h" 00054 #include "cvrChannel8.h" 00055 #include "cvrFunctor.h" 00056 #include "cvrList.h" 00057 #include "cvrBoundaryType.h" 00058 00059 namespace cvr { 00060 00061 /** 00062 * Class surfLocalDescriptor 00063 * 00064 * This class computes the SURF descriptor for given image locations, as 00065 * explained in detail in the paper: 00066 * 00067 * Herbert Bay, Tinne Tuytelaars, and Luc Van Gool. SURF: Speeded Up Robust 00068 * Features. In Proceedings of the 9th European Conference on Computer 00069 * Vision, May 2006. Available at 00070 * http://www.vision.ee.ethz.ch/~surf/papers.html 00071 * 00072 * The implementation is based on the interpretation of the paper, and 00073 * produce different results than the ones obtained from the closed-source 00074 * implementation of the authors. Any suggestions are always welcome. 00075 * 00076 * @see surfLocalDescriptor::parameters. 00077 * 00078 * @ingroup gFeatureExtr 00079 */ 00080 class surfLocalDescriptor : public functor { 00081 public: 00082 /** 00083 * Enumeration of the modes for the orientation considerations in the 00084 * descriptor computation. 00085 */ 00086 enum eOrientationMode { 00087 Ignore, /**< Ignore the orientation. This method is fast, but 00088 * the locations have to occur on the same direction. 00089 */ 00090 Approximate, /**< The regions are never rotated, but the individual 00091 * responses of the Haar filters will be considered as 00092 * approximations of the oriented gaussian derivative 00093 * which is steerable. The computation is fast but 00094 * not as reliable. 00095 */ 00096 Cluster /**< The location orientations will be discretized so that 00097 * just a finite number of rotations need to be computed. 00098 */ 00099 }; 00100 00101 /** 00102 * The parameters for the class surfLocalDescriptor 00103 */ 00104 class parameters : public functor::parameters { 00105 public: 00106 /** 00107 * Default constructor 00108 */ 00109 parameters(); 00110 00111 /** 00112 * Copy constructor 00113 * @param other the parameters object to be copied 00114 */ 00115 parameters(const parameters& other); 00116 00117 /** 00118 * Destructor 00119 */ 00120 ~parameters(); 00121 00122 /** 00123 * Copy the contents of a parameters object 00124 * @param other the parameters object to be copied 00125 * @return a reference to this parameters object 00126 */ 00127 parameters& copy(const parameters& other); 00128 00129 /** 00130 * Copy the contents of a parameters object 00131 * @param other the parameters object to be copied 00132 * @return a reference to this parameters object 00133 */ 00134 parameters& operator=(const parameters& other); 00135 00136 /** 00137 * Returns the complete name of the parameters class. 00138 */ 00139 virtual const std::string& name() const; 00140 00141 /** 00142 * Returns a pointer to a clone of the parameters. 00143 */ 00144 virtual parameters* clone() const; 00145 00146 /** 00147 * Returns a pointer to a new instance of the parameters. 00148 */ 00149 virtual parameters* newInstance() const; 00150 00151 /** 00152 * Write the parameters in the given ioHandler 00153 * @param handler the ioHandler to be used 00154 * @param complete if true (the default) the enclosing begin/end will 00155 * be also written, otherwise only the data block will be written. 00156 * @return true if write was successful 00157 */ 00158 virtual bool write(ioHandler& handler,const bool complete=true) const; 00159 00160 /** 00161 * Read the parameters from the given ioHandler 00162 * @param handler the ioHandler to be used 00163 * @param complete if true (the default) the enclosing begin/end will 00164 * be also written, otherwise only the data block will be written. 00165 * @return true if write was successful 00166 */ 00167 virtual bool read(ioHandler& handler,const bool complete=true); 00168 00169 // ------------------------------------------------ 00170 // the parameters 00171 // ------------------------------------------------ 00172 00173 /** 00174 * Mode for consideration of the orientation in the descriptor 00175 * computation. 00176 * 00177 * Depending on the speed requirements vs. precision, which at the same 00178 * time depend on the nature of the images, several modes are provided 00179 * for the descriptor computation, with respect to the consideration of 00180 * the orientation stored in the location. 00181 * 00182 * @see surfLocationDescriptor::eOrientationMode 00183 * 00184 * Default value: Approximate 00185 */ 00186 eOrientationMode orientationMode; 00187 00188 /** 00189 * Number of clusters. 00190 * 00191 * If the orientation mode is set to Cluster, then this is the number 00192 * of orientations being used. 00193 * 00194 * Default value: 12 00195 */ 00196 int orientationClusters; 00197 00198 /** 00199 * Size of the wavelet employed to compute the descriptors. This value 00200 * will be multiplied by location radius to produce de correct wavelet 00201 * size. 00202 * 00203 * Default value: 2 00204 */ 00205 int waveletSize; 00206 00207 /** 00208 * If true, the length of the descriptor will be multiplied by four, 00209 * since the statistics are split in terms of the signs of the wavelet 00210 * responses. If you set to true with the other parameters untouched, 00211 * then the SURF-128 features described in the original paper will be 00212 * generated. 00213 * 00214 * Default value: false; 00215 */ 00216 bool signSplit; 00217 00218 /** 00219 * Std. Deviation of the gaussian function for weights. 00220 * 00221 * The weights of the wavelet responses are computed with a gaussian that 00222 * reduces the effects of elements far away from the location center. 00223 * This is the standard deviation used for the gaussian function. 00224 * 00225 * Default value: 3.5 00226 */ 00227 float gaussianWeight; 00228 00229 /** 00230 * Number of subregions per dimension to be considered. 00231 * 00232 * For example, if you specify 4, then there will be 4x4=16 regions, each 00233 * one represented in the descriptor by several values. 00234 * 00235 * Default value: 4 00236 */ 00237 int numberOfSubregions; 00238 00239 /** 00240 * Number of samples per dimension considered in each subregion. The 00241 * step between samples is always s, i.e. the radius of the location (or 00242 * the scale where the location has been detected). 00243 * 00244 * Note that the size of the complete described window is given by this 00245 * value multiplied by the numberOfSubregions. 00246 * 00247 * Default value: 5 00248 */ 00249 int subregionSamples; 00250 00251 /** 00252 * Normalize descriptor length. 00253 * 00254 * If set to \c true, the length of the vector will be normalized to 1. 00255 * If set to \c false, the descriptors will be intensity variant. 00256 * 00257 * Default value: true 00258 */ 00259 bool normalize; 00260 00261 /** 00262 * Boundary type 00263 * 00264 * If part of a location falls outside the image, how this part should be 00265 * interpreted. (Note however, that the center of each location MUST lie 00266 * within the image boundaries. 00267 * 00268 * Default value: Constant 00269 */ 00270 eBoundaryType boundaryType; 00271 }; 00272 00273 /** 00274 * Default constructor 00275 */ 00276 surfLocalDescriptor(); 00277 00278 /** 00279 * Construct a functor using the given parameters 00280 */ 00281 surfLocalDescriptor(const parameters& par); 00282 00283 /** 00284 * Copy constructor 00285 * @param other the object to be copied 00286 */ 00287 surfLocalDescriptor(const surfLocalDescriptor& other); 00288 00289 /** 00290 * Destructor 00291 */ 00292 virtual ~surfLocalDescriptor(); 00293 00294 /** 00295 * Operates on the given argument. 00296 * 00297 * @param src channel8 with the image to be described. 00298 * @param locs list of locations to be described 00299 * @param desc resulting descritors computed for each location. 00300 * @return true if apply successful or false otherwise. 00301 */ 00302 bool apply(const channel8& src, 00303 const list<location>& locs, 00304 std::list<dvector>& desc) const; 00305 00306 /** 00307 * Operates on the given argument. 00308 * 00309 * @param src channel8 with the image to be described. 00310 * @param locs list of locations to be described 00311 * @param desc resulting descritors computed for each location. 00312 * @return true if apply successful or false otherwise. 00313 */ 00314 bool apply(const channel& src, 00315 const list<location>& locs, 00316 std::list<dvector>& desc) const; 00317 00318 /** 00319 * Operates on the given argument. 00320 * 00321 * @param src channel8 with the image to be described. 00322 * @param loc the locations to be described 00323 * @param desc resulting descritor computed for the given location. 00324 * @return true if apply successful or false otherwise. 00325 */ 00326 bool apply(const channel& src, 00327 const location& loc, 00328 dvector& desc) const; 00329 00330 /** 00331 * Copy data of "other" functor. 00332 * @param other the functor to be copied 00333 * @return a reference to this functor object 00334 */ 00335 surfLocalDescriptor& copy(const surfLocalDescriptor& other); 00336 00337 /** 00338 * Alias for copy member 00339 * @param other the functor to be copied 00340 * @return a reference to this functor object 00341 */ 00342 surfLocalDescriptor& operator=(const surfLocalDescriptor& other); 00343 00344 /** 00345 * Returns the complete name of the functor class 00346 */ 00347 virtual const std::string& name() const; 00348 00349 /** 00350 * Returns a pointer to a clone of this functor. 00351 */ 00352 virtual surfLocalDescriptor* clone() const; 00353 00354 /** 00355 * Returns a pointer to a new instance of this functor. 00356 */ 00357 virtual surfLocalDescriptor* newInstance() const; 00358 00359 /** 00360 * Returns used parameters 00361 */ 00362 const parameters& getParameters() const; 00363 00364 /** 00365 * Update the parameters 00366 */ 00367 bool updateParameters(); 00368 00369 private: 00370 /** 00371 * The dispatcherreal computation is done here 00372 */ 00373 template<typename T> 00374 bool helper(const matrix<T>& src, 00375 const list<location>& locs, 00376 std::list<dvector>& desc) const; 00377 00378 00379 /** 00380 * The real computation is done here, with an approximation of the 00381 * rotation. 00382 */ 00383 template<typename T> 00384 bool helperApprox(const matrix<T>& src, 00385 const list<location>& locs, 00386 std::list<dvector>& desc) const; 00387 00388 00389 /** 00390 * The real computation is done here, making a few rotations 00391 */ 00392 template<typename T> 00393 bool helperCluster(const matrix<T>& src, 00394 const list<location>& locs, 00395 std::list<dvector>& desc) const; 00396 00397 /** 00398 * The real computation is done here, ignoring the rotation 00399 */ 00400 template<typename T> 00401 bool helperIgnore(const matrix<T>& src, 00402 const list<location>& locs, 00403 std::list<dvector>& desc) const; 00404 00405 /** 00406 * Compute the shortest angular distance between to angles 00407 * 00408 * All angles have to be given in radians. 00409 */ 00410 inline float adist(const float a,const float b) const; 00411 00412 /** 00413 * Signed angular distance 00414 * 00415 * All angles have to be given in radians. 00416 * 00417 * If the angle a is after the angle b in the counter-clockwise direction 00418 * then the result is positive, otherwise it is negative. The absolute 00419 * value is always less than pi. 00420 */ 00421 inline float sadist(const float a,const float b) const; 00422 00423 00424 /** 00425 * Compute mean and variance of cluster 00426 */ 00427 void stats(const fvector& theSin, 00428 const fvector& theCos, 00429 const ivector& theLocs, 00430 const int numLocs, 00431 float& meanSin, 00432 float& meanCos, 00433 float& varSin, 00434 float& varCos) const; 00435 00436 /** 00437 * K-Means clustering of orientations 00438 * 00439 * This method splits the location list in several lists that share 00440 * the same locations. It uses the k-means algorithm to sort them out. 00441 * 00442 * @param locs The original list of locations 00443 * @param refs The locs list converted to a vector for random access. 00444 * @param clusters Each row of this matrix corresponds to an orientation 00445 * cluster, containing the index of the location in the 00446 * refs vector. 00447 * @param angles The centroid orientation of each cluster 00448 * @param sines The sine of the angle for each cluster 00449 * @param cosine The cosine of the angle for each cluster 00450 * @param numLocs The number of locations in each cluster (may be zero) 00451 */ 00452 bool cluster(const list<location>& locs, 00453 std::vector<location>& refs, 00454 imatrix& clusters, 00455 fvector& angles, 00456 fvector& sines, 00457 fvector& cosines, 00458 ivector& numLocs) const; 00459 00460 00461 /** 00462 * Gaussian weights 00463 */ 00464 fmatrix gaussian_; 00465 00466 /** 00467 * Some really private classes 00468 */ 00469 class block; 00470 class block4; 00471 class block8; 00472 }; 00473 00474 /** 00475 * Read a surfLocalDescriptor::eOrientationMode value 00476 * 00477 * @ingroup gStorable 00478 */ 00479 bool read(ioHandler& handler, 00480 surfLocalDescriptor::eOrientationMode& data); 00481 00482 /** 00483 * Write a surfLocalDescriptor::eOrientationMode value 00484 * 00485 * @ingroup gStorable 00486 */ 00487 bool write(ioHandler& handler, 00488 const surfLocalDescriptor::eOrientationMode& data); 00489 00490 00491 } 00492 00493 #endif 00494