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