[ 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)