vigra - vigra/convolution.hxx Source File

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

vigra/convolution.hxx |

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
    00004 /*                                                                      */
    00005 /*    This file is part of the VIGRA computer vision library.           */
    00006 /*    The VIGRA Website is                                              */
    00007 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
    00008 /*    Please direct questions, bug reports, and contributions to        */
    00009 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
    00010 /*        vigra@informatik.uni-hamburg.de                               */
    00011 /*                                                                      */
    00012 /*    Permission is hereby granted, free of charge, to any person       */
    00013 /*    obtaining a copy of this software and associated documentation    */
    00014 /*    files (the "Software"), to deal in the Software without           */
    00015 /*    restriction, including without limitation the rights to use,      */
    00016 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
    00017 /*    sell copies of the Software, and to permit persons to whom the    */
    00018 /*    Software is furnished to do so, subject to the following          */
    00019 /*    conditions:                                                       */
    00020 /*                                                                      */
    00021 /*    The above copyright notice and this permission notice shall be    */
    00022 /*    included in all copies or substantial portions of the             */
    00023 /*    Software.                                                         */
    00024 /*                                                                      */
    00025 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
    00026 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
    00027 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
    00028 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
    00029 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
    00030 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
    00031 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
    00032 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
    00033 /*                                                                      */
    00034 /************************************************************************/
    00035
    00036
    00037 #ifndef VIGRA_CONVOLUTION_HXX
    00038 #define VIGRA_CONVOLUTION_HXX
    00039
    00040 #include <functional>
    00041 #include "stdconvolution.hxx"
    00042 #include "separableconvolution.hxx"
    00043 #include "recursiveconvolution.hxx"
    00044 #include "nonlineardiffusion.hxx"
    00045 #include "combineimages.hxx"
    00046
    00047 /** \page Convolution Functions to Convolve Images and Signals
    00048
    00049     1D and 2D filters, including separable and recursive convolution, and non-linear diffusion
    00050
    00051     <b>\#include</b> <vigra/convolution.hxx><br>
    00052     Namespace: vigra
    00053
    00054     <UL style="list-style-image:url(documents/bullet.gif)">
    00055     <LI> \ref CommonConvolutionFilters
    00056          <BR>&nbsp;&nbsp;&nbsp;<em>Short-hands for the most common 2D convolution filters</em>
    00057     <LI> \ref MultiArrayConvolutionFilters
    00058          <BR>&nbsp;&nbsp;&nbsp;<em>Convolution filters for arbitrary dimensional arrays (MultiArray etc.)</em>
    00059     <LI> \ref ResamplingConvolutionFilters
    00060          <BR>&nbsp;&nbsp;&nbsp;<em>Resampling convolution filters</em>
    00061     <LI> \ref StandardConvolution
    00062          <BR>&nbsp;&nbsp;&nbsp;<em>2D non-separable convolution, with and without ROI mask </em>
    00063     <LI> \ref vigra::Kernel2D
    00064          <BR>&nbsp;&nbsp;&nbsp;<em>Generic 2-dimensional discrete convolution kernel </em>
    00065     <LI> \ref SeparableConvolution
    00066          <BR>&nbsp;&nbsp;&nbsp;<em>1D convolution and separable filters in 2 dimensions </em>
    00067     <LI> \ref vigra::Kernel1D
    00068          <BR>&nbsp;&nbsp;&nbsp;<em>Generic 1-dimensional discrete convolution kernel </em>
    00069     <LI> \ref RecursiveConvolution
    00070          <BR>&nbsp;&nbsp;&nbsp;<em>Recursive filters (1st and 2nd order)</em>
    00071     <LI> \ref NonLinearDiffusion
    00072          <BR>&nbsp;&nbsp;&nbsp;<em>Edge-preserving smoothing </em>
    00073     <LI> \ref BorderTreatmentMode
    00074          <BR>&nbsp;&nbsp;&nbsp;<em>Choose between different border treatment modes </em>
    00075     <LI> \ref KernelArgumentObjectFactories
    00076          <BR>&nbsp;&nbsp;&nbsp;<em>Factory functions to create argument objects to simplify passing kernels</em>
    00077     </UL>
    00078 */
    00079
    00080 /** \page KernelArgumentObjectFactories Kernel Argument Object Factories
    00081
    00082     These factory functions allow to create argument objects for 1D
    00083     and 2D convolution kernel analogously to
    00084     \ref ArgumentObjectFactories for images.
    00085
    00086     \section Kernel1dFactory kernel1d()
    00087
    00088         Pass a \ref vigra::Kernel1D to a 1D or separable convolution algorithm.
    00089
    00090         These factories can be used to create argument objects when we
    00091         are given instances or subclasses of \ref vigra::Kernel1D
    00092         (analogous to the \ref ArgumentObjectFactories for images).
    00093         These factory functions access <TT>kernel.center()</TT>,
    00094         <TT>kernel.left()</TT>, <TT>kernel.right()</TT>, <TT>kernel.accessor()</TT>,
    00095         and  <TT>kernel.borderTreatment()</TT> to obtain the necessary
    00096         information. The following factory functions are provided:
    00097
    00098         <table>
    00099         <tr><th bgcolor="#f0e0c0" colspan=2 align=left>
    00100             <TT>\ref vigra::Kernel1D "vigra::Kernel1D<SomeType>" kernel;</TT>
    00101             </th>
    00102         </tr>
    00103         <tr><td>
    00104         <TT>kernel1d(kernel)</TT>
    00105         </td><td>
    00106             create argument object from information provided by
    00107             kernel
    00108
    00109         </td></tr>
    00110         <tr><td>
    00111         <TT>kernel1d(kernel, vigra::BORDER_TREATMENT_CLIP)</TT>
    00112         </td><td>
    00113             create argument object from information provided by
    00114             kernel, but use given border treatment mode
    00115
    00116         </td></tr>
    00117         <tr><td>
    00118         <TT>kernel1d(kerneliterator, kernelaccessor,</TT><br>
    00119         <TT>                kernelleft, kernelright,</TT><br>
    00120         <TT>                vigra::BORDER_TREATMENT_CLIP)</TT>
    00121         </td><td>
    00122             create argument object from explicitly given iterator
    00123             (pointing to the center of th kernel), accessor,
    00124             left and right boundaries, and border treatment mode
    00125
    00126         </table>
    00127
    00128         For usage examples see
    00129         \ref SeparableConvolution "one-dimensional and separable convolution functions".
    00130
    00131     \section Kernel2dFactory kernel2d()
    00132
    00133         Pass a \ref vigra::Kernel2D to a 2D (non-separable) convolution algorithm.
    00134
    00135         These factories can be used to create argument objects when we
    00136         are given instances or subclasses of \ref vigra::Kernel2D
    00137         (analogous to the \ref ArgumentObjectFactories for images).
    00138         These factory functions access <TT>kernel.center()</TT>,
    00139         <TT>kernel.upperLeft()</TT>, <TT>kernel.lowerRight()</TT>, <TT>kernel.accessor()</TT>,
    00140         and  <TT>kernel.borderTreatment()</TT> to obtain the necessary
    00141         information. The following factory functions are provided:
    00142
    00143         <table>
    00144         <tr><th bgcolor="#f0e0c0" colspan=2 align=left>
    00145             <TT>\ref vigra::Kernel2D "vigra::Kernel2D<SomeType>" kernel;</TT>
    00146             </th>
    00147         </tr>
    00148         <tr><td>
    00149         <TT>kernel2d(kernel)</TT>
    00150         </td><td>
    00151             create argument object from information provided by
    00152             kernel
    00153
    00154         </td></tr>
    00155         <tr><td>
    00156         <TT>kernel2d(kernel, vigra::BORDER_TREATMENT_CLIP)</TT>
    00157         </td><td>
    00158             create argument object from information provided by
    00159             kernel, but use given border treatment mode
    00160
    00161         </td></tr>
    00162         <tr><td>
    00163         <TT>kernel2d(kerneliterator, kernelaccessor,</TT>
    00164         <TT>                upperleft, lowerright,</TT>
    00165         <TT>                vigra::BORDER_TREATMENT_CLIP)</TT>
    00166         </td><td>
    00167             create argument object from explicitly given iterator
    00168             (pointing to the center of th kernel), accessor,
    00169             upper left and lower right corners, and border treatment mode
    00170
    00171         </table>
    00172
    00173         For usage examples see \ref StandardConvolution "two-dimensional convolution functions".
    00174 */
    00175
    00176 namespace vigra {
    00177
    00178
    00179
    00180 /********************************************************/
    00181 /*                                                      */
    00182 /*             Common convolution filters               */
    00183 /*                                                      */
    00184 /********************************************************/
    00185
    00186 /** \addtogroup CommonConvolutionFilters Common Filters
    00187
    00188     These functions calculate common filters by appropriate sequences of calls
    00189     to \ref separableConvolveX() and \ref separableConvolveY().
    00190 */
    00191 //@{
    00192
    00193 /********************************************************/
    00194 /*                                                      */
    00195 /*                    convolveImage                     */
    00196 /*                                                      */
    00197 /********************************************************/
    00198
    00199 /** \brief Apply two separable filters successively, the first in x-direction,
    00200            the second in y-direction.
    00201
    00202     This function is a shorthand for the concatenation of a call to
    00203     \ref separableConvolveX() and \ref separableConvolveY()
    00204     with the given kernels.
    00205
    00206     <b> Declarations:</b>
    00207
    00208     pass arguments explicitly:
    00209     \code
    00210     namespace vigra {
    00211         template <class SrcIterator, class SrcAccessor,
    00212                   class DestIterator, class DestAccessor,
    00213                   class T>
    00214         void convolveImage(SrcIterator supperleft,
    00215                            SrcIterator slowerright, SrcAccessor sa,
    00216                            DestIterator dupperleft, DestAccessor da,
    00217                            Kernel1D<T> const & kx, Kernel1D<T> const & ky);
    00218     }
    00219     \endcode
    00220
    00221
    00222     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00223     \code
    00224     namespace vigra {
    00225         template <class SrcIterator, class SrcAccessor,
    00226                   class DestIterator, class DestAccessor,
    00227                   class T>
    00228         inline void
    00229         convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00230                       pair<DestIterator, DestAccessor> dest,
    00231                       Kernel1D<T> const & kx, Kernel1D<T> const & ky);
    00232     }
    00233     \endcode
    00234
    00235     <b> Usage:</b>
    00236
    00237     <b>\#include</b> <vigra/convolution.hxx>
    00238
    00239
    00240     \code
    00241     vigra::FImage src(w,h), dest(w,h);
    00242     ...
    00243
    00244     // implement sobel filter in x-direction
    00245     Kernel1D<double> kx, ky;
    00246     kx.initSymmetricGradient();
    00247     ky.initBinomial(1);
    00248
    00249     vigra::convolveImage(srcImageRange(src), destImage(dest), kx, ky);
    00250
    00251     \endcode
    00252
    00253 */
    00254 template <class SrcIterator, class SrcAccessor,
    00255           class DestIterator, class DestAccessor,
    00256           class T>
    00257 void convolveImage(SrcIterator supperleft,
    00258                    SrcIterator slowerright, SrcAccessor sa,
    00259                    DestIterator dupperleft, DestAccessor da,
    00260                    Kernel1D<T> const & kx, Kernel1D<T> const & ky)
    00261 {
    00262     typedef typename
    00263         NumericTraits<typename SrcAccessor::value_type>::RealPromote
    00264         TmpType;
    00265     BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
    00266
    00267     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
    00268                        destImage(tmp), kernel1d(kx));
    00269     separableConvolveY(srcImageRange(tmp),
    00270                        destIter(dupperleft, da), kernel1d(ky));
    00271 }
    00272
    00273 template <class SrcIterator, class SrcAccessor,
    00274           class DestIterator, class DestAccessor,
    00275           class T>
    00276 inline void
    00277 convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00278               pair<DestIterator, DestAccessor> dest,
    00279               Kernel1D<T> const & kx, Kernel1D<T> const & ky)
    00280 {
    00281     convolveImage(src.first, src.second, src.third,
    00282                   dest.first, dest.second, kx, ky);
    00283 }
    00284
    00285 /********************************************************/
    00286 /*                                                      */
    00287 /*                    simpleSharpening                  */
    00288 /*                                                      */
    00289 /********************************************************/
    00290
    00291 /** \brief Perform simple sharpening function.
    00292
    00293     This function uses \ref convolveImage() with the following filter:
    00294
    00295     \code
    00296     -sharpening_factor/16.0,    -sharpening_factor/8.0,    -sharpening_factor/16.0,
    00297     -sharpening_factor/8.0,   1.0+sharpening_factor*0.75,  -sharpening_factor/8.0,
    00298     -sharpening_factor/16.0,    -sharpening_factor/8.0,    -sharpening_factor/16.0;
    00299     \endcode
    00300
    00301     and uses <TT>BORDER_TREATMENT_REFLECT</TT> as border treatment mode.
    00302
    00303     <b> Preconditions:</b>
    00304     \code
    00305     1. sharpening_factor >= 0
    00306     2. scale >= 0
    00307     \endcode
    00308
    00309     <b> Declarations:</b>
    00310
    00311     <b> Declarations:</b>
    00312
    00313     pass arguments explicitly:
    00314     \code
    00315     namespace vigra {
    00316       template <class SrcIterator, class SrcAccessor,
    00317                 class DestIterator, class DestAccessor>
    00318       void simpleSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
    00319                             DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor)
    00320
    00321     }
    00322     \endcode
    00323
    00324
    00325     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00326     \code
    00327     namespace vigra {
    00328       template <class SrcIterator, class SrcAccessor,
    00329                 class DestIterator, class DestAccessor>
    00330       inline
    00331       void simpleSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00332                                     pair<DestIterator, DestAccessor> dest, double sharpening_factor)
    00333       {
    00334           simpleSharpening(src.first, src.second, src.third,
    00335                              dest.first, dest.second, sharpening_factor);
    00336       }
    00337
    00338     }
    00339     \endcode
    00340
    00341     <b> Usage:</b>
    00342
    00343     <b>\#include</b> <vigra/convolution.hxx>
    00344
    00345
    00346     \code
    00347     vigra::FImage src(w,h), dest(w,h);
    00348     ...
    00349
    00350     // sharpening with sharpening_factor = 0.1
    00351     vigra::simpleSharpening(srcImageRange(src), destImage(dest), 0.1);
    00352
    00353     \endcode
    00354
    00355 */
    00356 doxygen_overloaded_function(template <...> void simpleSharpening)
    00357
    00358 template <class SrcIterator, class SrcAccessor,
    00359           class DestIterator, class DestAccessor>
    00360 void simpleSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
    00361                     DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor)
    00362 {
    00363
    00364     vigra_precondition(sharpening_factor >= 0.0,
    00365                        "simpleSharpening(): amount of sharpening must be >= 0.");
    00366
    00367     Kernel2D<double> kernel;
    00368
    00369     kernel.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = -sharpening_factor/16.0,    -sharpening_factor/8.0,    -sharpening_factor/16.0,
    00370                                                         -sharpening_factor/8.0,   1.0+sharpening_factor*0.75,  -sharpening_factor/8.0,
    00371                                                         -sharpening_factor/16.0,    -sharpening_factor/8.0,    -sharpening_factor/16.0;
    00372
    00373     convolveImage(src_ul, src_lr, src_acc, dest_ul, dest_acc,
    00374                   kernel.center(), kernel.accessor(),
    00375                   kernel.upperLeft(), kernel.lowerRight() , BORDER_TREATMENT_REFLECT );
    00376 }
    00377
    00378 template <class SrcIterator, class SrcAccessor,
    00379           class DestIterator, class DestAccessor>
    00380 inline
    00381 void simpleSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00382                     pair<DestIterator, DestAccessor> dest, double sharpening_factor)
    00383 {
    00384     simpleSharpening(src.first, src.second, src.third,
    00385                      dest.first, dest.second, sharpening_factor);
    00386 }
    00387
    00388
    00389 /********************************************************/
    00390 /*                                                      */
    00391 /*                    gaussianSharpening                */
    00392 /*                                                      */
    00393 /********************************************************/
    00394
    00395 /** \brief Perform sharpening function with gaussian filter.
    00396
    00397
    00398     This function uses \ref gaussianSmoothing() at the given scale to create a
    00399     temporary image 'smooth' and than blends the original and smoothed image
    00400     according to the formula
    00401
    00402     \code
    00403     dest = (1 + sharpening_factor)*src - sharpening_factor*smooth
    00404     \endcode
    00405
    00406     <b> Preconditions:</b>
    00407     \code
    00408     1. sharpening_factor >= 0
    00409     2. scale >= 0
    00410     \endcode
    00411
    00412     <b> Declarations:</b>
    00413
    00414     pass arguments explicitly:
    00415     \code
    00416     namespace vigra {
    00417       template <class SrcIterator, class SrcAccessor,
    00418                 class DestIterator, class DestAccessor>
    00419       void gaussianSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
    00420                               DestIterator dest_ul, DestAccessor dest_acc,
    00421                               double sharpening_factor, double scale)
    00422     }
    00423     \endcode
    00424
    00425
    00426     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00427     \code
    00428     namespace vigra {
    00429       template <class SrcIterator, class SrcAccessor,
    00430                 class DestIterator, class DestAccessor>
    00431       void gaussianSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00432                                pair<DestIterator, DestAccessor> dest,
    00433                                double sharpening_factor, double scale)
    00434     }
    00435     \endcode
    00436
    00437     <b> Usage:</b>
    00438
    00439     <b>\#include</b> <vigra/convolution.hxx>
    00440
    00441
    00442     \code
    00443     vigra::FImage src(w,h), dest(w,h);
    00444     ...
    00445
    00446     // sharpening with sharpening_factor = 3.0
    00447     // smoothing with scale = 0.5
    00448     vigra::gaussianSmoothing(srcImageRange(src), destImage(dest), 3.0, 0.5);
    00449
    00450     \endcode
    00451
    00452 */
    00453 doxygen_overloaded_function(template <...> void gaussianSharpening)
    00454
    00455 template <class SrcIterator, class SrcAccessor,
    00456           class DestIterator, class DestAccessor>
    00457 void gaussianSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
    00458                         DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor,
    00459                         double scale)
    00460 {
    00461     vigra_precondition(sharpening_factor >= 0.0,
    00462                        "gaussianSharpening(): amount of sharpening must be >= 0");
    00463     vigra_precondition(scale >= 0.0,
    00464                        "gaussianSharpening(): scale parameter should be >= 0.");
    00465
    00466     typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote ValueType;
    00467
    00468     BasicImage<ValueType> tmp(src_lr - src_ul, SkipInitialization);
    00469
    00470     gaussianSmoothing(src_ul, src_lr, src_acc, tmp.upperLeft(), tmp.accessor(), scale);
    00471
    00472     SrcIterator i_src = src_ul;
    00473     DestIterator i_dest = dest_ul;
    00474     typename BasicImage<ValueType>::traverser tmp_ul = tmp.upperLeft();
    00475     typename BasicImage<ValueType>::traverser i_tmp = tmp_ul;
    00476     typename BasicImage<ValueType>::Accessor tmp_acc = tmp.accessor();
    00477
    00478     for(; i_src.y != src_lr.y ; i_src.y++, i_dest.y++, i_tmp.y++ )
    00479     {
    00480         for (;i_src.x != src_lr.x ; i_src.x++, i_dest.x++, i_tmp.x++ )
    00481         {
    00482             dest_acc.set((1.0 + sharpening_factor)*src_acc(i_src) - sharpening_factor*tmp_acc(i_tmp), i_dest);
    00483         }
    00484         i_src.x = src_ul.x;
    00485         i_dest.x = dest_ul.x;
    00486         i_tmp.x = tmp_ul.x;
    00487     }
    00488 }
    00489
    00490 template <class SrcIterator, class SrcAccessor,
    00491           class DestIterator, class DestAccessor>
    00492 void gaussianSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00493                         pair<DestIterator, DestAccessor> dest, double sharpening_factor,
    00494                         double scale)
    00495 {
    00496     gaussianSharpening(src.first, src.second, src.third,
    00497                        dest.first, dest.second,
    00498                        sharpening_factor, scale);
    00499 }
    00500
    00501
    00502
    00503 /********************************************************/
    00504 /*                                                      */
    00505 /*                    gaussianSmoothing                 */
    00506 /*                                                      */
    00507 /********************************************************/
    00508
    00509 /** \brief Perform isotropic Gaussian convolution.
    00510
    00511     This function is a shorthand for the concatenation of a call to
    00512     \ref separableConvolveX() and \ref separableConvolveY() with a
    00513     Gaussian kernel of the given scale. If two scales are provided,
    00514     smoothing in x and y direction will have different strength.
    00515     The function uses <TT>BORDER_TREATMENT_REFLECT</TT>.
    00516
    00517     <b> Declarations:</b>
    00518
    00519     pass arguments explicitly:
    00520     \code
    00521     namespace vigra {
    00522         template <class SrcIterator, class SrcAccessor,
    00523                   class DestIterator, class DestAccessor>
    00524         void gaussianSmoothing(SrcIterator supperleft,
    00525                                 SrcIterator slowerright, SrcAccessor sa,
    00526                                 DestIterator dupperleft, DestAccessor da,
    00527                                 double scale_x, double scale_y = scale_x);
    00528     }
    00529     \endcode
    00530
    00531
    00532     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00533     \code
    00534     namespace vigra {
    00535         template <class SrcIterator, class SrcAccessor,
    00536                   class DestIterator, class DestAccessor>
    00537         inline void
    00538         gaussianSmoothing(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00539                           pair<DestIterator, DestAccessor> dest,
    00540                           double scale_x, double scale_y = scale_x);
    00541     }
    00542     \endcode
    00543
    00544     <b> Usage:</b>
    00545
    00546     <b>\#include</b> <vigra/convolution.hxx>
    00547
    00548
    00549     \code
    00550     vigra::FImage src(w,h), dest(w,h);
    00551     ...
    00552
    00553     // smooth with scale = 3.0
    00554     vigra::gaussianSmoothing(srcImageRange(src), destImage(dest), 3.0);
    00555
    00556     \endcode
    00557
    00558 */
    00559 doxygen_overloaded_function(template <...> void gaussianSmoothing)
    00560
    00561 template <class SrcIterator, class SrcAccessor,
    00562           class DestIterator, class DestAccessor>
    00563 void
    00564 gaussianSmoothing(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor sa,
    00565                   DestIterator dupperleft, DestAccessor da,
    00566                   double scale_x, double scale_y)
    00567 {
    00568     typedef typename
    00569         NumericTraits<typename SrcAccessor::value_type>::RealPromote
    00570         TmpType;
    00571     BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
    00572
    00573     Kernel1D<double> smooth_x, smooth_y;
    00574     smooth_x.initGaussian(scale_x);
    00575     smooth_x.setBorderTreatment(BORDER_TREATMENT_REFLECT);
    00576     smooth_y.initGaussian(scale_y);
    00577     smooth_y.setBorderTreatment(BORDER_TREATMENT_REFLECT);
    00578
    00579     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
    00580                        destImage(tmp), kernel1d(smooth_x));
    00581     separableConvolveY(srcImageRange(tmp),
    00582                        destIter(dupperleft, da), kernel1d(smooth_y));
    00583 }
    00584
    00585 template <class SrcIterator, class SrcAccessor,
    00586           class DestIterator, class DestAccessor>
    00587 inline void
    00588 gaussianSmoothing(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor sa,
    00589                   DestIterator dupperleft, DestAccessor da,
    00590                   double scale)
    00591 {
    00592     gaussianSmoothing(supperleft, slowerright, sa,
    00593                       dupperleft, da,
    00594                       scale, scale);
    00595 }
    00596
    00597 template <class SrcIterator, class SrcAccessor,
    00598           class DestIterator, class DestAccessor>
    00599 inline void
    00600 gaussianSmoothing(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00601                   pair<DestIterator, DestAccessor> dest,
    00602                   double scale_x, double scale_y)
    00603 {
    00604     gaussianSmoothing(src.first, src.second, src.third,
    00605                  dest.first, dest.second, scale_x, scale_y);
    00606 }
    00607
    00608 template <class SrcIterator, class SrcAccessor,
    00609           class DestIterator, class DestAccessor>
    00610 inline void
    00611 gaussianSmoothing(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00612                   pair<DestIterator, DestAccessor> dest,
    00613                   double scale)
    00614 {
    00615     gaussianSmoothing(src.first, src.second, src.third,
    00616                       dest.first, dest.second, scale, scale);
    00617 }
    00618
    00619 /********************************************************/
    00620 /*                                                      */
    00621 /*                     gaussianGradient                 */
    00622 /*                                                      */
    00623 /********************************************************/
    00624
    00625 /** \brief Calculate the gradient vector by means of a 1st derivatives of
    00626     Gaussian filter.
    00627
    00628     This function is a shorthand for the concatenation of a call to
    00629     \ref separableConvolveX() and \ref separableConvolveY() with the
    00630     appropriate kernels at the given scale. Note that this function can either produce
    00631     two separate result images for the x- and y-components of the gradient, or write
    00632     into a vector valued image (with at least two components).
    00633
    00634     <b> Declarations:</b>
    00635
    00636     pass arguments explicitly:
    00637     \code
    00638     namespace vigra {
    00639         // write x and y component of the gradient into separate images
    00640         template <class SrcIterator, class SrcAccessor,
    00641                   class DestIteratorX, class DestAccessorX,
    00642                   class DestIteratorY, class DestAccessorY>
    00643         void gaussianGradient(SrcIterator supperleft,
    00644                               SrcIterator slowerright, SrcAccessor sa,
    00645                               DestIteratorX dupperleftx, DestAccessorX dax,
    00646                               DestIteratorY dupperlefty, DestAccessorY day,
    00647                               double scale);
    00648
    00649         // write x and y component of the gradient into a vector-valued image
    00650         template <class SrcIterator, class SrcAccessor,
    00651                  class DestIterator, class DestAccessor>
    00652         void gaussianGradient(SrcIterator supperleft,
    00653                               SrcIterator slowerright, SrcAccessor src,
    00654                               DestIterator dupperleft, DestAccessor dest,
    00655                               double scale);
    00656     }
    00657     \endcode
    00658
    00659
    00660     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00661     \code
    00662     namespace vigra {
    00663         // write x and y component of the gradient into separate images
    00664         template <class SrcIterator, class SrcAccessor,
    00665                   class DestIteratorX, class DestAccessorX,
    00666                   class DestIteratorY, class DestAccessorY>
    00667         void
    00668         gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00669                          pair<DestIteratorX, DestAccessorX> destx,
    00670                          pair<DestIteratorY, DestAccessorY> desty,
    00671                          double scale);
    00672
    00673         // write x and y component of the gradient into a vector-valued image
    00674         template <class SrcIterator, class SrcAccessor,
    00675                  class DestIterator, class DestAccessor>
    00676         void
    00677         gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00678                          pair<DestIterator, DestAccessor> dest,
    00679                          double scale);
    00680     }
    00681     \endcode
    00682
    00683     <b> Usage:</b>
    00684
    00685     <b>\#include</b> <vigra/convolution.hxx>
    00686
    00687
    00688     \code
    00689     vigra::FImage src(w,h), gradx(w,h), grady(w,h);
    00690     ...
    00691
    00692     // calculate gradient vector at scale = 3.0
    00693     vigra::gaussianGradient(srcImageRange(src),
    00694                              destImage(gradx), destImage(grady), 3.0);
    00695
    00696     \endcode
    00697
    00698 */
    00699 doxygen_overloaded_function(template <...> void gaussianGradient)
    00700
    00701 template <class SrcIterator, class SrcAccessor,
    00702           class DestIteratorX, class DestAccessorX,
    00703           class DestIteratorY, class DestAccessorY>
    00704 void gaussianGradient(SrcIterator supperleft,
    00705                         SrcIterator slowerright, SrcAccessor sa,
    00706                         DestIteratorX dupperleftx, DestAccessorX dax,
    00707                         DestIteratorY dupperlefty, DestAccessorY day,
    00708                         double scale)
    00709 {
    00710     typedef typename
    00711         NumericTraits<typename SrcAccessor::value_type>::RealPromote
    00712         TmpType;
    00713     BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
    00714
    00715     Kernel1D<double> smooth, grad;
    00716     smooth.initGaussian(scale);
    00717     grad.initGaussianDerivative(scale, 1);
    00718
    00719     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
    00720                        destImage(tmp), kernel1d(grad));
    00721     separableConvolveY(srcImageRange(tmp),
    00722                        destIter(dupperleftx, dax), kernel1d(smooth));
    00723     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
    00724                        destImage(tmp), kernel1d(smooth));
    00725     separableConvolveY(srcImageRange(tmp),
    00726                        destIter(dupperlefty, day), kernel1d(grad));
    00727 }
    00728
    00729 template <class SrcIterator, class SrcAccessor,
    00730           class DestIterator, class DestAccessor>
    00731 void gaussianGradient(SrcIterator supperleft,
    00732                         SrcIterator slowerright, SrcAccessor src,
    00733                         DestIterator dupperleft, DestAccessor dest,
    00734                         double scale)
    00735 {
    00736     VectorElementAccessor<DestAccessor> gradx(0, dest), grady(1, dest);
    00737     gaussianGradient(supperleft, slowerright, src,
    00738                      dupperleft, gradx, dupperleft, grady, scale);
    00739 }
    00740
    00741 template <class SrcIterator, class SrcAccessor,
    00742           class DestIteratorX, class DestAccessorX,
    00743           class DestIteratorY, class DestAccessorY>
    00744 inline void
    00745 gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00746                  pair<DestIteratorX, DestAccessorX> destx,
    00747                  pair<DestIteratorY, DestAccessorY> desty,
    00748                  double scale)
    00749 {
    00750     gaussianGradient(src.first, src.second, src.third,
    00751                  destx.first, destx.second, desty.first, desty.second, scale);
    00752 }
    00753
    00754 template <class SrcIterator, class SrcAccessor,
    00755           class DestIterator, class DestAccessor>
    00756 inline void
    00757 gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00758                  pair<DestIterator, DestAccessor> dest,
    00759                  double scale)
    00760 {
    00761     gaussianGradient(src.first, src.second, src.third,
    00762                      dest.first, dest.second, scale);
    00763 }
    00764
    00765 /** \brief Calculate the gradient magnitude by means of a 1st derivatives of
    00766     Gaussian filter.
    00767
    00768     This function calls gaussianGradient() and returns the pixel-wise magnitude of
    00769     the resulting gradient vectors. If the original image has multiple bands,
    00770     the squared gradient magnitude is computed for each band separately, and the
    00771     return value is the square root of the sum of these squared magnitudes.
    00772
    00773     <b> Declarations:</b>
    00774
    00775     pass arguments explicitly:
    00776     \code
    00777     namespace vigra {
    00778         template <class SrcIterator, class SrcAccessor,
    00779                   class DestIterator, class DestAccessor>
    00780         void gaussianGradientMagnitude(SrcIterator sul,
    00781                                        SrcIterator slr, SrcAccessor src,
    00782                                        DestIterator dupperleft, DestAccessor dest,
    00783                                        double scale);
    00784     }
    00785     \endcode
    00786
    00787
    00788     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00789     \code
    00790     namespace vigra {
    00791         template <class SrcIterator, class SrcAccessor,
    00792                   class DestIterator, class DestAccessor>
    00793         void
    00794         gaussianGradientMagnitude(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00795                                   pair<DestIterator, DestAccessor> dest,
    00796                                   double scale);
    00797     }
    00798     \endcode
    00799
    00800     <b> Usage:</b>
    00801
    00802     <b>\#include</b> <vigra/convolution.hxx>
    00803
    00804
    00805     \code
    00806     vigra::FImage src(w,h), grad(w,h);
    00807     ...
    00808
    00809     // calculate gradient magnitude at scale = 3.0
    00810     vigra::gaussianGradientMagnitude(srcImageRange(src), destImage(grad), 3.0);
    00811
    00812     \endcode
    00813
    00814 */
    00815 doxygen_overloaded_function(template <...> void gaussianGradientMagnitude)
    00816
    00817 template <class SrcIterator, class SrcAccessor,
    00818           class DestIterator, class DestAccessor>
    00819 void gaussianGradientMagnitude(SrcIterator sul,
    00820                                SrcIterator slr, SrcAccessor src,
    00821                                DestIterator dupperleft, DestAccessor dest,
    00822                                double scale)
    00823 {
    00824     typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
    00825     BasicImage<TmpType> gradx(slr-sul, SkipInitialization), grady(slr-sul, SkipInitialization);
    00826
    00827     gaussianGradient(srcIterRange(sul, slr, src),
    00828                      destImage(gradx), destImage(grady), scale);
    00829     combineTwoImages(srcImageRange(gradx), srcImage(grady), destIter(dupperleft, dest),
    00830                      MagnitudeFunctor<TmpType>());
    00831 }
    00832
    00833 template <class SrcIterator, class SrcAccessor,
    00834           class DestIterator, class DestAccessor>
    00835 inline void
    00836 gaussianGradientMagnitude(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00837                           pair<DestIterator, DestAccessor> dest,
    00838                           double scale)
    00839 {
    00840     gaussianGradientMagnitude(src.first, src.second, src.third,
    00841                               dest.first, dest.second, scale);
    00842 }
    00843
    00844 /********************************************************/
    00845 /*                                                      */
    00846 /*                 laplacianOfGaussian                  */
    00847 /*                                                      */
    00848 /********************************************************/
    00849
    00850 /** \brief Filter image with the Laplacian of Gaussian operator
    00851     at the given scale.
    00852
    00853     This function calls \ref separableConvolveX() and \ref separableConvolveY() with the appropriate 2nd derivative
    00854     of Gaussian kernels in x- and y-direction and then sums the results
    00855     to get the Laplacian.
    00856
    00857     <b> Declarations:</b>
    00858
    00859     pass arguments explicitly:
    00860     \code
    00861     namespace vigra {
    00862         template <class SrcIterator, class SrcAccessor,
    00863                   class DestIterator, class DestAccessor>
    00864         void laplacianOfGaussian(SrcIterator supperleft,
    00865                                 SrcIterator slowerright, SrcAccessor sa,
    00866                                 DestIterator dupperleft, DestAccessor da,
    00867                                 double scale);
    00868     }
    00869     \endcode
    00870
    00871
    00872     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00873     \code
    00874     namespace vigra {
    00875         template <class SrcIterator, class SrcAccessor,
    00876                   class DestIterator, class DestAccessor>
    00877         inline void
    00878         laplacianOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00879                           pair<DestIterator, DestAccessor> dest,
    00880                           double scale);
    00881     }
    00882     \endcode
    00883
    00884     <b> Usage:</b>
    00885
    00886     <b>\#include</b> <vigra/convolution.hxx>
    00887
    00888
    00889     \code
    00890     vigra::FImage src(w,h), dest(w,h);
    00891     ...
    00892
    00893     // calculate Laplacian of Gaussian at scale = 3.0
    00894     vigra::laplacianOfGaussian(srcImageRange(src), destImage(dest), 3.0);
    00895
    00896     \endcode
    00897
    00898 */
    00899 doxygen_overloaded_function(template <...> void laplacianOfGaussian)
    00900
    00901 template <class SrcIterator, class SrcAccessor,
    00902           class DestIterator, class DestAccessor>
    00903 void laplacianOfGaussian(SrcIterator supperleft,
    00904                         SrcIterator slowerright, SrcAccessor sa,
    00905                         DestIterator dupperleft, DestAccessor da,
    00906                         double scale)
    00907 {
    00908     typedef typename
    00909         NumericTraits<typename SrcAccessor::value_type>::RealPromote
    00910         TmpType;
    00911     BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization),
    00912                         tmpx(slowerright - supperleft, SkipInitialization),
    00913                         tmpy(slowerright - supperleft, SkipInitialization);
    00914
    00915     Kernel1D<double> smooth, deriv;
    00916     smooth.initGaussian(scale);
    00917     deriv.initGaussianDerivative(scale, 2);
    00918
    00919     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
    00920                        destImage(tmp), kernel1d(deriv));
    00921     separableConvolveY(srcImageRange(tmp),
    00922                        destImage(tmpx), kernel1d(smooth));
    00923     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
    00924                        destImage(tmp), kernel1d(smooth));
    00925     separableConvolveY(srcImageRange(tmp),
    00926                        destImage(tmpy), kernel1d(deriv));
    00927     combineTwoImages(srcImageRange(tmpx), srcImage(tmpy),
    00928                        destIter(dupperleft, da), std::plus<TmpType>());
    00929 }
    00930
    00931 template <class SrcIterator, class SrcAccessor,
    00932           class DestIterator, class DestAccessor>
    00933 inline void
    00934 laplacianOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00935                   pair<DestIterator, DestAccessor> dest,
    00936                   double scale)
    00937 {
    00938     laplacianOfGaussian(src.first, src.second, src.third,
    00939                  dest.first, dest.second, scale);
    00940 }
    00941
    00942 /********************************************************/
    00943 /*                                                      */
    00944 /*               hessianMatrixOfGaussian                */
    00945 /*                                                      */
    00946 /********************************************************/
    00947
    00948 /** \brief Filter image with the 2nd derivatives of the Gaussian
    00949     at the given scale to get the Hessian matrix.
    00950
    00951     The Hessian matrix is a symmetric matrix defined as:
    00952
    00953     \f[
    00954         \mbox{\rm Hessian}(I) = \left(
    00955         \begin{array}{cc}
    00956         G_{xx} \ast I & G_{xy} \ast I \\
    00957         G_{xy} \ast I & G_{yy} \ast I
    00958         \end{array} \right)
    00959     \f]
    00960
    00961     where \f$G_{xx}, G_{xy}, G_{yy}\f$ denote 2nd derivatives of Gaussians
    00962     at the given scale, and
    00963     \f$\ast\f$ is the convolution symbol. This function calls
    00964     \ref separableConvolveX() and \ref separableConvolveY()
    00965     with the appropriate 2nd derivative
    00966     of Gaussian kernels and puts the results in
    00967     the three destination images. The first destination image will
    00968     contain the second derivative in x-direction, the second one the mixed
    00969     derivative, and the third one holds the derivative in y-direction.
    00970
    00971     <b> Declarations:</b>
    00972
    00973     pass arguments explicitly:
    00974     \code
    00975     namespace vigra {
    00976         template <class SrcIterator, class SrcAccessor,
    00977                   class DestIteratorX, class DestAccessorX,
    00978                   class DestIteratorXY, class DestAccessorXY,
    00979                   class DestIteratorY, class DestAccessorY>
    00980         void hessianMatrixOfGaussian(SrcIterator supperleft,
    00981                                 SrcIterator slowerright, SrcAccessor sa,
    00982                                 DestIteratorX dupperleftx, DestAccessorX dax,
    00983                                 DestIteratorXY dupperleftxy, DestAccessorXY daxy,
    00984                                 DestIteratorY dupperlefty, DestAccessorY day,
    00985                                 double scale);
    00986     }
    00987     \endcode
    00988
    00989
    00990     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00991     \code
    00992     namespace vigra {
    00993         template <class SrcIterator, class SrcAccessor,
    00994                   class DestIteratorX, class DestAccessorX,
    00995                   class DestIteratorXY, class DestAccessorXY,
    00996                   class DestIteratorY, class DestAccessorY>
    00997         inline void
    00998         hessianMatrixOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00999                           pair<DestIteratorX, DestAccessorX> destx,
    01000                           pair<DestIteratorXY, DestAccessorXY> destxy,
    01001                           pair<DestIteratorY, DestAccessorY> desty,
    01002                           double scale);
    01003     }
    01004     \endcode
    01005
    01006     <b> Usage:</b>
    01007
    01008     <b>\#include</b> <vigra/convolution.hxx>
    01009
    01010
    01011     \code
    01012     vigra::FImage src(w,h), hxx(w,h), hxy(w,h), hyy(w,h);
    01013     ...
    01014
    01015     // calculate Hessian of Gaussian at scale = 3.0
    01016     vigra::hessianMatrixOfGaussian(srcImageRange(src),
    01017         destImage(hxx), destImage(hxy), destImage(hyy), 3.0);
    01018
    01019     \endcode
    01020
    01021 */
    01022 doxygen_overloaded_function(template <...> void hessianMatrixOfGaussian)
    01023
    01024 template <class SrcIterator, class SrcAccessor,
    01025           class DestIteratorX, class DestAccessorX,
    01026           class DestIteratorXY, class DestAccessorXY,
    01027           class DestIteratorY, class DestAccessorY>
    01028 void hessianMatrixOfGaussian(SrcIterator supperleft,
    01029                         SrcIterator slowerright, SrcAccessor sa,
    01030                         DestIteratorX dupperleftx, DestAccessorX dax,
    01031                         DestIteratorXY dupperleftxy, DestAccessorXY daxy,
    01032                         DestIteratorY dupperlefty, DestAccessorY day,
    01033                         double scale)
    01034 {
    01035     typedef typename
    01036         NumericTraits<typename SrcAccessor::value_type>::RealPromote
    01037         TmpType;
    01038     BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
    01039
    01040     Kernel1D<double> smooth, deriv1, deriv2;
    01041     smooth.initGaussian(scale);
    01042     deriv1.initGaussianDerivative(scale, 1);
    01043     deriv2.initGaussianDerivative(scale, 2);
    01044
    01045     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
    01046                        destImage(tmp), kernel1d(deriv2));
    01047     separableConvolveY(srcImageRange(tmp),
    01048                        destIter(dupperleftx, dax), kernel1d(smooth));
    01049     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
    01050                        destImage(tmp), kernel1d(smooth));
    01051     separableConvolveY(srcImageRange(tmp),
    01052                        destIter(dupperlefty, day), kernel1d(deriv2));
    01053     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
    01054                        destImage(tmp), kernel1d(deriv1));
    01055     separableConvolveY(srcImageRange(tmp),
    01056                        destIter(dupperleftxy, daxy), kernel1d(deriv1));
    01057 }
    01058
    01059 template <class SrcIterator, class SrcAccessor,
    01060           class DestIteratorX, class DestAccessorX,
    01061           class DestIteratorXY, class DestAccessorXY,
    01062           class DestIteratorY, class DestAccessorY>
    01063 inline void
    01064 hessianMatrixOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01065                   pair<DestIteratorX, DestAccessorX> destx,
    01066                   pair<DestIteratorXY, DestAccessorXY> destxy,
    01067                   pair<DestIteratorY, DestAccessorY> desty,
    01068                   double scale)
    01069 {
    01070     hessianMatrixOfGaussian(src.first, src.second, src.third,
    01071                  destx.first, destx.second,
    01072                  destxy.first, destxy.second,
    01073                  desty.first, desty.second,
    01074                  scale);
    01075 }
    01076
    01077 /********************************************************/
    01078 /*                                                      */
    01079 /*                   structureTensor                    */
    01080 /*                                                      */
    01081 /********************************************************/
    01082
    01083 /** \brief Calculate the Structure Tensor for each pixel of
    01084  and image, using Gaussian (derivative) filters.
    01085
    01086     The Structure Tensor is is a smoothed version of the Euclidean product
    01087     of the gradient vector with itself. I.e. it's a symmetric matrix defined as:
    01088
    01089     \f[
    01090         \mbox{\rm StructurTensor}(I) = \left(
    01091         \begin{array}{cc}
    01092         G \ast (I_x I_x) & G \ast (I_x I_y) \\
    01093         G \ast (I_x I_y) & G \ast (I_y I_y)
    01094         \end{array} \right) = \left(
    01095         \begin{array}{cc}
    01096         A & C \\
    01097         C & B
    01098         \end{array} \right)
    01099     \f]
    01100
    01101     where \f$G\f$ denotes Gaussian smoothing at the <i>outer scale</i>,
    01102     \f$I_x, I_y\f$ are the gradient components taken at the <i>inner scale</i>,
    01103     \f$\ast\f$ is the convolution symbol, and \f$I_x I_x\f$ etc. are pixelwise
    01104     products of the 1st derivative images. This function calls
    01105     \ref separableConvolveX() and \ref separableConvolveY() with the
    01106     appropriate Gaussian kernels and puts the results in
    01107     the three separate destination images (where the first one will
    01108     contain \f$G \ast (I_x I_x)\f$, the second one \f$G \ast (I_x I_y)\f$, and the
    01109     third one holds \f$G \ast (I_y I_y)\f$), or into a single 3-band image (where the bands
    01110     hold the result in the same order as above). The latter form is also applicable when
    01111     the source image is a multi-band image (e.g. RGB). In this case, tensors are
    01112     first computed for each band separately, and then summed up to get a single result tensor.
    01113
    01114     <b> Declarations:</b>
    01115
    01116     pass arguments explicitly:
    01117     \code
    01118     namespace vigra {
    01119         // create three separate destination images
    01120         template <class SrcIterator, class SrcAccessor,
    01121                   class DestIteratorX, class DestAccessorX,
    01122                   class DestIteratorXY, class DestAccessorXY,
    01123                   class DestIteratorY, class DestAccessorY>
    01124         void structureTensor(SrcIterator supperleft,
    01125                                 SrcIterator slowerright, SrcAccessor sa,
    01126                                 DestIteratorX dupperleftx, DestAccessorX dax,
    01127                                 DestIteratorXY dupperleftxy, DestAccessorXY daxy,
    01128                                 DestIteratorY dupperlefty, DestAccessorY day,
    01129                                 double inner_scale, double outer_scale);
    01130
    01131         // create a single 3-band destination image
    01132         template <class SrcIterator, class SrcAccessor,
    01133                   class DestIterator, class DestAccessor>
    01134         void structureTensor(SrcIterator supperleft,
    01135                                 SrcIterator slowerright, SrcAccessor sa,
    01136                                 DestIterator dupperleft, DestAccessor da,
    01137                                 double inner_scale, double outer_scale);
    01138     }
    01139     \endcode
    01140
    01141
    01142     use argument objects in conjunction with \ref ArgumentObjectFactories :
    01143     \code
    01144     namespace vigra {
    01145         // create three separate destination images
    01146         template <class SrcIterator, class SrcAccessor,
    01147                   class DestIteratorX, class DestAccessorX,
    01148                   class DestIteratorXY, class DestAccessorXY,
    01149                   class DestIteratorY, class DestAccessorY>
    01150         void
    01151         structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01152                           pair<DestIteratorX, DestAccessorX> destx,
    01153                           pair<DestIteratorXY, DestAccessorXY> destxy,
    01154                           pair<DestIteratorY, DestAccessorY> desty,
    01155                           double nner_scale, double outer_scale);
    01156
    01157         // create a single 3-band destination image
    01158         template <class SrcIterator, class SrcAccessor,
    01159                   class DestIterator, class DestAccessor>
    01160         void
    01161         structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01162                           pair<DestIterator, DestAccessor> dest,
    01163                           double nner_scale, double outer_scale);
    01164     }
    01165     \endcode
    01166
    01167     <b> Usage:</b>
    01168
    01169     <b>\#include</b> <vigra/convolution.hxx>
    01170
    01171
    01172     \code
    01173     vigra::FImage src(w,h), stxx(w,h), stxy(w,h), styy(w,h);
    01174     vigra::BasicImage<TinyVector<float, 3> > st(w,h);
    01175     ...
    01176
    01177     // calculate Structure Tensor at inner scale = 1.0 and outer scale = 3.0
    01178     vigra::structureTensor(srcImageRange(src),
    01179         destImage(stxx), destImage(stxy), destImage(styy), 1.0, 3.0);
    01180
    01181     // dto. with a single 3-band destination image
    01182     vigra::structureTensor(srcImageRange(src), destImage(st), 1.0, 3.0);
    01183
    01184     \endcode
    01185
    01186 */
    01187 doxygen_overloaded_function(template <...> void structureTensor)
    01188
    01189 template <class SrcIterator, class SrcAccessor,
    01190           class DestIteratorX, class DestAccessorX,
    01191           class DestIteratorXY, class DestAccessorXY,
    01192           class DestIteratorY, class DestAccessorY>
    01193 void structureTensor(SrcIterator supperleft,
    01194                         SrcIterator slowerright, SrcAccessor sa,
    01195                         DestIteratorX dupperleftx, DestAccessorX dax,
    01196                         DestIteratorXY dupperleftxy, DestAccessorXY daxy,
    01197                         DestIteratorY dupperlefty, DestAccessorY day,
    01198                         double inner_scale, double outer_scale)
    01199 {
    01200     typedef typename
    01201         NumericTraits<typename SrcAccessor::value_type>::RealPromote
    01202         TmpType;
    01203     BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization),
    01204                         tmpx(slowerright - supperleft, SkipInitialization),
    01205                         tmpy(slowerright - supperleft, SkipInitialization);
    01206
    01207     gaussianGradient(srcIterRange(supperleft, slowerright, sa),
    01208            destImage(tmpx), destImage(tmpy), inner_scale);
    01209     combineTwoImages(srcImageRange(tmpx), srcImage(tmpx),
    01210                      destImage(tmp), std::multiplies<TmpType>());
    01211     gaussianSmoothing(srcImageRange(tmp),
    01212                       destIter(dupperleftx, dax), outer_scale);
    01213     combineTwoImages(srcImageRange(tmpy), srcImage(tmpy),
    01214                      destImage(tmp), std::multiplies<TmpType>());
    01215     gaussianSmoothing(srcImageRange(tmp),
    01216                       destIter(dupperlefty, day), outer_scale);
    01217     combineTwoImages(srcImageRange(tmpx), srcImage(tmpy),
    01218                      destImage(tmp), std::multiplies<TmpType>());
    01219     gaussianSmoothing(srcImageRange(tmp),
    01220                       destIter(dupperleftxy, daxy), outer_scale);
    01221 }
    01222
    01223 template <class SrcIterator, class SrcAccessor,
    01224           class DestIteratorX, class DestAccessorX,
    01225           class DestIteratorXY, class DestAccessorXY,
    01226           class DestIteratorY, class DestAccessorY>
    01227 inline void
    01228 structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01229                   pair<DestIteratorX, DestAccessorX> destx,
    01230                   pair<DestIteratorXY, DestAccessorXY> destxy,
    01231                   pair<DestIteratorY, DestAccessorY> desty,
    01232                   double inner_scale, double outer_scale)
    01233 {
    01234     structureTensor(src.first, src.second, src.third,
    01235                  destx.first, destx.second,
    01236                  destxy.first, destxy.second,
    01237                  desty.first, desty.second,
    01238                  inner_scale, outer_scale);
    01239 }
    01240
    01241 namespace detail {
    01242
    01243 template <class SrcIterator, class SrcAccessor,
    01244           class DestIterator, class DestAccessor>
    01245 void structureTensor(SrcIterator supperleft,
    01246                      SrcIterator slowerright, SrcAccessor src,
    01247                      DestIterator dupperleft, DestAccessor dest,
    01248                      double inner_scale, double outer_scale,
    01249                      VigraTrueType /* isScalar */)
    01250 {
    01251     typedef VectorElementAccessor<DestAccessor> DA;
    01252     structureTensor(supperleft, slowerright, src,
    01253                     dupperleft, DA(0, dest),
    01254                     dupperleft, DA(1, dest),
    01255                     dupperleft, DA(2, dest),
    01256                     inner_scale, outer_scale);
    01257 }
    01258
    01259 template <class SrcIterator, class SrcAccessor,
    01260           class DestIterator, class DestAccessor>
    01261 void structureTensor(SrcIterator supperleft,
    01262                      SrcIterator slowerright, SrcAccessor src,
    01263                      DestIterator dupperleft, DestAccessor dest,
    01264                      double inner_scale, double outer_scale,
    01265                      VigraFalseType /* isScalar */)
    01266 {
    01267     int bands = src.size(supperleft);
    01268     typedef VectorElementAccessor<SrcAccessor> SA;
    01269
    01270     structureTensor(supperleft, slowerright, SA(0, src),
    01271                     dupperleft, dest,
    01272                     inner_scale, outer_scale,
    01273                     VigraTrueType() /* isScalar */);
    01274
    01275     BasicImage<typename DestAccessor::value_type> st(slowerright - supperleft, SkipInitialization);
    01276     for(int k=1; k < bands; ++k)
    01277     {
    01278         structureTensor(supperleft, slowerright, SA(k, src),
    01279                         st.upperLeft(), st.accessor(),
    01280                         inner_scale, outer_scale,
    01281                         VigraTrueType() /* isScalar */);
    01282         combineTwoImages(srcImageRange(st), srcIter(dupperleft, dest), destIter(dupperleft, dest),
    01283                          std::plus<typename DestAccessor::value_type>());
    01284     }
    01285 }
    01286
    01287 } // namespace detail
    01288
    01289 template <class SrcIterator, class SrcAccessor,
    01290           class DestIterator, class DestAccessor>
    01291 void structureTensor(SrcIterator supperleft,
    01292                         SrcIterator slowerright, SrcAccessor src,
    01293                         DestIterator dupperleft, DestAccessor dest,
    01294                         double inner_scale, double outer_scale)
    01295 {
    01296     typedef typename
    01297         NumericTraits<typename SrcAccessor::value_type>::isScalar isScalar;
    01298     detail::structureTensor(supperleft, slowerright, src,
    01299                             dupperleft, dest, inner_scale, outer_scale, isScalar());
    01300 }
    01301
    01302 template <class SrcIterator, class SrcAccessor,
    01303           class DestIterator, class DestAccessor>
    01304 inline void
    01305 structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01306                   pair<DestIterator, DestAccessor> dest,
    01307                   double inner_scale, double outer_scale)
    01308 {
    01309     structureTensor(src.first, src.second, src.third,
    01310                     dest.first, dest.second,
    01311                     inner_scale, outer_scale);
    01312 }
    01313
    01314 //@}
    01315
    01316 } // namespace vigra
    01317
    01318 #endif // VIGRA_CONVOLUTION_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.9.0 (Tue Nov 6 2012)