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

multi_distance.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2003-2007 by Kasim Terzic, Christian-Dennis Rahn */
4 /* and Ullrich Koethe */
5 /* */
6 /* This file is part of the VIGRA computer vision library. */
7 /* The VIGRA Website is */
8 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
9 /* Please direct questions, bug reports, and contributions to */
10 /* ullrich.koethe@iwr.uni-heidelberg.de or */
11 /* vigra@informatik.uni-hamburg.de */
12 /* */
13 /* Permission is hereby granted, free of charge, to any person */
14 /* obtaining a copy of this software and associated documentation */
15 /* files (the "Software"), to deal in the Software without */
16 /* restriction, including without limitation the rights to use, */
17 /* copy, modify, merge, publish, distribute, sublicense, and/or */
18 /* sell copies of the Software, and to permit persons to whom the */
19 /* Software is furnished to do so, subject to the following */
20 /* conditions: */
21 /* */
22 /* The above copyright notice and this permission notice shall be */
23 /* included in all copies or substantial portions of the */
24 /* Software. */
25 /* */
26 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
27 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
28 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
29 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
30 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
31 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
32 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
33 /* OTHER DEALINGS IN THE SOFTWARE. */
34 /* */
35 /************************************************************************/
36 
37 #ifndef VIGRA_MULTI_DISTANCE_HXX
38 #define VIGRA_MULTI_DISTANCE_HXX
39 
40 #include <vector>
41 #include <functional>
42 #include "array_vector.hxx"
43 #include "multi_array.hxx"
44 #include "accessor.hxx"
45 #include "numerictraits.hxx"
46 #include "navigator.hxx"
47 #include "metaprogramming.hxx"
48 #include "multi_pointoperators.hxx"
49 #include "functorexpression.hxx"
50 
51 namespace vigra
52 {
53 
54 namespace detail
55 {
56 
57 template <class Value>
58 struct DistParabolaStackEntry
59 {
60  double left, center, right;
61  Value prevVal;
62 
63  DistParabolaStackEntry(Value const & p, double l, double c, double r)
64  : left(l), center(c), right(r), prevVal(p)
65  {}
66 };
67 
68 /********************************************************/
69 /* */
70 /* distParabola */
71 /* */
72 /* Version with sigma (parabola spread) for morphology */
73 /* */
74 /********************************************************/
75 
76 template <class SrcIterator, class SrcAccessor,
77  class DestIterator, class DestAccessor >
78 void distParabola(SrcIterator is, SrcIterator iend, SrcAccessor sa,
79  DestIterator id, DestAccessor da, double sigma )
80 {
81  // We assume that the data in the input is distance squared and treat it as such
82  double w = iend - is;
83  if(w <= 0)
84  return;
85 
86  double sigma2 = sigma * sigma;
87  double sigma22 = 2.0 * sigma2;
88 
89  typedef typename SrcAccessor::value_type SrcType;
90  typedef DistParabolaStackEntry<SrcType> Influence;
91  std::vector<Influence> _stack;
92  _stack.push_back(Influence(sa(is), 0.0, 0.0, w));
93 
94  ++is;
95  double current = 1.0;
96  while(current < w )
97  {
98  Influence & s = _stack.back();
99  double diff = current - s.center;
100  double intersection = current + (sa(is) - s.prevVal - sigma2*sq(diff)) / (sigma22 * diff);
101 
102  if( intersection < s.left) // previous point has no influence
103  {
104  _stack.pop_back();
105  if(_stack.empty())
106  {
107  _stack.push_back(Influence(sa(is), 0.0, current, w));
108  }
109  else
110  {
111  continue; // try new top of stack without advancing current
112  }
113  }
114  else if(intersection < s.right)
115  {
116  s.right = intersection;
117  _stack.push_back(Influence(sa(is), intersection, current, w));
118  }
119  ++is;
120  ++current;
121  }
122 
123  // Now we have the stack indicating which rows are influenced by (and therefore
124  // closest to) which row. We can go through the stack and calculate the
125  // distance squared for each element of the column.
126  typename std::vector<Influence>::iterator it = _stack.begin();
127  for(current = 0.0; current < w; ++current, ++id)
128  {
129  while( current >= it->right)
130  ++it;
131  da.set(sigma2 * sq(current - it->center) + it->prevVal, id);
132  }
133 }
134 
135 template <class SrcIterator, class SrcAccessor,
136  class DestIterator, class DestAccessor>
137 inline void distParabola(triple<SrcIterator, SrcIterator, SrcAccessor> src,
138  pair<DestIterator, DestAccessor> dest, double sigma)
139 {
140  distParabola(src.first, src.second, src.third,
141  dest.first, dest.second, sigma);
142 }
143 
144 /********************************************************/
145 /* */
146 /* internalSeparableMultiArrayDistTmp */
147 /* */
148 /********************************************************/
149 
150 template <class SrcIterator, class SrcShape, class SrcAccessor,
151  class DestIterator, class DestAccessor, class Array>
152 void internalSeparableMultiArrayDistTmp(
153  SrcIterator si, SrcShape const & shape, SrcAccessor src,
154  DestIterator di, DestAccessor dest, Array const & sigmas, bool invert)
155 {
156  // Sigma is the spread of the parabolas. It determines the structuring element size
157  // for ND morphology. When calculating the distance transforms, sigma is usually set to 1,
158  // unless one wants to account for anisotropic pixel pitch
159  enum { N = SrcShape::static_size};
160 
161  // we need the Promote type here if we want to invert the image (dilation)
162  typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType;
163 
164  // temporary array to hold the current line to enable in-place operation
165  ArrayVector<TmpType> tmp( shape[0] );
166 
167  typedef MultiArrayNavigator<SrcIterator, N> SNavigator;
168  typedef MultiArrayNavigator<DestIterator, N> DNavigator;
169 
170 
171  // only operate on first dimension here
172  SNavigator snav( si, shape, 0 );
173  DNavigator dnav( di, shape, 0 );
174 
175  using namespace vigra::functor;
176 
177  for( ; snav.hasMore(); snav++, dnav++ )
178  {
179  // first copy source to temp for maximum cache efficiency
180  // Invert the values if necessary. Only needed for grayscale morphology
181  if(invert)
182  transformLine( snav.begin(), snav.end(), src, tmp.begin(),
183  typename AccessorTraits<TmpType>::default_accessor(),
184  Param(NumericTraits<TmpType>::zero())-Arg1());
185  else
186  copyLine( snav.begin(), snav.end(), src, tmp.begin(),
187  typename AccessorTraits<TmpType>::default_accessor() );
188 
189  detail::distParabola( srcIterRange(tmp.begin(), tmp.end(),
190  typename AccessorTraits<TmpType>::default_const_accessor()),
191  destIter( dnav.begin(), dest ), sigmas[0] );
192  }
193 
194  // operate on further dimensions
195  for( int d = 1; d < N; ++d )
196  {
197  DNavigator dnav( di, shape, d );
198 
199  tmp.resize( shape[d] );
200 
201 
202  for( ; dnav.hasMore(); dnav++ )
203  {
204  // first copy source to temp for maximum cache efficiency
205  copyLine( dnav.begin(), dnav.end(), dest,
206  tmp.begin(), typename AccessorTraits<TmpType>::default_accessor() );
207 
208  detail::distParabola( srcIterRange(tmp.begin(), tmp.end(),
209  typename AccessorTraits<TmpType>::default_const_accessor()),
210  destIter( dnav.begin(), dest ), sigmas[d] );
211  }
212  }
213  if(invert) transformMultiArray( di, shape, dest, di, dest, -Arg1());
214 }
215 
216 template <class SrcIterator, class SrcShape, class SrcAccessor,
217  class DestIterator, class DestAccessor, class Array>
218 inline void internalSeparableMultiArrayDistTmp( SrcIterator si, SrcShape const & shape, SrcAccessor src,
219  DestIterator di, DestAccessor dest, Array const & sigmas)
220 {
221  internalSeparableMultiArrayDistTmp( si, shape, src, di, dest, sigmas, false );
222 }
223 
224 template <class SrcIterator, class SrcShape, class SrcAccessor,
225  class DestIterator, class DestAccessor>
226 inline void internalSeparableMultiArrayDistTmp( SrcIterator si, SrcShape const & shape, SrcAccessor src,
227  DestIterator di, DestAccessor dest)
228 {
229  ArrayVector<double> sigmas(shape.size(), 1.0);
230  internalSeparableMultiArrayDistTmp( si, shape, src, di, dest, sigmas, false );
231 }
232 
233 } // namespace detail
234 
235 /** \addtogroup MultiArrayDistanceTransform Euclidean distance transform for multi-dimensional arrays.
236 
237  These functions perform the Euclidean distance transform an arbitrary dimensional
238  array that is specified by iterators (compatible to \ref MultiIteratorPage)
239  and shape objects. It can therefore be applied to a wide range of data structures
240  (\ref vigra::MultiArrayView, \ref vigra::MultiArray etc.).
241 */
242 //@{
243 
244 /********************************************************/
245 /* */
246 /* separableMultiDistSquared */
247 /* */
248 /********************************************************/
249 
250 /** \brief Euclidean distance squared on multi-dimensional arrays.
251 
252  The algorithm is taken from Donald Bailey: "An Efficient Euclidean Distance Transform",
253  Proc. IWCIA'04, Springer LNCS 3322, 2004.
254 
255  <b> Declarations:</b>
256 
257  pass arbitrary-dimensional array views:
258  \code
259  namespace vigra {
260  // explicitly specify pixel pitch for each coordinate
261  template <unsigned int N, class T1, class S1,
262  class T2, class S2,
263  class Array>
264  void
265  separableMultiDistSquared(MultiArrayView<N, T1, S1> const & source,
266  MultiArrayView<N, T2, S2> dest,
267  bool background,
268  Array const & pixelPitch);
269 
270  // use default pixel pitch = 1.0 for each coordinate
271  template <unsigned int N, class T1, class S1,
272  class T2, class S2>
273  void
274  separableMultiDistSquared(MultiArrayView<N, T1, S1> const & source,
275  MultiArrayView<N, T2, S2> dest,
276  bool background);
277  }
278  \endcode
279 
280  \deprecatedAPI{separableMultiDistSquared}
281  pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors :
282  \code
283  namespace vigra {
284  // explicitly specify pixel pitch for each coordinate
285  template <class SrcIterator, class SrcShape, class SrcAccessor,
286  class DestIterator, class DestAccessor, class Array>
287  void
288  separableMultiDistSquared( SrcIterator s, SrcShape const & shape, SrcAccessor src,
289  DestIterator d, DestAccessor dest,
290  bool background,
291  Array const & pixelPitch);
292 
293  // use default pixel pitch = 1.0 for each coordinate
294  template <class SrcIterator, class SrcShape, class SrcAccessor,
295  class DestIterator, class DestAccessor>
296  void
297  separableMultiDistSquared(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
298  DestIterator diter, DestAccessor dest,
299  bool background);
300 
301  }
302  \endcode
303  use argument objects in conjunction with \ref ArgumentObjectFactories :
304  \code
305  namespace vigra {
306  // explicitly specify pixel pitch for each coordinate
307  template <class SrcIterator, class SrcShape, class SrcAccessor,
308  class DestIterator, class DestAccessor, class Array>
309  void
310  separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAccessor> const & source,
311  pair<DestIterator, DestAccessor> const & dest,
312  bool background,
313  Array const & pixelPitch);
314 
315  // use default pixel pitch = 1.0 for each coordinate
316  template <class SrcIterator, class SrcShape, class SrcAccessor,
317  class DestIterator, class DestAccessor>
318  void
319  separableMultiDistSquared(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
320  pair<DestIterator, DestAccessor> const & dest,
321  bool background);
322 
323  }
324  \endcode
325  \deprecatedEnd
326 
327  This function performs a squared Euclidean squared distance transform on the given
328  multi-dimensional array. Both source and destination
329  arrays are represented by iterators, shape objects and accessors.
330  The destination array is required to already have the correct size.
331 
332  This function expects a mask as its source, where background pixels are
333  marked as zero, and non-background pixels as non-zero. If the parameter
334  <i>background</i> is true, then the squared distance of all background
335  pixels to the nearest object is calculated. Otherwise, the distance of all
336  object pixels to the nearest background pixel is calculated.
337 
338  Optionally, one can pass an array that specifies the pixel pitch in each direction.
339  This is necessary when the data have non-uniform resolution (as is common in confocal
340  microscopy, for example).
341 
342  This function may work in-place, which means that <tt>siter == diter</tt> is allowed.
343  A full-sized internal array is only allocated if working on the destination
344  array directly would cause overflow errors (i.e. if
345  <tt> NumericTraits<typename DestAccessor::value_type>::max() < N * M*M</tt>, where M is the
346  size of the largest dimension of the array.
347 
348  <b> Usage:</b>
349 
350  <b>\#include</b> <vigra/multi_distance.hxx><br/>
351  Namespace: vigra
352 
353  \code
354  Shape3 shape(width, height, depth);
355  MultiArray<3, unsigned char> source(shape);
356  MultiArray<3, unsigned int> dest(shape);
357  ...
358 
359  // Calculate Euclidean distance squared for all background pixels
360  separableMultiDistSquared(source, dest, true);
361  \endcode
362 
363  \see vigra::distanceTransform(), vigra::separableMultiDistance()
364 */
365 doxygen_overloaded_function(template <...> void separableMultiDistSquared)
366 
367 template <class SrcIterator, class SrcShape, class SrcAccessor,
368  class DestIterator, class DestAccessor, class Array>
369 void separableMultiDistSquared( SrcIterator s, SrcShape const & shape, SrcAccessor src,
370  DestIterator d, DestAccessor dest, bool background,
371  Array const & pixelPitch)
372 {
373  int N = shape.size();
374 
375  typedef typename SrcAccessor::value_type SrcType;
376  typedef typename DestAccessor::value_type DestType;
377  typedef typename NumericTraits<DestType>::RealPromote Real;
378 
379  SrcType zero = NumericTraits<SrcType>::zero();
380 
381  double dmax = 0.0;
382  bool pixelPitchIsReal = false;
383  for( int k=0; k<N; ++k)
384  {
385  if(int(pixelPitch[k]) != pixelPitch[k])
386  pixelPitchIsReal = true;
387  dmax += sq(pixelPitch[k]*shape[k]);
388  }
389 
390  using namespace vigra::functor;
391 
392  if(dmax > NumericTraits<DestType>::toRealPromote(NumericTraits<DestType>::max())
393  || pixelPitchIsReal) // need a temporary array to avoid overflows
394  {
395  // Threshold the values so all objects have infinity value in the beginning
396  Real maxDist = (Real)dmax, rzero = (Real)0.0;
397  MultiArray<SrcShape::static_size, Real> tmpArray(shape);
398  if(background == true)
399  transformMultiArray( s, shape, src,
400  tmpArray.traverser_begin(), typename AccessorTraits<Real>::default_accessor(),
401  ifThenElse( Arg1() == Param(zero), Param(maxDist), Param(rzero) ));
402  else
403  transformMultiArray( s, shape, src,
404  tmpArray.traverser_begin(), typename AccessorTraits<Real>::default_accessor(),
405  ifThenElse( Arg1() != Param(zero), Param(maxDist), Param(rzero) ));
406 
407  detail::internalSeparableMultiArrayDistTmp( tmpArray.traverser_begin(),
408  shape, typename AccessorTraits<Real>::default_accessor(),
409  tmpArray.traverser_begin(),
410  typename AccessorTraits<Real>::default_accessor(), pixelPitch);
411 
412  copyMultiArray(srcMultiArrayRange(tmpArray), destIter(d, dest));
413  }
414  else // work directly on the destination array
415  {
416  // Threshold the values so all objects have infinity value in the beginning
417  DestType maxDist = DestType(std::ceil(dmax)), rzero = (DestType)0;
418  if(background == true)
419  transformMultiArray( s, shape, src, d, dest,
420  ifThenElse( Arg1() == Param(zero), Param(maxDist), Param(rzero) ));
421  else
422  transformMultiArray( s, shape, src, d, dest,
423  ifThenElse( Arg1() != Param(zero), Param(maxDist), Param(rzero) ));
424 
425  detail::internalSeparableMultiArrayDistTmp( d, shape, dest, d, dest, pixelPitch);
426  }
427 }
428 
429 template <class SrcIterator, class SrcShape, class SrcAccessor,
430  class DestIterator, class DestAccessor>
431 inline
432 void separableMultiDistSquared( SrcIterator s, SrcShape const & shape, SrcAccessor src,
433  DestIterator d, DestAccessor dest, bool background)
434 {
435  ArrayVector<double> pixelPitch(shape.size(), 1.0);
436  separableMultiDistSquared( s, shape, src, d, dest, background, pixelPitch );
437 }
438 
439 template <class SrcIterator, class SrcShape, class SrcAccessor,
440  class DestIterator, class DestAccessor, class Array>
441 inline void separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAccessor> const & source,
442  pair<DestIterator, DestAccessor> const & dest, bool background,
443  Array const & pixelPitch)
444 {
445  separableMultiDistSquared( source.first, source.second, source.third,
446  dest.first, dest.second, background, pixelPitch );
447 }
448 
449 template <class SrcIterator, class SrcShape, class SrcAccessor,
450  class DestIterator, class DestAccessor>
451 inline void separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAccessor> const & source,
452  pair<DestIterator, DestAccessor> const & dest, bool background)
453 {
454  separableMultiDistSquared( source.first, source.second, source.third,
455  dest.first, dest.second, background );
456 }
457 
458 template <unsigned int N, class T1, class S1,
459  class T2, class S2,
460  class Array>
461 inline void
462 separableMultiDistSquared(MultiArrayView<N, T1, S1> const & source,
463  MultiArrayView<N, T2, S2> dest, bool background,
464  Array const & pixelPitch)
465 {
466  vigra_precondition(source.shape() == dest.shape(),
467  "separableMultiDistSquared(): shape mismatch between input and output.");
468  separableMultiDistSquared( srcMultiArrayRange(source),
469  destMultiArray(dest), background, pixelPitch );
470 }
471 
472 template <unsigned int N, class T1, class S1,
473  class T2, class S2>
474 inline void
475 separableMultiDistSquared(MultiArrayView<N, T1, S1> const & source,
476  MultiArrayView<N, T2, S2> dest, bool background)
477 {
478  vigra_precondition(source.shape() == dest.shape(),
479  "separableMultiDistSquared(): shape mismatch between input and output.");
480  separableMultiDistSquared( srcMultiArrayRange(source),
481  destMultiArray(dest), background );
482 }
483 
484 /********************************************************/
485 /* */
486 /* separableMultiDistance */
487 /* */
488 /********************************************************/
489 
490 /** \brief Euclidean distance on multi-dimensional arrays.
491 
492  <b> Declarations:</b>
493 
494  pass arbitrary-dimensional array views:
495  \code
496  namespace vigra {
497  // explicitly specify pixel pitch for each coordinate
498  template <unsigned int N, class T1, class S1,
499  class T2, class S2, class Array>
500  void
501  separableMultiDistance(MultiArrayView<N, T1, S1> const & source,
502  MultiArrayView<N, T2, S2> dest,
503  bool background,
504  Array const & pixelPitch);
505 
506  // use default pixel pitch = 1.0 for each coordinate
507  template <unsigned int N, class T1, class S1,
508  class T2, class S2>
509  void
510  separableMultiDistance(MultiArrayView<N, T1, S1> const & source,
511  MultiArrayView<N, T2, S2> dest,
512  bool background);
513  }
514  \endcode
515 
516  \deprecatedAPI{separableMultiDistance}
517  pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors :
518  \code
519  namespace vigra {
520  // explicitly specify pixel pitch for each coordinate
521  template <class SrcIterator, class SrcShape, class SrcAccessor,
522  class DestIterator, class DestAccessor, class Array>
523  void
524  separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcAccessor src,
525  DestIterator d, DestAccessor dest,
526  bool background,
527  Array const & pixelPitch);
528 
529  // use default pixel pitch = 1.0 for each coordinate
530  template <class SrcIterator, class SrcShape, class SrcAccessor,
531  class DestIterator, class DestAccessor>
532  void
533  separableMultiDistance(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
534  DestIterator diter, DestAccessor dest,
535  bool background);
536 
537  }
538  \endcode
539  use argument objects in conjunction with \ref ArgumentObjectFactories :
540  \code
541  namespace vigra {
542  // explicitly specify pixel pitch for each coordinate
543  template <class SrcIterator, class SrcShape, class SrcAccessor,
544  class DestIterator, class DestAccessor, class Array>
545  void
546  separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccessor> const & source,
547  pair<DestIterator, DestAccessor> const & dest,
548  bool background,
549  Array const & pixelPitch);
550 
551  // use default pixel pitch = 1.0 for each coordinate
552  template <class SrcIterator, class SrcShape, class SrcAccessor,
553  class DestIterator, class DestAccessor>
554  void
555  separableMultiDistance(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
556  pair<DestIterator, DestAccessor> const & dest,
557  bool background);
558 
559  }
560  \endcode
561  \deprecatedEnd
562 
563  This function performs a Euclidean distance transform on the given
564  multi-dimensional array. It simply calls \ref separableMultiDistSquared()
565  and takes the pixel-wise square root of the result. See \ref separableMultiDistSquared()
566  for more documentation.
567 
568  <b> Usage:</b>
569 
570  <b>\#include</b> <vigra/multi_distance.hxx><br/>
571  Namespace: vigra
572 
573  \code
574  Shape3 shape(width, height, depth);
575  MultiArray<3, unsigned char> source(shape);
576  MultiArray<3, float> dest(shape);
577  ...
578 
579  // Calculate Euclidean distance squared for all background pixels
580  separableMultiDistance(source, dest, true);
581  \endcode
582 
583  \see vigra::distanceTransform(), vigra::separableMultiDistSquared()
584 */
585 doxygen_overloaded_function(template <...> void separableMultiDistance)
586 
587 template <class SrcIterator, class SrcShape, class SrcAccessor,
588  class DestIterator, class DestAccessor, class Array>
589 void separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcAccessor src,
590  DestIterator d, DestAccessor dest, bool background,
591  Array const & pixelPitch)
592 {
593  separableMultiDistSquared( s, shape, src, d, dest, background, pixelPitch);
594 
595  // Finally, calculate the square root of the distances
596  using namespace vigra::functor;
597 
598  transformMultiArray( d, shape, dest, d, dest, sqrt(Arg1()) );
599 }
600 
601 template <class SrcIterator, class SrcShape, class SrcAccessor,
602  class DestIterator, class DestAccessor>
603 void separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcAccessor src,
604  DestIterator d, DestAccessor dest, bool background)
605 {
606  separableMultiDistSquared( s, shape, src, d, dest, background);
607 
608  // Finally, calculate the square root of the distances
609  using namespace vigra::functor;
610 
611  transformMultiArray( d, shape, dest, d, dest, sqrt(Arg1()) );
612 }
613 
614 template <class SrcIterator, class SrcShape, class SrcAccessor,
615  class DestIterator, class DestAccessor, class Array>
616 inline void separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccessor> const & source,
617  pair<DestIterator, DestAccessor> const & dest, bool background,
618  Array const & pixelPitch)
619 {
620  separableMultiDistance( source.first, source.second, source.third,
621  dest.first, dest.second, background, pixelPitch );
622 }
623 
624 template <class SrcIterator, class SrcShape, class SrcAccessor,
625  class DestIterator, class DestAccessor>
626 inline void separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccessor> const & source,
627  pair<DestIterator, DestAccessor> const & dest, bool background)
628 {
629  separableMultiDistance( source.first, source.second, source.third,
630  dest.first, dest.second, background );
631 }
632 
633 template <unsigned int N, class T1, class S1,
634  class T2, class S2, class Array>
635 inline void
636 separableMultiDistance(MultiArrayView<N, T1, S1> const & source,
637  MultiArrayView<N, T2, S2> dest,
638  bool background,
639  Array const & pixelPitch)
640 {
641  vigra_precondition(source.shape() == dest.shape(),
642  "separableMultiDistance(): shape mismatch between input and output.");
643  separableMultiDistance( srcMultiArrayRange(source),
644  destMultiArray(dest), background, pixelPitch );
645 }
646 
647 template <unsigned int N, class T1, class S1,
648  class T2, class S2>
649 inline void
650 separableMultiDistance(MultiArrayView<N, T1, S1> const & source,
651  MultiArrayView<N, T2, S2> dest,
652  bool background)
653 {
654  vigra_precondition(source.shape() == dest.shape(),
655  "separableMultiDistance(): shape mismatch between input and output.");
656  separableMultiDistance( srcMultiArrayRange(source),
657  destMultiArray(dest), background );
658 }
659 
660 //@}
661 
662 } //-- namespace vigra
663 
664 
665 #endif //-- VIGRA_MULTI_DISTANCE_HXX
vigra::GridGraph< N, DirectedTag >::vertex_descriptor source(typename vigra::GridGraph< N, DirectedTag >::edge_descriptor const &e, vigra::GridGraph< N, DirectedTag > const &g)
Get a vertex descriptor for the start vertex of edge e in graph g (API: boost).
Definition: multi_gridgraph.hxx:2786
void separableMultiDistSquared(...)
Euclidean distance squared on multi-dimensional arrays.
Definition: accessor.hxx:43
void separableMultiDistance(...)
Euclidean distance on multi-dimensional arrays.
Definition: inspectimage.hxx:255
NumericTraits< T >::Promote sq(T t)
The square function.
Definition: mathutil.hxx:344
void copyMultiArray(...)
Copy a multi-dimensional array.
void transformMultiArray(...)
Transform a multi-dimensional array with a unary function or functor.
int ceil(FixedPoint< IntBits, FracBits > v)
rounding up.
Definition: fixedpoint.hxx:675
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root.
Definition: fixedpoint.hxx:616

© 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.10.0