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