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