last update 20 Sep 2009 |
00001 /* 00002 * Copyright (C) 2007 by Pablo Alvarado 00003 * 00004 * This file is part of the Computer Vision and Robotics Library (CVR-Lib) 00005 * 00006 * The CVR-Lib is free software; you can redistribute it and/or 00007 * modify it under the terms of the BSD License. 00008 * 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without 00012 * modification, are permitted provided that the following conditions are met: 00013 * 00014 * 1. Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 00017 * 2. Redistributions in binary form must reproduce the above copyright notice, 00018 * this list of conditions and the following disclaimer in the documentation 00019 * and/or other materials provided with the distribution. 00020 * 00021 * 3. Neither the name of the authors nor the names of its contributors may be 00022 * used to endorse or promote products derived from this software without 00023 * specific prior written permission. 00024 * 00025 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00026 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00028 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00029 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00030 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00031 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00032 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00033 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00034 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00035 * POSSIBILITY OF SUCH DAMAGE. 00036 */ 00037 00038 /** 00039 * \file cvrIntegralImage.h 00040 * Contains the class cvr::integralImage, 00041 * which is used as a preliminary stage of several other algorithms 00042 * that need to convolve with boxes filled with a constant value. 00043 * \author Pablo Alvarado 00044 * \date 16.10.2007 00045 * 00046 * revisions ..: $Id: cvrIntegralImage.h,v 1.10 2008/01/16 21:52:26 alvarado Exp $ 00047 */ 00048 00049 #ifndef _CVR_INTEGRAL_IMAGE_H_ 00050 #define _CVR_INTEGRAL_IMAGE_H_ 00051 00052 #include "cvrMatrix.h" 00053 #include "cvrFunctor.h" 00054 #include "cvrBoundaryType.h" 00055 00056 namespace cvr { 00057 00058 /** 00059 * Class integralImage 00060 * 00061 * The integral image, (which in the CVR-Lib should it be better called the 00062 * integral channel, but for consistency with the literature we leave it as 00063 * is) is the image \f$I_\Sigma(x,y)\f$ obtained from the channel 00064 * \f$I(x,y)\f$ with the following convention: 00065 * \f[ 00066 * I_\Sigma(x,y) = \sum_{i=0}^{x}\sum_{j=0}^{y} I(i,j) 00067 * \f] 00068 * 00069 * From this integral image, the computation of any sum of intensities over 00070 * any upright, rectangular area can be done with only four additions, 00071 * independent of the area size. 00072 * 00073 * The computation of the integral image is very efficient. It needs just 00074 * one pass of the orignal image to be obtained, with just two additions per 00075 * pixel. 00076 * 00077 * The class provides a collection of useful methods to compute the sum of 00078 * elements in a rectangular window, for which the parameter boundaryType 00079 * makes a lot of sense. 00080 * 00081 * @see integralImage::parameters. 00082 * 00083 * @ingroup gLinearFilters 00084 */ 00085 class integralImage : public functor { 00086 public: 00087 /** 00088 * The parameters for the class integralImage 00089 */ 00090 class parameters : public functor::parameters { 00091 public: 00092 /** 00093 * Default constructor 00094 */ 00095 parameters(); 00096 00097 /** 00098 * Copy constructor 00099 * @param other the parameters object to be copied 00100 */ 00101 parameters(const parameters& other); 00102 00103 /** 00104 * Destructor 00105 */ 00106 ~parameters(); 00107 00108 /** 00109 * Copy the contents of a parameters object 00110 * @param other the parameters object to be copied 00111 * @return a reference to this parameters object 00112 */ 00113 parameters& copy(const parameters& other); 00114 00115 /** 00116 * Copy the contents of a parameters object 00117 * @param other the parameters object to be copied 00118 * @return a reference to this parameters object 00119 */ 00120 parameters& operator=(const parameters& other); 00121 00122 /** 00123 * Returns the complete name of the parameters class. 00124 */ 00125 virtual const std::string& name() const; 00126 00127 /** 00128 * Returns a pointer to a clone of the parameters. 00129 */ 00130 virtual parameters* clone() const; 00131 00132 /** 00133 * Returns a pointer to a new instance of the parameters. 00134 */ 00135 virtual parameters* newInstance() const; 00136 00137 /** 00138 * Write the parameters in the given ioHandler 00139 * @param handler the ioHandler to be used 00140 * @param complete if true (the default) the enclosing begin/end will 00141 * be also written, otherwise only the data block will be written. 00142 * @return true if write was successful 00143 */ 00144 virtual bool write(ioHandler& handler,const bool complete=true) const; 00145 00146 /** 00147 * Read the parameters from the given ioHandler 00148 * @param handler the ioHandler to be used 00149 * @param complete if true (the default) the enclosing begin/end will 00150 * be also written, otherwise only the data block will be written. 00151 * @return true if write was successful 00152 */ 00153 virtual bool read(ioHandler& handler,const bool complete=true); 00154 00155 // ------------------------------------------------ 00156 // the parameters 00157 // ------------------------------------------------ 00158 00159 /** 00160 * Boundary type. 00161 * 00162 * Default value: Zero 00163 */ 00164 eBoundaryType boundaryType; 00165 00166 }; 00167 00168 /** 00169 * Default constructor 00170 */ 00171 integralImage(); 00172 00173 /** 00174 * Construct with the given boundary type 00175 */ 00176 integralImage(const eBoundaryType boundaryType); 00177 00178 /** 00179 * Construct a functor using the given parameters 00180 */ 00181 integralImage(const parameters& par); 00182 00183 /** 00184 * Copy constructor 00185 * @param other the object to be copied 00186 */ 00187 integralImage(const integralImage& other); 00188 00189 /** 00190 * Destructor 00191 */ 00192 virtual ~integralImage(); 00193 00194 /** 00195 * Compute the integral image of a ubyte matrix. 00196 * 00197 * @param src matrix<ubyte> with the source data. 00198 * @param dest matrix<ubyte> where the result will be left. 00199 * @return true if apply successful or false otherwise. 00200 */ 00201 bool apply(const matrix<ubyte>& src, matrix<int32>& dest) const; 00202 00203 /** 00204 * Compute the integral image of an fmatrix. 00205 * 00206 * @param src fmatrix with the source data. 00207 * @param dest fmatrix where the result will be left. 00208 * @return true if apply successful or false otherwise. 00209 */ 00210 bool apply(const fmatrix& src, fmatrix& dest) const; 00211 00212 /** 00213 * @name Convenience window sums with boundary considerations. 00214 * 00215 * This methods used the computed integral image to produce the sum of 00216 * elements of the originary channel falling inside a given window. 00217 * 00218 * These methods are relatively slow, since they check if a part of the 00219 * window falls outside the image and take the necessary measures depending 00220 * on the boundary type selected. The methods are designed to produce 00221 * valid results if and only if at least a part of the window falls over 00222 * the image. 00223 * 00224 * If in your application you know for sure that the window falls 00225 * completely inside the image, and at least with one pixel free on the top 00226 * and left boundaries, then you may want to use the unchecked 00227 * internalSum() methods. 00228 * 00229 * The NoBoundary type will return 0 if any part of the given window falls 00230 * outside the image. 00231 * 00232 * You have to ensure that the \c from arguments correspond to the top-left 00233 * corner or the window, and that the \c to arguments correspond to the 00234 * bottom-right one. 00235 * 00236 * \warning Invalid results are provided if the complete window falls 00237 * outside the image. You must ensure that the image is not empty 00238 * when you call these methods. 00239 */ 00240 //@{ 00241 /** 00242 * Convenience method to use the computed integral image to produce the 00243 * sum of the results in the provided rectangle. 00244 * 00245 * @param intImage an integral image computed with apply() 00246 * @param rect the delimiter of a window whose pixels have to be sumed. 00247 */ 00248 inline int32 sum(const matrix<int32>& intImage, 00249 const irectangle& rect) const; 00250 00251 /** 00252 * Convenience method to use the computed integral image to produce the 00253 * sum of the results in the provided rectangle. 00254 * 00255 * @param intImage an integral image computed with apply() 00256 * @param from initial point of area to be summed. 00257 * @param to final point of area to be summed. 00258 * 00259 * @return the computed sum 00260 */ 00261 inline int32 sum(const matrix<int32>& intImage, 00262 const ipoint& from, 00263 const ipoint& to) const; 00264 00265 /** 00266 * Convenience method to use the computed integral image to produce the 00267 * sum of the results in the provided rectangle. 00268 * 00269 * @param intImage an integral image computed with apply() 00270 * @param fromX initial x coordinate of area to be summed. 00271 * @param fromY initial y coordinate of area to be summed. 00272 * @param toX final x coordinate of area to be summed. 00273 * @param toY final y coordinate of area to be summed. 00274 * 00275 * @return the computed sum 00276 */ 00277 inline int32 sum(const matrix<int32>& intImage, 00278 const int fromX, const int fromY, 00279 const int toX, const int toY) const; 00280 00281 /** 00282 * Convenience method to use the computed integral image to produce the 00283 * sum of the results in the provided rectangle. 00284 * 00285 * @param intImage an integral image computed with apply() 00286 * @param rect the delimiter of a window whose pixels have to be sumed. 00287 * 00288 * @return the computed sum 00289 */ 00290 inline float sum(const fmatrix& intImage, 00291 const irectangle& rect) const; 00292 00293 /** 00294 * Convenience method to use the computed integral image to produce the 00295 * sum of the results in the provided rectangle. 00296 * 00297 * @param intImage an integral image computed with apply() 00298 * @param from initial point of area to be summed. 00299 * @param to final point of area to be summed. 00300 * 00301 * @return the computed sum 00302 */ 00303 inline float sum(const fmatrix& intImage, 00304 const ipoint& from, 00305 const ipoint& to) const; 00306 00307 /** 00308 * Convenience method to use the computed integral image to produce the 00309 * sum of the results in the provided rectangle. 00310 * 00311 * @param intImage an integral image computed with apply() 00312 * @param fromX initial x coordinate of area to be summed. 00313 * @param fromY initial y coordinate of area to be summed. 00314 * @param toX final x coordinate of area to be summed. 00315 * @param toY final y coordinate of area to be summed. 00316 * 00317 * @return the computed sum 00318 */ 00319 inline float sum(const matrix<float>& intImage, 00320 const int fromX, const int fromY, 00321 const int toX, const int toY) const; 00322 //@} 00323 00324 /** 00325 * @name Convenience window sums without boundary considerations. 00326 * 00327 * These methods use the computed integral image to produce the sum of 00328 * elements of the originary channel falling inside a given window. 00329 * 00330 * They are relatively fast, since they assume that the complete window 00331 * falls into the image and at least one pixel border has been left on the 00332 * top and on the left. If this is not the case, you have to use the sum() 00333 * methods instead. 00334 * 00335 * \warning If this condition is not met, the debug version will report an 00336 * assert when accessing the matrix at invalid indices, and the release 00337 * version probably will crash due to a segmentation fault. 00338 * 00339 * This method is used when you know for sure that the window falls 00340 * completely inside the image, and leaves at least one pixel free on the 00341 * top and left boundaries. 00342 */ 00343 00344 //@{ 00345 /** 00346 * Convenience method to use the computed integral image to produce the 00347 * sum of the results in the provided rectangle. 00348 * 00349 * @param intImage an integral image computed with apply() 00350 * @param rect the delimiter of a window whose pixels have to be sumed. 00351 */ 00352 inline int32 internalSum(const matrix<int32>& intImage, 00353 const irectangle& rect) const; 00354 00355 /** 00356 * Convenience method to use the computed integral image to produce the 00357 * sum of the results in the provided rectangle. 00358 * 00359 * @param intImage an integral image computed with apply() 00360 * @param from initial point of area to be summed. 00361 * @param to final point of area to be summed. 00362 * 00363 * @return the computed sum 00364 */ 00365 inline int32 internalSum(const matrix<int32>& intImage, 00366 const ipoint& from, 00367 const ipoint& to) const; 00368 00369 /** 00370 * Convenience method to use the computed integral image to produce the 00371 * sum of the results in the provided rectangle. 00372 * 00373 * @param intImage an integral image computed with apply() 00374 * @param fromX initial x coordinate of area to be summed. 00375 * @param fromY initial y coordinate of area to be summed. 00376 * @param toX final x coordinate of area to be summed. 00377 * @param toY final y coordinate of area to be summed. 00378 * 00379 * @return the computed sum 00380 */ 00381 inline int32 internalSum(const matrix<int32>& intImage, 00382 const int fromX, const int fromY, 00383 const int toX, const int toY) const; 00384 00385 /** 00386 * Convenience method to use the computed integral image to produce the 00387 * sum of the results in the provided rectangle. 00388 * 00389 * @param intImage an integral image computed with apply() 00390 * @param rect the delimiter of a window whose pixels have to be sumed. 00391 * 00392 * @return the computed sum 00393 */ 00394 inline float internalSum(const fmatrix& intImage, 00395 const irectangle& rect) const; 00396 00397 /** 00398 * Convenience method to use the computed integral image to produce the 00399 * sum of the results in the provided rectangle. 00400 * 00401 * @param intImage an integral image computed with apply() 00402 * @param from initial point of area to be summed. 00403 * @param to final point of area to be summed. 00404 * 00405 * @return the computed sum 00406 */ 00407 inline float internalSum(const fmatrix& intImage, 00408 const ipoint& from, 00409 const ipoint& to) const; 00410 00411 /** 00412 * Convenience method to use the computed integral image to produce the 00413 * sum of the results in the provided rectangle. 00414 * 00415 * @param intImage an integral image computed with apply() 00416 * @param fromX initial x coordinate of area to be summed. 00417 * @param fromY initial y coordinate of area to be summed. 00418 * @param toX final x coordinate of area to be summed. 00419 * @param toY final y coordinate of area to be summed. 00420 * 00421 * @return the computed sum 00422 */ 00423 inline float internalSum(const matrix<float>& intImage, 00424 const int fromX, const int fromY, 00425 const int toX, const int toY) const; 00426 00427 //@} 00428 00429 /** 00430 * Copy data of "other" functor. 00431 * @param other the functor to be copied 00432 * @return a reference to this functor object 00433 */ 00434 integralImage& copy(const integralImage& other); 00435 00436 /** 00437 * Alias for copy member 00438 * @param other the functor to be copied 00439 * @return a reference to this functor object 00440 */ 00441 integralImage& operator=(const integralImage& other); 00442 00443 /** 00444 * Returns the complete name of the functor class 00445 */ 00446 virtual const std::string& name() const; 00447 00448 /** 00449 * Returns a pointer to a clone of this functor. 00450 */ 00451 virtual integralImage* clone() const; 00452 00453 /** 00454 * Returns a pointer to a new instance of this functor. 00455 */ 00456 virtual integralImage* newInstance() const; 00457 00458 /** 00459 * Returns used parameters 00460 */ 00461 const parameters& getParameters() const; 00462 00463 /** 00464 * Update parameters 00465 */ 00466 bool updateParameters(); 00467 00468 private: 00469 /** 00470 * General implementation of the integration 00471 */ 00472 template<typename T,typename U> 00473 bool integrate(const matrix<T>& src,matrix<U>& dest) const; 00474 00475 # ifndef NDEBUG 00476 00477 // Implementation in debug mode is accelerated by avoiding a switch 00478 // which costs too much without optimizations 00479 00480 /** 00481 * Internal base class for all boundary-bounded sum methods 00482 * This is faster than a switch of boundary types 00483 */ 00484 template<typename T> 00485 class dispatcher { 00486 public: 00487 /** 00488 * Constructor 00489 */ 00490 dispatcher(); 00491 /** 00492 * Desttructor 00493 */ 00494 virtual ~dispatcher(); 00495 00496 /** 00497 * The virtual method for everybody 00498 * 00499 * The default implementation returns the zero boundary case 00500 */ 00501 virtual T sumBox(const matrix<T>& intImage, 00502 const int fromX,const int fromY, 00503 const int toX,const int toY) const; 00504 00505 protected: 00506 /** 00507 * Convenience method to use the computed integral image to produce the 00508 * sum of the results in the provided rectangle. 00509 * 00510 * @param intImage an integral image computed with apply() 00511 * @param from initial point of area to be summed. 00512 * @param to final point of area to be summed. 00513 */ 00514 inline T internalSum(const matrix<T>& intImage, 00515 const int fromX,const int fromY, 00516 const int toX,const int toY) const; 00517 00518 }; 00519 00520 /** 00521 * Internal class no-boundary 00522 */ 00523 template<typename T> 00524 class sumNoBoundary : public dispatcher<T> { 00525 public: 00526 /** 00527 * Constructor 00528 */ 00529 sumNoBoundary(); 00530 00531 00532 /** 00533 * The virtual method for everybody 00534 */ 00535 virtual T sumBox(const matrix<T>& intImage, 00536 const int fromX,const int fromY, 00537 const int toX,const int toY) const; 00538 }; 00539 00540 /** 00541 * Internal class for zero 00542 */ 00543 template<typename T> 00544 class sumZero : public dispatcher<T> { 00545 public: 00546 /** 00547 * Constructor 00548 */ 00549 sumZero(); 00550 }; 00551 00552 /** 00553 * Internal class for constant 00554 */ 00555 template<typename T> 00556 class sumConstant : public dispatcher<T> { 00557 public: 00558 /** 00559 * Constructor 00560 */ 00561 sumConstant(); 00562 00563 00564 /** 00565 * The virtual method for everybody 00566 */ 00567 virtual T sumBox(const matrix<T>& intImage, 00568 const int fromX,const int fromY, 00569 const int toX,const int toY) const; 00570 }; 00571 00572 /** 00573 * Internal class for periodic 00574 */ 00575 template<typename T> 00576 class sumPeriodic : public dispatcher<T> { 00577 public: 00578 /** 00579 * Constructor 00580 */ 00581 sumPeriodic(); 00582 00583 /** 00584 * The virtual method for everybody 00585 */ 00586 virtual T sumBox(const matrix<T>& intImage, 00587 const int fromX,const int fromY, 00588 const int toX,const int toY) const; 00589 }; 00590 00591 /** 00592 * Internal class for mirror 00593 */ 00594 template<typename T> 00595 class sumMirror : public dispatcher<T> { 00596 public: 00597 /** 00598 * Constructor 00599 */ 00600 sumMirror(); 00601 00602 00603 /** 00604 * The virtual method for everybody 00605 */ 00606 virtual T sumBox(const matrix<T>& intImage, 00607 const int fromX,const int fromY, 00608 const int toX,const int toY) const; 00609 }; 00610 00611 /** 00612 * Dispatcher for sum methods 00613 */ 00614 dispatcher<float>* sumFloat_; 00615 00616 /** 00617 * Dispatcher for sum methods 00618 */ 00619 dispatcher<int32>* sumInt_; 00620 00621 # else 00622 00623 00624 // Implementation in release mode is based on a switch, which is 00625 // efficiently optimized by the compiler 00626 00627 /** 00628 * The sum dispatcher 00629 */ 00630 00631 template<typename T> 00632 inline T sumDispatcher(const matrix<T>& intImage, 00633 const int fromX,const int fromY, 00634 const int toX,const int toY) const; 00635 00636 /** 00637 * SumBox considers the zero boundary, and is used by the other 00638 * methods, to be compatible with the debug dispatcher method we keep 00639 * just this name 00640 */ 00641 template<typename T> 00642 T sumBox(const matrix<T>& intImage, 00643 const int fromX,const int fromY, 00644 const int toX,const int toY) const; 00645 00646 template<typename T> 00647 T sumNoBoundary(const matrix<T>& intImage, 00648 const int fromX,const int fromY, 00649 const int toX,const int toY) const; 00650 00651 template<typename T> 00652 T sumConstant(const matrix<T>& intImage, 00653 const int fromX,const int fromY, 00654 const int toX,const int toY) const; 00655 00656 template<typename T> 00657 T sumPeriodic(const matrix<T>& intImage, 00658 const int fromX,const int fromY, 00659 const int toX,const int toY) const; 00660 00661 template<typename T> 00662 T sumMirror(const matrix<T>& intImage, 00663 const int fromX,const int fromY, 00664 const int toX,const int toY) const; 00665 00666 #endif 00667 00668 /** 00669 * Shadow of the parameters to save some critical time in the 00670 * sum methods 00671 */ 00672 eBoundaryType boundaryType_; 00673 00674 }; 00675 } 00676 00677 #include "cvrIntegralImage_inline.h" 00678 00679 #endif 00680