CVR-Lib last update 20 Sep 2009

cvrIntegralImage.h

Go to the documentation of this file.
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 

Generated on Sun Sep 20 22:07:59 2009 for CVR-Lib by Doxygen 1.5.8