LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiSquareConvolution.h

00001 /*
00002  * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 
00024 /*----------------------------------------------------------------
00025  * project ....: LTI Digital Image/Signal Processing Library
00026  * file .......: ltiSquareConvolution.h
00027  * authors ....: Pablo Alvarado
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 13.10.2000
00030  * revisions ..: $Id: ltiSquareConvolution.h,v 1.8 2006/02/08 11:55:56 ltilib Exp $
00031  */
00032 
00033 #ifndef _LTI_SQUARE_CONVOLUTION_H_
00034 #define _LTI_SQUARE_CONVOLUTION_H_
00035 
00036 #include "ltiObject.h"
00037 #include "ltiMatrix.h"
00038 #include "ltiFilter.h"
00039 
00040 namespace lti {
00041   /**
00042    * This is an efficient implementation of the convolution with a
00043    * square or rectangular kernel.  The template parameter T defines
00044    * the type of the matrix or vector to be filtered, and A represents
00045    * the accumulator class, which allows different modi for the
00046    * convolution.
00047    *
00048    * The class A must implement following members:
00049    *  - constructor(int)          for initialization with the value 0.
00050    *  - operator+=(T x)           for accumulation,
00051    *  - operator-=(T x)           for "deaccumulation",
00052    *  - operator=(T x)            for assignation of a value of type T
00053    *  - operator/(T x,T y) const  returns f(x)/y instead of x/y.
00054    *                              For example for L2 norm f(x) = sqrt(x).
00055    *  - operator T() const        returns the contents casted to type T
00056    *
00057    * This way, you can use any simple-types (as int, char, double...)
00058    * as accumulator for a linear filter, or a user-defined class for a
00059    * region normalization with any norm!  For an example of an accumulator
00060    * class see lti::chrominanzHistogram::l2accumulator<T>.
00061    *
00062    * Note that for convolving a rectangular filter kernel with a channel8,
00063    * you shoud use an instance squareConvolution<ubyte,int>.  If you forget
00064    * the "int" parameter, some quite noisy overflowing effects should be
00065    * expected!
00066    *
00067    * @see parameters
00068    */
00069   template<class T,class A=T>
00070     class squareConvolution : public filter {
00071       public:
00072 
00073       /**
00074        * the parameters for the class squareConvolution
00075        */
00076       class parameters : public filter::parameters {
00077         public:
00078         /**
00079          * default constructor to initialize a kernel of k x k size centered
00080          * at (0,0)
00081          */
00082         parameters(const int k = 3) : filter::parameters() {
00083           initSquare(k);
00084         }
00085 
00086         /**
00087          * copy constructor
00088          * @param other the parameters object to be copied
00089          */
00090         parameters(const parameters& other) 
00091           : filter::parameters() {
00092           copy(other);
00093         };
00094 
00095         /**
00096          * destructor
00097          */
00098         ~parameters() {};
00099 
00100         /**
00101          * returns name of this type
00102          */
00103         const char* getTypeName() const {
00104           return "squareConvolution::parameters";
00105         };
00106 
00107         /**
00108          * copy the contents of a parameters object
00109          * @param other the parameters object to be copied
00110          * @return a reference to this parameters object
00111          */
00112         parameters& copy(const parameters& other)  {
00113 #       ifndef _LTI_MSC_6
00114           // MS Visual C++ 6 is not able to compile this...
00115           filter::parameters::copy(other);
00116 #       else
00117           // ...so we have to use this workaround.
00118           // Conditional on that, copy may not be virtual.
00119           filter::parameters& (filter::parameters::* p_copy)
00120             (const filter::parameters&) =
00121             filter::parameters::copy;
00122           (this->*p_copy)(other);
00123 #       endif
00124 
00125           kernelSize = other.kernelSize;
00126           kernelNorm = other.kernelNorm;
00127 
00128           return *this;
00129         };
00130 
00131         /**
00132          * returns a pointer to a clone of the parameters
00133          */
00134         virtual functor::parameters* clone() const  {
00135           return new parameters(*this);
00136         };
00137 
00138         /**
00139          * write the parameters in the given ioHandler
00140          * @param handler the ioHandler to be used
00141          * @param complete if true (the default) the enclosing begin/end will
00142          *        be also written, otherwise only the data block will be
00143          *        written.
00144          * @return true if write was successful
00145          */
00146 #     ifndef _LTI_MSC_6
00147         virtual bool write(ioHandler& handler,const bool complete=true) const
00148 #     else
00149         bool writeMS(ioHandler& handler,const bool complete=true) const
00150 #     endif
00151         {
00152           bool b = true;
00153           if (complete) {
00154             b = handler.writeBegin();
00155           }
00156 
00157           if (b) {
00158             lti::write(handler,"kernelSize",kernelSize);
00159             lti::write(handler,"kernelNorm",kernelNorm);
00160           }
00161 
00162 #       ifndef _LTI_MSC_6
00163           // This is the standard C++ code, which MS Visual C++ 6 is not
00164           // able to compile...
00165           b = b && filter::parameters::write(handler,false);
00166 #       else
00167           bool (modifier::parameters::* p_writeMS)(ioHandler&,
00168                                                    const bool) const =
00169             modifier::parameters::writeMS;
00170           b = b && (this->*p_writeMS)(handler,false);
00171 #       endif
00172 
00173           if (complete) {
00174             b = b && handler.writeEnd();
00175           }
00176 
00177           return b;
00178         }
00179 
00180 #     ifdef _LTI_MSC_6
00181         virtual bool write(ioHandler& handler,
00182                            const bool complete = true) const {
00183            // ...we need this workaround to cope with another really
00184            // awful MSVC bug.
00185            return writeMS(handler,complete);
00186         }
00187 #     endif
00188 
00189         /**
00190          * read the parameters from the given ioHandler
00191          * @param handler the ioHandler to be used
00192          * @param complete if true (the default) the enclosing begin/end will
00193          *        be also read, otherwise only the data block will be read.
00194          * @return true if write was successful
00195          */
00196 #     ifndef _LTI_MSC_6
00197         virtual bool read(ioHandler& handler,const bool complete = true)
00198 #     else
00199         bool readMS(ioHandler& handler,const bool complete=true)
00200 #     endif
00201         {
00202           bool b = true;
00203           if (complete) {
00204             b = handler.readBegin();
00205           }
00206 
00207           if (b) {
00208             lti::read(handler,"kernelSize",kernelSize);
00209             lti::read(handler,"kernelNorm",kernelNorm);
00210           }
00211 
00212 #     ifndef _LTI_MSC_6
00213           // This is the standard C++ code, which MS Visual C++ 6 is not
00214           // able to compile...
00215           b = b && filter::parameters::read(handler,false);
00216 #     else
00217           bool (modifier::parameters::* p_readMS)(ioHandler&,const bool) =
00218           modifier::parameters::readMS;
00219           b = b && (this->*p_readMS)(handler,false);
00220 #     endif
00221 
00222           if (complete) {
00223             b = b && handler.readEnd();
00224           }
00225 
00226           return b;
00227         }
00228 
00229 #     ifdef _LTI_MSC_6
00230         virtual bool read(ioHandler& handler,const bool complete=true) {
00231           // ...we need this workaround to cope with another really awful MSVC
00232           // bug.
00233           return readMS(handler,complete);
00234         }
00235 #      endif
00236 
00237         /**
00238          * The rectangular kernel will have the value "1/kernelNorm"
00239          * between the limits specified by this rectangle.  When
00240          * convolving a vector, the "y" coordinates of this kernelSize
00241          * will be ignored.
00242          * Default value: rectangle(-1,-1,1,1), i.e. a 3x3 kernel
00243          */
00244         rectangle kernelSize;
00245 
00246         /**
00247          * The norm is the value which will be considered as "1.0" for the
00248          * elements of the kernel.  The default value is 9 (for a 3x3 kernel).
00249          * You can consider the square filter always as a kernel with nxn
00250          * "ones".
00251          * After the convolution, the resulting image will be divide by this
00252          * value.  The implementation combines the convolution with this
00253          * normalization!
00254          */
00255         T kernelNorm;
00256 
00257         /**
00258          * Initialize the parameters for a symmetric square kernel sizeXsize,
00259          * where the sum of all elements equals one.
00260          * If the size is even, it will be "fixed" to the next odd number
00261          */
00262         void initSquare(const int size) {
00263           int realSize(size);
00264           if ((size % 2) == 0) {
00265             realSize++;
00266           }
00267 
00268           kernelNorm = static_cast<T>(realSize*realSize);
00269 
00270           realSize/=2;
00271           kernelSize.ul.x = -realSize;
00272           kernelSize.ul.y = -realSize;
00273           kernelSize.br.x = +realSize;
00274           kernelSize.br.y = +realSize;
00275         };
00276 
00277       };
00278 
00279       /**
00280        * default constructor
00281        */
00282       squareConvolution();
00283 
00284       /**
00285        * constructor to initialize the parameters with an square filter
00286        * of k x k size.
00287        */
00288       squareConvolution(const int k);
00289 
00290       /**
00291        * copy constructor
00292        * @param other the object to be copied
00293        */
00294       squareConvolution(const squareConvolution& other);
00295 
00296       /**
00297        * destructor
00298        */
00299       virtual ~squareConvolution();
00300 
00301       /**
00302        * returns the name of this type ("squareConvolution")
00303        */
00304       virtual const char* getTypeName() const;
00305 
00306       /**
00307        * operates on the given %parameter.
00308        * @param srcdest matrix<T> with the source data.  The result
00309        *                 will be left here too.
00310        * @return true if successful, false otherwise.
00311        */
00312       bool apply(matrix<T>& srcdest) const;
00313 
00314       /**
00315        * operates on the given %parameter.
00316        * @param srcdest vector<T> with the source data.  The result
00317        *                 will be left here too.
00318        * @return true if successful, false otherwise.
00319        */
00320       bool apply(vector<T>& srcdest) const;
00321 
00322       /**
00323        * operates on a copy of the given %parameters.
00324        * @param src matrix<T> with the source data.
00325        * @param dest matrix<T> where the result will be left.
00326        * @return true if successful, false otherwise.
00327        */
00328       bool apply(const matrix<T>& src,matrix<T>& dest) const;
00329 
00330       /**
00331        * operates on a copy of the given %parameters.
00332        * @param src vector<T> with the source data.
00333        * @param dest vector<T> where the result will be left.
00334        * @return true if successful, false otherwise.
00335        */
00336       bool apply(const vector<T>& src,vector<T>& dest) const;
00337 
00338       /**
00339        * copy data of "other" functor.
00340        * @param other the functor to be copied
00341        * @return a reference to this functor object
00342        */
00343       squareConvolution& copy(const squareConvolution& other);
00344 
00345       /**
00346        * returns a pointer to a clone of this functor.
00347        */
00348       virtual functor* clone() const;
00349 
00350       /**
00351        * returns used parameters
00352        */
00353       const parameters& getParameters() const;
00354 
00355       protected:
00356       /**
00357        * applies the vertical part of the kernel to the matrix
00358        * @param src matrix<T> with the source data.
00359        * @param dest matrix<T> where the result will be left.
00360        * @result a reference to the <code>dest</code>.
00361        */
00362       matrix<T>& applyCol(const matrix<T>& src,matrix<T>& dest) const;
00363 
00364       private:
00365       /**
00366        * calculate the real index in an vector of size srcSize for a
00367        * mirrored boundary
00368        */
00369       inline int getMirrorIndex(const int& x,
00370                                 const int& srcSize,
00371                                 bool& mirror) const;
00372 
00373     };
00374 
00375 
00376 
00377 }
00378 
00379 #include "ltiSquareConvolution_template.h"
00380 
00381 #endif

Generated on Sat Apr 10 15:26:15 2010 for LTI-Lib by Doxygen 1.6.1