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

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
VIGRA 1.6.0 (5 Nov 2009)