latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 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-Lib: Image Processing and Computer Vision Library 00026 * file .......: ltiScaleSpacePyramid.h 00027 * authors ....: Pablo Alvarado, Frederik Lange 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 17.03.2003 00030 * revisions ..: $Id: ltiScaleSpacePyramid.h,v 1.6 2006/02/08 11:47:36 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_SCALESPACE_PYRAMID_H_ 00034 #define _LTI_SCALESPACE_PYRAMID_H_ 00035 00036 #include "ltiObject.h" 00037 #include "ltiFunctor.h" 00038 #include "ltiPyramid.h" 00039 00040 #include "ltiInterpolatorType.h" 00041 #include "ltiNearestNeighborInterpolator.h" 00042 #include "ltiBilinearInterpolator.h" 00043 #include "ltiBiquadraticInterpolator.h" 00044 00045 #include "ltiMath.h" 00046 00047 namespace lti { 00048 00049 /** 00050 * Image pyramid to represent the scale space. 00051 * 00052 * This pyramid can be used for scale-dependent image access. At 00053 * construction time the input channel is downsampled to several 00054 * scales as specified with the resize()-method. 00055 * 00056 * Each channel is downsampled by "factor"-parameter with Gaussian 00057 * convolution applied. This factor is usually greater than 0.5 (the 00058 * usual one in image pyramids), but still must be less than 1.0. 00059 * This is done to archieve a much higher precision. 00060 * 00061 * As with other pyramids, the template type T represents the image type. 00062 * Usually you will want to use an scaleSpacePyramid<channel>. 00063 * 00064 * For this class the term "level" denotes one of the existent layers of 00065 * the pyramid. The term "scale" denotes a real value. The "levels" 00066 * have explicit scales, that can be obtaind with getLevelScale(). 00067 * 00068 */ 00069 template<class T> 00070 class scaleSpacePyramid : public pyramid<T> { 00071 public: 00072 /** 00073 * Type of elements of the channels of type T 00074 */ 00075 typedef typename T::value_type value_type; 00076 00077 /** 00078 * Parameters for the generation of scaleSpace pyramids. 00079 * 00080 * Even if scaleSpacePyramid is by no means a functor, the 00081 * number of parameters required in its generation is large enough to 00082 * justify the use of a parameters class. It is just inherited from 00083 * functor::parameters to reuse the interface defined there. 00084 */ 00085 class parameters : public functor::parameters { 00086 public: 00087 /** 00088 * default constructor 00089 */ 00090 parameters() : functor::parameters() { 00091 automaticKernel = bool(true); 00092 kernelSize = int(5); 00093 kernelVariance = double(1.6*1.6); 00094 gaussian = bool(false); 00095 factor = double(0.793700526); // (0.5^(1/3)) 00096 interpolatorType = BilinearInterpolator; 00097 }; 00098 00099 /** 00100 * copy constructor 00101 * @param other the parameters object to be copied 00102 */ 00103 parameters(const parameters& other) : functor::parameters() { 00104 copy(other); 00105 } 00106 00107 /** 00108 * destructor 00109 */ 00110 ~parameters() { 00111 }; 00112 00113 /** 00114 * returns name of this type 00115 */ 00116 const char* getTypeName() const { 00117 return "scaleSpacePyramid::parameters"; 00118 }; 00119 00120 /** 00121 * copy the contents of a parameters object 00122 * @param other the parameters object to be copied 00123 * @return a reference to this parameters object 00124 */ 00125 parameters& copy(const parameters& other) { 00126 # ifndef _LTI_MSC_6 00127 // MS Visual C++ 6 is not able to compile this... 00128 functor::parameters::copy(other); 00129 # else 00130 // ...so we have to use this workaround. 00131 // Conditional on that, copy may not be virtual. 00132 functor::parameters& (functor::parameters::* p_copy) 00133 (const functor::parameters&) = 00134 functor::parameters::copy; 00135 (this->*p_copy)(other); 00136 # endif 00137 00138 00139 automaticKernel = other.automaticKernel; 00140 kernelSize = other.kernelSize; 00141 kernelVariance = other.kernelVariance; 00142 gaussian = other.gaussian; 00143 factor = other.factor; 00144 interpolatorType = other.interpolatorType; 00145 00146 return *this; 00147 }; 00148 00149 /** 00150 * copy the contents of a parameters object 00151 * @param other the parameters object to be copied 00152 * @return a reference to this parameters object 00153 */ 00154 parameters& operator=(const parameters& other) { 00155 return copy(other); 00156 }; 00157 00158 /** 00159 * returns a pointer to a clone of the parameters 00160 */ 00161 virtual functor::parameters* clone() const { 00162 return new parameters(*this); 00163 }; 00164 00165 # ifndef _LTI_MSC_6 00166 /** 00167 * write the parameters in the given ioHandler 00168 * @param handler the ioHandler to be used 00169 * @param complete if true (the default) the enclosing begin/end will 00170 * be also written, otherwise only the data block will be written. 00171 * @return true if write was successful 00172 */ 00173 virtual bool write(ioHandler& handler,const bool complete=true) const 00174 # else 00175 /** 00176 * this function is required by MSVC only, as a workaround for a 00177 * very awful bug, which exists since MSVC V.4.0, and still by 00178 * V.6.0 with all bugfixes (so called "service packs") remains 00179 * there... This method is also public due to another bug, so please 00180 * NEVER EVER call this method directly: use write() instead 00181 */ 00182 bool writeMS(ioHandler& handler,const bool complete=true) const 00183 # endif 00184 { 00185 bool b = true; 00186 if (complete) { 00187 b = handler.writeBegin(); 00188 } 00189 00190 if (b) { 00191 lti::write(handler,"factor",factor); 00192 lti::write(handler,"interpolatorType",interpolatorType); 00193 lti::write(handler,"gaussian",gaussian); 00194 lti::write(handler,"automaticKernel",automaticKernel); 00195 lti::write(handler,"kernelSize",kernelSize); 00196 lti::write(handler,"kernelVariance",kernelVariance); 00197 } 00198 00199 # ifndef _LTI_MSC_6 00200 // This is the standard C++ code, which MS Visual C++ 6 is not able to 00201 // compile... 00202 b = b && functor::parameters::write(handler,false); 00203 # else 00204 bool (functor::parameters::* p_writeMS)(ioHandler&, 00205 const bool) const = 00206 functor::parameters::writeMS; 00207 b = b && (this->*p_writeMS)(handler,false); 00208 # endif 00209 00210 if (complete) { 00211 b = b && handler.writeEnd(); 00212 } 00213 00214 return b; 00215 } 00216 00217 # ifdef _LTI_MSC_6 00218 /** 00219 * write the parameters in the given ioHandler 00220 * @param handler the ioHandler to be used 00221 * @param complete if true (the default) the enclosing begin/end will 00222 * be also written, otherwise only the data block will be written. 00223 * @return true if write was successful 00224 */ 00225 bool write(ioHandler& handler, 00226 const bool complete=true) const { 00227 // ...we need this workaround to cope with another really 00228 // awful MSVC bug. 00229 return writeMS(handler,complete); 00230 } 00231 # endif 00232 00233 00234 # ifndef _LTI_MSC_6 00235 /** 00236 * read the parameters from the given ioHandler 00237 * @param handler the ioHandler to be used 00238 * @param complete if true (the default) the enclosing begin/end will 00239 * be also written, otherwise only the data block will be written. 00240 * @return true if write was successful 00241 */ 00242 virtual bool read(ioHandler& handler,const bool complete=true) 00243 # else 00244 /** 00245 * this function is required by MSVC only, as a workaround for a 00246 * very awful bug, which exists since MSVC V.4.0, and still by 00247 * V.6.0 with all bugfixes (so called "service packs") remains 00248 * there... This method is also public due to another bug, so please 00249 * NEVER EVER call this method directly: use read() instead 00250 */ 00251 bool readMS(ioHandler& handler,const bool complete=true) 00252 # endif 00253 { 00254 bool b = true; 00255 if (complete) { 00256 b = handler.readBegin(); 00257 } 00258 00259 if (b) { 00260 b = lti::read(handler,"factor",factor) && b; 00261 b = lti::read(handler,"interpolatorType",interpolatorType) && b; 00262 b = lti::read(handler,"gaussian",gaussian) && b; 00263 b = lti::read(handler,"automaticKernel",automaticKernel) && b; 00264 b = lti::read(handler,"kernelSize",kernelSize) && b; 00265 b = lti::read(handler,"kernelVariance",kernelVariance) && b; 00266 } 00267 00268 # ifndef _LTI_MSC_6 00269 // This is the standard C++ code, which MS Visual C++ 6 is not 00270 // able to compile... 00271 b = b && functor::parameters::read(handler,false); 00272 # else 00273 bool (functor::parameters::* p_readMS)(ioHandler&, 00274 const bool) = 00275 functor::parameters::readMS; 00276 b = b && (this->*p_readMS)(handler,false); 00277 # endif 00278 00279 if (complete) { 00280 b = b && handler.readEnd(); 00281 } 00282 00283 return b; 00284 } 00285 00286 # ifdef _LTI_MSC_6 00287 /** 00288 * read the parameters from the given ioHandler 00289 * @param handler the ioHandler to be used 00290 * @param complete if true (the default) the enclosing begin/end will 00291 * be also written, otherwise only the data block will be written. 00292 * @return true if write was successful 00293 */ 00294 bool read(ioHandler& handler,const bool complete=true) { 00295 // ...we need this workaround to cope with another really awful MSVC 00296 // bug. 00297 return readMS(handler,complete); 00298 } 00299 # endif 00300 00301 // ------------------------------------------------ 00302 // the parameters 00303 // ------------------------------------------------ 00304 00305 /** 00306 * Specify if each level in the pyramid should be smoothed with a 00307 * Gaussian kernel or not. 00308 * 00309 * Default: false 00310 */ 00311 bool gaussian; 00312 00313 /** 00314 * Kernel size used to smooth each pyramid level. 00315 * 00316 * Used only if the automaticKernel mode is set to false and 00317 * Gaussian smoothing is desired. 00318 * 00319 * Default is 5 00320 */ 00321 int kernelSize; 00322 00323 /** 00324 * Kernel variance 00325 * 00326 * Used only if the automaticKernel mode is set to false and 00327 * Gaussian smoothing is desired. 00328 * 00329 * Default value: 1.6*1.6 00330 */ 00331 double kernelVariance; 00332 00333 /** 00334 * Automatic kernel computation. 00335 * 00336 * The size and the variance of the smoothing kernel are determined 00337 * depending on the factor for downsampling. 00338 * 00339 * Default value: true 00340 */ 00341 bool automaticKernel; 00342 00343 /** 00344 * Scale factor between adjacent pyramid layers. 00345 * 00346 * This parameter determines the factor between the resolution 00347 * resolution(n) = resolution(0) * factor^n 00348 * 00349 * This value should be in the interval ]0.5,1.0[ in order for many 00350 * of the interpolation methods to work properly. 00351 * 00352 * Default: cubic root of 0.5 == 0.793700526 00353 */ 00354 double factor; 00355 00356 /** 00357 * Interpolation mode used. 00358 * 00359 * The "downsampling" will use interpolation to get values between the 00360 * pixels of a higher resolution level. 00361 * 00362 * Default: BilinearInterpolator 00363 */ 00364 eInterpolatorType interpolatorType; 00365 }; 00366 00367 /** 00368 * Default constructor 00369 */ 00370 scaleSpacePyramid<T>(); 00371 00372 /** 00373 * Create a pyramid with the given number of levels and the given 00374 * parameters 00375 */ 00376 scaleSpacePyramid<T>(const int levels, 00377 const parameters& par = parameters()); 00378 00379 /** 00380 * Copy constructor 00381 * 00382 * @param other the object to be copied 00383 */ 00384 scaleSpacePyramid<T>(const scaleSpacePyramid<T>& other); 00385 00386 /** 00387 * Destructor 00388 */ 00389 virtual ~scaleSpacePyramid<T>(); 00390 00391 /** 00392 * Returns the name of this type ("scaleSpacePyramid<T>") 00393 */ 00394 virtual const char* getTypeName() const; 00395 00396 /** 00397 * Copy data of "other" functor. 00398 * 00399 * @param other the functor to be copied 00400 * @return a reference to this functor object 00401 */ 00402 scaleSpacePyramid<T>& copy(const scaleSpacePyramid<T>& other); 00403 00404 /** 00405 * Alias for copy member 00406 * 00407 * @param other the functor to be copied 00408 * @return a reference to this functor object 00409 */ 00410 scaleSpacePyramid<T>& operator=(const scaleSpacePyramid<T>& other); 00411 00412 /** 00413 * Returns a pointer to a clone of this pyramid. 00414 */ 00415 virtual mathObject* clone() const; 00416 00417 /** 00418 * Change the number of resolutions of the pyramid 00419 * 00420 * @param levels the new number of levels or layers of the pyramid 00421 * @param copyData if true (default), the old data will be keeped. 00422 * If false, all data will be lost. 00423 */ 00424 void resize(const int& levels, 00425 const bool& copyData=true); 00426 00427 /** 00428 * set parameters 00429 */ 00430 virtual bool setParameters(const parameters& par); 00431 00432 /** 00433 * Get a read-only reference to parameters. 00434 */ 00435 const parameters& getParameters() const; 00436 00437 /** 00438 * Generate the pyramid of the given object. 00439 * 00440 * The pyramid will contain the number of levels specified in 00441 * the construction or in the resize() method. 00442 * 00443 * The level "0" will correspond to the original channel or 00444 * image. The level \e i+1 is always a parameters::factor 00445 * times smaller than the level \e i at each axis. 00446 */ 00447 void generate(const T& src); 00448 00449 /** 00450 * Generate the pyramid of the given object. 00451 * 00452 * The pyramid will contain the number of resolutions specified 00453 * by \a theResolutions. 00454 * 00455 * The level "0" will correspond to the original channel or 00456 * image. The resolution \e i+1 is always a parameters::factor 00457 * times smaller than the level \e i at each axis. 00458 */ 00459 void generate(const T& src,const int& numLevels); 00460 00461 /** 00462 * @name Scale-space access operators 00463 * 00464 * The scale space can be accessed at any real x,y and scale values. 00465 * Interpolation is necessary to get a spatial subpixel or a value 00466 * between scales. The methods can use several one-dimensional 00467 * interpolations, which is relative fast to compute, or can use 00468 * more precise but much expensive two or three dimensional 00469 * interpolation polynoms. 00470 * 00471 * The spatial coordinates are always given with respect to the first 00472 * level (level 0), which mean they must be between (0,0) and 00473 * (at(0).lastColumn(),at(0).lastRow()). 00474 */ 00475 //@{ 00476 00477 /** 00478 * Get an "in level" nearest neighbor interpolation. 00479 * 00480 * The given level \a lev must be in the pyramid. 00481 */ 00482 value_type nearestAt(const float y,const float x,const int lev) const; 00483 00484 /** 00485 * Get an "in level" bilinear interpolation. 00486 * 00487 * The given level \a lev must be in the pyramid. 00488 */ 00489 value_type bilinearAt(const float y,const float x,const int lev) const; 00490 00491 /** 00492 * Get an "in level" biquadratic interpolation. 00493 * 00494 * The given level \a lev must be in the pyramid. 00495 */ 00496 value_type biquadraticAt(const float y,const float x,const int lev) const; 00497 00498 /** 00499 * Get an "in level" quadratic interpolation. 00500 * 00501 * The given level \a lev must be in the pyramid. 00502 * 00503 * Since the pixel (x,y) at level \a lev has eight neighbors and the 00504 * quadratic function only six coefficients, the least square error 00505 * quadratic surface passing exactly through the middle point will be 00506 * computed, i.e. five of the six coefficients will be determined using 00507 * the eight neighbor points of the middle one. 00508 * 00509 * Please note that there is an overload of this function for a 00510 * scale value \a s instead of a level, which does a similar task but also 00511 * interpolates between levels (see 00512 * quadraticAt(const float,const float,const float)). 00513 */ 00514 value_type quadraticAt(const float y,const float x,const int lev) const; 00515 00516 /** 00517 * Get a "between-scales" trilinear interpolation. 00518 * 00519 * The given scale \a s must be in the pyramid, 00520 * i.e. s>=0 and s<=parameters::factor^size()-1 00521 */ 00522 value_type trilinearAt(const float y,const float x,const float s) const; 00523 00524 /** 00525 * Get an "between-scales" triquadratic interpolation 00526 * 00527 * The given scale \a s must be in the pyramid, 00528 * i.e. s>=0 and s<=parameters::factor^size()-1 00529 */ 00530 value_type triquadraticAt(const float y,const float x,const float s) const; 00531 00532 /** 00533 * Compute for the given (x,y) spatial coordinates three "in-level" 00534 * quadratic interpolations at the three nearest levels of the given 00535 * scale \a s, and from the three new values interpolate 00536 * quadratically for the corresponding scale value. 00537 * 00538 * The given scale \a s must be in the pyramid, 00539 * i.e. s>=0 and s<=parameters::factor^(size()-1) 00540 * 00541 * This is therefore a combination between 2D and 1D quadratic 00542 * interpolations. 00543 * 00544 * Note that if the scale \a s is integer it is faster to call the other 00545 * quadraticAt method that expects the level of the pyramid. 00546 * 00547 * @see quadraticAt(const float,const float,const int) const; 00548 */ 00549 value_type quadraticAt(const float y,const float x,const float s) const; 00550 //@} 00551 00552 /** 00553 * Get the scale corresponding for a circular area of the given 00554 * radius. 00555 * 00556 * At the scale 0, the radius of a pixel is 0.5. 00557 */ 00558 float getScaleForRadius(const float radius) const; 00559 00560 /** 00561 * Get the radius of one "pixel" for the given level. 00562 * 00563 * At the level 0, the radius of a pixel is 0.5. 00564 */ 00565 float getRadiusForScale(const float scale) const; 00566 00567 /** 00568 * Return the scale for the levels of the pyramid 00569 */ 00570 inline const double& getLevelScale(const int level) const; 00571 00572 /** 00573 * Type of extrema detected at a given point 00574 */ 00575 enum eExtremaType { 00576 NoExtremum=0, /**< No extremum point has been detected */ 00577 Minimum, /**< A (local) minimum has been detected */ 00578 Maximum, /**< A (local) maximum has been detected */ 00579 }; 00580 00581 /** 00582 * Seaches for an extremum with sub-pixel accuracy in a 3x3 region 00583 * around the given access point. 00584 * 00585 * A 2D quadratic function will be used to compute the sub-pixel values. 00586 * 00587 * Note that it only makes sense to call this method if the 00588 * (col,row) point of the given level is already a extremum or a 00589 * minimum in the discrete coordinates system, i.e. if the point 00590 * is greater (smaller) than its eight neighbors. Otherwise this method 00591 * will just return "NoExtremum". 00592 * 00593 * @param row row in coordinates of the given level, i.e. this value must 00594 * be between 0 and at(level).rows() 00595 * @param col column in coordinates of the given level, i.e. this value 00596 * must be between 0 and at(level).columns() 00597 * @param level level at which the extremum must be looked for. 00598 * @param spRow in case a extremum is found in the 3x3 region, this is the 00599 * row of the found extremum using the coordinates of the 00600 * corresponding level. 00601 * @param spCol in case a extremum is found in the 3x3 region, this is the 00602 * column of the found extremum using the coordinates of the 00603 * corresponding level. 00604 * 00605 * @return the type of extremum detected. In case a 00606 * maximum/minimum was found, the spRow and spCol will contain the 00607 * position with sub-pixel precision of the found extremum. 00608 */ 00609 eExtremaType interpolateExtremum(const int row, 00610 const int col, 00611 const int level, 00612 float& spRow, 00613 float& spCol) const; 00614 00615 00616 /** 00617 * Seaches for an extremum with sub-pixel accuracy in a 3x3x3 region 00618 * around the given access point. 00619 * 00620 * A 3D quadratic function will be used to compute the sub-pixel values. 00621 * 00622 * This function will only work if the parameters::factor is in ]0.5,1.0[. 00623 * 00624 * Note that in makes only sense to call this method if the (col,row) 00625 * point of the given level is already a extremum in the discrete 00626 * coordinates system, i.e. if the point is greater than its 26 00627 * neighbors. Otherwise this method will just return "NoExtremum". 00628 * 00629 * @param row row in coordinates of the given level, i.e. this value must 00630 * be between 0 and at(level).rows() 00631 * @param col column in coordinates of the given level, i.e. this value 00632 * must be between 0 and at(level).columns() 00633 * @param level level at which the extremum must be looked for. 00634 * @param spRow in case an extremum is found in the 3x3x3 region, this is 00635 * the row of the found extremum using the coordinates of 00636 * the corresponding level. 00637 * @param spCol in case an extremum is found in the 3x3x3 region, this is 00638 * the column of the found extremum using the coordinates of 00639 * the corresponding level. 00640 * @param scale in case an extremum is found in the 3x3x3 region, this is 00641 * the scale of the found extremum. 00642 * 00643 * @return the type of extremum detected. In case a 00644 * maximum/minimum was found, the spRow, spCol and scale will 00645 * contain the position with sub-pixel precision of the found 00646 * extremum. 00647 */ 00648 eExtremaType interpolateExtremum(const int row, 00649 const int col, 00650 const int level, 00651 float& spRow, 00652 float& spCol, 00653 float& scale) const; 00654 00655 00656 /** 00657 * Seaches the maximum with sub-pixel accuracy in a 3x3 region around the 00658 * access point. 00659 * 00660 * A 2D quadratic function will be used to compute the sub-pixel values. 00661 * 00662 * Note that in makes only sense to call this method if the (col,row) 00663 * point of the given level is already a maximum in the discrete 00664 * coordinates system, i.e. if the point is greater than its eight 00665 * neighbors. Otherwise this method will just return false 00666 * 00667 * @param row row in coordinates of the given level, i.e. this value must 00668 * be between 0 and at(level).rows() 00669 * @param col column in coordinates of the given level, i.e. this value 00670 * must be between 0 and at(level).columns() 00671 * @param level level at which the maximum must be looked for. 00672 * @param spRow in case a maximum is found in the 3x3 region, this is the 00673 * row of the found maximum using the coordinates of the 00674 * corresponding level. 00675 * @param spCol in case a maximum is found in the 3x3 region, this is the 00676 * column of the found maximum using the coordinates of the 00677 * corresponding level. 00678 * 00679 * @return true if a maximum was found within the 3x3 region. In this case 00680 * the spRow and spCol will contain the position with sub-pixel 00681 * precision of the found maximum. In case there is a maximum, 00682 * but not in the 3x3 region, or only a minimum or saddle point 00683 * is found, then false will be returned. 00684 */ 00685 bool interpolateMaximum(const int row, 00686 const int col, 00687 const int level, 00688 float& spRow, 00689 float& spCol) const; 00690 00691 /** 00692 * Seaches the maximum with sub-pixel accuracy in a 3x3x3 region around the 00693 * access point. 00694 * 00695 * A 3D quadratic function will be used to compute the sub-pixel values. 00696 * 00697 * This function will only work if the parameters::factor is in ]0.5,1.0[. 00698 * 00699 * Note that in makes only sense to call this method if the (col,row) 00700 * point of the given level is already a maximum in the discrete 00701 * coordinates system, i.e. if the point is greater than its 26 00702 * neighbors. Otherwise this method will just return false 00703 * 00704 * @param row row in coordinates of the given level, i.e. this value must 00705 * be between 0 and at(level).rows() 00706 * @param col column in coordinates of the given level, i.e. this value 00707 * must be between 0 and at(level).columns() 00708 * @param level level at which the maximum must be looked for. 00709 * @param spRow in case a maximum is found in the 3x3x3 region, this is 00710 * the row of the found extremum using the coordinates of 00711 * the corresponding level. 00712 * @param spCol in case an maximum is found in the 3x3x3 region, this is 00713 * the column of the found extremum using the coordinates of 00714 * the corresponding level. 00715 * @param scale in case an maximum is found in the 3x3x3 region, this is 00716 * the scale of the found extremum. 00717 * 00718 * @return true if a maximum was found within the 3x3 region. In this case 00719 * the spRow and spCol will contain the position with sub-pixel 00720 * precision of the found maximum. In case there is a maximum, 00721 * but not in the 3x3 region, or only a minimum or saddle point 00722 * is found, then false will be returned. 00723 */ 00724 bool interpolateMaximum(const int row, 00725 const int col, 00726 const int level, 00727 float& spRow, 00728 float& spCol, 00729 float& scale) const; 00730 00731 /** 00732 * Check if the given pixel at the given level (in the respective 00733 * coordinate system) is a maximum in the 3x3 neighborhood. 00734 * 00735 * @param row row of the point to be checked. It must be between 0 and 00736 * at(level).lastRow(), but for the borders false will be 00737 * always returned, as a "constant boundary" will be always 00738 * assumed. 00739 * @param col column of the point to be checked. It must be between 0 and 00740 * at(level).lastColumn(), but for the borders false will be 00741 * always returned, as a "constant boundary" will be always 00742 * assumed. 00743 * @param level the level where the maximum has to be checked. 00744 */ 00745 bool checkMaximum(const int row, 00746 const int col, 00747 const int level) const; 00748 00749 /** 00750 * Check if the given pixel at the given level (in the respective 00751 * coordinates) is a maximum in the 3x3x3 neighborhood 00752 * 00753 * @param row row of the point to be checked. It must be between 0 and 00754 * at(level).lastRow(), but for the borders false will be 00755 * always returned, as a "constant boundary" will be always 00756 * assumed. 00757 * @param col column of the point to be checked. It must be between 0 and 00758 * at(level).lastColumn(), but for the borders false will be 00759 * always returned, as a "constant boundary" will be always 00760 * assumed. 00761 * @param level the level where the maximum has to be checked. 00762 */ 00763 bool checkInterlevelMaximum(const int row, 00764 const int col, 00765 const int level) const; 00766 00767 /** 00768 * Map the coordinates of the given level into coordinates of level 0 00769 */ 00770 inline void mapToLevel0(const int level, 00771 const float row, 00772 const float col, 00773 float& row0, 00774 float& col0) const; 00775 00776 /** 00777 * Map the coordinates of level 0 into the coordinates of the given level 00778 */ 00779 inline void mapToLevel(const int level, 00780 const float& row0, 00781 const float& col0, 00782 float& row, 00783 float& col) const; 00784 00785 /** 00786 * Map the coordinates from level "from" to level "to" 00787 */ 00788 inline void mapToLevel(const int fromLevel, 00789 const int toLevel, 00790 const float& rowFrom, 00791 const float& colFrom, 00792 float& rowTo, 00793 float& colTo) const; 00794 00795 protected: 00796 /** 00797 * Functor used for nearest neighbor interpolation 00798 */ 00799 nearestNeighborInterpolator<value_type> nnIpl; 00800 00801 /** 00802 * Functor used to bilinear interpolate 00803 */ 00804 bilinearInterpolator<value_type> bilinIpl; 00805 00806 /** 00807 * Functor used to biquadratic interpolate 00808 */ 00809 biquadraticInterpolator<value_type> biquadIpl; 00810 00811 /** 00812 * Access with constant boundary 00813 */ 00814 inline value_type cstAt(const T& img,const int y,const int x) const; 00815 00816 /** 00817 * This "transparent" accumulator returns the first input value, while 00818 * it accumulates in the second variable 00819 */ 00820 inline const value_type& tacc(const value_type& in, 00821 value_type& out) const; 00822 00823 protected: 00824 /** 00825 * The parameters in use 00826 */ 00827 parameters param; 00828 00829 /** 00830 * Vector containing the real scaling factors used for each level in 00831 * the pyramid. 00832 */ 00833 dvector levelFactor; 00834 00835 /** 00836 * Initialize the values for the levelFactor. 00837 * It assumes that the vector has the proper size. 00838 */ 00839 void initLevelFactor(); 00840 00841 }; 00842 00843 00844 } 00845 00846 #include "ltiScaleSpacePyramid_template.h" 00847 #endif