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

| vigra/multi_convolution.hxx |
--- | --- | ---

    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)