CVR-Lib last update 20 Sep 2009

cvrSeparableKernel.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1998-2004
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  *
00006  * This file is part of the Computer Vision and Robotics Library (CVR-Lib)
00007  *
00008  * The CVR-Lib is free software; you can redistribute it and/or
00009  * modify it under the terms of the BSD License.
00010  *
00011  * All rights reserved.
00012  *
00013  * Redistribution and use in source and binary forms, with or without
00014  * modification, are permitted provided that the following conditions are met:
00015  *
00016  * 1. Redistributions of source code must retain the above copyright notice,
00017  *    this list of conditions and the following disclaimer.
00018  *
00019  * 2. Redistributions in binary form must reproduce the above copyright notice,
00020  *    this list of conditions and the following disclaimer in the documentation
00021  *    and/or other materials provided with the distribution.
00022  *
00023  * 3. Neither the name of the authors nor the names of its contributors may be
00024  *    used to endorse or promote products derived from this software without
00025  *    specific prior written permission.
00026  *
00027  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00028  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00029  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00030  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00031  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00032  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00033  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00034  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00035  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00036  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00037  * POSSIBILITY OF SUCH DAMAGE.
00038  */
00039 
00040 /** 
00041  * \file   cvrSeparableKernel.h
00042  *         Contains the template class seperableKernel<T>
00043  * \author Pablo Alvarado
00044  * \date   28.04.2000
00045  *
00046  * $Id: cvrSeparableKernel.h,v 1.7 2006/09/05 09:10:38 doerfler Exp $
00047  */
00048 
00049 #ifndef _CVR_SEPARABLE_KERNEL_H_
00050 #define _CVR_SEPARABLE_KERNEL_H_
00051 
00052 #include "cvrKernel1D.h"
00053 #include "cvrKernel2D.h"
00054 #include "cvrTypes.h"
00055 
00056 #include <vector>
00057 
00058 namespace cvr {
00059 
00060   /**
00061    * Separable Kernel.
00062    *
00063    * A separable kernel is a %vector of one dimensional kernels.
00064    * If a two dimensional kernel can be separated, the convolution can be
00065    * applied in a very efficient way.
00066    *
00067    * A filter kernel K is called separable "in one pair", if the matrix
00068    * representation of K can be produced as an outer product of two
00069    * one-dimensional kernels Kx and Ky.
00070    *
00071    * The template type of this class should coincide with the template class of
00072    * the matrix or channel to be convolved with.  For example, if you want to
00073     * convolve a separableKernel with a cvr::channel, you will need a
00074    * separableKernel<channel::value_type> or separableKernel<float>.
00075    *
00076    * If you instantiate a separableKernel of a fixed point type, like
00077    * separableKernel<int> or separableKernel<ubyte>, you also need to consider
00078    * the "norm" of the kernel (see cvr::separableKernel<T>::getNorm() and
00079    * cvr::separableKernel<T>::setNorm(const T&)). This "norm" allows the
00080    * representation of numbers less than 1.0.  You can see this norm as the
00081    * value to be consider as 1.0, when operating with the kernel.  For example,
00082    * if you have a separableKernel<ubyte> with the values [64,128,64] and
00083    * norm=255, the the interpreted values during convolution will be
00084    * [0.25,0.5,0.25].  With floating-point types, the norm will be always
00085    * assumed to be 1.0.  For other types the default norms are the following:
00086    * (see cvr::typeInfo)
00087    *
00088    * - For int:              65536
00089    * - For ubyte:              255
00090    * - Otherwise:              1.0
00091    *
00092    * @see convolution
00093    *
00094    */
00095   template<class T>
00096   class separableKernel : public container {
00097   protected:
00098     /**
00099      * A pair of 1D kernels
00100      */
00101     struct kernelPair {
00102       /**
00103        * Row kernel
00104        */
00105       kernel1D<T> row;
00106 
00107       /**
00108        * Column kernel
00109        */
00110       kernel1D<T> column;
00111     };
00112 
00113   public:
00114     /**
00115      * Default constructor
00116      */
00117     separableKernel();
00118 
00119     /**
00120      * Copy constructor
00121      * @param other the kernel to be copied.
00122      */
00123     separableKernel(const separableKernel& other);
00124 
00125     /**
00126      * Construct a separable kernel with one filter pair, all elements
00127      * of the subfilters initialized with the given value.
00128      * @param from first index of the one dimensional filter kernel
00129      * @param to   last index of the one dimensional filter kernel
00130      * @param iniValue initial value for the kernel elements
00131      */
00132     separableKernel(const int from,const int to,const T& iniValue=T());
00133 
00134     /**
00135      * Construct a symmetrical separable kernel
00136      *
00137      * The resulting separable kernel will have just one filter pair, where
00138      * the row and column filters are identical.
00139      *
00140      * @param subkernel the one-dimensional kernel to be used as row and
00141      *                  column filter.
00142      */
00143     separableKernel(const kernel1D<T>& subkernel);
00144 
00145     /**
00146      * Destructor
00147      */
00148     virtual ~separableKernel();
00149 
00150     /**
00151      * Copy member
00152      * @param other the kernel to be copied.
00153      * @return a reference to this instance
00154      */
00155     separableKernel& copy(const separableKernel& other);
00156 
00157     /**
00158      * Returns the name of this type 
00159      */
00160     virtual const std::string& name() const;
00161 
00162     /**
00163      * Clone member
00164      * @return a pointer to a copy of this instance
00165      */
00166     virtual separableKernel* clone() const;
00167 
00168     
00169     /**
00170      * Return a new instance of a separable kernel
00171      * @return a pointer to a new instance
00172      */
00173     virtual separableKernel* newInstance() const;
00174 
00175     /**
00176      * Copy from kernel of another type
00177      * @param other a separable kernel of another type
00178      * @return a reference to this instance
00179      */
00180     template<class U>
00181     separableKernel& castFrom(const separableKernel<U>& other) {
00182       // implementation needs to be here due to VC++ bug
00183       kernels_.resize(other.getNumberOfPairs());
00184       for (unsigned int i=0;i<kernels_.size();i++) {
00185   kernels_[i].row.castFrom(other.getRowFilter(i));
00186   kernels_[i].column.castFrom(other.getColumnFilter(i));
00187       }
00188       return (*this);
00189     }
00190 
00191     /**
00192      * Separate a 2D kernel into 1D kernels
00193      *
00194      * Try to separate the two dimensional kernel \a k.  Stop the
00195      * separation if the error between original and separated kernel is less
00196      * than \a maxDev.
00197      *
00198      * @param k the two dimensional filter to be separated
00199      * @param maxDev the maximal deviation per element to be achieved
00200      * @return true if the separation succeeded or false otherwise.
00201      */
00202     bool separate(const kernel2D<T>& k,const double &maxDev=0.01);
00203 
00204     /**
00205      * Number of filter pairs
00206      */
00207     int getNumberOfPairs() const;
00208 
00209     /**
00210      * Set the number of column/row 1D-filters
00211      */
00212     void setNumberOfPairs(const int numPairs);
00213 
00214     /**
00215      * Return a row-kernel
00216      * @param i the index of the row filter.  This value must be between
00217      *        0 and getNumberOfPairs()
00218      */
00219     inline kernel1D<T>& getRowFilter(const int i) {
00220       // check for limits
00221       assert(i<static_cast<int>(kernels_.size()));
00222       return kernels_[i].row;
00223     };
00224 
00225     /**
00226      * Return a column-kernel
00227      * @param i the index of the column filter.  This value must be between
00228      *        0 and getNumberOfPairs()
00229      */
00230     inline kernel1D<T>& getColumnFilter(const int i) {
00231       // check for limits
00232       assert(i<static_cast<int>(kernels_.size()));
00233       return kernels_[i].column;
00234     };
00235 
00236     /**
00237      * Return an unmodifiable row kernel
00238      * @param i the index of the row filter.  This value must be between
00239      *        0 and getNumberOfPairs()
00240      */
00241     inline const kernel1D<T>& getRowFilter(const int i) const {
00242       // check for limits
00243       assert(i<static_cast<int>(kernels_.size()));
00244       return kernels_[i].row;
00245     }
00246 
00247     /**
00248      * Return an unmodifiable column kernel
00249      * @param i the index of the column filter.  This value must be between
00250      *        0 and getNumberOfPairs()
00251      */
00252     inline const kernel1D<T>& getColumnFilter(const int i) const {
00253       // check for limits
00254       assert(i<static_cast<int>(kernels_.size()));
00255       return kernels_[i].column;
00256     };
00257 
00258     /**
00259      * Normalize divides all elements by norm and set the norm to 1!
00260      */
00261     void normalize();
00262 
00263     /**
00264      * Multiply each 1D kernel with a constant value
00265      * @param value the value to be multiplied with
00266      * @return a reference to this object
00267      */
00268     separableKernel<T>& multiply(const T& value);
00269 
00270     /**
00271      * Set the norm of each individual 1D kernel to the given value
00272      * @param newNorm the value to be used as norm
00273      * @return a reference to this object
00274      */
00275     void setNorm(const T& newNorm);
00276 
00277     /**
00278      * Returns the sum of the elements of the resulting 2D kernel
00279      */
00280     T computeSumOfElements() const;
00281 
00282     /**
00283      * Mirror the other kernel and leave the result here, i.e.
00284      * at(y,x) = other.at(-y,-x);
00285      * @param other the kernel to be copied and then mirrored
00286      * @return a reference to this instance
00287      */
00288     separableKernel<T>& mirror(const separableKernel<T>& other);
00289 
00290     /**
00291      * Mirror this kernel, i.e.
00292      * at(y,x) = at(-y,-x);
00293      * @return a reference to this instance
00294      */
00295     separableKernel<T>& mirror();
00296 
00297     /**
00298      * Write the object in the given ioHandler
00299      */
00300     virtual bool write(ioHandler& handler,const bool complete = true) const;
00301 
00302     /**
00303      * Read the object from the given ioHandler
00304      */
00305     virtual bool read(ioHandler& handler,const bool complete = true);
00306 
00307     /**
00308      * @name Apply Methods
00309      */
00310     //@{
00311 
00312     /**
00313      * Applies a C-function to each element of the kernel.
00314      * 
00315      * In the following example, kernel \a kernel is initialized with
00316      * 4.0. After applying \a sqrt(), all elements of \a kernel are 2.0.
00317      * \code
00318      * separableKernel<float> kern(-2,2,4.0);
00319      * kern.apply(sqrt);
00320      * \endcode
00321      * @param function a pointer to a C-function
00322      * @return a reference to the actual kernel
00323      */
00324     separableKernel<T>& apply(T (*function)(T));
00325 
00326     /**
00327      * Applies a C-function to each element of the kernel.
00328      * @param function a pointer to a C-function
00329      * @return a reference to the actual kernel
00330      */
00331     separableKernel<T>& apply(T (*function)(const T&));
00332 
00333     /**
00334      * Applies a C-function to each element of the other kernel and leaves
00335      * the result here.
00336      * @param other the source kernel
00337      * @param function a pointer to a C-function
00338      * @return a reference to the actual kernel
00339      */
00340     separableKernel<T>& apply(const separableKernel<T>& other,
00341             T (*function)(T));
00342 
00343 
00344     /**
00345      * Applies a C-function to each element the other kernel and
00346      * leaves the result here.
00347      *
00348      * @param other the kernel with the source data
00349      * @param function a pointer to a C-function
00350      * @return a reference to the actual kernel
00351      */
00352     separableKernel<T>& apply(const separableKernel<T>& other,
00353             T (*function)(const T&));
00354 
00355     //@}
00356 
00357   protected:
00358     /**
00359      * List of one-dimensional row kernels
00360      */
00361     std::vector< kernelPair > kernels_;
00362   };
00363 
00364   // ----------------------------------------------------------
00365   //   Typical used types
00366   // ----------------------------------------------------------
00367 
00368   /**
00369    * Separable kernel of integers
00370    */
00371   typedef separableKernel<int>    iseparableKernel;
00372 
00373   /**
00374    * Separable kernel of floats
00375    */
00376   typedef separableKernel<float>  fseparableKernel;
00377 
00378   /**
00379    * Separable kernel of doubles
00380    */
00381   typedef separableKernel<double> dseparableKernel;
00382 
00383   /**
00384    * Separable kernel of unsigned bytes
00385    */
00386   typedef separableKernel<ubyte>  bseparableKernel;
00387 
00388 
00389   // ----------------------------------------------------------
00390   //   stream output
00391   // ----------------------------------------------------------
00392 
00393   /**
00394    * outputs the separable kernel \p kern on a stream \p s. The kernel pairs
00395    * are printed in the order they are stored in the separable kernel:
00396    *
00397    * \code
00398    * (((first row kernel)
00399    *   (first column kernel))
00400    *  ((second row kernel)
00401    *   (second column kernel))
00402    *   ...
00403    *  ((last row kernel)
00404    *   (last column kerne)))
00405    * \endcode
00406    */
00407   template <class T>
00408   std::ostream& operator<<(std::ostream& s, const separableKernel<T>& kern);
00409 
00410 }
00411 
00412 #endif
00413 

Generated on Sun Sep 20 22:08:00 2009 for CVR-Lib by Doxygen 1.5.8