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