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

details vigra/convolution.hxx VIGRA

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.2.0, Aug 07 2003 )                                    */
00008 /*    You may use, modify, and distribute this software according       */
00009 /*    to the terms stated in the LICENSE file included in               */
00010 /*    the VIGRA distribution.                                           */
00011 /*                                                                      */
00012 /*    The VIGRA Website is                                              */
00013 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00014 /*    Please direct questions, bug reports, and contributions to        */
00015 /*        koethe@informatik.uni-hamburg.de                              */
00016 /*                                                                      */
00017 /*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
00018 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
00019 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
00020 /*                                                                      */
00021 /************************************************************************/
00022 
00023 
00024 #ifndef VIGRA_CONVOLUTION_HXX
00025 #define VIGRA_CONVOLUTION_HXX
00026 
00027 #include <functional>
00028 #include "stdconvolution.hxx"
00029 #include "vigra/separableconvolution.hxx"
00030 #include "vigra/recursiveconvolution.hxx"
00031 #include "vigra/nonlineardiffusion.hxx"
00032 #include "vigra/combineimages.hxx"
00033 
00034 /** \page Convolution Functions to Convolve Images and Signals
00035 
00036     1D and 2D filters, including separable and recursive convolution, and non-linear diffusion
00037 
00038     <b>\#include</b> "<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>"<br>
00039     Namespace: vigra
00040 
00041     <DL>
00042     <DT>
00043         <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif">
00044         \ref CommonConvolutionFilters
00045         <DD><em>Short-hands for the most common convolution filters</em>
00046     <DT>
00047         <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif">
00048         \ref BorderTreatmentMode
00049         <DD><em>Choose between different border treatment modes </em>
00050     <DT>
00051         <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif">
00052         \ref StandardConvolution
00053         <DD><em>2D non-separable convolution, with and without ROI mask </em>
00054     <DT>
00055         <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif">
00056         \ref vigra::Kernel2D
00057         <DD><em>Generic 2-dimensional convolution kernel </em>
00058     <DT>
00059         <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif">
00060         \ref SeparableConvolution
00061         <DD> <em>1D convolution and separable filters in 2 dimensions </em>
00062     <DT>
00063         <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif">
00064         \ref vigra::Kernel1D
00065         <DD> <em>Generic 1-dimensional convolution kernel </em>
00066     <DT>
00067         <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif">
00068         \ref RecursiveConvolution
00069         <DD> <em>Recursive implementation of the exponential filter and its derivatives </em>
00070     <DT>
00071         <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif">
00072         \ref NonLinearDiffusion
00073         <DD> <em>Edge-preserving smoothing </em>
00074     <DT>
00075         <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif">
00076         \ref KernelArgumentObjectFactories
00077         <DD> <em>Factory functions to create argument objects to simplify passing kernels</em>
00078     </DL>
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><td>
00101             \htmlonly
00102             <th bgcolor="#f0e0c0" colspan=2 align=left>
00103             \endhtmlonly
00104             <TT>\ref vigra::Kernel1D "vigra::Kernel1D<SomeType>" kernel;</TT>
00105             \htmlonly
00106             </th>
00107             \endhtmlonly
00108         </td></tr>
00109         <tr><td>
00110     <TT>kernel1d(kernel)</TT>
00111         </td><td>
00112         create argument object from information provided by
00113         kernel
00114 
00115         </td></tr>
00116         <tr><td>
00117     <TT>kernel1d(kernel, vigra::BORDER_TREATMENT_CLIP)</TT>
00118         </td><td>
00119         create argument object from information provided by
00120         kernel, but use given border treatment mode
00121 
00122         </td></tr>
00123         <tr><td>
00124     <TT>kernel1d(kerneliterator, kernelaccessor,</TT><br>
00125     <TT>                kernelleft, kernelright,</TT><br>
00126     <TT>                vigra::BORDER_TREATMENT_CLIP)</TT>
00127         </td><td>
00128         create argument object from explicitly given iterator
00129         (pointing to the center of th kernel), accessor,
00130         left and right boundaries, and border treatment mode
00131 
00132     </table>
00133 
00134     For usage examples see
00135     \ref SeparableConvolution "one-dimensional and separable convolution functions".
00136 
00137     \section Kernel2dFactory kernel2d()
00138 
00139     Pass a \ref vigra::Kernel2D to a 2D (non-separable) convolution algorithm.
00140 
00141     These factories can be used to create argument objects when we
00142     are given instances or subclasses of \ref vigra::Kernel2D
00143     (analogous to the \ref ArgumentObjectFactories for images).
00144     These factory functions access <TT>kernel.center()</TT>,
00145         <TT>kernel.upperLeft()</TT>, <TT>kernel.lowerRight()</TT>, <TT>kernel.accessor()</TT>,
00146     and  <TT>kernel.borderTreatment()</TT> to obtain the necessary
00147     information. The following factory functions are provided:
00148 
00149     <table>
00150         <tr><td>
00151             \htmlonly
00152             <th bgcolor="#f0e0c0" colspan=2 align=left>
00153             \endhtmlonly
00154             <TT>\ref vigra::Kernel2D "vigra::Kernel2D<SomeType>" kernel;</TT>
00155             \htmlonly
00156             </th>
00157             \endhtmlonly
00158         </td></tr>
00159         <tr><td>
00160     <TT>kernel2d(kernel)</TT>
00161         </td><td>
00162         create argument object from information provided by
00163         kernel
00164 
00165         </td></tr>
00166         <tr><td>
00167     <TT>kernel2d(kernel, vigra::BORDER_TREATMENT_CLIP)</TT>
00168         </td><td>
00169         create argument object from information provided by
00170         kernel, but use given border treatment mode
00171 
00172         </td></tr>
00173         <tr><td>
00174     <TT>kernel2d(kerneliterator, kernelaccessor,</TT>
00175     <TT>                upperleft, lowerright,</TT>
00176     <TT>                vigra::BORDER_TREATMENT_CLIP)</TT>
00177         </td><td>
00178         create argument object from explicitly given iterator
00179         (pointing to the center of th kernel), accessor,
00180         upper left and lower right corners, and border treatment mode
00181 
00182     </table>
00183 
00184     For usage examples see \ref StandardConvolution "two-dimensional convolution functions".
00185 */
00186 
00187 namespace vigra {
00188 
00189 
00190 
00191 /********************************************************/
00192 /*                                                      */
00193 /*             Common convolution filters               */
00194 /*                                                      */
00195 /********************************************************/
00196 
00197 /** \addtogroup CommonConvolutionFilters Common Filters
00198 
00199     These functions calculate common filters by appropriate sequences of calls 
00200     to \link SeparableConvolution#separableConvolveX separableConvolveX\endlink()
00201     and \link SeparableConvolution#separableConvolveY separableConvolveY\endlink().
00202 */
00203 //@{
00204 
00205 /********************************************************/
00206 /*                                                      */
00207 /*                    convolveImage                     */
00208 /*                                                      */
00209 /********************************************************/
00210 
00211 /** \brief Apply two separable filters successively, the first in x-direction, 
00212            the second in y-direction.
00213 
00214     This function is a shorthand for the concatenation of a call to
00215     \link SeparableConvolution#separableConvolveX separableConvolveX\endlink()
00216     and \link SeparableConvolution#separableConvolveY separableConvolveY\endlink() 
00217     with the given kernels.
00218 
00219     <b> Declarations:</b>
00220 
00221     pass arguments explicitly:
00222     \code
00223     namespace vigra {
00224         template <class SrcIterator, class SrcAccessor,
00225                   class DestIterator, class DestAccessor,
00226                   class T>
00227         void convolveImage(SrcIterator supperleft,
00228                            SrcIterator slowerright, SrcAccessor sa,
00229                            DestIterator dupperleft, DestAccessor da,
00230                            Kernel1D<T> const & kx, Kernel1D<T> const & ky);
00231     }
00232     \endcode
00233 
00234 
00235     use argument objects in conjuction with \ref ArgumentObjectFactories:
00236     \code
00237     namespace vigra {
00238         template <class SrcIterator, class SrcAccessor,
00239                   class DestIterator, class DestAccessor,
00240                   class T>
00241         inline void
00242         convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00243                       pair<DestIterator, DestAccessor> dest,
00244                       Kernel1D<T> const & kx, Kernel1D<T> const & ky);
00245     }
00246     \endcode
00247 
00248     <b> Usage:</b>
00249 
00250     <b>\#include</b> "<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>"
00251 
00252 
00253     \code
00254     vigra::FImage src(w,h), dest(w,h);
00255     ...
00256 
00257     // implement sobel filter in x-direction
00258     Kernel1D<double> kx, ky;
00259     kx.initSymmetricGradient();
00260     ky.initBinomial(1);
00261     
00262     vigra::convolveImage(srcImageRange(src), destImage(dest), kx, ky);
00263 
00264     \endcode
00265 
00266 */
00267 template <class SrcIterator, class SrcAccessor,
00268           class DestIterator, class DestAccessor,
00269           class T>
00270 void convolveImage(SrcIterator supperleft,
00271                    SrcIterator slowerright, SrcAccessor sa,
00272                    DestIterator dupperleft, DestAccessor da,
00273                    Kernel1D<T> const & kx, Kernel1D<T> const & ky)
00274 {
00275     typedef typename
00276         NumericTraits<typename SrcAccessor::value_type>::RealPromote
00277         TmpType;
00278     BasicImage<TmpType> tmp(slowerright - supperleft);
00279 
00280     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
00281                        destImage(tmp), kernel1d(kx));
00282     separableConvolveY(srcImageRange(tmp),
00283                        destIter(dupperleft, da), kernel1d(ky));
00284 }
00285 
00286 template <class SrcIterator, class SrcAccessor,
00287           class DestIterator, class DestAccessor,
00288           class T>
00289 inline void
00290 convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00291               pair<DestIterator, DestAccessor> dest,
00292               Kernel1D<T> const & kx, Kernel1D<T> const & ky)
00293 {
00294     convolveImage(src.first, src.second, src.third,
00295                   dest.first, dest.second, kx, ky);
00296 }
00297 
00298 /********************************************************/
00299 /*                                                      */
00300 /*                    simpleSharpening                  */
00301 /*                                                      */
00302 /********************************************************/
00303 
00304 /** \brief Perform simple sharpening function.
00305 
00306     This function use \link StandardConvolution#convolveImage convolveImage\endlink( ) with following filter:
00307     
00308     \code
00309     -sharpening_factor/16.0,    -sharpening_factor/8.0,    -sharpening_factor/16.0,
00310     -sharpening_factor/8.0,   1.0+sharpening_factor*0.75,  -sharpening_factor/8.0,
00311     -sharpening_factor/16.0,    -sharpening_factor/8.0,    -sharpening_factor/16.0;    
00312     \endcode
00313     
00314     and use <TT>BORDER_TREATMENT_REFLECT</TT> as border treatment mode.
00315 
00316     <b> Preconditions:</b>
00317     \code  
00318     1. sharpening_factor >= 0
00319     2. scale >= 0
00320     \endcode
00321 
00322     <b> Declarations:</b>
00323 
00324     <b> Declarations:</b>
00325 
00326     pass arguments explicitly:
00327     \code
00328     namespace vigra {
00329       template <class SrcIterator, class SrcAccessor,
00330                 class DestIterator, class DestAccessor>
00331       void simpleSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
00332                             DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor)
00333 
00334     }
00335     \endcode
00336 
00337 
00338     use argument objects in conjuction with \ref ArgumentObjectFactories:
00339     \code
00340     namespace vigra {
00341       template <class SrcIterator, class SrcAccessor, 
00342             class DestIterator, class DestAccessor>
00343       inline
00344       void simpleSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00345                         pair<DestIterator, DestAccessor> dest, double sharpening_factor)
00346       {
00347       simpleSharpening(src.first, src.second, src.third,
00348                dest.first, dest.second, sharpening_factor);
00349       }
00350 
00351     }
00352     \endcode
00353 
00354     <b> Usage:</b>
00355 
00356     <b>\#include</b> "<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>"
00357 
00358 
00359     \code
00360     vigra::FImage src(w,h), dest(w,h);
00361     ...
00362 
00363     // sharpening with sharpening_factor = 0.1
00364     vigra::simpleSharpening(srcImageRange(src), destImage(dest), 0.1);
00365 
00366     \endcode
00367 
00368 */    
00369 template <class SrcIterator, class SrcAccessor,
00370       class DestIterator, class DestAccessor>
00371 void simpleSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
00372                     DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor)
00373 {
00374 
00375     vigra_precondition(sharpening_factor >= 0.0,
00376                "simpleSharpening(): amount of sharpening must be >= 0.");
00377 
00378     Kernel2D<double> kernel;
00379 
00380     kernel.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = -sharpening_factor/16.0,    -sharpening_factor/8.0,    -sharpening_factor/16.0,
00381                                                         -sharpening_factor/8.0,   1.0+sharpening_factor*0.75,  -sharpening_factor/8.0,
00382                                                         -sharpening_factor/16.0,    -sharpening_factor/8.0,    -sharpening_factor/16.0;
00383 
00384     convolveImage(src_ul, src_lr, src_acc, dest_ul, dest_acc, 
00385           kernel.center(), kernel.accessor(), 
00386           kernel.upperLeft(), kernel.lowerRight() , BORDER_TREATMENT_REFLECT );
00387 }
00388 
00389 template <class SrcIterator, class SrcAccessor, 
00390       class DestIterator, class DestAccessor>
00391 inline
00392 void simpleSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00393             pair<DestIterator, DestAccessor> dest, double sharpening_factor)
00394 {
00395     simpleSharpening(src.first, src.second, src.third,
00396              dest.first, dest.second, sharpening_factor);
00397 }
00398 
00399 
00400 /********************************************************/
00401 /*                                                      */
00402 /*                    gaussianSharpening                */
00403 /*                                                      */
00404 /********************************************************/
00405 
00406 /** \brief Perform sharpening function with gaussian filter.
00407 
00408 
00409     This function use the 
00410     \link vigra::gaussianSmoothing gaussianSmoothing \endlink()
00411     at first and scale the source image 
00412     (\code src \endcode) with the \code scale \endcode
00413     factor in an temporary image (\code tmp \endcode). At second the new 
00414     pixel in the destination image will be with following
00415     formel calculate:
00416     \code
00417     dest = (1 + sharpening_factor)*src - sharpening_factor*tmp
00418     \endcode
00419 
00420     <b> Preconditions:</b>
00421     \code  
00422     1. sharpening_factor >= 0
00423     2. scale >= 0
00424     \endcode
00425 
00426     <b> Declarations:</b>
00427 
00428     pass arguments explicitly:
00429     \code
00430     namespace vigra {
00431       template <class SrcIterator, class SrcAccessor,
00432             class DestIterator, class DestAccessor>
00433       void gaussianSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
00434                   DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor, 
00435                   double scale)
00436     }
00437     \endcode
00438 
00439 
00440     use argument objects in conjuction with \ref ArgumentObjectFactories:
00441     \code
00442     namespace vigra {
00443       template <class SrcIterator, class SrcAccessor,
00444             class DestIterator, class DestAccessor>
00445       void gaussianSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00446                   pair<DestIterator, DestAccessor> dest, double sharpening_factor, 
00447                   double scale)
00448     }
00449     \endcode
00450 
00451     <b> Usage:</b>
00452 
00453     <b>\#include</b> "<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>"
00454 
00455 
00456     \code
00457     vigra::FImage src(w,h), dest(w,h);
00458     ...
00459 
00460     // sharpening with sharpening_factor = 3.0
00461     // smoothing with scale = 0.5
00462     vigra::gaussianSmoothing(srcImageRange(src), destImage(dest), 3.0, 0.5);
00463 
00464     \endcode
00465 
00466 */    
00467 template <class SrcIterator, class SrcAccessor,
00468       class DestIterator, class DestAccessor>
00469 void gaussianSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
00470             DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor, 
00471             double scale)
00472 {
00473     vigra_precondition(sharpening_factor >= 0.0,
00474                "gaussianSharpening(): amount of sharpening must be >= 0");
00475     vigra_precondition(scale >= 0.0,
00476                "gaussianSharpening(): scale parameter should be >= 0.");
00477 
00478     typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote ValueType;
00479 
00480     BasicImage<ValueType> tmp(src_lr - src_ul);
00481     typename BasicImage<ValueType>::Accessor tmp_acc = tmp.accessor();
00482 
00483     gaussianSmoothing(src_ul, src_lr, src_acc, tmp.upperLeft(), tmp_acc, scale);
00484 
00485     SrcIterator i_src = src_ul;
00486     DestIterator i_dest = dest_ul;
00487     typename BasicImage<ValueType>::traverser tmp_ul = tmp.upperLeft();
00488     typename BasicImage<ValueType>::traverser i_tmp = tmp_ul;
00489 
00490     for(; i_src.y != src_lr.y ; i_src.y++, i_dest.y++, i_tmp.y++ )
00491     {
00492     for (;i_src.x != src_lr.x ; i_src.x++, i_dest.x++, i_tmp.x++ )
00493         {
00494         dest_acc.set((1.0 + sharpening_factor)*src_acc(i_src) - sharpening_factor*tmp_acc(i_tmp), i_dest);
00495     }
00496     i_src.x = src_ul.x;
00497     i_dest.x = dest_ul.x;
00498     i_tmp.x = tmp_ul.x;
00499     }
00500 }
00501 
00502 template <class SrcIterator, class SrcAccessor,
00503       class DestIterator, class DestAccessor>
00504 void gaussianSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00505             pair<DestIterator, DestAccessor> dest, double sharpening_factor, 
00506             double scale)
00507 {
00508     gaussianSharpening(src.first, src.second, src.third,
00509                dest.first, dest.second,
00510                sharpening_factor, scale);
00511 }
00512 
00513 
00514 
00515 /********************************************************/
00516 /*                                                      */
00517 /*                    gaussianSmoothing                 */
00518 /*                                                      */
00519 /********************************************************/
00520 
00521 /** \brief Perform isotropic Gaussian convolution.
00522 
00523     This function is a shorthand for the concatenation of a call to
00524     \link SeparableConvolution#separableConvolveX separableConvolveX\endlink()
00525     and \link SeparableConvolution#separableConvolveY separableConvolveY\endlink() with a
00526     Gaussian kernel of the given scale. The function uses 
00527     <TT>BORDER_TREATMENT_REFLECT</TT>.
00528 
00529     <b> Declarations:</b>
00530 
00531     pass arguments explicitly:
00532     \code
00533     namespace vigra {
00534         template <class SrcIterator, class SrcAccessor,
00535                   class DestIterator, class DestAccessor>
00536         void gaussianSmoothing(SrcIterator supperleft,
00537                                 SrcIterator slowerright, SrcAccessor sa,
00538                                 DestIterator dupperleft, DestAccessor da,
00539                                 double scale);
00540     }
00541     \endcode
00542 
00543 
00544     use argument objects in conjuction with \ref ArgumentObjectFactories:
00545     \code
00546     namespace vigra {
00547         template <class SrcIterator, class SrcAccessor,
00548                   class DestIterator, class DestAccessor>
00549         inline void
00550         gaussianSmoothing(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00551                           pair<DestIterator, DestAccessor> dest,
00552                           double scale);
00553     }
00554     \endcode
00555 
00556     <b> Usage:</b>
00557 
00558     <b>\#include</b> "<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>"
00559 
00560 
00561     \code
00562     vigra::FImage src(w,h), dest(w,h);
00563     ...
00564 
00565     // smooth with scale = 3.0
00566     vigra::gaussianSmoothing(srcImageRange(src), destImage(dest), 3.0);
00567 
00568     \endcode
00569 
00570 */
00571 template <class SrcIterator, class SrcAccessor,
00572           class DestIterator, class DestAccessor>
00573 void gaussianSmoothing(SrcIterator supperleft,
00574                         SrcIterator slowerright, SrcAccessor sa,
00575                         DestIterator dupperleft, DestAccessor da,
00576                         double scale)
00577 {
00578     typedef typename
00579         NumericTraits<typename SrcAccessor::value_type>::RealPromote
00580         TmpType;
00581     BasicImage<TmpType> tmp(slowerright - supperleft);
00582 
00583     Kernel1D<double> smooth;
00584     smooth.initGaussian(scale);
00585     smooth.setBorderTreatment(BORDER_TREATMENT_REFLECT);
00586 
00587     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
00588                        destImage(tmp), kernel1d(smooth));
00589     separableConvolveY(srcImageRange(tmp),
00590                        destIter(dupperleft, da), kernel1d(smooth));
00591 }
00592 
00593 template <class SrcIterator, class SrcAccessor,
00594           class DestIterator, class DestAccessor>
00595 inline void
00596 gaussianSmoothing(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00597                   pair<DestIterator, DestAccessor> dest,
00598                   double scale)
00599 {
00600     gaussianSmoothing(src.first, src.second, src.third,
00601                  dest.first, dest.second, scale);
00602 }
00603 
00604 /********************************************************/
00605 /*                                                      */
00606 /*                     gaussianGradient                 */
00607 /*                                                      */
00608 /********************************************************/
00609 
00610 /** \brief Calculate the gradient vector by means of a 1st derivatives of
00611     Gaussian filter.
00612 
00613     This function is a shorthand for the concatenation of a call to
00614     \link SeparableConvolution#separableConvolveX separableConvolveX\endlink()
00615     and \link SeparableConvolution#separableConvolveY separableConvolveY\endlink() with the
00616     appropriate kernels at the given scale. Note that this function produces
00617     <i>two</i> result images.
00618 
00619     <b> Declarations:</b>
00620 
00621     pass arguments explicitly:
00622     \code
00623     namespace vigra {
00624         template <class SrcIterator, class SrcAccessor,
00625                   class DestIteratorX, class DestAccessorX,
00626                   class DestIteratorY, class DestAccessorY>
00627         void gaussianGradient(SrcIterator supperleft,
00628                                 SrcIterator slowerright, SrcAccessor sa,
00629                                 DestIteratorX dupperleftx, DestAccessorX dax,
00630                                 DestIteratorY dupperlefty, DestAccessorY day,
00631                                 double scale);
00632     }
00633     \endcode
00634 
00635 
00636     use argument objects in conjuction with \ref ArgumentObjectFactories:
00637     \code
00638     namespace vigra {
00639         template <class SrcIterator, class SrcAccessor,
00640                   class DestIteratorX, class DestAccessorX,
00641                   class DestIteratorY, class DestAccessorY>
00642         inline void
00643         gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00644                           pair<DestIteratorX, DestAccessorX> destx,
00645                           pair<DestIteratorY, DestAccessorY> desty,
00646                           double scale);
00647     }
00648     \endcode
00649 
00650     <b> Usage:</b>
00651 
00652     <b>\#include</b> "<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>"
00653 
00654 
00655     \code
00656     vigra::FImage src(w,h), gradx(w,h), grady(w,h);
00657     ...
00658 
00659     // calculate gradient vector at scale = 3.0
00660     vigra::gaussianGradient(srcImageRange(src),
00661                              destImage(gradx), destImage(grady), 3.0);
00662 
00663     \endcode
00664 
00665 */
00666 template <class SrcIterator, class SrcAccessor,
00667           class DestIteratorX, class DestAccessorX,
00668           class DestIteratorY, class DestAccessorY>
00669 void gaussianGradient(SrcIterator supperleft,
00670                         SrcIterator slowerright, SrcAccessor sa,
00671                         DestIteratorX dupperleftx, DestAccessorX dax,
00672                         DestIteratorY dupperlefty, DestAccessorY day,
00673                         double scale)
00674 {
00675     typedef typename
00676         NumericTraits<typename SrcAccessor::value_type>::RealPromote
00677         TmpType;
00678     BasicImage<TmpType> tmp(slowerright - supperleft);
00679 
00680     Kernel1D<double> smooth, grad;
00681     smooth.initGaussian(scale);
00682     grad.initGaussianDerivative(scale, 1);
00683 
00684     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
00685                        destImage(tmp), kernel1d(grad));
00686     separableConvolveY(srcImageRange(tmp),
00687                        destIter(dupperleftx, dax), kernel1d(smooth));
00688     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
00689                        destImage(tmp), kernel1d(smooth));
00690     separableConvolveY(srcImageRange(tmp),
00691                        destIter(dupperlefty, day), kernel1d(grad));
00692 }
00693 
00694 template <class SrcIterator, class SrcAccessor,
00695           class DestIteratorX, class DestAccessorX,
00696           class DestIteratorY, class DestAccessorY>
00697 inline void
00698 gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00699                   pair<DestIteratorX, DestAccessorX> destx,
00700                   pair<DestIteratorY, DestAccessorY> desty,
00701                   double scale)
00702 {
00703     gaussianGradient(src.first, src.second, src.third,
00704                  destx.first, destx.second, desty.first, desty.second, scale);
00705 }
00706 
00707 /********************************************************/
00708 /*                                                      */
00709 /*                 laplacianOfGaussian                  */
00710 /*                                                      */
00711 /********************************************************/
00712 
00713 /** \brief Filter image with the Laplacian of Gaussian operator
00714     at the given scale.
00715 
00716     This function calls \link SeparableConvolution#separableConvolveX separableConvolveX\endlink() and
00717     \link SeparableConvolution#separableConvolveY separableConvolveY\endlink() with the appropriate 2nd derivative
00718     of Gaussian kernels in x- and y-direction and then sums the results
00719     to get the Laplacian.
00720 
00721     <b> Declarations:</b>
00722 
00723     pass arguments explicitly:
00724     \code
00725     namespace vigra {
00726         template <class SrcIterator, class SrcAccessor,
00727                   class DestIterator, class DestAccessor>
00728         void laplacianOfGaussian(SrcIterator supperleft,
00729                                 SrcIterator slowerright, SrcAccessor sa,
00730                                 DestIterator dupperleft, DestAccessor da,
00731                                 double scale);
00732     }
00733     \endcode
00734 
00735 
00736     use argument objects in conjuction with \ref ArgumentObjectFactories:
00737     \code
00738     namespace vigra {
00739         template <class SrcIterator, class SrcAccessor,
00740                   class DestIterator, class DestAccessor>
00741         inline void
00742         laplacianOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00743                           pair<DestIterator, DestAccessor> dest,
00744                           double scale);
00745     }
00746     \endcode
00747 
00748     <b> Usage:</b>
00749 
00750     <b>\#include</b> "<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>"
00751 
00752 
00753     \code
00754     vigra::FImage src(w,h), dest(w,h);
00755     ...
00756 
00757     // calculate Laplacian of Gaussian at scale = 3.0
00758     vigra::laplacianOfGaussian(srcImageRange(src), destImage(dest), 3.0);
00759 
00760     \endcode
00761 
00762 */
00763 template <class SrcIterator, class SrcAccessor,
00764           class DestIterator, class DestAccessor>
00765 void laplacianOfGaussian(SrcIterator supperleft,
00766                         SrcIterator slowerright, SrcAccessor sa,
00767                         DestIterator dupperleft, DestAccessor da,
00768                         double scale)
00769 {
00770     typedef typename
00771         NumericTraits<typename SrcAccessor::value_type>::RealPromote
00772         TmpType;
00773     BasicImage<TmpType> tmp(slowerright - supperleft),
00774                         tmpx(slowerright - supperleft),
00775                         tmpy(slowerright - supperleft);
00776 
00777     Kernel1D<double> smooth, deriv;
00778     smooth.initGaussian(scale);
00779     deriv.initGaussianDerivative(scale, 2);
00780 
00781     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
00782                        destImage(tmp), kernel1d(deriv));
00783     separableConvolveY(srcImageRange(tmp),
00784                        destImage(tmpx), kernel1d(smooth));
00785     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
00786                        destImage(tmp), kernel1d(smooth));
00787     separableConvolveY(srcImageRange(tmp),
00788                        destImage(tmpy), kernel1d(deriv));
00789     combineTwoImages(srcImageRange(tmpx), srcImage(tmpy),
00790                        destIter(dupperleft, da), std::plus<TmpType>());
00791 }
00792 
00793 template <class SrcIterator, class SrcAccessor,
00794           class DestIterator, class DestAccessor>
00795 inline void
00796 laplacianOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00797                   pair<DestIterator, DestAccessor> dest,
00798                   double scale)
00799 {
00800     laplacianOfGaussian(src.first, src.second, src.third,
00801                  dest.first, dest.second, scale);
00802 }
00803 
00804 /********************************************************/
00805 /*                                                      */
00806 /*               hessianMatrixOfGaussian                */
00807 /*                                                      */
00808 /********************************************************/
00809 
00810 /** \brief Filter image with the 2nd derivatives of the Gaussian
00811     at the given scale to get the Hessian matrix.
00812 
00813     The Hessian matrix is a symmetric matrix defined as:
00814 
00815         \f[
00816                 \mbox{\rm Hessian}(I) = \left(
00817                 \begin{array}{cc}
00818                 G_{xx} \ast I & G_{xy} \ast I \\
00819                 G_{xy} \ast I & G_{yy} \ast I
00820                 \end{array} \right)
00821         \f]
00822 
00823     where \f$G_{xx}, G_{xy}, G_{yy}\f$ denote 2nd derivatives of Gaussians
00824     at the given scale, and
00825     \f$\ast\f$ is the convolution symbol. This function calls
00826     \link SeparableConvolution#separableConvolveX separableConvolveX\endlink() and
00827     \link SeparableConvolution#separableConvolveY separableConvolveY\endlink()
00828     with the appropriate 2nd derivative
00829     of Gaussian kernels and puts the results in
00830     the three destination images. The first destination image will
00831     contain the second derivative in x-direction, the second one the mixed
00832     derivative, and the third one holds the derivative in y-direction.
00833 
00834     <b> Declarations:</b>
00835 
00836     pass arguments explicitly:
00837     \code
00838     namespace vigra {
00839         template <class SrcIterator, class SrcAccessor,
00840                   class DestIteratorX, class DestAccessorX,
00841                   class DestIteratorXY, class DestAccessorXY,
00842                   class DestIteratorY, class DestAccessorY>
00843         void hessianMatrixOfGaussian(SrcIterator supperleft,
00844                                 SrcIterator slowerright, SrcAccessor sa,
00845                                 DestIteratorX dupperleftx, DestAccessorX dax,
00846                                 DestIteratorXY dupperleftxy, DestAccessorXY daxy,
00847                                 DestIteratorY dupperlefty, DestAccessorY day,
00848                                 double scale);
00849     }
00850     \endcode
00851 
00852 
00853     use argument objects in conjuction with \ref ArgumentObjectFactories:
00854     \code
00855     namespace vigra {
00856         template <class SrcIterator, class SrcAccessor,
00857                   class DestIteratorX, class DestAccessorX,
00858                   class DestIteratorXY, class DestAccessorXY,
00859                   class DestIteratorY, class DestAccessorY>
00860         inline void
00861         hessianMatrixOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00862                           pair<DestIteratorX, DestAccessorX> destx,
00863                           pair<DestIteratorXY, DestAccessorXY> destxy,
00864                           pair<DestIteratorY, DestAccessorY> desty,
00865                           double scale);
00866     }
00867     \endcode
00868 
00869     <b> Usage:</b>
00870 
00871     <b>\#include</b> "<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>"
00872 
00873 
00874     \code
00875     vigra::FImage src(w,h), hxx(w,h), hxy(w,h), hyy(w,h);
00876     ...
00877 
00878     // calculate Hessian of Gaussian at scale = 3.0
00879     vigra::hessianMatrixOfGaussian(srcImageRange(src),
00880         destImage(hxx), destImage(hxy), destImage(hyy), 3.0);
00881 
00882     \endcode
00883 
00884 */
00885 template <class SrcIterator, class SrcAccessor,
00886           class DestIteratorX, class DestAccessorX,
00887           class DestIteratorXY, class DestAccessorXY,
00888           class DestIteratorY, class DestAccessorY>
00889 void hessianMatrixOfGaussian(SrcIterator supperleft,
00890                         SrcIterator slowerright, SrcAccessor sa,
00891                         DestIteratorX dupperleftx, DestAccessorX dax,
00892                         DestIteratorXY dupperleftxy, DestAccessorXY daxy,
00893                         DestIteratorY dupperlefty, DestAccessorY day,
00894                         double scale)
00895 {
00896     typedef typename
00897         NumericTraits<typename SrcAccessor::value_type>::RealPromote
00898         TmpType;
00899     BasicImage<TmpType> tmp(slowerright - supperleft);
00900 
00901     Kernel1D<double> smooth, deriv1, deriv2;
00902     smooth.initGaussian(scale);
00903     deriv1.initGaussianDerivative(scale, 1);
00904     deriv2.initGaussianDerivative(scale, 2);
00905 
00906     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
00907                        destImage(tmp), kernel1d(deriv2));
00908     separableConvolveY(srcImageRange(tmp),
00909                        destIter(dupperleftx, dax), kernel1d(smooth));
00910     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
00911                        destImage(tmp), kernel1d(smooth));
00912     separableConvolveY(srcImageRange(tmp),
00913                        destIter(dupperlefty, day), kernel1d(deriv2));
00914     separableConvolveX(srcIterRange(supperleft, slowerright, sa),
00915                        destImage(tmp), kernel1d(deriv1));
00916     separableConvolveY(srcImageRange(tmp),
00917                        destIter(dupperleftxy, daxy), kernel1d(deriv1));
00918 }
00919 
00920 template <class SrcIterator, class SrcAccessor,
00921           class DestIteratorX, class DestAccessorX,
00922           class DestIteratorXY, class DestAccessorXY,
00923           class DestIteratorY, class DestAccessorY>
00924 inline void
00925 hessianMatrixOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00926                   pair<DestIteratorX, DestAccessorX> destx,
00927                   pair<DestIteratorXY, DestAccessorXY> destxy,
00928                   pair<DestIteratorY, DestAccessorY> desty,
00929                   double scale)
00930 {
00931     hessianMatrixOfGaussian(src.first, src.second, src.third,
00932                  destx.first, destx.second,
00933                  destxy.first, destxy.second,
00934                  desty.first, desty.second,
00935                  scale);
00936 }
00937 
00938 /********************************************************/
00939 /*                                                      */
00940 /*                   structureTensor                    */
00941 /*                                                      */
00942 /********************************************************/
00943 
00944 /** \brief Calculate the Structure Tensor for each pixel of
00945  and image, using Gaussian (derivative) filters.
00946 
00947     The Structure Tensor is is a smoothed version of the Euclidean product
00948     of the gradient vector with itself. I.e. it's a symmetric matrix defined as:
00949 
00950         \f[
00951                 \mbox{\rm StructurTensor}(I) = \left(
00952                 \begin{array}{cc}
00953                 G \ast (I_x I_x) & G \ast (I_x I_y) \\
00954                 G \ast (I_x I_y) & G \ast (I_y I_y)
00955                 \end{array} \right) = \left(
00956                 \begin{array}{cc}
00957                 A & C \\
00958                 C & B
00959                 \end{array} \right)
00960         \f]
00961 
00962     where \f$G\f$ denotes Gaussian smoothing at the <i>outer scale</i>,
00963     \f$I_x, I_y\f$ are the gradient components taken at the <i>inner scale</i>,
00964     \f$\ast\f$ is the convolution symbol, and \f$I_x I_x\f$ etc. are pixelwise
00965     products of the 1st derivative images. This function calls
00966     \link SeparableConvolution#separableConvolveX separableConvolveX\endlink()
00967     and \link SeparableConvolution#separableConvolveY separableConvolveY\endlink() with the
00968     appropriate Gaussian kernels and puts the results in
00969     the three destination images. The first destination image will
00970     contain \f$G \ast (I_x I_x)\f$, the second one \f$G \ast (I_x I_y)\f$, and the
00971     third one holds \f$G \ast (I_y I_y)\f$.
00972 
00973     <b> Declarations:</b>
00974 
00975     pass arguments explicitly:
00976     \code
00977     namespace vigra {
00978         template <class SrcIterator, class SrcAccessor,
00979                   class DestIteratorX, class DestAccessorX,
00980                   class DestIteratorXY, class DestAccessorXY,
00981                   class DestIteratorY, class DestAccessorY>
00982         void structureTensor(SrcIterator supperleft,
00983                                 SrcIterator slowerright, SrcAccessor sa,
00984                                 DestIteratorX dupperleftx, DestAccessorX dax,
00985                                 DestIteratorXY dupperleftxy, DestAccessorXY daxy,
00986                                 DestIteratorY dupperlefty, DestAccessorY day,
00987                                 double inner_scale, double outer_scale);
00988     }
00989     \endcode
00990 
00991 
00992     use argument objects in conjuction with \ref ArgumentObjectFactories:
00993     \code
00994     namespace vigra {
00995         template <class SrcIterator, class SrcAccessor,
00996                   class DestIteratorX, class DestAccessorX,
00997                   class DestIteratorXY, class DestAccessorXY,
00998                   class DestIteratorY, class DestAccessorY>
00999         inline void
01000         structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src,
01001                           pair<DestIteratorX, DestAccessorX> destx,
01002                           pair<DestIteratorXY, DestAccessorXY> destxy,
01003                           pair<DestIteratorY, DestAccessorY> desty,
01004                           double nner_scale, double outer_scale);
01005     }
01006     \endcode
01007 
01008     <b> Usage:</b>
01009 
01010     <b>\#include</b> "<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>"
01011 
01012 
01013     \code
01014     vigra::FImage src(w,h), stxx(w,h), stxy(w,h), styy(w,h);
01015     ...
01016 
01017     // calculate Structure Tensor at inner scale = 1.0 and outer scale = 3.0
01018     vigra::structureTensor(srcImageRange(src),
01019         destImage(stxx), destImage(stxy), destImage(styy), 1.0, 3.0);
01020 
01021     \endcode
01022 
01023 */
01024 template <class SrcIterator, class SrcAccessor,
01025           class DestIteratorX, class DestAccessorX,
01026           class DestIteratorXY, class DestAccessorXY,
01027           class DestIteratorY, class DestAccessorY>
01028 void structureTensor(SrcIterator supperleft,
01029                         SrcIterator slowerright, SrcAccessor sa,
01030                         DestIteratorX dupperleftx, DestAccessorX dax,
01031                         DestIteratorXY dupperleftxy, DestAccessorXY daxy,
01032                         DestIteratorY dupperlefty, DestAccessorY day,
01033                         double inner_scale, double outer_scale)
01034 {
01035     typedef typename
01036         NumericTraits<typename SrcAccessor::value_type>::RealPromote
01037         TmpType;
01038     BasicImage<TmpType> tmp(slowerright - supperleft),
01039                         tmpx(slowerright - supperleft),
01040                         tmpy(slowerright - supperleft);
01041 
01042     gaussianGradient(srcIterRange(supperleft, slowerright, sa),
01043            destImage(tmpx), destImage(tmpy), inner_scale);
01044     combineTwoImages(srcImageRange(tmpx), srcImage(tmpx),
01045                      destImage(tmp), std::multiplies<TmpType>());
01046     gaussianSmoothing(srcImageRange(tmp),
01047                       destIter(dupperleftx, dax), outer_scale);
01048     combineTwoImages(srcImageRange(tmpy), srcImage(tmpy),
01049                      destImage(tmp), std::multiplies<TmpType>());
01050     gaussianSmoothing(srcImageRange(tmp),
01051                       destIter(dupperlefty, day), outer_scale);
01052     combineTwoImages(srcImageRange(tmpx), srcImage(tmpy),
01053                      destImage(tmp), std::multiplies<TmpType>());
01054     gaussianSmoothing(srcImageRange(tmp),
01055                       destIter(dupperleftxy, daxy), outer_scale);
01056 }
01057 
01058 template <class SrcIterator, class SrcAccessor,
01059           class DestIteratorX, class DestAccessorX,
01060           class DestIteratorXY, class DestAccessorXY,
01061           class DestIteratorY, class DestAccessorY>
01062 inline void
01063 structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src,
01064                   pair<DestIteratorX, DestAccessorX> destx,
01065                   pair<DestIteratorXY, DestAccessorXY> destxy,
01066                   pair<DestIteratorY, DestAccessorY> desty,
01067                   double inner_scale, double outer_scale)
01068 {
01069     structureTensor(src.first, src.second, src.third,
01070                  destx.first, destx.second,
01071                  destxy.first, destxy.second,
01072                  desty.first, desty.second,
01073                  inner_scale, outer_scale);
01074 }
01075 
01076 //@}
01077 
01078 } // namespace vigra
01079 
01080 #endif // VIGRA_CONVOLUTION_HXX

© Ullrich Köthe (koethe@informatik.uni-hamburg.de)
Cognitive Systems Group, University of Hamburg, Germany

html generated using doxygen and Python
VIGRA 1.2.0 (7 Aug 2003)