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

vigra/convolution.hxx VIGRA

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)