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