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