[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

vigra/affinegeometry.hxx

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 2005-2006 by Ullrich Koethe                  */
00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
00005 /*                                                                      */
00006 /*    This file is part of the VIGRA computer vision library.           */
00007 /*    ( Version 1.6.0, Aug 13 2008 )                                    */
00008 /*    The VIGRA Website is                                              */
00009 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00010 /*    Please direct questions, bug reports, and contributions to        */
00011 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
00012 /*        vigra@informatik.uni-hamburg.de                               */
00013 /*                                                                      */
00014 /*    Permission is hereby granted, free of charge, to any person       */
00015 /*    obtaining a copy of this software and associated documentation    */
00016 /*    files (the "Software"), to deal in the Software without           */
00017 /*    restriction, including without limitation the rights to use,      */
00018 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00019 /*    sell copies of the Software, and to permit persons to whom the    */
00020 /*    Software is furnished to do so, subject to the following          */
00021 /*    conditions:                                                       */
00022 /*                                                                      */
00023 /*    The above copyright notice and this permission notice shall be    */
00024 /*    included in all copies or substantial portions of the             */
00025 /*    Software.                                                         */
00026 /*                                                                      */
00027 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00028 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00029 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00030 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00031 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00032 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00033 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00034 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */                
00035 /*                                                                      */
00036 /************************************************************************/
00037  
00038 #ifndef VIGRA_AFFINEGEOMETRY_HXX
00039 #define VIGRA_AFFINEGEOMETRY_HXX
00040 
00041 #include "mathutil.hxx"
00042 #include "matrix.hxx"
00043 #include "tinyvector.hxx"
00044 #include "splineimageview.hxx"
00045 #include <cmath>
00046 
00047 namespace vigra {
00048 
00049 /** \addtogroup GeometricTransformations Geometric Transformations
00050 */
00051 //@{
00052 
00053 /********************************************************/
00054 /*                                                      */
00055 /*                create affine matrices                */
00056 /*                                                      */
00057 /********************************************************/
00058 
00059 /** \brief Create homogeneous matrix representing a 2D translation.
00060  
00061     For use with \ref affineWarpImage().
00062 */
00063 inline
00064 linalg::TemporaryMatrix<double> translationMatrix2D(TinyVector<double, 2> const & shift)
00065 {
00066     linalg::TemporaryMatrix<double> ret(identityMatrix<double>(3));
00067     ret(0,2) = shift[0];
00068     ret(1,2) = shift[1];
00069     return ret;
00070 }
00071 
00072 /** \brief Create homogeneous matrix representing a 2D uniform scaling about the coordinate origin.
00073  
00074     For use with \ref affineWarpImage().
00075 */
00076 inline
00077 linalg::TemporaryMatrix<double> scalingMatrix2D(double scalingFactor)
00078 {
00079     linalg::TemporaryMatrix<double> ret(identityMatrix<double>(3));
00080     ret(0,0) = scalingFactor;
00081     ret(1,1) = scalingFactor;
00082     return ret;
00083 }
00084 
00085 /** \brief Create homogeneous matrix representing a 2D non-uniform scaling about the coordinate origin.
00086  
00087     For use with \ref affineWarpImage().
00088 */
00089 inline
00090 linalg::TemporaryMatrix<double> scalingMatrix2D(double sx, double sy)
00091 {
00092     linalg::TemporaryMatrix<double> ret(identityMatrix<double>(3));
00093     ret(0,0) = sx;
00094     ret(1,1) = sy;
00095     return ret;
00096 }
00097 
00098 /** \brief Create homogeneous matrix representing a 2D shearing.
00099  
00100     For use with \ref affineWarpImage().
00101 */
00102 inline
00103 linalg::TemporaryMatrix<double> shearMatrix2D(double s01, double s10)
00104 {
00105     linalg::TemporaryMatrix<double> ret(identityMatrix<double>(3));
00106     ret(0,1) = s01;
00107     ret(1,0) = s10;
00108     return ret;
00109 }
00110 
00111 /** \brief Create homogeneous matrix representing a 2D rotation about the coordinate origin.
00112  
00113     For use with \ref affineWarpImage(). Angle must be in radians.
00114 */
00115 inline
00116 linalg::TemporaryMatrix<double> rotationMatrix2DRadians(double angle)
00117 {
00118     linalg::TemporaryMatrix<double> ret(identityMatrix<double>(3));
00119     double s = std::sin(angle);
00120     double c = std::cos(angle);
00121     ret(0,0) = c;
00122     ret(1,1) = c;
00123     ret(0,1) = -s;
00124     ret(1,0) = s;
00125     return ret;
00126 }
00127 
00128 /** \brief Create homogeneous matrix representing a 2D rotation about the coordinate origin.
00129  
00130     For use with \ref affineWarpImage(). Angle must be in degrees.
00131 */
00132 inline
00133 linalg::TemporaryMatrix<double> rotationMatrix2DDegrees(double angle)
00134 {
00135     return rotationMatrix2DRadians(angle*M_PI/180.0);
00136 }
00137 
00138 /** \brief Create homogeneous matrix representing a 2D rotation about the given point.
00139  
00140     For use with \ref affineWarpImage(). Angle must be in radians.
00141 */
00142 inline
00143 linalg::TemporaryMatrix<double> rotationMatrix2DRadians(double angle, TinyVector<double, 2> const & center)
00144 {
00145     return translationMatrix2D(center) * rotationMatrix2DRadians(angle) * translationMatrix2D(-center);
00146 }
00147 
00148 /** \brief Create homogeneous matrix representing a 2D rotation about the given point.
00149  
00150     For use with \ref affineWarpImage(). Angle must be in degrees.
00151 */
00152 inline
00153 linalg::TemporaryMatrix<double> rotationMatrix2DDegrees(double angle, TinyVector<double, 2> const & center)
00154 {
00155     return rotationMatrix2DRadians(angle*M_PI/180.0, center);
00156 }
00157 
00158 /********************************************************/
00159 /*                                                      */
00160 /*                      rotateImage                     */
00161 /*                                                      */
00162 /********************************************************/
00163 
00164 /** \brief Rotate image by an arbitrary angle.
00165 
00166     The algorithm performs a rotation about the given center point (the image center by default)
00167     using the given SplineImageView for interpolation. The destination image must have the same size
00168     as the source SplineImageView. The rotation is counter-clockwise, and the angle must be given in degrees.
00169     
00170     <b> Declarations:</b>
00171     
00172     pass arguments explicitly:
00173     \code
00174     namespace vigra {
00175         // rotate about given center point
00176         template <int ORDER, class T, 
00177                   class DestIterator, class DestAccessor>
00178         void rotateImage(SplineImageView<ORDER, T> const & src,
00179                          DestIterator id, DestAccessor dest, 
00180                          double angleInDegree, TinyVector<double, 2> const & center);
00181                          
00182         // rotate about image center
00183         template <int ORDER, class T, 
00184                   class DestIterator, class DestAccessor>
00185         void 
00186         rotateImage(SplineImageView<ORDER, T> const & src,
00187                     DestIterator id, DestAccessor dest, 
00188                     double angleInDegree)
00189     }
00190     \endcode
00191     
00192     use argument objects in conjunction with \ref ArgumentObjectFactories :
00193     \code
00194     namespace vigra {
00195         // rotate about given center point
00196         template <int ORDER, class T, 
00197                   class DestIterator, class DestAccessor>
00198         void 
00199         rotateImage(SplineImageView<ORDER, T> const & src,
00200                     pair<DestImageIterator, DestAccessor> dest, 
00201                     double angleInDegree, TinyVector<double, 2> const & center);
00202 
00203         // rotate about image center
00204         template <int ORDER, class T, 
00205                   class DestIterator, class DestAccessor>
00206         void 
00207         rotateImage(SplineImageView<ORDER, T> const & src,
00208                     pair<DestImageIterator, DestAccessor> dest, 
00209                     double angleInDegree);
00210     }
00211     \endcode
00212     
00213     <b> Usage:</b>
00214     
00215         <b>\#include</b> <<a href="affinegeometry_8hxx-source.html">vigra/affinegeometry.hxx</a>><br>
00216         Namespace: vigra
00217     
00218     \code
00219     
00220     Image src(width, height);
00221     vigra::SplineImageView<3, Image::value_type> spline(srcImageRange(src));
00222     
00223     Image dest(width, height);
00224     
00225     vigra::rotateImage(spline, destImage(dest), 38.5);
00226     
00227     \endcode
00228 
00229     <b> Required Interface:</b>
00230     
00231     \code
00232     DestImageIterator dest_upperleft;
00233     
00234     double x = ..., y = ...;
00235     
00236     if (spline.isInside(x,y))
00237         dest_accessor.set(spline(x, y), dest_upperleft);
00238 
00239     \endcode
00240 */
00241 doxygen_overloaded_function(template <...> void rotateImage)
00242 
00243 template <int ORDER, class T, 
00244           class DestIterator, class DestAccessor>
00245 void rotateImage(SplineImageView<ORDER, T> const & src,
00246                  DestIterator id, DestAccessor dest, 
00247                  double angleInDegree, TinyVector<double, 2> const & center)
00248 {
00249     int w = src.width();
00250     int h = src.height();
00251     
00252     double angle = angleInDegree*M_PI/180.0;
00253     double c = std::cos(angle);
00254     double s = std::sin(angle);
00255     
00256     for(int y = 0; y < h; ++y, ++id.y)
00257     {
00258         typename DestIterator::row_iterator rd = id.rowIterator();
00259         double sy =  (y - center[1])*c - center[0]*s + center[1];
00260         double sx = -(y - center[1])*s - center[0]*c + center[0];
00261         for(int x=0; x < w; ++x, ++rd, sx += c, sy += s)
00262         {
00263             if(src.isInside(sx, sy))
00264                 dest.set(src(sx, sy), rd);
00265         }
00266     }
00267 }
00268 
00269 template <int ORDER, class T, 
00270           class DestIterator, class DestAccessor>
00271 inline void 
00272 rotateImage(SplineImageView<ORDER, T> const & src,
00273             pair<DestIterator, DestAccessor> dest, 
00274             double angleInDegree, TinyVector<double, 2> const & center)
00275 {
00276     rotateImage(src, dest.first, dest.second, angleInDegree, center);
00277 }
00278 
00279 template <int ORDER, class T, 
00280           class DestIterator, class DestAccessor>
00281 inline void 
00282 rotateImage(SplineImageView<ORDER, T> const & src,
00283             DestIterator id, DestAccessor dest, 
00284             double angleInDegree)
00285 {
00286     TinyVector<double, 2> center((src.width()-1.0) / 2.0, (src.height()-1.0) / 2.0);
00287     rotateImage(src, id, dest, angleInDegree, center);
00288 }
00289 
00290 template <int ORDER, class T, 
00291           class DestIterator, class DestAccessor>
00292 inline void 
00293 rotateImage(SplineImageView<ORDER, T> const & src,
00294             pair<DestIterator, DestAccessor> dest, 
00295             double angleInDegree)
00296 {
00297     TinyVector<double, 2> center((src.width()-1.0) / 2.0, (src.height()-1.0) / 2.0);
00298     rotateImage(src, dest.first, dest.second, angleInDegree, center);
00299 }
00300 
00301 /********************************************************/
00302 /*                                                      */
00303 /*                  affineWarpImage                     */
00304 /*                                                      */
00305 /********************************************************/
00306 
00307 /** \brief Warp an image according to an affine transformation.
00308 
00309     <b> Declarations:</b>
00310     
00311     pass arguments explicitly:
00312     \code
00313     namespace vigra {
00314         template <int ORDER, class T, 
00315                 class DestIterator, class DestAccessor,
00316                 class C>
00317         void affineWarpImage(SplineImageView<ORDER, T> const & src,
00318                             DestIterator dul, DestIterator dlr, DestAccessor dest, 
00319                             MultiArrayView<2, double, C> const & affineMatrix);
00320     }
00321     \endcode
00322     
00323     use argument objects in conjunction with \ref ArgumentObjectFactories :
00324     \code
00325     namespace vigra {
00326         template <int ORDER, class T, 
00327                 class DestIterator, class DestAccessor,
00328                 class C>
00329         void affineWarpImage(SplineImageView<ORDER, T> const & src,
00330                             triple<DestIterator, DestIterator, DestAccessor> dest, 
00331                             MultiArrayView<2, double, C> const & affineMatrix);
00332     }
00333     \endcode
00334     
00335     The algorithm applies the given \a affineMatrix to the <i>destination coordinates</i> and copies
00336     the image value from the resulting source coordinates, using the given SplineImageView \a src for interpolation. 
00337     If the resulting coordinate is outside the source image, nothing will be writen at that destination point.
00338     
00339     \code
00340         for all dest pixels:
00341             currentSrcCoordinate = affineMatrix * currentDestCoordinate;
00342             if src.isInside(currentSrcCoordinate):
00343                 dest[currentDestCoordinate] = src[currentSrcCoordinate]; // copy an interpolated value
00344     \endcode
00345     
00346     The matrix represent a 2-dimensional affine transform by means of homogeneous coordinates,
00347     i.e. it must be a 3x3 matrix whose last row is (0,0,1).
00348     
00349     <b> Usage:</b>
00350     
00351         <b>\#include</b> <<a href="affinegeometry_8hxx-source.html">vigra/affinegeometry.hxx</a>><br>
00352         Namespace: vigra
00353     
00354     \code
00355     
00356     Image src(width, height);
00357     vigra::SplineImageView<3, Image::value_type> spline(srcImageRange(src));
00358     
00359     Image dest1(width, height);
00360     
00361     // equivalent (up to round-off errors) with 
00362     //     rotateImage(spline, destImage(dest1), 45.0);
00363     TinyVector<double, 2> center((width-1.0)/2.0, (height-1.0)/2.0);
00364     affineWarpImage(spline, destImageRange(dest1), rotationMatrix2DDegrees(45.0, center));
00365     
00366     Image dest2(2*width-1, 2*height-1);
00367     
00368     // equivalent (up to round-off errors) with 
00369     //     resizeImageSplineInterpolation(srcImageRange(img), destImageRange(dest2));
00370     // note that scaleFactor = 0.5, because we must pass the transformation from destination to source
00371     affineWarpImage(spline, destImageRange(dest2), scalingMatrix2D(0.5));
00372     
00373     \endcode
00374 
00375     <b> Required Interface:</b>
00376     
00377     \code
00378     DestImageIterator dest_upperleft;
00379     
00380     double x = ..., y = ...;
00381     
00382     if (spline.isInside(x,y))
00383         dest_accessor.set(spline(x, y), dest_upperleft);
00384 
00385     \endcode
00386     
00387     <b>See also:</b> Functions to specify affine transformation: \ref translationMatrix2D(), \ref scalingMatrix2D(), 
00388                     \ref shearMatrix2D(), \ref rotationMatrix2DRadians(), \ref rotationMatrix2DDegrees()
00389 */
00390 doxygen_overloaded_function(template <...> void affineWarpImage)
00391 
00392 template <int ORDER, class T, 
00393           class DestIterator, class DestAccessor,
00394           class C>
00395 void affineWarpImage(SplineImageView<ORDER, T> const & src,
00396                      DestIterator dul, DestIterator dlr, DestAccessor dest, 
00397                      MultiArrayView<2, double, C> const & affineMatrix)
00398 {
00399     vigra_precondition(rowCount(affineMatrix) == 3 && columnCount(affineMatrix) == 3 && 
00400                        affineMatrix(2,0) == 0.0 && affineMatrix(2,1) == 0.0 && affineMatrix(2,2) == 1.0,
00401         "affineWarpImage(): matrix doesn't represent an affine transformation with homogeneous 2D coordinates.");
00402          
00403     
00404     double w = dlr.x - dul.x;
00405     double h = dlr.y - dul.y;
00406     
00407     for(double y = 0.0; y < h; ++y, ++dul.y)
00408     {
00409         typename DestIterator::row_iterator rd = dul.rowIterator();
00410         for(double x=0.0; x < w; ++x, ++rd)
00411         {
00412             double sx = x*affineMatrix(0,0) + y*affineMatrix(0,1) + affineMatrix(0,2);
00413             double sy = x*affineMatrix(1,0) + y*affineMatrix(1,1) + affineMatrix(1,2);
00414             if(src.isInside(sx, sy))
00415                 dest.set(src(sx, sy), rd);
00416         }
00417     }
00418 }
00419 
00420 template <int ORDER, class T, 
00421           class DestIterator, class DestAccessor,
00422           class C>
00423 inline
00424 void affineWarpImage(SplineImageView<ORDER, T> const & src,
00425                      triple<DestIterator, DestIterator, DestAccessor> dest, 
00426                      MultiArrayView<2, double, C> const & affineMatrix)
00427 {
00428     affineWarpImage(src, dest.first, dest.second, dest.third, affineMatrix);
00429 }
00430 
00431 
00432 //@}
00433 
00434 } // namespace vigra
00435 
00436 
00437 #endif /* VIGRA_AFFINEGEOMETRY_HXX */

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
VIGRA 1.6.0 (13 Aug 2008)