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