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

vigra/multi_distance.hxx |

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*     Copyright 2003-2007 by Kasim Terzic, Christian-Dennis Rahn       */
    00004 /*                        and Ullrich Koethe                            */
    00005 /*                                                                      */
    00006 /*    This file is part of the VIGRA computer vision library.           */
    00007 /*    The VIGRA Website is                                              */
    00008 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
    00009 /*    Please direct questions, bug reports, and contributions to        */
    00010 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
    00011 /*        vigra@informatik.uni-hamburg.de                               */
    00012 /*                                                                      */
    00013 /*    Permission is hereby granted, free of charge, to any person       */
    00014 /*    obtaining a copy of this software and associated documentation    */
    00015 /*    files (the "Software"), to deal in the Software without           */
    00016 /*    restriction, including without limitation the rights to use,      */
    00017 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
    00018 /*    sell copies of the Software, and to permit persons to whom the    */
    00019 /*    Software is furnished to do so, subject to the following          */
    00020 /*    conditions:                                                       */
    00021 /*                                                                      */
    00022 /*    The above copyright notice and this permission notice shall be    */
    00023 /*    included in all copies or substantial portions of the             */
    00024 /*    Software.                                                         */
    00025 /*                                                                      */
    00026 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
    00027 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
    00028 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
    00029 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
    00030 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
    00031 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
    00032 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
    00033 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
    00034 /*                                                                      */
    00035 /************************************************************************/
    00036
    00037 #ifndef VIGRA_MULTI_DISTANCE_HXX
    00038 #define VIGRA_MULTI_DISTANCE_HXX
    00039
    00040 #include <vector>
    00041 #include <functional>
    00042 #include "array_vector.hxx"
    00043 #include "multi_array.hxx"
    00044 #include "accessor.hxx"
    00045 #include "numerictraits.hxx"
    00046 #include "navigator.hxx"
    00047 #include "metaprogramming.hxx"
    00048 #include "multi_pointoperators.hxx"
    00049 #include "functorexpression.hxx"
    00050
    00051 namespace vigra
    00052 {
    00053
    00054 namespace detail
    00055 {
    00056
    00057 template <class Value>
    00058 struct DistParabolaStackEntry
    00059 {
    00060     double left, center, right;
    00061     Value prevVal;
    00062
    00063     DistParabolaStackEntry(Value const & p, double l, double c, double r)
    00064     : left(l), center(c), right(r), prevVal(p)
    00065     {}
    00066 };
    00067
    00068 /********************************************************/
    00069 /*                                                      */
    00070 /*                distParabola                          */
    00071 /*                                                      */
    00072 /*  Version with sigma (parabola spread) for morphology */
    00073 /*                                                      */
    00074 /********************************************************/
    00075
    00076 template <class SrcIterator, class SrcAccessor,
    00077           class DestIterator, class DestAccessor >
    00078 void distParabola(SrcIterator is, SrcIterator iend, SrcAccessor sa,
    00079                   DestIterator id, DestAccessor da, double sigma )
    00080 {
    00081     // We assume that the data in the input is distance squared and treat it as such
    00082     double w = iend - is;
    00083     double sigma2 = sigma * sigma;
    00084     double sigma22 = 2.0 * sigma2;
    00085
    00086     typedef typename SrcAccessor::value_type SrcType;
    00087     typedef DistParabolaStackEntry<SrcType> Influence;
    00088     std::vector<Influence> _stack;
    00089     _stack.push_back(Influence(sa(is), 0.0, 0.0, w));
    00090
    00091     ++is;
    00092     double current = 1.0;
    00093     while(current < w )
    00094     {
    00095         Influence & s = _stack.back();
    00096         double diff = current - s.center;
    00097         double intersection = current + (sa(is) - s.prevVal - sigma2*sq(diff)) / (sigma22 * diff);
    00098
    00099         if( intersection < s.left) // previous point has no influence
    00100         {
    00101             _stack.pop_back();
    00102             if(_stack.empty())
    00103             {
    00104                 _stack.push_back(Influence(sa(is), 0.0, current, w));
    00105             }
    00106             else
    00107             {
    00108                 continue; // try new top of stack without advancing current
    00109             }
    00110         }
    00111         else if(intersection < s.right)
    00112         {
    00113             s.right = intersection;
    00114             _stack.push_back(Influence(sa(is), intersection, current, w));
    00115         }
    00116         ++is;
    00117         ++current;
    00118     }
    00119
    00120     // Now we have the stack indicating which rows are influenced by (and therefore
    00121     // closest to) which row. We can go through the stack and calculate the
    00122     // distance squared for each element of the column.
    00123     typename std::vector<Influence>::iterator it = _stack.begin();
    00124     for(current = 0.0; current < w; ++current, ++id)
    00125     {
    00126         while( current >= it->right)
    00127             ++it;
    00128         da.set(sigma2 * sq(current - it->center) + it->prevVal, id);
    00129     }
    00130 }
    00131
    00132 template <class SrcIterator, class SrcAccessor,
    00133           class DestIterator, class DestAccessor>
    00134 inline void distParabola(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00135                          pair<DestIterator, DestAccessor> dest, double sigma)
    00136 {
    00137     distParabola(src.first, src.second, src.third,
    00138                  dest.first, dest.second, sigma);
    00139 }
    00140
    00141 /********************************************************/
    00142 /*                                                      */
    00143 /*        internalSeparableMultiArrayDistTmp            */
    00144 /*                                                      */
    00145 /********************************************************/
    00146
    00147 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00148           class DestIterator, class DestAccessor, class Array>
    00149 void internalSeparableMultiArrayDistTmp(
    00150                       SrcIterator si, SrcShape const & shape, SrcAccessor src,
    00151                       DestIterator di, DestAccessor dest, Array const & sigmas, bool invert)
    00152 {
    00153     // Sigma is the spread of the parabolas. It determines the structuring element size
    00154     // for ND morphology. When calculating the distance transforms, sigma is usually set to 1,
    00155     // unless one wants to account for anisotropic pixel pitch
    00156     enum { N =  SrcShape::static_size};
    00157
    00158     // we need the Promote type here if we want to invert the image (dilation)
    00159     typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType;
    00160
    00161     // temporary array to hold the current line to enable in-place operation
    00162     ArrayVector<TmpType> tmp( shape[0] );
    00163
    00164     typedef MultiArrayNavigator<SrcIterator, N> SNavigator;
    00165     typedef MultiArrayNavigator<DestIterator, N> DNavigator;
    00166
    00167
    00168     // only operate on first dimension here
    00169     SNavigator snav( si, shape, 0 );
    00170     DNavigator dnav( di, shape, 0 );
    00171
    00172     using namespace vigra::functor;
    00173
    00174     for( ; snav.hasMore(); snav++, dnav++ )
    00175     {
    00176             // first copy source to temp for maximum cache efficiency
    00177             // Invert the values if necessary. Only needed for grayscale morphology
    00178             if(invert)
    00179                 transformLine( snav.begin(), snav.end(), src, tmp.begin(),
    00180                                typename AccessorTraits<TmpType>::default_accessor(),
    00181                                Param(NumericTraits<TmpType>::zero())-Arg1());
    00182             else
    00183                 copyLine( snav.begin(), snav.end(), src, tmp.begin(),
    00184                           typename AccessorTraits<TmpType>::default_accessor() );
    00185
    00186             detail::distParabola( srcIterRange(tmp.begin(), tmp.end(),
    00187                           typename AccessorTraits<TmpType>::default_const_accessor()),
    00188                           destIter( dnav.begin(), dest ), sigmas[0] );
    00189     }
    00190
    00191     // operate on further dimensions
    00192     for( int d = 1; d < N; ++d )
    00193     {
    00194         DNavigator dnav( di, shape, d );
    00195
    00196         tmp.resize( shape[d] );
    00197
    00198
    00199         for( ; dnav.hasMore(); dnav++ )
    00200         {
    00201              // first copy source to temp for maximum cache efficiency
    00202              copyLine( dnav.begin(), dnav.end(), dest,
    00203                        tmp.begin(), typename AccessorTraits<TmpType>::default_accessor() );
    00204
    00205              detail::distParabola( srcIterRange(tmp.begin(), tmp.end(),
    00206                            typename AccessorTraits<TmpType>::default_const_accessor()),
    00207                            destIter( dnav.begin(), dest ), sigmas[d] );
    00208         }
    00209     }
    00210     if(invert) transformMultiArray( di, shape, dest, di, dest, -Arg1());
    00211 }
    00212
    00213 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00214           class DestIterator, class DestAccessor, class Array>
    00215 inline void internalSeparableMultiArrayDistTmp( SrcIterator si, SrcShape const & shape, SrcAccessor src,
    00216                                                 DestIterator di, DestAccessor dest, Array const & sigmas)
    00217 {
    00218     internalSeparableMultiArrayDistTmp( si, shape, src, di, dest, sigmas, false );
    00219 }
    00220
    00221 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00222           class DestIterator, class DestAccessor>
    00223 inline void internalSeparableMultiArrayDistTmp( SrcIterator si, SrcShape const & shape, SrcAccessor src,
    00224                                                 DestIterator di, DestAccessor dest)
    00225 {
    00226     ArrayVector<double> sigmas(shape.size(), 1.0);
    00227     internalSeparableMultiArrayDistTmp( si, shape, src, di, dest, sigmas, false );
    00228 }
    00229
    00230 } // namespace detail
    00231
    00232 /** \addtogroup MultiArrayDistanceTransform Euclidean distance transform for multi-dimensional arrays.
    00233
    00234     These functions perform the Euclidean distance transform an arbitrary dimensional
    00235     array that is specified by iterators (compatible to \ref MultiIteratorPage)
    00236     and shape objects. It can therefore be applied to a wide range of data structures
    00237     (\ref vigra::MultiArrayView, \ref vigra::MultiArray etc.).
    00238 */
    00239 //@{
    00240
    00241 /********************************************************/
    00242 /*                                                      */
    00243 /*             separableMultiDistSquared                */
    00244 /*                                                      */
    00245 /********************************************************/
    00246
    00247 /** \brief Euclidean distance squared on multi-dimensional arrays.
    00248
    00249     The algorithm is taken from Donald Bailey: "An Efficient Euclidean Distance Transform",
    00250     Proc. IWCIA'04, Springer LNCS 3322, 2004.
    00251
    00252     <b> Declarations:</b>
    00253
    00254     pass arguments explicitly:
    00255     \code
    00256     namespace vigra {
    00257         // explicitly specify pixel pitch for each coordinate
    00258         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00259                   class DestIterator, class DestAccessor, class Array>
    00260         void
    00261         separableMultiDistSquared( SrcIterator s, SrcShape const & shape, SrcAccessor src,
    00262                                    DestIterator d, DestAccessor dest,
    00263                                    bool background,
    00264                                    Array const & pixelPitch);
    00265
    00266         // use default pixel pitch = 1.0 for each coordinate
    00267         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00268                   class DestIterator, class DestAccessor>
    00269         void
    00270         separableMultiDistSquared(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
    00271                                   DestIterator diter, DestAccessor dest,
    00272                                   bool background);
    00273
    00274     }
    00275     \endcode
    00276
    00277     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00278     \code
    00279     namespace vigra {
    00280         // explicitly specify pixel pitch for each coordinate
    00281         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00282                   class DestIterator, class DestAccessor, class Array>
    00283         void
    00284         separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAccessor> const & source,
    00285                                    pair<DestIterator, DestAccessor> const & dest,
    00286                                    bool background,
    00287                                    Array const & pixelPitch);
    00288
    00289         // use default pixel pitch = 1.0 for each coordinate
    00290         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00291                   class DestIterator, class DestAccessor>
    00292         void
    00293         separableMultiDistSquared(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
    00294                                   pair<DestIterator, DestAccessor> const & dest,
    00295                                   bool background);
    00296
    00297     }
    00298     \endcode
    00299
    00300     This function performs a squared Euclidean squared distance transform on the given
    00301     multi-dimensional array. Both source and destination
    00302     arrays are represented by iterators, shape objects and accessors.
    00303     The destination array is required to already have the correct size.
    00304
    00305     This function expects a mask as its source, where background pixels are
    00306     marked as zero, and non-background pixels as non-zero. If the parameter
    00307     <i>background</i> is true, then the squared distance of all background
    00308     pixels to the nearest object is calculated. Otherwise, the distance of all
    00309     object pixels to the nearest background pixel is calculated.
    00310
    00311     Optionally, one can pass an array that specifies the pixel pitch in each direction.
    00312     This is necessary when the data have non-uniform resolution (as is common in confocal
    00313     microscopy, for example).
    00314
    00315     This function may work in-place, which means that <tt>siter == diter</tt> is allowed.
    00316     A full-sized internal array is only allocated if working on the destination
    00317     array directly would cause overflow errors (i.e. if
    00318     <tt> NumericTraits<typename DestAccessor::value_type>::max() < N * M*M</tt>, where M is the
    00319     size of the largest dimension of the array.
    00320
    00321     <b> Usage:</b>
    00322
    00323     <b>\#include</b> <vigra/multi_distance.hxx>
    00324
    00325     \code
    00326     MultiArray<3, unsigned char>::size_type shape(width, height, depth);
    00327     MultiArray<3, unsigned char> source(shape);
    00328     MultiArray<3, unsigned int> dest(shape);
    00329     ...
    00330
    00331     // Calculate Euclidean distance squared for all background pixels
    00332     separableMultiDistSquared(srcMultiArrayRange(source), destMultiArray(dest), true);
    00333     \endcode
    00334
    00335     \see vigra::distanceTransform(), vigra::separableMultiDistance()
    00336 */
    00337 doxygen_overloaded_function(template <...> void separableMultiDistSquared)
    00338
    00339 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00340           class DestIterator, class DestAccessor, class Array>
    00341 void separableMultiDistSquared( SrcIterator s, SrcShape const & shape, SrcAccessor src,
    00342                                 DestIterator d, DestAccessor dest, bool background,
    00343                                 Array const & pixelPitch)
    00344 {
    00345     int N = shape.size();
    00346
    00347     typedef typename SrcAccessor::value_type SrcType;
    00348     typedef typename DestAccessor::value_type DestType;
    00349     typedef typename NumericTraits<DestType>::RealPromote Real;
    00350
    00351     SrcType zero = NumericTraits<SrcType>::zero();
    00352
    00353     double dmax = 0.0;
    00354     bool pixelPitchIsReal = false;
    00355     for( int k=0; k<N; ++k)
    00356     {
    00357         if(int(pixelPitch[k]) != pixelPitch[k])
    00358             pixelPitchIsReal = true;
    00359         dmax += sq(pixelPitch[k]*shape[k]);
    00360     }
    00361
    00362     using namespace vigra::functor;
    00363
    00364     if(dmax > NumericTraits<DestType>::toRealPromote(NumericTraits<DestType>::max())
    00365        || pixelPitchIsReal) // need a temporary array to avoid overflows
    00366     {
    00367         // Threshold the values so all objects have infinity value in the beginning
    00368         Real maxDist = (Real)dmax, rzero = (Real)0.0;
    00369         MultiArray<SrcShape::static_size, Real> tmpArray(shape);
    00370         if(background == true)
    00371             transformMultiArray( s, shape, src,
    00372                                  tmpArray.traverser_begin(), typename AccessorTraits<Real>::default_accessor(),
    00373                                  ifThenElse( Arg1() == Param(zero), Param(maxDist), Param(rzero) ));
    00374         else
    00375             transformMultiArray( s, shape, src,
    00376                                  tmpArray.traverser_begin(), typename AccessorTraits<Real>::default_accessor(),
    00377                                  ifThenElse( Arg1() != Param(zero), Param(maxDist), Param(rzero) ));
    00378
    00379         detail::internalSeparableMultiArrayDistTmp( tmpArray.traverser_begin(),
    00380                 shape, typename AccessorTraits<Real>::default_accessor(),
    00381                 tmpArray.traverser_begin(),
    00382                 typename AccessorTraits<Real>::default_accessor(), pixelPitch);
    00383
    00384         copyMultiArray(srcMultiArrayRange(tmpArray), destIter(d, dest));
    00385     }
    00386     else        // work directly on the destination array
    00387     {
    00388         // Threshold the values so all objects have infinity value in the beginning
    00389         DestType maxDist = DestType(std::ceil(dmax)), rzero = (DestType)0;
    00390         if(background == true)
    00391             transformMultiArray( s, shape, src, d, dest,
    00392                                  ifThenElse( Arg1() == Param(zero), Param(maxDist), Param(rzero) ));
    00393         else
    00394             transformMultiArray( s, shape, src, d, dest,
    00395                                  ifThenElse( Arg1() != Param(zero), Param(maxDist), Param(rzero) ));
    00396
    00397         detail::internalSeparableMultiArrayDistTmp( d, shape, dest, d, dest, pixelPitch);
    00398     }
    00399 }
    00400
    00401 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00402           class DestIterator, class DestAccessor, class Array>
    00403 inline void separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAccessor> const & source,
    00404                                        pair<DestIterator, DestAccessor> const & dest, bool background,
    00405                                        Array const & pixelPitch)
    00406 {
    00407     separableMultiDistSquared( source.first, source.second, source.third,
    00408                                dest.first, dest.second, background, pixelPitch );
    00409 }
    00410
    00411 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00412           class DestIterator, class DestAccessor>
    00413 inline
    00414 void separableMultiDistSquared( SrcIterator s, SrcShape const & shape, SrcAccessor src,
    00415                                 DestIterator d, DestAccessor dest, bool background)
    00416 {
    00417     ArrayVector<double> pixelPitch(shape.size(), 1.0);
    00418     separableMultiDistSquared( s, shape, src, d, dest, background, pixelPitch );
    00419 }
    00420
    00421 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00422           class DestIterator, class DestAccessor>
    00423 inline void separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAccessor> const & source,
    00424                                        pair<DestIterator, DestAccessor> const & dest, bool background)
    00425 {
    00426     separableMultiDistSquared( source.first, source.second, source.third,
    00427                                dest.first, dest.second, background );
    00428 }
    00429
    00430 /********************************************************/
    00431 /*                                                      */
    00432 /*             separableMultiDistance                   */
    00433 /*                                                      */
    00434 /********************************************************/
    00435
    00436 /** \brief Euclidean distance on multi-dimensional arrays.
    00437
    00438     <b> Declarations:</b>
    00439
    00440     pass arguments explicitly:
    00441     \code
    00442     namespace vigra {
    00443         // explicitly specify pixel pitch for each coordinate
    00444         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00445                   class DestIterator, class DestAccessor, class Array>
    00446         void
    00447         separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcAccessor src,
    00448                                 DestIterator d, DestAccessor dest,
    00449                                 bool background,
    00450                                 Array const & pixelPitch);
    00451
    00452         // use default pixel pitch = 1.0 for each coordinate
    00453         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00454                   class DestIterator, class DestAccessor>
    00455         void
    00456         separableMultiDistance(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
    00457                                DestIterator diter, DestAccessor dest,
    00458                                bool background);
    00459
    00460     }
    00461     \endcode
    00462
    00463     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00464     \code
    00465     namespace vigra {
    00466         // explicitly specify pixel pitch for each coordinate
    00467         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00468                   class DestIterator, class DestAccessor, class Array>
    00469         void
    00470         separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccessor> const & source,
    00471                                 pair<DestIterator, DestAccessor> const & dest,
    00472                                 bool background,
    00473                                 Array const & pixelPitch);
    00474
    00475         // use default pixel pitch = 1.0 for each coordinate
    00476         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00477                   class DestIterator, class DestAccessor>
    00478         void
    00479         separableMultiDistance(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
    00480                                pair<DestIterator, DestAccessor> const & dest,
    00481                                bool background);
    00482
    00483     }
    00484     \endcode
    00485
    00486     This function performs a Euclidean distance transform on the given
    00487     multi-dimensional array. It simply calls \ref separableMultiDistSquared()
    00488     and takes the pixel-wise square root of the result. See \ref separableMultiDistSquared()
    00489     for more documentation.
    00490
    00491     <b> Usage:</b>
    00492
    00493     <b>\#include</b> <vigra/multi_distance.hxx>
    00494
    00495     \code
    00496     MultiArray<3, unsigned char>::size_type shape(width, height, depth);
    00497     MultiArray<3, unsigned char> source(shape);
    00498     MultiArray<3, float> dest(shape);
    00499     ...
    00500
    00501     // Calculate Euclidean distance squared for all background pixels
    00502     separableMultiDistance(srcMultiArrayRange(source), destMultiArray(dest), true);
    00503     \endcode
    00504
    00505     \see vigra::distanceTransform(), vigra::separableMultiDistSquared()
    00506 */
    00507 doxygen_overloaded_function(template <...> void separableMultiDistance)
    00508
    00509 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00510           class DestIterator, class DestAccessor, class Array>
    00511 void separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcAccessor src,
    00512                              DestIterator d, DestAccessor dest, bool background,
    00513                              Array const & pixelPitch)
    00514 {
    00515     separableMultiDistSquared( s, shape, src, d, dest, background, pixelPitch);
    00516
    00517     // Finally, calculate the square root of the distances
    00518     using namespace vigra::functor;
    00519
    00520     transformMultiArray( d, shape, dest, d, dest, sqrt(Arg1()) );
    00521 }
    00522
    00523 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00524           class DestIterator, class DestAccessor>
    00525 void separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcAccessor src,
    00526                              DestIterator d, DestAccessor dest, bool background)
    00527 {
    00528     separableMultiDistSquared( s, shape, src, d, dest, background);
    00529
    00530     // Finally, calculate the square root of the distances
    00531     using namespace vigra::functor;
    00532
    00533     transformMultiArray( d, shape, dest, d, dest, sqrt(Arg1()) );
    00534 }
    00535
    00536 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00537           class DestIterator, class DestAccessor, class Array>
    00538 inline void separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccessor> const & source,
    00539                                     pair<DestIterator, DestAccessor> const & dest, bool background,
    00540                                     Array const & pixelPitch)
    00541 {
    00542     separableMultiDistance( source.first, source.second, source.third,
    00543                             dest.first, dest.second, background, pixelPitch );
    00544 }
    00545
    00546 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00547           class DestIterator, class DestAccessor>
    00548 inline void separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccessor> const & source,
    00549                                     pair<DestIterator, DestAccessor> const & dest, bool background)
    00550 {
    00551     separableMultiDistance( source.first, source.second, source.third,
    00552                             dest.first, dest.second, background );
    00553 }
    00554
    00555 //@}
    00556
    00557 } //-- namespace vigra
    00558
    00559
    00560 #endif        //-- VIGRA_MULTI_DISTANCE_HXX

© 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.9.0 (Tue Nov 6 2012)