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

details vigra/multi_convolution.hxx VIGRA

00001 //-- -*- c++ -*-
00002 /************************************************************************/
00003 /*                                                                      */
00004 /*               Copyright 2003 by Christian-Dennis Rahn                */
00005 /*                        and Ullrich Koethe                            */
00006 /*       Cognitive Systems Group, University of Hamburg, Germany        */
00007 /*                                                                      */
00008 /*    This file is part of the VIGRA computer vision library.           */
00009 /*    ( Version 1.3.2, Jan 27 2005 )                                    */
00010 /*    You may use, modify, and distribute this software according       */
00011 /*    to the terms stated in the LICENSE file included in               */
00012 /*    the VIGRA distribution.                                           */
00013 /*                                                                      */
00014 /*    The VIGRA Website is                                              */
00015 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00016 /*    Please direct questions, bug reports, and contributions to        */
00017 /*        koethe@informatik.uni-hamburg.de                              */
00018 /*                                                                      */
00019 /*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
00020 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
00022 /*                                                                      */
00023 /************************************************************************/
00024 
00025 #ifndef VIGRA_MULTI_CONVOLUTION_H
00026 #define VIGRA_MULTI_CONVOLUTION_H
00027 
00028 #include <vigra/separableconvolution.hxx>
00029 #include <vigra/array_vector.hxx>
00030 #include <vigra/multi_array.hxx>
00031 #include <vigra/accessor.hxx>
00032 #include <vigra/numerictraits.hxx>
00033 #include <vigra/navigator.hxx>
00034 #include <vigra/metaprogramming.hxx>
00035 #include <vigra/multi_pointoperators.hxx>
00036 
00037 
00038 namespace vigra
00039 {
00040 
00041 
00042 namespace detail
00043 {
00044 
00045 /********************************************************/
00046 /*                                                      */
00047 /*        internalSeparableConvolveMultiArray           */
00048 /*                                                      */
00049 /********************************************************/
00050 
00051 template <class SrcIterator, class SrcShape, class SrcAccessor,
00052           class DestIterator, class DestAccessor, class KernelIterator>
00053 void
00054 internalSeparableConvolveMultiArrayTmp(
00055                       SrcIterator si, SrcShape const & shape, SrcAccessor src,
00056                       DestIterator di, DestAccessor dest, KernelIterator kit)
00057 {
00058     enum { N = 1 + SrcIterator::level };
00059 
00060     typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType;
00061 
00062     // temporay array to hold the current line to enable in-place operation
00063     ArrayVector<TmpType> tmp( shape[0] );
00064 
00065     typedef MultiArrayNavigator<SrcIterator, N> SNavigator;
00066     typedef MultiArrayNavigator<DestIterator, N> DNavigator;
00067 
00068     { // only operate on first dimension here
00069         SNavigator snav( si, shape, 0 );
00070         DNavigator dnav( di, shape, 0 );
00071 
00072         for( ; snav.hasMore(); snav++, dnav++ )
00073         {
00074              // first copy source to temp for maximum cache efficiency
00075              copyLine( snav.begin(), snav.end(), src,
00076                        tmp.begin(), typename AccessorTraits<TmpType>::default_accessor() );
00077 
00078              convolveLine( srcIterRange(tmp.begin(), tmp.end(),
00079                                         typename AccessorTraits<TmpType>::default_const_accessor()),
00080                            destIter( dnav.begin(), dest ),
00081                            kernel1d( *kit ) );
00082         }
00083         ++kit;
00084     }
00085 
00086     // operate on further dimensions
00087     for( int d = 1; d < N; ++d, ++kit )
00088     {
00089         DNavigator dnav( di, shape, d );
00090 
00091         tmp.resize( shape[d] );
00092 
00093         for( ; dnav.hasMore(); dnav++ )
00094         {
00095              // first copy source to temp for maximum cache efficiency
00096              copyLine( dnav.begin(), dnav.end(), dest,
00097                        tmp.begin(), typename AccessorTraits<TmpType>::default_accessor() );
00098 
00099              convolveLine( srcIterRange(tmp.begin(), tmp.end(),
00100                                         typename AccessorTraits<TmpType>::default_const_accessor()),
00101                            destIter( dnav.begin(), dest ),
00102                            kernel1d( *kit ) );
00103         }
00104     }
00105 }
00106 
00107 
00108 } // namespace detail
00109 
00110 /** \addtogroup MultiArrayConvolutionFilters Convolution filters for multi-dimensional arrays.
00111 
00112     These functions realize a separable convolution on an arbitrary dimensional
00113     array that is specified by iterators (compatible to \ref MultiIteratorPage)
00114     and shape objects. It can therefore be applied to a wide range of data structures
00115     (\ref vigra::MultiArrayView, \ref vigra::MultiArray etc.).
00116 */
00117 //@{
00118 
00119 /********************************************************/
00120 /*                                                      */
00121 /*             separableConvolveMultiArray              */
00122 /*                                                      */
00123 /********************************************************/
00124 
00125 /** \brief Separated convolution on multi-dimensional arrays.
00126 
00127     This function computes a separated convolution on all dimensions
00128     of the given multi-dimensional array. Both source and destination
00129     arrays are represented by iterators, shape objects and accessors.
00130     The destination array is required to already have the correct size.
00131 
00132     There are two variants of this functions: one takes a single kernel
00133     of type \ref vigra::Kernel1D which is then applied to all dimensions,
00134     whereas the other requires an iterator referencing a sequence of
00135     \ref vigra::Kernel1D objects, one for every dimension of the data.
00136     Then the first kernel in this sequence is applied to the innermost
00137     dimension (e.g. the x-dimension of an image), while the last is applied to the
00138     outermost dimension (e.g. the z-dimension in a 3D image).
00139 
00140     This function may work in-place, which means that <tt>siter == diter</tt> is allowed.
00141     A full-sized internal array is only allocated if working on the destination
00142     array directly would cause round-off errors (i.e. if
00143     <tt>typeid(typename NumericTraits<typename DestAccessor::value_type>::RealPromote)
00144     != typeid(typename DestAccessor::value_type)</tt>.
00145 
00146     <b> Declarations:</b>
00147 
00148     pass arguments explicitly:
00149     \code
00150     namespace vigra {
00151         // apply the same kernel to all dimensions
00152         template <class SrcIterator, class SrcShape, class SrcAccessor,
00153                   class DestIterator, class DestAccessor, class T>
00154         void
00155         separableConvolveMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
00156                                     DestIterator diter, DestAccessor dest,
00157                                     Kernel1D<T> const & kernel);
00158 
00159         // apply each kernel from the sequence `kernels“ in turn
00160         template <class SrcIterator, class SrcShape, class SrcAccessor,
00161                   class DestIterator, class DestAccessor, class KernelIterator>
00162         void
00163         separableConvolveMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
00164                                     DestIterator diter, DestAccessor dest,
00165                                     KernelIterator kernels);
00166     }
00167     \endcode
00168 
00169     use argument objects in conjunction with \ref ArgumentObjectFactories:
00170     \code
00171     namespace vigra {
00172         // apply the same kernel to all dimensions
00173         template <class SrcIterator, class SrcShape, class SrcAccessor,
00174                   class DestIterator, class DestAccessor, class T>
00175         void
00176         separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
00177                                     pair<DestIterator, DestAccessor> const & dest,
00178                                     Kernel1D<T> const & kernel);
00179 
00180         // apply each kernel from the sequence `kernels“ in turn
00181         template <class SrcIterator, class SrcShape, class SrcAccessor,
00182                   class DestIterator, class DestAccessor, class KernelIterator>
00183         void
00184         separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
00185                                     pair<DestIterator, DestAccessor> const & dest,
00186                                     KernelIterator kernels);
00187     }
00188     \endcode
00189 
00190     <b> Usage:</b>
00191 
00192     <b>\#include</b> "<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>"
00193 
00194     \code
00195     MultiArray<3, unsigned char>::size_type shape(width, height, depth);
00196     MultiArray<3, unsigned char> source(shape);
00197     MultiArray<3, float> dest(shape);
00198     ...
00199     Kernel1D<float> gauss;
00200     gauss.initGaussian(sigma);
00201 
00202     // perform Gaussian smoothing on all dimensions
00203     separableConvolveMultiArray(srcMultiArrayRange(source), destMultiArray(dest), gauss);
00204     \endcode
00205 
00206     \see vigra::Kernel1D, convolveLine()
00207 */
00208 template <class SrcIterator, class SrcShape, class SrcAccessor,
00209           class DestIterator, class DestAccessor, class KernelIterator>
00210 void
00211 separableConvolveMultiArray( SrcIterator s, SrcShape const & shape, SrcAccessor src,
00212                              DestIterator d, DestAccessor dest, KernelIterator kernels )
00213 {
00214     typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType;
00215 
00216     if(!IsSameType<TmpType, typename DestAccessor::value_type>::boolResult)
00217     {
00218         // need a temporary array to avoid rounding errors
00219         MultiArray<SrcShape::static_size, TmpType> tmpArray(shape);
00220         detail::internalSeparableConvolveMultiArrayTmp( s, shape, src,
00221              tmpArray.traverser_begin(), typename AccessorTraits<TmpType>::default_accessor(), kernels );
00222         copyMultiArray(srcMultiArrayRange(tmpArray), destIter(d, dest));
00223     }
00224     else
00225     {
00226         // work directly on the destination array
00227         detail::internalSeparableConvolveMultiArrayTmp( s, shape, src, d, dest, kernels );
00228     }
00229 }
00230 
00231 template <class SrcIterator, class SrcShape, class SrcAccessor,
00232           class DestIterator, class DestAccessor, class KernelIterator>
00233 inline
00234 void separableConvolveMultiArray(
00235     triple<SrcIterator, SrcShape, SrcAccessor> const & source,
00236     pair<DestIterator, DestAccessor> const & dest, KernelIterator kit )
00237 {
00238     separableConvolveMultiArray( source.first, source.second, source.third,
00239                                  dest.first, dest.second, kit );
00240 }
00241 
00242 template <class SrcIterator, class SrcShape, class SrcAccessor,
00243           class DestIterator, class DestAccessor, class T>
00244 inline void
00245 separableConvolveMultiArray( SrcIterator s, SrcShape const & shape, SrcAccessor src,
00246                              DestIterator d, DestAccessor dest,
00247                              Kernel1D<T> const & kernel )
00248 {
00249     ArrayVector<Kernel1D<T> > kernels(shape.size(), kernel);
00250 
00251     separableConvolveMultiArray( s, shape, src, d, dest, kernels.begin() );
00252 }
00253 
00254 template <class SrcIterator, class SrcShape, class SrcAccessor,
00255           class DestIterator, class DestAccessor, class T>
00256 inline void
00257 separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
00258                             pair<DestIterator, DestAccessor> const & dest,
00259                             Kernel1D<T> const & kernel )
00260 {
00261     ArrayVector<Kernel1D<T> > kernels(source.second.size(), kernel);
00262 
00263     separableConvolveMultiArray( source.first, source.second, source.third,
00264                                  dest.first, dest.second, kernels.begin() );
00265 }
00266 
00267 /********************************************************/
00268 /*                                                      */
00269 /*            convolveMultiArrayOneDimension            */
00270 /*                                                      */
00271 /********************************************************/
00272 
00273 /** \brief Convolution along a single dimension of a multi-dimensional arrays.
00274 
00275     This function computes a convolution along one dimension (specified by
00276     the parameter <tt>dim</tt> of the given multi-dimensional array with the given
00277     <tt>kernel</tt>. Both source and destination arrays are represented by
00278     iterators, shape objects and accessors. The destination array is required to
00279     already have the correct size.
00280 
00281     This function may work in-place, which means that <tt>siter == diter</tt> is allowed.
00282 
00283     <b> Declarations:</b>
00284 
00285     pass arguments explicitly:
00286     \code
00287     namespace vigra {
00288         template <class SrcIterator, class SrcShape, class SrcAccessor,
00289                   class DestIterator, class DestAccessor, class T>
00290         void
00291         convolveMultiArrayOneDimension(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
00292                                        DestIterator diter, DestAccessor dest,
00293                                        unsigned int dim, vigra::Kernel1D<T> const & kernel);
00294     }
00295     \endcode
00296 
00297     use argument objects in conjunction with \ref ArgumentObjectFactories:
00298     \code
00299     namespace vigra {
00300         template <class SrcIterator, class SrcShape, class SrcAccessor,
00301                   class DestIterator, class DestAccessor, class T>
00302         void
00303         convolveMultiArrayOneDimension(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
00304                                        pair<DestIterator, DestAccessor> const & dest,
00305                                        unsigned int dim, vigra::Kernel1D<T> const & kernel);
00306     }
00307     \endcode
00308 
00309     <b> Usage:</b>
00310 
00311     <b>\#include</b> "<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>"
00312 
00313     \code
00314     MultiArray<3, unsigned char>::size_type shape(width, height, depth);
00315     MultiArray<3, unsigned char> source(shape);
00316     MultiArray<3, float> dest(shape);
00317     ...
00318     Kernel1D<float> gauss;
00319     gauss.initGaussian(sigma);
00320 
00321     // perform Gaussian smoothing along dimensions 1 (height)
00322     convolveMultiArrayOneDimension(srcMultiArrayRange(source), destMultiArray(dest), 1, gauss);
00323     \endcode
00324 
00325     \see separableConvolveMultiArray()
00326 */
00327 template <class SrcIterator, class SrcShape, class SrcAccessor,
00328           class DestIterator, class DestAccessor, class T>
00329 void
00330 convolveMultiArrayOneDimension(SrcIterator s, SrcShape const & shape, SrcAccessor src,
00331                                DestIterator d, DestAccessor dest,
00332                                unsigned int dim, vigra::Kernel1D<T> const & kernel )
00333 {
00334     enum { N = 1 + SrcIterator::level };
00335     vigra_precondition( dim < N,
00336                         "convolveMultiArrayOneDimension(): The dimension number to convolve must be smaller "
00337                         "than the data dimensionality" );
00338 
00339     typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType;
00340     ArrayVector<TmpType> tmp( shape[dim] );
00341 
00342     typedef MultiArrayNavigator<SrcIterator, N> SNavigator;
00343     typedef MultiArrayNavigator<DestIterator, N> DNavigator;
00344 
00345     SNavigator snav( s, shape, dim );
00346     DNavigator dnav( d, shape, dim );
00347 
00348     for( ; snav.hasMore(); snav++, dnav++ )
00349     {
00350          // first copy source to temp for maximum cache efficiency
00351          copyLine( snav.begin(), snav.end(), src,
00352            tmp.begin(), typename AccessorTraits<TmpType>::default_accessor() );
00353 
00354          convolveLine( srcIterRange( tmp.begin(), tmp.end(), typename AccessorTraits<TmpType>::default_const_accessor()),
00355                        destIter( dnav.begin(), dest ),
00356                        kernel1d( kernel ) );
00357     }
00358 }
00359 
00360 template <class SrcIterator, class SrcShape, class SrcAccessor,
00361           class DestIterator, class DestAccessor, class T>
00362 inline void
00363 convolveMultiArrayOneDimension(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
00364                                pair<DestIterator, DestAccessor> const & dest,
00365                                unsigned int dim, vigra::Kernel1D<T> const & kernel )
00366 {
00367     convolveMultiArrayOneDimension( source.first, source.second, source.third,
00368                                    dest.first, dest.second, dim, kernel );
00369 }
00370 
00371 /********************************************************/
00372 /*                                                      */
00373 /*             gaussianSmoothMultiArray                 */
00374 /*                                                      */
00375 /********************************************************/
00376 
00377 /** \brief Isotropic Gaussian smoothing of a multi-dimensional arrays.
00378 
00379     This function computes an isotropic convolution of the given multi-dimensional
00380     array with a Gaussian filter at the given standard deviation <tt>sigma</tt>.
00381     Both source and destination arrays are represented by
00382     iterators, shape objects and accessors. The destination array is required to
00383     already have the correct size. This function may work in-place, which means
00384     that <tt>siter == diter</tt> is allowed. It is implemented by a call to
00385     \ref separableConvolveMultiArray() with the appropriate kernel.
00386     If the data are anisotropic (different pixel size along different dimensions)
00387     you should call \ref separableConvolveMultiArray() directly with the appropriate
00388     anisotropic Gaussians.
00389 
00390     <b> Declarations:</b>
00391 
00392     pass arguments explicitly:
00393     \code
00394     namespace vigra {
00395         template <class SrcIterator, class SrcShape, class SrcAccessor,
00396                   class DestIterator, class DestAccessor>
00397         void
00398         gaussianSmoothMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
00399                                  DestIterator diter, DestAccessor dest,
00400                                  double sigma);
00401     }
00402     \endcode
00403 
00404     use argument objects in conjunction with \ref ArgumentObjectFactories:
00405     \code
00406     namespace vigra {
00407         template <class SrcIterator, class SrcShape, class SrcAccessor,
00408                   class DestIterator, class DestAccessor>
00409         void
00410         gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
00411                                  pair<DestIterator, DestAccessor> const & dest,
00412                                  double sigma);
00413     }
00414     \endcode
00415 
00416     <b> Usage:</b>
00417 
00418     <b>\#include</b> "<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>"
00419 
00420     \code
00421     MultiArray<3, unsigned char>::size_type shape(width, height, depth);
00422     MultiArray<3, unsigned char> source(shape);
00423     MultiArray<3, float> dest(shape);
00424     ...
00425     // perform isotropic Gaussian smoothing at scale `sigma“
00426     gaussianSmoothMultiArray(srcMultiArrayRange(source), destMultiArray(dest), sigma);
00427     \endcode
00428 
00429     \see separableConvolveMultiArray()
00430 */
00431 template <class SrcIterator, class SrcShape, class SrcAccessor,
00432           class DestIterator, class DestAccessor>
00433 void
00434 gaussianSmoothMultiArray( SrcIterator s, SrcShape const & shape, SrcAccessor src,
00435                    DestIterator d, DestAccessor dest, double sigma )
00436 {
00437     typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote kernel_type;
00438     Kernel1D<kernel_type> gauss;
00439     gauss.initGaussian( sigma );
00440 
00441     separableConvolveMultiArray( s, shape, src, d, dest, gauss);
00442 }
00443 
00444 template <class SrcIterator, class SrcShape, class SrcAccessor,
00445           class DestIterator, class DestAccessor>
00446 inline void
00447 gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
00448                   pair<DestIterator, DestAccessor> const & dest,
00449                   double sigma )
00450 {
00451     gaussianSmoothMultiArray( source.first, source.second, source.third,
00452                               dest.first, dest.second, sigma );
00453 }
00454 
00455 /********************************************************/
00456 /*                                                      */
00457 /*             gaussianGradientMultiArray               */
00458 /*                                                      */
00459 /********************************************************/
00460 
00461 /** \brief Calculate Gaussian gradient of a multi-dimensional arrays.
00462 
00463     This function computes the Gaussian gradient of the given multi-dimensional
00464     array with a sequence of first-derivative-of-Gaussian filters at the given
00465     standard deviation <tt>sigma</tt> (differentiation is applied to each dimension
00466     in turn, starting with the innermost dimension). Both source and destination arrays
00467     are represented by iterators, shape objects and accessors. The destination array is
00468     required to have a vector valued pixel type with as many elements as the number of
00469     dimensions. This function is implemented by calls to
00470     \ref separableConvolveMultiArray() with the appropriate kernels.
00471     If the data are anisotropic (different pixel size along different dimensions)
00472     you should call \ref separableConvolveMultiArray() directly with the appropriate
00473     anisotropic Gaussian derivatives.
00474 
00475     <b> Declarations:</b>
00476 
00477     pass arguments explicitly:
00478     \code
00479     namespace vigra {
00480         template <class SrcIterator, class SrcShape, class SrcAccessor,
00481                   class DestIterator, class DestAccessor>
00482         void
00483         gaussianGradientMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
00484                                    DestIterator diter, DestAccessor dest,
00485                                    double sigma);
00486     }
00487     \endcode
00488 
00489     use argument objects in conjunction with \ref ArgumentObjectFactories:
00490     \code
00491     namespace vigra {
00492         template <class SrcIterator, class SrcShape, class SrcAccessor,
00493                   class DestIterator, class DestAccessor>
00494         void
00495         gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
00496                                    pair<DestIterator, DestAccessor> const & dest,
00497                                    double sigma);
00498     }
00499     \endcode
00500 
00501     <b> Usage:</b>
00502 
00503     <b>\#include</b> "<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>"
00504 
00505     \code
00506     MultiArray<3, unsigned char>::size_type shape(width, height, depth);
00507     MultiArray<3, unsigned char> source(shape);
00508     MultiArray<3, TinyVector<float, 3> > dest(shape);
00509     ...
00510     // compute Gaussian gradient at scale sigma
00511     gaussianGradientMultiArray(srcMultiArrayRange(source), destMultiArray(dest), sigma);
00512     \endcode
00513 
00514     <b> Required Interface:</b>
00515 
00516     see \ref convolveImage(), in addition:
00517 
00518     \code
00519     int dimension = 0;
00520     VectorElementAccessor<DestAccessor> elementAccessor(0, dest);
00521     \endcode
00522 
00523     \see separableConvolveMultiArray()
00524 */
00525 template <class SrcIterator, class SrcShape, class SrcAccessor,
00526           class DestIterator, class DestAccessor>
00527 void
00528 gaussianGradientMultiArray( SrcIterator si, SrcShape const & shape, SrcAccessor src,
00529                 DestIterator di, DestAccessor dest, double sigma )
00530 {
00531     typedef typename DestAccessor::value_type DestType;
00532     typedef typename NumericTraits<typename DestType::value_type>::RealPromote kernel_type;
00533 
00534     Kernel1D<kernel_type> gauss, derivative;
00535     gauss.initGaussian(sigma);
00536     derivative.initGaussianDerivative(sigma, 1);
00537 
00538     typedef VectorElementAccessor<DestAccessor> ElementAccessor;
00539 
00540     // compute gradient components
00541     for(unsigned int d = 0; d < shape.size(); ++d )
00542     {
00543         ArrayVector<Kernel1D<kernel_type> > kernels(shape.size(), gauss);
00544         kernels[d] = derivative;
00545         separableConvolveMultiArray( si, shape, src, di, ElementAccessor(d, dest), kernels.begin());
00546     }
00547 }
00548 
00549 template <class SrcIterator, class SrcShape, class SrcAccessor,
00550           class DestIterator, class DestAccessor>
00551 inline void
00552 gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
00553                   pair<DestIterator, DestAccessor> const & dest, double sigma )
00554 {
00555     gaussianGradientMultiArray( source.first, source.second, source.third,
00556                               dest.first, dest.second, sigma );
00557 }
00558 
00559 /********************************************************/
00560 /*                                                      */
00561 /*             symmetricGradientMultiArray              */
00562 /*                                                      */
00563 /********************************************************/
00564 
00565 /** \brief Calculate gradient of a multi-dimensional arrays using symmetric difference filters.
00566 
00567     This function computes the gradient of the given multi-dimensional
00568     array with a sequence of symmetric difference filters a (differentiation is applied
00569     to each dimension in turn, starting with the innermost dimension). Both source and
00570     destination arrays are represented by iterators, shape objects and accessors.
00571     The destination array is required to have a vector valued pixel type with as many
00572     elements as the number of dimensions. This function is implemented by calls to
00573     \ref convolveMultiArrayOneDimension() with the symmetric difference kernel.
00574 
00575     <b> Declarations:</b>
00576 
00577     pass arguments explicitly:
00578     \code
00579     namespace vigra {
00580         template <class SrcIterator, class SrcShape, class SrcAccessor,
00581                   class DestIterator, class DestAccessor>
00582         void
00583         symmetricGradientMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
00584                                     DestIterator diter, DestAccessor dest);
00585     }
00586     \endcode
00587 
00588     use argument objects in conjunction with \ref ArgumentObjectFactories:
00589     \code
00590     namespace vigra {
00591         template <class SrcIterator, class SrcShape, class SrcAccessor,
00592                   class DestIterator, class DestAccessor>
00593         void
00594         symmetricGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
00595                                     pair<DestIterator, DestAccessor> const & dest);
00596     }
00597     \endcode
00598 
00599     <b> Usage:</b>
00600 
00601     <b>\#include</b> "<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>"
00602 
00603     \code
00604     MultiArray<3, unsigned char>::size_type shape(width, height, depth);
00605     MultiArray<3, unsigned char> source(shape);
00606     MultiArray<3, TinyVector<float, 3> > dest(shape);
00607     ...
00608     // compute gradient
00609     symmetricGradientMultiArray(srcMultiArrayRange(source), destMultiArray(dest));
00610     \endcode
00611 
00612     <b> Required Interface:</b>
00613 
00614     see \ref convolveImage(), in addition:
00615 
00616     \code
00617     int dimension = 0;
00618     VectorElementAccessor<DestAccessor> elementAccessor(0, dest);
00619     \endcode
00620 
00621     \see convolveMultiArrayOneDimension()
00622 */
00623 template <class SrcIterator, class SrcShape, class SrcAccessor,
00624           class DestIterator, class DestAccessor>
00625 void
00626 symmetricGradientMultiArray(SrcIterator si, SrcShape const & shape, SrcAccessor src,
00627                    DestIterator di, DestAccessor dest)
00628 {
00629     typedef typename DestAccessor::value_type DestType;
00630     typedef typename NumericTraits<typename DestType::value_type>::RealPromote kernel_type;
00631 
00632     Kernel1D<kernel_type> filter;
00633     filter.initSymmetricGradient();
00634 
00635     typedef VectorElementAccessor<DestAccessor> ElementAccessor;
00636 
00637     // compute gradient components
00638     for(unsigned int d = 0; d < shape.size(); ++d )
00639     {
00640         convolveMultiArrayOneDimension(si, shape, src,
00641                                        di, ElementAccessor(d, dest),
00642                                        d, filter);
00643     }
00644 }
00645 
00646 template <class SrcIterator, class SrcShape, class SrcAccessor,
00647           class DestIterator, class DestAccessor>
00648 inline void
00649 symmetricGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
00650                             pair<DestIterator, DestAccessor> const & dest )
00651 {
00652     symmetricGradientMultiArray(source.first, source.second, source.third,
00653                                 dest.first, dest.second);
00654 }
00655 
00656 //@}
00657 
00658 } //-- namespace vigra
00659 
00660 
00661 #endif        //-- VIGRA_MULTI_CONVOLUTION_H

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