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

ltiGeometricTransform.h

00001 /*
00002  * Copyright (C) 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 .......: ltiGeometricTransform.h
00027  * authors ....: Ruediger Weiler
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 5.2.2001
00030  * revisions ..: $Id: ltiGeometricTransform.h,v 1.20 2006/02/08 11:12:09 ltilib Exp $
00031  */
00032 
00033 #ifndef _LTI_GEOMETRIC_TRANSFORM_H_
00034 #define _LTI_GEOMETRIC_TRANSFORM_H_
00035 
00036 #include "ltiMacroSymbols.h"
00037 
00038 #include "ltiMath.h"
00039 #include "ltiMatrix.h"
00040 #include "ltiTypeInfo.h"
00041 #include "ltiHTypes.h"
00042 
00043 #include "ltiPointList.h"
00044 
00045 #include "ltiModifier.h"
00046 
00047 #include "ltiInterpolatorType.h"
00048 #include "ltiBilinearInterpolator.h"
00049 #include "ltiBiquadraticInterpolator.h"
00050 #include "ltiGenericInterpolator.h"
00051 #include "ltiNearestNeighborInterpolator.h"
00052 
00053 #include <limits>
00054 
00055 namespace lti {
00056 
00057   /**
00058    * This functor implements an generic geometric transform based on a 
00059    * homogeneous matrix, which is able to represent rotations, translations
00060    * scalings and all other possibilites of homographies.
00061    *
00062    * You can use your own matrix to generate a special geometric
00063    * transformation, or you can use the member functions of the parameters
00064    * class to generate the matrix and vectors for a given translation,
00065    * rotation and scaling.
00066    *
00067    * You can use all the three functions in arbitrary order and number to
00068    * build your transform matrix sequentially.
00069    *
00070    * With the <code>invert()</code> member of the parameters class you can
00071    * invert the matrix for the reverse transformation. The speed in general
00072    * only depends on the size of the image or the size of the pointList.
00073    *
00074    * Please note that even if the transformation can have a 3D nature (4x4
00075    * homogeneous matrix) and you can turn, shift or scale the image plane 
00076    * in any of the three coordinates, the input image is always a 2D object
00077    * with z-coordinate zero.  A typical error is trying to apply the inverse
00078    * transformation matrix to reconstruct a 3D rotation: this cannot work
00079    * because of the missing third coordinate for each pixel.
00080    *
00081    * There are also a few specialized functors to achieve isolated
00082    * transformation tasks in a much faster way.  A derived class also
00083    * restricts the transformation to a similarity transformation (see
00084    * lti::similarityTransform2D).
00085    *
00086    * @see lti::flipImage, lti::rotation, lti::scaling
00087    *
00088    * @ingroup gGeometry
00089    */
00090   class geometricTransform : public modifier {
00091   public:
00092     /**
00093      * The parameters for the class geometricTransform
00094      */
00095     class parameters : public modifier::parameters {
00096     public:
00097       /**
00098        * Invert the homogeneous transformation matrix.
00099        */
00100       void invert();
00101 
00102       /**
00103        * Set the scaling factor of the homogeneous matrix.  This is achieved
00104        * multiplying the existing matrix with a resize matrix. If you
00105        * use this function on an unit matrix you get the following matrix:
00106        * \f[ \begin{bmatrix} thefpoint.x & 0           & 0 & 0 \\
00107        *                  0           & thefpoint.y & 0 & 0 \\
00108        *                  0           & 0           & 1 & 0 \\
00109        *                  0           & 0           & 0 & 1 \end{bmatrix} \f]
00110        */
00111       void scale(const tpoint<double>& thefPoint);
00112 
00113       /**
00114        * Set the scaling factor of the homogeneous matrix.  This is achieved
00115        * multiplying the existing matrix with a resize matrix. If you
00116        * use this function on an unit matrix you get the following matrix:
00117        * \f[ \begin{bmatrix} thefpoint.x & 0           & 0 & 0 \\
00118        *                  0           & thefpoint.y & 0 & 0 \\
00119        *                  0           & 0           & thefpoint.z & 0 \\
00120        *                  0           & 0           & 0 & 1 \end{bmatrix} \f]
00121        */
00122       void scale(const tpoint3D<double>& thefPoint);
00123 
00124       /**
00125        * Special scale function with only one parameter
00126        * for x, y and z scale
00127        * \f[ \begin{bmatrix} x & 0 & 0 & 0 \\
00128        *                     0 & x & 0 & 0 \\
00129        *                     0 & 0 & x & 0 \\
00130        *                     0 & 0 & 0 & 1 \end{bmatrix} \f]
00131        */
00132       void scale(const double& x);
00133 
00134       /**
00135        * This function adds the point to the translation
00136        * vector.  (z component assumed 0)
00137        */
00138       void shift(const tpoint<double>& thefPoint);
00139 
00140       /**
00141        * This function adds the point to the translation
00142        * vector.
00143        */
00144       void shift(const tpoint3D<double>& thefPoint);
00145 
00146       /**
00147        * Multiply the existing matrix with a rotation matrix.
00148        * The vectors <code>center</code> and <code>axis</code> have the
00149        * dimension 3.
00150        * @param center this vector is the center of the rotation.
00151        * @param axis this vector is the rotation-axis.
00152        * @param angle the rotation angle in radians.
00153        */
00154       void rotate(const vector<double>& center,
00155                   const vector<double>& axis,
00156                   const double& angle);
00157 
00158       /**
00159        * Multiply the existing matrix with a rotation matrix.
00160        * The vectors <code>center</code> and <code>axis</code> have the
00161        * dimension 3.
00162        * @param center this vector is the center of the rotation.
00163        * @param axis this vector is the rotation-axis.
00164        * @param angle the rotation angle in radians.
00165        */
00166       void rotate(const tpoint3D<double>& center,
00167                   const tpoint3D<double>& axis,
00168                   const double& angle);
00169 
00170       /**
00171        * Special rotate function with the center set to the origin:
00172        * The rotation axis is set to the z-axis
00173        */
00174       void rotate(const double& angle);
00175 
00176       /**
00177        * This function erase the tranfomation matrix,translation
00178        * vector and the rotation center. The matrix is overwriten with
00179        * the unit matrix.
00180        */
00181       void clear(void);
00182 
00183       /**
00184        * Default constructor
00185        */
00186       parameters();
00187 
00188       /**
00189        * Copy constructor
00190        * @param other the parameters object to be copied
00191        */
00192       parameters(const parameters& other);
00193 
00194       /**
00195        * Destructor
00196        */
00197       ~parameters();
00198 
00199       /**
00200        * Returns name of this type
00201        */
00202       const char* getTypeName() const;
00203 
00204       /**
00205        * Copy the contents of a parameters object
00206        * @param other the parameters object to be copied
00207        * @return a reference to this parameters object
00208        */
00209       parameters& copy(const parameters& other);
00210 
00211       /**
00212        * Copy the contents of a parameters object
00213        * @param other the parameters object to be copied
00214        * @return a reference to this parameters object
00215        */
00216       parameters& operator=(const parameters& other);
00217 
00218       /**
00219        * Returns a pointer to a clone of the parameters
00220        */
00221       virtual functor::parameters* clone() const;
00222 
00223       /**
00224        * Write the parameters in the given ioHandler
00225        * @param handler the ioHandler to be used
00226        * @param complete if true (the default) the enclosing begin/end will
00227        *        be also written, otherwise only the data block will be written.
00228        * @return true if write was successful
00229        */
00230       virtual bool write(ioHandler& handler,const bool complete=true) const;
00231 
00232       /**
00233        * Write the parameters in the given ioHandler
00234        * @param handler the ioHandler to be used
00235        * @param complete if true (the default) the enclosing begin/end will
00236        *        be also written, otherwise only the data block will be written.
00237        * @return true if write was successful
00238        */
00239       virtual bool read(ioHandler& handler,const bool complete=true);
00240 
00241 #     ifdef _LTI_MSC_6
00242       /**
00243        * This function is required by MSVC only, as a workaround for a
00244        * very awful bug, which exists since MSVC V.4.0, and still by
00245        * V.6.0 with all bugfixes (so called "service packs") remains
00246        * there...  This method is also public due to another bug, so please
00247        * NEVER EVER call this method directly: use read() instead
00248        */
00249       bool readMS(ioHandler& handler,const bool complete=true);
00250 
00251       /**
00252        * This function is required by MSVC only, as a workaround for a
00253        * very awful bug, which exists since MSVC V.4.0, and still by
00254        * V.6.0 with all bugfixes (so called "service packs") remains
00255        * there...  This method is also public due to another bug, so please
00256        * NEVER EVER call this method directly: use write() instead
00257        */
00258       bool writeMS(ioHandler& handler,const bool complete=true) const;
00259 #     endif
00260 
00261       // ------------------------------------------------
00262       // the parameters
00263       // ------------------------------------------------
00264 
00265       /**
00266        * The transMatrix stores the matrix for the geometric transformation.
00267        * The functions rotate ,scale, and invert access the matrix.
00268        *
00269        * Default value:  unit matrix
00270        */
00271       hMatrix3D<float> transMatrix;
00272 
00273       /**
00274        * If keepDimensions is true, the virtual position and size of
00275        * the matrix are retained unchanged.  Otherwise the position and size
00276        * will be changed so that all points in the new image are displayed
00277        *
00278        * Default value:  true
00279        */
00280       bool keepDimensions;
00281 
00282       /**
00283        * Interpolator to be used.
00284        *
00285        * Default value: BilinearInterpolator
00286        *
00287        * @see lti::eInterpolatorType
00288        */
00289       eInterpolatorType interpolator;
00290     };
00291 
00292     // -----------------------------------------------------------------------
00293     //   Helper classes
00294     // -----------------------------------------------------------------------
00295   protected:
00296     /**
00297      * Structure to avoid the use of the access operator of matrices
00298      */
00299     struct fastMatrix {
00300       /**
00301        * Constructor
00302        */ 
00303       fastMatrix(const hMatrix3D<float>& m);
00304 
00305       /**
00306        * Constructor
00307        */
00308       fastMatrix(const hMatrix2D<float>& m);
00309       
00310       /**
00311        * The matrix is copied first in these variables to avoid the access
00312        * operator [y,x] which takes some more time...
00313        */
00314       float m00,m01,m02,m03,
00315             m10,m11,m12,m13,
00316             m30,m31,m32,m33;
00317     };
00318 
00319     /**
00320      * Transform 2D point
00321      *
00322      * Uses the given "fastMatrix" to transform the source point into the
00323      * destination point.
00324      */
00325     template<class value_type>
00326     inline void transf(const tpoint<value_type>& src,
00327                        tpoint<value_type>& dest,
00328                        const fastMatrix& m) const {
00329       // apply the matrix on the point src result is returned in dest
00330       // regular apply of the function
00331       const float factor = m.m30*src.x + m.m31*src.y + m.m33;      
00332       condRoundCastTo(((m.m00*src.x + m.m01*src.y + m.m03)/factor),dest.x);
00333       condRoundCastTo(((m.m10*src.x + m.m11*src.y + m.m13)/factor),dest.y);
00334     }
00335 
00336     /*
00337      * The template parameter I specifies the interpolator functor to
00338      * be used.
00339      * Valid types for I are all classes inherited from
00340      * scalarValueInterpolation.  The type of the matrices will
00341      * be typename I::value_type
00342      */
00343     template<class I>
00344     class helper {
00345     public:
00346       // type of matrices
00347       typedef typename I::value_type value_type;
00348 
00349     private:
00350 
00351       /*
00352        * The interpolator is created only once with the helper
00353        */
00354       I inpol;
00355 
00356       /*
00357        * parameters used by the apply method
00358        */
00359       parameters param;
00360 
00361       /*
00362        * transform 3D point
00363        */
00364       inline void transf(const tpoint3D<float>& src,
00365                          tpoint<float>& dest,
00366                          const fastMatrix& m) const {
00367         // apply the matrix on the point src result is returned in dest
00368         // regular apply of the function
00369         const float factor = (m.m30*src.x + m.m31*src.y + m.m32*src.z + m.m33);
00370         dest.x = ((m.m00*src.x + m.m01*src.y + m.m02*src.z + m.m03))/factor;
00371         dest.y = ((m.m10*src.x + m.m11*src.y + m.m12*src.z + m.m13))/factor;
00372       }
00373 
00374       // requirements of the helper class
00375     public:
00376       // default constructor
00377       helper() {};
00378       
00379       // constructor
00380       helper(const parameters& par) : param(par) {
00381         inpol.setBoundaryType(par.boundaryType);
00382       };
00383 
00384       // set parameters
00385       bool setParameters(const parameters& par) {
00386         param.copy(par);
00387         inpol.setBoundaryType(par.boundaryType);
00388         return true;
00389       }
00390       
00391       // apply method
00392       bool tApply(const matrix<value_type>& src,
00393                         matrix<value_type>& dest,
00394                         point& offset) const {
00395         if (src.empty()) {
00396           return false;
00397         }
00398 
00399         // Get parameters
00400         hMatrix3D<float> mat;
00401         mat.invert(param.transMatrix);
00402         
00403         if (param.keepDimensions) {
00404           dest.resize(src.size(),value_type(),false,false);
00405           offset.set(0,0);
00406         } else {
00407           // calculate the position of the four corners and use them to
00408           // define the size and offset of the new matrix
00409           tpoint<float> tr,tl,br,bl;
00410           param.transMatrix.multiply(tpoint<float>(0,0),tl);
00411           param.transMatrix.multiply(tpoint<float>((float)src.lastColumn(),0),
00412                                      tr);
00413           param.transMatrix.multiply(tpoint<float>(0,(float)src.lastRow()),bl);
00414           param.transMatrix.multiply(tpoint<float>((float)src.lastColumn(),
00415                                                    (float)src.lastRow()),br);
00416           
00417           point theMin,theMax;
00418           theMin.x = iround(min(min(tr.x,tl.x),min(br.x,bl.x)));
00419           theMax.x = iround(max(max(tr.x,tl.x),max(br.x,bl.x)));
00420           theMin.y = iround(min(min(tr.y,tl.y),min(br.y,bl.y)));
00421           theMax.y = iround(max(max(tr.y,tl.y),max(br.y,bl.y)));
00422           
00423           dest.resize(theMax.y-theMin.y+1,theMax.x-theMin.x+1,
00424                       value_type(),false,false);
00425           
00426           // now translate the transformation matrix to avoid using the
00427           // offset for every pixel:
00428           // note that the matrix must be
00429           hMatrix3D<float> matT;
00430           matT.translate(hPoint3D<float>((float)theMin.x,(float)theMin.y,0));
00431           mat.multiply(matT);
00432           // give the offset to the outside world
00433           offset = theMin;
00434         }
00435         
00436         tpoint<float> q;
00437         tpoint3D<float> p;
00438         const float sizex(static_cast<float>(dest.columns()));
00439         const float sizey(static_cast<float>(dest.rows()));
00440         
00441         float t2,a,b,c,d,r22,tmp;
00442         t2 = mat.at(2,3);
00443         r22 = mat.at(2,2);
00444         
00445         a = t2*mat.at(3,0)-mat.at(3,3)*mat.at(2,0);
00446         b = t2*mat.at(3,1)-mat.at(3,3)*mat.at(2,1);
00447         
00448         c = mat.at(3,2)*mat.at(2,0) - mat.at(3,0)*r22;
00449         d = mat.at(3,2)*mat.at(2,1) - mat.at(3,1)*r22;
00450         
00451         const fastMatrix fmat(mat);
00452         
00453         for (p.y=0;p.y<sizey;++p.y) {
00454           for (p.x=0;p.x<sizex;++p.x) {
00455             tmp = (c*p.x + d*p.y +r22);
00456             if (tmp == 0) {
00457               dest.at(static_cast<int>(p.y),
00458                       static_cast<int>(p.x)) = value_type(0);
00459             } else {
00460               p.z = (a*p.x+b*p.y-t2)/tmp;
00461               transf(p,q,fmat);
00462               dest.at(static_cast<int>(p.y),
00463                       static_cast<int>(p.x)) = inpol.interpolate(src,q.y,q.x);
00464             }
00465           }
00466         }
00467         
00468         return true;
00469       }
00470 
00471     // end of helper class
00472     };
00473 
00474     /*
00475      * Interpolator collection
00476      *
00477      * This is a class to get at compile time an appropriate helper class
00478      * for a given image type
00479      */
00480     template<class T>
00481     class interpolatorCollection {
00482     public:
00483 
00484 #ifdef _LTI_GNUC_2
00485       geometricTransform::helper< nearestNeighborInterpolator<T> > nearest;
00486       geometricTransform::helper< bilinearInterpolator<T> >        bilinear;
00487       geometricTransform::helper< biquadraticInterpolator<T> >     biquadratic;
00488       geometricTransform::helper< genericInterpolator<T> >         bicubic;
00489 #else
00490       helper< nearestNeighborInterpolator<T> > nearest;
00491       helper< bilinearInterpolator<T> >        bilinear;
00492       helper< biquadraticInterpolator<T> >     biquadratic;
00493       helper< genericInterpolator<T> >         bicubic;
00494 #endif
00495       interpolatorCollection() {};
00496 
00497       interpolatorCollection(const parameters& par)
00498         : nearest(par),bilinear(par),biquadratic(par),bicubic(par) {};
00499 
00500       bool setParameters(const parameters& par) {
00501         return (nearest.setParameters(par) &&
00502                 bilinear.setParameters(par) &&
00503                 biquadratic.setParameters(par) &&
00504                 bicubic.setParameters(par));
00505       }
00506     };
00507 
00508     /**
00509      * Some attributes with the interpolators to save the creation time
00510      * in the apply methods
00511      */
00512     //@{
00513     interpolatorCollection<double>   dcollect;
00514     interpolatorCollection<float>    fcollect;
00515     interpolatorCollection<int>      icollect;
00516     interpolatorCollection<ubyte>    bcollect;
00517     interpolatorCollection<rgbPixel> ccollect;
00518     //@}
00519 
00520     /**
00521      * Methods that return the proper collection type
00522      *
00523      * The dummy argument \a a is only there to allow the compiler to chose
00524      * the proper method.
00525      */
00526     //@{
00527     inline const interpolatorCollection<double>& 
00528     getCollection(double& a) const {
00529       a = 1.0;
00530       return dcollect;
00531     }
00532     inline const interpolatorCollection<float>& getCollection(float& a) const {
00533       a = 2.0;
00534       return fcollect;
00535     }
00536     inline const interpolatorCollection<int>& getCollection(int& a) const {
00537       a = 3;
00538       return icollect;
00539     }
00540     inline const interpolatorCollection<ubyte>& getCollection(ubyte& a) const {
00541       a = 4;
00542       return bcollect;
00543     }
00544     inline const interpolatorCollection<rgbPixel>&
00545     getCollection(rgbPixel& a) const {
00546       a = rgbPixel(5,5,5);
00547       return ccollect;
00548     }
00549       
00550     //@}
00551 
00552     // -----------------------------------------------------------------------
00553     //   Geometric Transform Functor
00554     // -----------------------------------------------------------------------
00555   public:
00556     /**
00557      * Default constructor
00558      */
00559     geometricTransform();
00560 
00561     /**
00562      * Default constructor with parameters object
00563      */
00564     geometricTransform(const parameters& par);
00565 
00566     /**
00567      * Copy constructor
00568      * @param other the object to be copied
00569      */
00570     geometricTransform(const geometricTransform& other);
00571 
00572     /**
00573      * Destructor
00574      */
00575     virtual ~geometricTransform();
00576 
00577     /**
00578      * Returns the name of this type ("geometricTransform")
00579      */
00580     virtual const char* getTypeName() const;
00581 
00582     /**
00583      * @name Apply methods for points and point lists
00584      */
00585     //@{
00586 
00587     // implementation of template member must be here (in header file) due
00588     // to MS VC++ bug.
00589 
00590     /**
00591      * Apply the geometric transformation to the given point
00592      * @param srcdest point with the source data.  The result
00593      *                 will be left here too.
00594      * @return true if successful, false otherwise
00595      */
00596     template<class T>
00597     bool apply(tpoint<T>& srcdest) const {
00598       tpoint<T> src(srcdest);
00599       return apply(src,srcdest);
00600     }
00601 
00602     /**
00603      * Apply the geometric transformation on src point and leave the result on
00604      * dest.
00605      * @param src point with the source data.
00606      * @param dest point where the result will be left.
00607      * @return true if successful, false otherwise
00608      */
00609     template<class T>
00610     bool apply(const tpoint<T>& src,tpoint<T>& dest) const {
00611       //transform one Point
00612       const fastMatrix mat(getParameters().transMatrix);
00613       transf(src,dest,mat);
00614       return true;
00615     }
00616 
00617     /**
00618      * Applies the geometric transformation on the given %parameter.
00619      * The transformation is applied on each point of the list.
00620      * @param srcdest pointList with the source data.  The result
00621      *                 will be left here too.
00622      * @return true if successful, false otherwise
00623      */
00624     template<class T>
00625     bool apply(tpointList<T>& srcdest) const {
00626 
00627       typename tpointList<T>::iterator it,eit;
00628       tpoint<T> tmp;
00629 
00630       it = srcdest.begin();
00631       eit = srcdest.end();
00632 
00633       const fastMatrix mat(getParameters().transMatrix);
00634 
00635       while(it!=eit) {
00636         transf(*it,tmp,mat);
00637         (*it).copy(tmp);
00638         ++it;
00639       }
00640       return true;
00641     }
00642 
00643     /**
00644      * Applies the geometric transformation on the given %parameter.
00645      * The transformation is applied on each point of the list.
00646      * @param src pointList with the source data.
00647      * @param dest pointList where the result will be left.
00648      * @return true if successful, false otherwise
00649      */
00650     template<class T>
00651     bool apply(const tpointList<T>& src,
00652                      tpointList<T>& dest) const {
00653       typename tpointList<T>::const_iterator it,eit;
00654       tpoint<T> tmp;
00655 
00656       it = src.begin();
00657       eit = src.end();
00658       dest.clear();
00659 
00660       const fastMatrix mat(getParameters().transMatrix);
00661 
00662       while(it!=eit) {
00663         transf(*it,tmp,mat);
00664         dest.push_back(tmp);
00665         ++it;
00666       }
00667 
00668       return true;
00669     }
00670     //@}
00671 
00672     /**
00673      * @name Apply methods for matrices
00674      */
00675     //@{
00676 
00677     /**
00678      * Applies the geometric transformation on the given %parameter.
00679      * The transformation is applied on each point of the matrix.
00680      *
00681      * @param srcdest matix with the source data.  The result
00682      *                 will be left here too.
00683      * @return true if successful or false otherwise.
00684      */
00685     template<class T>
00686     inline bool apply(matrix<T>& srcdest) const {
00687       matrix<T> dest;
00688       if (apply(srcdest,dest)) {
00689         dest.detach(srcdest);
00690         return true;
00691       }
00692       return false;
00693     }
00694 
00695     /**
00696      * Applies the geometric transformation on the given %parameter.
00697      * The transformation is applied on each point of the matrix.
00698      *
00699      * @param src matrix with the source data.
00700      * @param dest the result will be left here.
00701      * @param offset if you specified parameters::keepDimensions as false,
00702      *        then this is the offset added to each pixel transformation to
00703      *        obtain the results in a positive range.  It is usefull if you
00704      *        also transform some points and want to obtain their value
00705      *        in the destination image.
00706      * @return true if successful or false otherwise.
00707      */
00708     template<class T>
00709     inline bool apply(const matrix<T>& src,
00710                             matrix<T>& dest,
00711                             point& offset) const {
00712       const parameters& param = getParameters();
00713       T tmp; // a dummy value used to select the proper collection
00714       switch(param.interpolator) {
00715         case NearestNeighborInterpolator: {
00716           return getCollection(tmp).nearest.tApply(src,dest,offset);
00717         } break;   
00718         case BiquadraticInterpolator: {
00719           return getCollection(tmp).biquadratic.tApply(src,dest,offset);
00720         } break;
00721         case BicubicInterpolator: {
00722           return getCollection(tmp).bicubic.tApply(src,dest,offset);
00723         } break;
00724         default: {
00725           return getCollection(tmp).bilinear.tApply(src,dest,offset);
00726         }
00727       }
00728       return false;
00729     }
00730 
00731     /**
00732      * Applies the geometric transformation on the given %parameter.
00733      * The transformation is applied on each point of the matrix.
00734      *
00735      * @param src matrix with the source data.
00736      * @param dest the result will be left here.
00737      * @return true if successful or false otherwise.
00738      */
00739     template<class T>
00740     inline bool apply(const matrix<T>& src,matrix<T>& dest) const {
00741       point offset;
00742       return apply(src,dest,offset);
00743     }
00744     //@}
00745 
00746     /**
00747      * @name Shortcuts for usual transformations.
00748      *
00749      * Example:
00750      * \code
00751      * // Usual parameters
00752      * lti::geometricTransform::parameters geoPar;
00753      * geoPar.keepDimensions = true;
00754      * geoPar.boundaryType = lti::Mirror;
00755      *
00756      * // Create geometric transformation object
00757      * lti::geometricTransform geoTrans(geoPar);
00758      *
00759      * // images 
00760      * lti::image img(256,256,lti::Black),res;
00761      *
00762      * // initialize your image with something
00763      * (img.getRow(img.rows()/2)).fill(lti::Red);
00764      *
00765      * // Rotate an image using shortcuts and default interpolator
00766      * geoTrans.rotate(img,res,45*Pi/180);  // rotate 45 degrees
00767      * \endcode
00768      */
00769     //@{
00770     /**
00771      * Scale the src image on copy.
00772      *
00773      * You usually want to set parameters::keepDimensions to false when using
00774      * this method.
00775      *
00776      * @see lti::scaling
00777      *
00778      * @param src source image
00779      * @param dest matrix where the result will be left
00780      * @param factor point containing the scaling factor for x and y
00781      *               coordinates
00782      * @return true if successful, false otherwise.
00783      */
00784     template<class T>
00785     bool scale(const matrix<T>& src,
00786                      matrix<T>& dest,
00787                const tpoint<float>& factor) {
00788       parameters par(getParameters());
00789       par.clear();
00790       par.scale(factor);
00791       setParameters(par);
00792       return apply(src,dest);
00793     }
00794 
00795     /**
00796      * Scale the srcdest image on-place
00797      *
00798      * You usually want to set parameters::keepDimensions to false when using
00799      * this method.
00800      *
00801      * @see lti::scaling
00802      *
00803      * @param srcdest source image.  The result will be left here too.
00804      * @param factor point containing the scaling factor for x and y
00805      *               coordinates
00806      * @return true if successful, false otherwise.
00807      */
00808     template<class T>
00809     bool scale(matrix<T>& srcdest,
00810                const tpoint<float>& factor) {
00811       matrix<T> tmp;
00812       if (scale(srcdest,tmp,factor)) {
00813         tmp.detach(srcdest);
00814         return true;
00815       }
00816       return false;
00817     }
00818 
00819     /**
00820      * Rotate the src image on copy
00821      *
00822      * @see lti::rotation
00823      *
00824      * @param src source image
00825      * @param dest matrix where the result will be left
00826      * @param angle angle in radians to rotate the image
00827      * @param center rotation point (takes effect only if \c keepDimensions
00828      *               in the parameters is set to true).  The default value
00829      *               ensures rotation on the image center.
00830      * @return true if successful, false otherwise.
00831      */
00832     template<class T>
00833     bool rotate(const matrix<T>& src,
00834                       matrix<T>& dest,
00835                 const double& angle,
00836                 const point& center=point(std::numeric_limits<int>::max(),
00837                                           std::numeric_limits<int>::max())) {
00838       
00839       tpoint3D<double> c;
00840       if ((center.x == std::numeric_limits<int>::max()) &&
00841           (center.y == std::numeric_limits<int>::max())) {
00842         c.x=src.columns()/2;
00843         c.y=src.rows()/2;
00844       } else {
00845         c.x=center.x;
00846         c.y=center.y;
00847       }
00848       c.z=0;
00849       tpoint3D<double> ax(0,0,1.0);
00850 
00851       parameters par(getParameters());
00852       par.clear();
00853       par.rotate(c,ax,angle);
00854       setParameters(par);
00855 
00856       return apply(src,dest);
00857     }
00858 
00859     /**
00860      * Rotate the image on place 
00861      *
00862      * @see lti::rotation
00863      *
00864      * @param srcdest matrix with source data and where the result will be left
00865      * @param angle angle in radians to rotate the image
00866      * @param center rotation point (takes effect only if \c keepDimensions
00867      *               in the parameters is set to true).  The default value
00868      *               ensures rotation on the image center.
00869      * @return true if successful, false otherwise.
00870      */
00871     template<class T>
00872     bool rotate(matrix<T>& srcdest,
00873                 const double& angle,
00874                 const point& center=point(std::numeric_limits<int>::max(),
00875                                           std::numeric_limits<int>::max())) {
00876       matrix<T> tmp;
00877       if (rotate(srcdest,tmp,angle,center)) {
00878         tmp.detach(srcdest);
00879         return true;
00880       }
00881       return false;
00882     }
00883     //@}
00884 
00885     /**
00886      * Copy data of "other" functor.
00887      * @param other the functor to be copied
00888      * @return a reference to this functor object
00889      */
00890     geometricTransform& copy(const geometricTransform& other);
00891 
00892     /**
00893      * Returns a pointer to a clone of this functor.
00894      */
00895     virtual functor* clone() const;
00896 
00897     /**
00898      * Returns used parameters
00899      */
00900     const parameters& getParameters() const;
00901 
00902     /**
00903      * Set parameters
00904      */
00905     virtual bool updateParameters();
00906 
00907   };
00908 }
00909 
00910 #endif

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