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

localminmax.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2010 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 #ifndef VIGRA_LOCALMINMAX_HXX
37 #define VIGRA_LOCALMINMAX_HXX
38 
39 #include <vector>
40 #include <functional>
41 #include "utilities.hxx"
42 #include "stdimage.hxx"
43 #include "initimage.hxx"
44 #include "labelimage.hxx"
45 #include "labelvolume.hxx"
46 #include "pixelneighborhood.hxx"
47 #include "voxelneighborhood.hxx"
48 
49 namespace vigra
50 {
51 
52 /** \addtogroup LocalMinMax Local Minima and Maxima
53 
54  Detect local minima and maxima in a gray level image,
55  including extremal plateaus larger than 1 pixel
56 */
57 //@{
58 
59 namespace detail {
60 
61 template <class SrcIterator, class SrcAccessor,
62  class Neighborhood,
63  class Compare>
64 inline bool
65 isLocalExtremum(SrcIterator is, SrcAccessor sa, Neighborhood,
66  typename SrcAccessor::value_type threshold,
67  Compare compare, AtImageBorder atBorder)
68 {
69  typename SrcAccessor::value_type v = sa(is);
70 
71  if(!compare(v, threshold))
72  return false;
73 
74  int directionCount = Neighborhood::nearBorderDirectionCount(atBorder);
75  RestrictedNeighborhoodCirculator<SrcIterator, Neighborhood> sc(is, atBorder);
76  for(int i = 0; i < directionCount; ++i, ++sc)
77  {
78  if(!compare(v, sa(sc)))
79  return false;
80  }
81  return true;
82 }
83 
84 template <class SrcIterator, class SrcAccessor,
85  class DestIterator, class DestAccessor,
86  class DestValue, class Neighborhood,
87  class Compare>
88 void
89 localMinMax(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
90  DestIterator dul, DestAccessor da,
91  DestValue marker, Neighborhood neighborhood,
92  typename SrcAccessor::value_type threshold,
93  Compare compare,
94  bool allowExtremaAtBorder = false)
95 {
96  int w = slr.x - sul.x;
97  int h = slr.y - sul.y;
98 
99  int x, y;
100 
101  if(allowExtremaAtBorder)
102  {
103  SrcIterator is = sul;
104  DestIterator id = dul;
105 
106  for(x=0; x<w; ++x, ++is.x, ++id.x)
107  {
108  if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
109  isAtImageBorder(x, 0, w, h)))
110  da.set(marker, id);
111  }
112 
113  is = sul + Diff2D(0,1);
114  id = dul + Diff2D(0,1);
115 
116  for(y=1; y<h-1; ++y, ++is.y, ++id.y)
117  {
118  if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
119  isAtImageBorder(0, y, w, h)))
120  da.set(marker, id);
121  }
122 
123  is = sul + Diff2D(w-1,1);
124  id = dul + Diff2D(w-1,1);
125 
126  for(y=1; y<h-1; ++y, ++is.y, ++id.y)
127  {
128  if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
129  isAtImageBorder(w-1, y, w, h)))
130  da.set(marker, id);
131  }
132 
133  is = sul + Diff2D(0,h-1);
134  id = dul + Diff2D(0,h-1);
135 
136  for(x=0; x<w; ++x, ++is.x, ++id.x)
137  {
138  if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
139  isAtImageBorder(x, h-1, w, h)))
140  da.set(marker, id);
141  }
142  }
143 
144  w -= 2;
145  h -= 2;
146  sul += Diff2D(1,1);
147  dul += Diff2D(1,1);
148 
149  for(y=0; y<h; ++y, ++sul.y, ++dul.y)
150  {
151  SrcIterator sx = sul;
152  DestIterator dx = dul;
153 
154  for(x=0; x<w; ++x, ++sx.x, ++dx.x)
155  {
156  typename SrcAccessor::value_type v = sa(sx);
157 
158  if(!compare(v, threshold))
159  continue;
160 
161  int i;
162  NeighborhoodCirculator<SrcIterator, Neighborhood> sc(sx);
163  for(i = 0; i < Neighborhood::DirectionCount; ++i, ++sc)
164  {
165  if(!compare(v, sa(sc)))
166  break;
167  }
168 
169  if(i == Neighborhood::DirectionCount)
170  da.set(marker, dx);
171  }
172  }
173 }
174 
175 template<class SrcIterator, class SrcShape, class SrcAccessor,
176  class DestIterator, class DestAccessor, class DestValue,
177  class Neighborhood, class Compare>
178 void
179 localMinMax3D(SrcIterator sul, SrcShape shp, SrcAccessor sa,
180  DestIterator dul, DestAccessor da,
181  DestValue marker,
182  Neighborhood neighborhood,
183  typename SrcAccessor::value_type threshold,
184  Compare compare,
185  bool allowExtremaAtBorder = false)
186 {
187  int w = shp[0];
188  int h = shp[1];
189  int d = shp[2];
190 
191  int x, y, z;
192 
193  if (allowExtremaAtBorder)
194  {
195  throw std::runtime_error("not implemented!");
196  /*
197  SrcIterator is = sul;
198  DestIterator id = dul;
199 
200  for(x=0; x<w; ++x, ++is.x, ++id.x)
201  {
202  if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
203  isAtImageBorder(x, 0, w, h)))
204  da.set(marker, id);
205  }
206 
207  is = sul + Diff2D(0,1);
208  id = dul + Diff2D(0,1);
209 
210  for(y=1; y<h-1; ++y, ++is.y, ++id.y)
211  {
212  if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
213  isAtImageBorder(0, y, w, h)))
214  da.set(marker, id);
215  }
216 
217  is = sul + Diff2D(w-1,1);
218  id = dul + Diff2D(w-1,1);
219 
220  for(y=1; y<h-1; ++y, ++is.y, ++id.y)
221  {
222  if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
223  isAtImageBorder(w-1, y, w, h)))
224  da.set(marker, id);
225  }
226 
227  is = sul + Diff2D(0,h-1);
228  id = dul + Diff2D(0,h-1);
229 
230  for(x=0; x<w; ++x, ++is.x, ++id.x)
231  {
232  if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
233  isAtImageBorder(x, h-1, w, h)))
234  da.set(marker, id);
235  }
236  */
237  }
238 
239  w -= 2;
240  h -= 2;
241  d -= 2;
242  sul.dim0() += 1;
243  sul.dim1() += 1;
244  sul.dim2() += 1;
245  dul += Diff3D(1, 1, 1);
246 
247  SrcIterator zs = sul;
248  DestIterator zd = dul;
249 
250  for (z = 0; z != d; ++z, ++zs.dim2(), ++zd.dim2())
251  {
252  SrcIterator ys(zs);
253  DestIterator yd(zd);
254 
255  for (y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1())
256  {
257  SrcIterator xs(ys);
258  DestIterator xd(yd);
259 
260  for (x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0())
261  {
262 
263  typename SrcAccessor::value_type v = sa(xs);
264  if (!compare(v, threshold))
265  continue;
266 
267  int i;
268  NeighborhoodCirculator<SrcIterator, Neighborhood> sc(xs);
269  for (i = 0; i < Neighborhood::DirectionCount; ++i, ++sc)
270  {
271  if(!compare(v, sa(sc)))
272  break;
273  }
274 
275  if(i == Neighborhood::DirectionCount)
276  da.set(marker, xd);
277  }
278  }
279  }
280 }
281 
282 template <class SrcIterator, class SrcAccessor,
283  class DestIterator, class DestAccessor, class DestValue,
284  class Neighborhood, class Compare, class Equal>
285 void
286 extendedLocalMinMax(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
287  DestIterator dul, DestAccessor da, DestValue marker,
288  Neighborhood /*neighborhood*/,
289  Compare compare, Equal equal,
290  typename SrcAccessor::value_type threshold,
291  bool allowExtremaAtBorder = false)
292 {
293  typedef typename SrcAccessor::value_type SrcType;
294 
295  int w = slr.x - sul.x;
296  int h = slr.y - sul.y;
297 
298  int i,x,y;
299 
300  BasicImage<int> labels(w,h);
301 
302  int number_of_regions =
303  labelImage(sul, slr, sa, labels.upperLeft(), labels.accessor(),
304  (Neighborhood::DirectionCount == 8), equal);
305 
306  // assume that a region is a extremum until the opposite is proved
307  std::vector<unsigned char> isExtremum(number_of_regions+1, (unsigned char)1);
308 
309  BasicImage<int>::traverser ly = labels.upperLeft();
310 
311  for(y=0; y<h; ++y, ++sul.y, ++ly.y)
312  {
313  SrcIterator sx = sul;
314  BasicImage<int>::traverser lx(ly);
315 
316  for(x=0; x<w; ++x, ++sx.x, ++lx.x)
317  {
318  int lab = *lx;
319  SrcType v = sa(sx);
320 
321  if(isExtremum[lab] == 0)
322  continue;
323 
324  if(!compare(v, threshold))
325  {
326  // mark all regions that don't exceed the threshold as non-extremum
327  isExtremum[lab] = 0;
328  continue;
329  }
330 
331  AtImageBorder atBorder = isAtImageBorder(x, y, w, h);
332  if(atBorder == NotAtBorder)
333  {
334  NeighborhoodCirculator<SrcIterator, Neighborhood> sc(sx);
335  NeighborhoodCirculator<BasicImage<int>::traverser, Neighborhood> lc(lx);
336  for(i=0; i<Neighborhood::DirectionCount; ++i, ++sc, ++lc)
337  {
338  if(lab != *lc && compare(sa(sc),v))
339  {
340  isExtremum[lab] = 0;
341  break;
342  }
343  }
344  }
345  else
346  {
347  if(allowExtremaAtBorder)
348  {
349  RestrictedNeighborhoodCirculator<SrcIterator, Neighborhood>
350  sc(sx, atBorder), scend(sc);
351  do
352  {
353  if(lab != *(lx+sc.diff()) && compare(sa(sc),v))
354  {
355  isExtremum[lab] = 0;
356  break;
357  }
358  }
359  while(++sc != scend);
360  }
361  else
362  {
363  isExtremum[lab] = 0;
364  }
365  }
366  }
367  }
368 
369  ly = labels.upperLeft();
370  for(y=0; y<h; ++y, ++dul.y, ++ly.y)
371  {
372  DestIterator xd = dul;
373  BasicImage<int>::Iterator lx(ly);
374 
375  for(x=0; x<w; ++x, ++xd.x, ++lx.x)
376  {
377  if(isExtremum[*lx])
378  da.set(marker, xd);
379  }
380  }
381 }
382 
383 template<class SrcIterator, class SrcShape, class SrcAccessor,
384  class DestIterator, class DestAccessor, class DestValue,
385  class Neighborhood, class Compare, class Equal>
386 void
387 extendedLocalMinMax3D(SrcIterator sul, SrcShape shp, SrcAccessor sa,
388  DestIterator dul, DestAccessor da,
389  DestValue marker,
390  Neighborhood neighbourhood,
391  Compare compare,
392  Equal equal,
393  typename SrcAccessor::value_type threshold,
394  bool allowExtremaAtBorder = false)
395 {
396  typedef typename SrcAccessor::value_type SrcType;
397 
398  int w = shp[0];
399  int h = shp[1];
400  int d = shp[2];
401 
402  int i, x, y, z;
403 
404  MultiArray<3, int> labels(shp);
405 
406  int number_of_regions =
407  labelVolume(sul, shp, sa, labels.traverser_begin(),
408  typename AccessorTraits<int>::default_accessor(),
409  neighbourhood);
410 
411  MultiArray<3, int>::traverser zl(labels.traverser_begin());
412 
413  SrcIterator zs = sul;
414  DestIterator zd = dul;
415 
416  // assume that a region is a extremum until the opposite is proved
417  std::vector<unsigned char> isExtremum(number_of_regions + 1, (unsigned char)1);
418 
419  for (z = 0; z != d; ++z, ++zs.dim2(), ++zd.dim2(), ++zl.dim2())
420  {
421  SrcIterator ys(zs);
422  DestIterator yd(zd);
423  MultiArray<3, int>::traverser yl(zl);
424 
425  for (y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1(), ++yl.dim1())
426  {
427  SrcIterator xs(ys);
428  DestIterator xd(yd);
429  MultiArray<3, int>::traverser xl(yl);
430 
431  for (x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0(), ++xl.dim0())
432  {
433 
434  int lab = *xl;
435  SrcType v = sa(xs);
436 
437  if (isExtremum[lab] == 0)
438  continue;
439 
440  if (!compare(v, threshold))
441  {
442  // mark all regions that don't exceed the threshold as non-extremum
443  isExtremum[lab] = 0;
444  continue;
445  }
446 
447  AtVolumeBorder atBorder = isAtVolumeBorder(x, y, z, w, h, d);
448  if (atBorder == NotAtBorder)
449  {
450  NeighborhoodCirculator<SrcIterator, Neighborhood> sc(xs);
451  NeighborhoodCirculator<MultiArray<3, int>::traverser, Neighborhood> lc(xl);
452  for (i = 0; i < Neighborhood::DirectionCount; ++i, ++sc, ++lc)
453  {
454  if (lab != *lc && compare(sa(sc), v))
455  {
456 
457  isExtremum[lab] = 0;
458  break;
459  }
460  }
461  }
462  else
463  {
464  if (allowExtremaAtBorder)
465  {
466  RestrictedNeighborhoodCirculator<SrcIterator, Neighborhood>
467  sc(xs, atBorder), scend(sc);
468  do
469  {
470  if (lab != *(xl + sc.diff()) && compare(sa(sc), v))
471  {
472  isExtremum[lab] = 0;
473  break;
474  }
475  }
476  while (++sc != scend);
477  }
478  else
479  {
480  isExtremum[lab] = 0;
481  }
482  }
483  }
484  }
485  }
486 
487  zl = labels.traverser_begin();
488  zs = sul;
489  zd = dul;
490 
491  for (z = 0; z != d; ++z, ++zs.dim2(), ++zd.dim2(), ++zl.dim2())
492  {
493  SrcIterator ys(zs);
494  DestIterator yd(zd);
495  MultiArray<3, int>::traverser yl(zl);
496 
497  for (y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1(), ++yl.dim1())
498  {
499  SrcIterator xs(ys);
500  DestIterator xd(yd);
501  MultiArray<3, int>::traverser xl(yl);
502 
503  for (x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0(), ++xl.dim0())
504  {
505  if(isExtremum[*xl])
506  da.set(marker, xd);
507  }
508  }
509  }
510 }
511 
512 template <class SrcIterator, class SrcAccessor,
513  class DestIterator, class DestAccessor, class DestValue,
514  class Neighborhood, class Compare, class Equal>
515 void
516 extendedLocalMinMaxOld(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
517  DestIterator dul, DestAccessor da, DestValue marker,
518  Neighborhood /*neighborhood*/,
519  Compare compare, Equal equal,
520  typename SrcAccessor::value_type threshold,
521  bool allowExtremaAtBorder = false)
522 {
523  typedef typename SrcAccessor::value_type SrcType;
524 
525  int w = slr.x - sul.x;
526  int h = slr.y - sul.y;
527 
528  int i,x,y;
529 
530  BasicImage<int> labels(w,h);
531 
532  int number_of_regions =
533  labelImage(sul, slr, sa, labels.upperLeft(), labels.accessor(),
534  (Neighborhood::DirectionCount == 8), equal);
535 
536  // assume that a region is a extremum until the opposite is proved
537  std::vector<unsigned char> isExtremum(number_of_regions+1, (unsigned char)1);
538 
539  BasicImage<int>::traverser ly = labels.upperLeft();
540 
541  for(y=0; y<h; ++y, ++sul.y, ++ly.y)
542  {
543  SrcIterator sx = sul;
544  BasicImage<int>::traverser lx(ly);
545 
546  for(x=0; x<w; ++x, ++sx.x, ++lx.x)
547  {
548  int lab = *lx;
549  SrcType v = sa(sx);
550  if(x == 0 || y == 0 || x == w-1 || y == h-1 || !compare(v, threshold))
551  {
552  // mark all regions that touch the image border as non-extremum
553  // likewise for all pixels that don't exceed the threshold
554  isExtremum[lab] = 0;
555  continue;
556  }
557 
558  NeighborhoodCirculator<SrcIterator, Neighborhood> sc(sx);
559  NeighborhoodCirculator<BasicImage<int>::traverser, Neighborhood> lc(lx);
560  for(i=0; i<Neighborhood::DirectionCount; ++i, ++sc, ++lc)
561  {
562  if(lab != *lc && compare(sa(sc),v))
563  isExtremum[lab] = 0;
564  }
565 
566  }
567  }
568 
569  ly = labels.upperLeft();
570  for(y=0; y<h; ++y, ++dul.y, ++ly.y)
571  {
572  DestIterator xd = dul;
573  BasicImage<int>::Iterator lx(ly);
574 
575  for(x=0; x<w; ++x, ++xd.x, ++lx.x)
576  {
577  if(isExtremum[*lx])
578  da.set(marker, xd);
579  }
580  }
581 }
582 
583 } // namespace detail
584 
585 
586 /** \brief Options object for localMinima() and localMaxima().
587 
588  <b> Usage:</b>
589 
590  <b>\#include</b> <vigra/localminmax.hxx><br>
591  Namespace: vigra
592 
593  \code
594  vigra::BImage src(w,h), minima(w,h);
595  ... // fill src
596 
597  // use 4-neighborhood, allow minima at the image border,
598  // and discard those where the gray value is not below 5
599  vigra::localMinima(srcImageRange(src), destImage(minima),
600  vigra::LocalMinmaxOptions().neighborhood(4).allowAtBorder().threshold(5));
601 
602  \endcode
603 */
605 {
606  public:
607  double marker, thresh;
608  int neigh;
609  bool use_threshold, allow_at_border, allow_plateaus;
610 
611  /**\brief Construct default options object.
612  *
613  Defaults are: marker value '1', no threshold, indirect neighborhood,
614  don't allow extrema at border and extremal plateaus.
615  */
617  : marker(1.0),
618  thresh(0.0),
619  neigh(1),
620  use_threshold(false),
621  allow_at_border(false),
622  allow_plateaus(false)
623  {}
624 
625  /**\brief Use the given neighborhood.
626 
627  The value '0' indicates direct neighborhood (i.e. 4-neighborhood
628  in 2D, 6-neighborhood in 3D, 2*N neighborhood in N-D), the value '1'
629  indicates indirect neighborhood (i.e. 8-neighborhood in 2D,
630  26-neighborhood in 3D, 3<sup>N</sup>-1 neighborhood in N-D). The specific number
631  of neighbors for the desired dimension can also be used.
632 
633  Default: 1 (indirect neighborhood)
634  */
636  {
637  neigh = n;
638  return *this;
639  }
640 
641  /**\brief Mark extrema in the destination image with the given value.
642 
643  Default: 1
644  */
646  {
647  marker = m;
648  return *this;
649  }
650 
651  /**\brief Threshold the extrema.
652 
653  Discard minima whose gray value is not below the threshold.
654  and maxima whose gray level is not above the threshold.
655 
656  Default: don't threshold (i.e. return all extrema)
657  */
659  {
660  use_threshold = true;
661  thresh = t;
662  return *this;
663  }
664 
665  /**\brief Detect extrema at the image border.
666 
667  Default: false
668  */
670  {
671  allow_at_border = f;
672  return *this;
673  }
674 
675  /**\brief Allow extremal plateaus.
676 
677  That is regions of constant gray value whose neighbors are all
678  higher (minima) or lower than the value of the region.
679 
680  Default: false
681  */
683  {
684  allow_plateaus = f;
685  return *this;
686  }
687 };
688 
689 
690 /********************************************************/
691 /* */
692 /* localMinima */
693 /* */
694 /********************************************************/
695 
696 /** \brief Find local minima in an image or multi-dimensional array.
697 
698  Note: the function is not yet implemented for arbitrary dimensional
699  arrays, but see \ref localMinima3D() for 3D.
700 
701  By default, minima are defined as points which are not
702  at the array border and whose value is lower than the value
703  of all indirect neighbors (i.e. 8-neighbors in 2D,
704  26-neighbors in 3D, 3<sup>N</sup>-1 neighbors in N-D).
705  The detected points will be marked
706  with the default value 1 in the destination array.
707 
708  The defaults can be overridden in various ways by providing
709  \ref LocalMinmaxOptions : you can switch to the direct neighborhood
710  (i.e. 4-neighborhood in 2D, 6-neighborhood in 3D, 2*N neighborhood
711  in N-D), allow minima at the border, discard minima where the function
712  value is not below a given threshold, allow extended minima
713  (i.e. minima that form minimal plateaus rather than isolated pixels --
714  note that this option is only supported for 2D images),
715  and change the marker in the destination image. See usage examples below
716  for details.
717 
718  There are also variants of the localMinima() function where parameters
719  are passed explicitly rather than via an option object. These versions
720  of the function are deprecated, but will be kept for compatibility.
721 
722  <b> Declarations:</b>
723 
724  use arbitrary-dimensional arrays:
725  \code
726  namespace vigra {
727  template <unsigned int N, class T1, class C1, class T2, class C2>
728  void
729  localMinima(MultiArrayView<N, T1, C1> src,
730  MultiArrayView<N, T2, C2> dest,
731  LocalMinmaxOptions const & options = LocalMinmaxOptions());
732  }
733  \endcode
734 
735  pass image iterators explicitly:
736  \code
737  namespace vigra {
738  template <class SrcIterator, class SrcAccessor,
739  class DestIterator, class DestAccessor>
740  void
741  localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
742  DestIterator dul, DestAccessor da,
743  LocalMinmaxOptions const & options = LocalMinmaxOptions());
744  }
745  \endcode
746 
747  use argument objects in conjunction with \ref ArgumentObjectFactories :
748  \code
749  namespace vigra {
750  template <class SrcIterator, class SrcAccessor,
751  class DestIterator, class DestAccessor>
752  void
753  localMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
754  pair<DestIterator, DestAccessor> dest,
755  LocalMinmaxOptions const & options = LocalMinmaxOptions());
756  }
757  \endcode
758 
759  <b> Usage:</b>
760 
761  <b>\#include</b> <vigra/localminmax.hxx><br>
762  <b>\#include</b> <vigra/multi_localminmax.hxx><br>
763  Namespace: vigra
764 
765  \code
766  // 3D examples using MultiArray
767  vigra::MultiArrayShape<3>::type shape(w,h,d);
768  vigra::MultiArray<3, unsigned char> src(shape), minima(shape);
769  ... // fill src
770 
771  // use default parameterisation
772  vigra::localMinima(src, minima);
773 
774  // reset destination image
775  minima = 0;
776 
777  // use 6-neighborhood and allow minima at the image border
778  vigra::localMinima(src, minima,
779  vigra::LocalMinmaxOptions().neighborhood(6).allowAtBorder());
780  \endcode
781 
782  \code
783  // 2D examples using BasicImage
784  vigra::BImage src(w,h), minima(w,h);
785  ... // fill src
786 
787  // use default parameterisation
788  vigra::localMinima(srcImageRange(src), destImage(minima));
789 
790  // reset destination image
791  minima = 0;
792 
793  // use 4-neighborhood and allow minima at the image border
794  vigra::localMinima(srcImageRange(src), destImage(minima),
795  vigra::LocalMinmaxOptions().neighborhood(4).allowAtBorder());
796 
797  // reset destination image
798  minima = 0;
799 
800  // allow extended minima (minimal plateaus) and use value '255' as a marker
801  vigra::localMinima(srcImageRange(src), destImage(minima),
802  vigra::LocalMinmaxOptions().allowPlateaus().markWith(255));
803  \endcode
804 
805  <b> Required Interface:</b>
806 
807  \code
808  SrcIterator src_upperleft, src_lowerright;
809  DestIterator dest_upperleft;
810 
811  SrcAccessor src_accessor;
812  DestAccessor dest_accessor;
813 
814  SrcAccessor::value_type u = src_accessor(src_upperleft);
815 
816  u < u
817  \endcode
818 */
819 doxygen_overloaded_function(template <...> void localMinima)
820 
821 template <class SrcIterator, class SrcAccessor,
822  class DestIterator, class DestAccessor>
823 inline void
824 localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
825  DestIterator dul, DestAccessor da,
826  LocalMinmaxOptions const & options = LocalMinmaxOptions())
827 {
828  typedef typename SrcAccessor::value_type SrcType;
829  typedef typename DestAccessor::value_type DestType;
830 
831  SrcType threshold = options.use_threshold
832  ? std::min(NumericTraits<SrcType>::max(), (SrcType)options.thresh)
833  : NumericTraits<SrcType>::max();
834  DestType marker = (DestType)options.marker;
835 
836  if(options.allow_plateaus)
837  {
838  if(options.neigh == 0 || options.neigh == 4)
839  {
840  detail::extendedLocalMinMax(sul, slr, sa, dul, da, marker, FourNeighborCode(),
841  std::less<SrcType>(), std::equal_to<SrcType>(),
842  threshold, options.allow_at_border);
843  }
844  else if(options.neigh == 1 || options.neigh == 8)
845  {
846  detail::extendedLocalMinMax(sul, slr, sa, dul, da, marker, EightNeighborCode(),
847  std::less<SrcType>(), std::equal_to<SrcType>(),
848  threshold, options.allow_at_border);
849  }
850  else
851  vigra_precondition(false, "localMinima(): neighborhood must be 4 or 8.");
852 
853  }
854  else
855  {
856  if(options.neigh == 0 || options.neigh == 4)
857  {
858  detail::localMinMax(sul, slr, sa, dul, da, marker, FourNeighborCode(),
859  threshold, std::less<SrcType>(), options.allow_at_border);
860  }
861  else if(options.neigh == 1 || options.neigh == 8)
862  {
863  detail::localMinMax(sul, slr, sa, dul, da, marker, EightNeighborCode(),
864  threshold, std::less<SrcType>(), options.allow_at_border);
865  }
866  else
867  vigra_precondition(false, "localMinima(): neighborhood must be 4 or 8.");
868  }
869 }
870 
871 template <class SrcIterator, class SrcAccessor,
872  class DestIterator, class DestAccessor,
873  class DestValue>
874 inline void
875 localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
876  DestIterator dul, DestAccessor da,
877  DestValue marker, FourNeighborCode neighborhood)
878 {
879  detail::localMinMax(sul, slr, sa, dul, da, marker, neighborhood,
881  std::less<typename SrcAccessor::value_type>());
882 }
883 
884 template <class SrcIterator, class SrcAccessor,
885  class DestIterator, class DestAccessor,
886  class DestValue>
887 inline void
888 localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
889  DestIterator dul, DestAccessor da,
890  DestValue marker, EightNeighborCode neighborhood)
891 {
892  detail::localMinMax(sul, slr, sa, dul, da, marker, neighborhood,
894  std::less<typename SrcAccessor::value_type>());
895 }
896 
897 template <class SrcIterator, class SrcAccessor,
898  class DestIterator, class DestAccessor, class DestValue>
899 inline void
900 localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
901  DestIterator dul, DestAccessor da,
902  DestValue marker)
903 {
904  localMinima(sul, slr, sa, dul, da, marker, EightNeighborCode());
905 }
906 
907 template <class SrcIterator, class SrcAccessor,
908  class DestIterator, class DestAccessor,
909  class DestValue>
910 inline void
911 localMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
912  pair<DestIterator, DestAccessor> dest,
913  DestValue marker, FourNeighborCode neighborhood)
914 {
915  localMinima(src.first, src.second, src.third,
916  dest.first, dest.second, marker, neighborhood);
917 }
918 
919 template <class SrcIterator, class SrcAccessor,
920  class DestIterator, class DestAccessor,
921  class DestValue>
922 inline void
923 localMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
924  pair<DestIterator, DestAccessor> dest,
925  DestValue marker, EightNeighborCode neighborhood)
926 {
927  localMinima(src.first, src.second, src.third,
928  dest.first, dest.second, marker, neighborhood);
929 }
930 
931 template <class SrcIterator, class SrcAccessor,
932  class DestIterator, class DestAccessor, class DestValue>
933 inline void
934 localMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
935  pair<DestIterator, DestAccessor> dest,
936  DestValue marker)
937 {
938  localMinima(src.first, src.second, src.third,
939  dest.first, dest.second, marker, EightNeighborCode());
940 }
941 
942 template <class SrcIterator, class SrcAccessor,
943  class DestIterator, class DestAccessor>
944 inline void
945 localMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
946  pair<DestIterator, DestAccessor> dest,
947  LocalMinmaxOptions const & options = LocalMinmaxOptions())
948 {
949  localMinima(src.first, src.second, src.third,
950  dest.first, dest.second, options);
951 }
952 
953 /**************************************************************************/
954 
955 /********************************************************/
956 /* */
957 /* localMinima3D */
958 /* */
959 /********************************************************/
960 
961 /** \brief Find local minima in a 3D multi array.
962 
963  By default, minima are defined as points which are not
964  at the array border and whose value is lower than the value
965  of all indirect neighbors.
966  The detected points will be marked. See localMinima() for more details.
967 
968  */
969 doxygen_overloaded_function(template <...> void localMinima3D)
970 
971 template<class SrcIterator, class SrcAccessor, class SrcShape,
972  class DestIterator, class DestAccessor, class DestValue>
973 inline void
974 localMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
975  DestIterator dul, DestAccessor da,
976  DestValue marker,
977  NeighborCode3DTwentySix neighborhood)
978 {
979  detail::localMinMax3D(sul, slr, sa, dul, da, marker, neighborhood,
981  std::less<typename SrcAccessor::value_type>());
982 }
983 
984 template<class SrcIterator, class SrcAccessor, class SrcShape,
985  class DestIterator, class DestAccessor, class DestValue>
986 inline void
987 localMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
988  DestIterator dul, DestAccessor da,
989  DestValue marker,
990  NeighborCode3DSix neighborhood)
991 {
992  detail::localMinMax3D(sul, slr, sa, dul, da, marker, neighborhood,
994  std::less<typename SrcAccessor::value_type>());
995 }
996 
997 template<class SrcIterator, class SrcShape, class SrcAccessor,
998  class DestIterator, class DestAccessor, class DestValue>
999 inline void
1000 localMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
1001  DestIterator dul, DestAccessor da,
1002  DestValue marker)
1003 {
1004  localMinima3D(sul, slr, sa, dul, da, marker, NeighborCode3DSix());
1005 }
1006 
1007 template<class SrcIterator, class SrcShape, class SrcAccessor,
1008  class DestIterator, class DestAccessor, class DestValue>
1009 inline void
1010 localMinima3D(triple<SrcIterator, SrcShape, SrcAccessor> src,
1011  pair<DestIterator, DestAccessor> dest,
1012  DestValue marker,
1013  NeighborCode3DSix neighborhood)
1014 {
1015  localMinima3D(src.first, src.second, src.third, dest.first, dest.second,
1016  marker, neighborhood);
1017 }
1018 
1019 template<class SrcIterator, class SrcShape, class SrcAccessor,
1020  class DestIterator, class DestAccessor, class DestValue>
1021 inline void
1022 localMinima3D(triple<SrcIterator, SrcShape, SrcAccessor> src,
1023  pair<DestIterator, DestAccessor> dest,
1024  DestValue marker,
1025  NeighborCode3DTwentySix neighborhood)
1026 {
1027  localMinima3D(src.first, src.second, src.third, dest.first, dest.second,
1028  marker, neighborhood);
1029 }
1030 
1031 /**************************************************************************/
1032 
1033 /********************************************************/
1034 /* */
1035 /* localMaxima */
1036 /* */
1037 /********************************************************/
1038 
1039 /** \brief Find local maxima in an image or multi-dimensional array.
1040 
1041  Note: the function is not yet implemented for arbitrary dimensional
1042  arrays, but see \ref localMaxima3D() for 3D.
1043 
1044  By default, maxima are defined as points which are not
1045  at the array border and whose value is higher than the value
1046  of all indirect neighbors (i.e. 8-neighbors in 2D,
1047  26-neighbors in 3D, 3<sup>N</sup>-1 neighbors in N-D).
1048  The detected points will be marked
1049  with the default value 1 in the destination array.
1050 
1051  The defaults can be overridden in various ways by providing
1052  \ref LocalMinmaxOptions : you can switch to the direct neighborhood
1053  (i.e. 4-neighborhood in 2D, 6-neighborhood in 3D, 2*N neighborhood
1054  in N-D), allow maxima at the border, discard maxima where the function
1055  value is not above a given threshold, allow extended maxima
1056  (i.e. maxima that form maximal plateaus rather than isolated pixels --
1057  note that this option is only supported for 2D images),
1058  and change the marker in the destination image. See usage examples below
1059  for details.
1060 
1061  There are also variants of the localMaxima() function where parameters
1062  are passed explicitly rather than via an option object. These versions
1063  of the function are deprecated, but will be kept for compatibility.
1064 
1065  <b> Declarations:</b>
1066 
1067  use arbitrary-dimensional arrays:
1068  \code
1069  namespace vigra {
1070  template <unsigned int N, class T1, class C1, class T2, class C2>
1071  void
1072  localMaxima(MultiArrayView<N, T1, C1> src,
1073  MultiArrayView<N, T2, C2> dest,
1074  LocalMinmaxOptions const & options = LocalMinmaxOptions());
1075  }
1076  \endcode
1077 
1078  pass image iterators explicitly:
1079  \code
1080  namespace vigra {
1081  template <class SrcIterator, class SrcAccessor,
1082  class DestIterator, class DestAccessor>
1083  void
1084  localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1085  DestIterator dul, DestAccessor da,
1086  LocalMinmaxOptions const & options = LocalMinmaxOptions());
1087  }
1088  \endcode
1089 
1090  use argument objects in conjunction with \ref ArgumentObjectFactories :
1091  \code
1092  namespace vigra {
1093  template <class SrcIterator, class SrcAccessor,
1094  class DestIterator, class DestAccessor>
1095  void
1096  localMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1097  pair<DestIterator, DestAccessor> dest,
1098  LocalMinmaxOptions const & options = LocalMinmaxOptions());
1099  }
1100  \endcode
1101 
1102  <b> Usage:</b>
1103 
1104  <b>\#include</b> <vigra/localminmax.hxx><br>
1105  <b>\#include</b> <vigra/multi_localminmax.hxx><br>
1106  Namespace: vigra
1107 
1108  \code
1109  // 3D examples using MultiArray
1110  vigra::MultiArrayShape<3>::type shape(w,h,d);
1111  vigra::MultiArray<3, unsigned char> src(shape), maxima(shape);
1112  ... // fill src
1113 
1114  // use default parameterisation
1115  vigra::localMaxima(src, maxima);
1116 
1117  // reset destination image
1118  maxima = 0;
1119 
1120  // use 6-neighborhood and allow maxima at the image border
1121  vigra::localMaxima(src, maxima,
1122  vigra::LocalMinmaxOptions().neighborhood(6).allowAtBorder());
1123  \endcode
1124 
1125  \code
1126  // 2D examples using BasicImage
1127  vigra::BImage src(w,h), maxima(w,h);
1128  ... // fill src
1129 
1130  // use default parameterisation
1131  vigra::localMaxima(srcImageRange(src), destImage(maxima));
1132 
1133  // reset destination image
1134  maxima = 0;
1135 
1136  // use 4-neighborhood and allow maxima at the image border
1137  vigra::localMaxima(srcImageRange(src), destImage(maxima),
1138  vigra::LocalMinmaxOptions().neighborhood(4).allowAtBorder());
1139 
1140  // reset destination image
1141  maxima = 0;
1142 
1143  // allow extended maxima (maximal plateaus) and use value '255' as a marker
1144  vigra::localMaxima(srcImageRange(src), destImage(maxima),
1145  vigra::LocalMinmaxOptions().allowPlateaus().markWith(255));
1146  \endcode
1147 
1148  <b> Required Interface:</b>
1149 
1150  \code
1151  SrcIterator src_upperleft, src_lowerright;
1152  DestIterator dest_upperleft;
1153 
1154  SrcAccessor src_accessor;
1155  DestAccessor dest_accessor;
1156 
1157  SrcAccessor::value_type u = src_accessor(src_upperleft);
1158 
1159  u < u
1160  \endcode
1161 */
1162 doxygen_overloaded_function(template <...> void localMaxima)
1163 
1164 template <class SrcIterator, class SrcAccessor,
1165  class DestIterator, class DestAccessor>
1166 inline void
1167 localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1168  DestIterator dul, DestAccessor da,
1169  LocalMinmaxOptions const & options = LocalMinmaxOptions())
1170 {
1171  typedef typename SrcAccessor::value_type SrcType;
1172  typedef typename DestAccessor::value_type DestType;
1173 
1174  SrcType threshold = options.use_threshold
1175  ? std::max(NumericTraits<SrcType>::min(), (SrcType)options.thresh)
1176  : NumericTraits<SrcType>::min();
1177  DestType marker = (DestType)options.marker;
1178 
1179  if(options.allow_plateaus)
1180  {
1181  if(options.neigh == 0 || options.neigh == 4)
1182  {
1183  detail::extendedLocalMinMax(sul, slr, sa, dul, da, marker, FourNeighborCode(),
1184  std::greater<SrcType>(), std::equal_to<SrcType>(),
1185  threshold, options.allow_at_border);
1186  }
1187  else if(options.neigh == 1 || options.neigh == 8)
1188  {
1189  detail::extendedLocalMinMax(sul, slr, sa, dul, da, marker, EightNeighborCode(),
1190  std::greater<SrcType>(), std::equal_to<SrcType>(),
1191  threshold, options.allow_at_border);
1192  }
1193  else
1194  vigra_precondition(false, "localMaxima(): neighborhood must be 4 or 8.");
1195  }
1196  else
1197  {
1198  if(options.neigh == 0 || options.neigh == 4)
1199  {
1200  detail::localMinMax(sul, slr, sa, dul, da, marker, FourNeighborCode(),
1201  threshold, std::greater<SrcType>(), options.allow_at_border);
1202  }
1203  else if(options.neigh == 1 || options.neigh == 8)
1204  {
1205  detail::localMinMax(sul, slr, sa, dul, da, marker, EightNeighborCode(),
1206  threshold, std::greater<SrcType>(), options.allow_at_border);
1207  }
1208  else
1209  vigra_precondition(false, "localMaxima(): neighborhood must be 4 or 8.");
1210  }
1211 }
1212 
1213 template <class SrcIterator, class SrcAccessor,
1214  class DestIterator, class DestAccessor,
1215  class DestValue>
1216 inline void
1217 localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1218  DestIterator dul, DestAccessor da,
1219  DestValue marker, FourNeighborCode neighborhood)
1220 {
1221  detail::localMinMax(sul, slr, sa, dul, da, marker, neighborhood,
1223  std::greater<typename SrcAccessor::value_type>());
1224 }
1225 
1226 template <class SrcIterator, class SrcAccessor,
1227  class DestIterator, class DestAccessor,
1228  class DestValue>
1229 inline void
1230 localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1231  DestIterator dul, DestAccessor da,
1232  DestValue marker, EightNeighborCode neighborhood)
1233 {
1234  detail::localMinMax(sul, slr, sa, dul, da, marker, neighborhood,
1236  std::greater<typename SrcAccessor::value_type>());
1237 }
1238 
1239 template <class SrcIterator, class SrcAccessor,
1240  class DestIterator, class DestAccessor, class DestValue>
1241 inline void
1242 localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1243  DestIterator dul, DestAccessor da,
1244  DestValue marker)
1245 {
1246  localMaxima(sul, slr, sa, dul, da, marker, EightNeighborCode());
1247 }
1248 
1249 template <class SrcIterator, class SrcAccessor,
1250  class DestIterator, class DestAccessor,
1251  class DestValue>
1252 inline void
1253 localMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1254  pair<DestIterator, DestAccessor> dest,
1255  DestValue marker, FourNeighborCode neighborhood)
1256 {
1257  localMaxima(src.first, src.second, src.third,
1258  dest.first, dest.second, marker, neighborhood);
1259 }
1260 
1261 template <class SrcIterator, class SrcAccessor,
1262  class DestIterator, class DestAccessor,
1263  class DestValue>
1264 inline void
1265 localMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1266  pair<DestIterator, DestAccessor> dest,
1267  DestValue marker, EightNeighborCode neighborhood)
1268 {
1269  localMaxima(src.first, src.second, src.third,
1270  dest.first, dest.second, marker, neighborhood);
1271 }
1272 
1273 template <class SrcIterator, class SrcAccessor,
1274  class DestIterator, class DestAccessor, class DestValue>
1275 inline void
1276 localMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1277  pair<DestIterator, DestAccessor> dest,
1278  DestValue marker)
1279 {
1280  localMaxima(src.first, src.second, src.third,
1281  dest.first, dest.second, marker, EightNeighborCode());
1282 }
1283 
1284 template <class SrcIterator, class SrcAccessor,
1285  class DestIterator, class DestAccessor>
1286 inline void
1287 localMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1288  pair<DestIterator, DestAccessor> dest,
1289  LocalMinmaxOptions const & options = LocalMinmaxOptions())
1290 {
1291  localMaxima(src.first, src.second, src.third,
1292  dest.first, dest.second, options);
1293 }
1294 
1295 /**************************************************************************/
1296 
1297 /********************************************************/
1298 /* */
1299 /* localMaxima3D */
1300 /* */
1301 /********************************************************/
1302 
1303 /** \brief Find local maxima in a 3D multi array.
1304 
1305  By default, maxima are defined as points which are not
1306  at the array border and whose value is higher than the value
1307  of all indirect neighbors.
1308  The detected points will be marked as specified. See localMaxima() for mor details.
1309  */
1310 doxygen_overloaded_function(template <...> void localMaxima3D)
1311 
1312 template<class SrcIterator, class SrcShape, class SrcAccessor,
1313  class DestIterator, class DestAccessor, class DestValue>
1314 inline void
1315 localMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
1316  DestIterator dul, DestAccessor da,
1317  DestValue marker,
1318  NeighborCode3DSix neighborhood)
1319 {
1320  detail::localMinMax3D(sul, slr, sa, dul, da, marker, neighborhood,
1322  std::greater<typename SrcAccessor::value_type>());
1323 }
1324 
1325 template<class SrcIterator, class SrcShape, class SrcAccessor,
1326  class DestIterator, class DestAccessor, class DestValue>
1327 inline void
1328 localMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
1329  DestIterator dul, DestAccessor da,
1330  DestValue marker,
1331  NeighborCode3DTwentySix neighborhood)
1332 {
1333  detail::localMinMax3D(sul, slr, sa, dul, da, marker, neighborhood,
1335  std::greater<typename SrcAccessor::value_type>());
1336 }
1337 
1338 template<class SrcIterator, class SrcShape, class SrcAccessor,
1339  class DestIterator, class DestAccessor, class DestValue>
1340 inline void
1341 localMaxima3D(triple<SrcIterator, SrcShape, SrcAccessor> src,
1342  pair<DestIterator, DestAccessor> dest,
1343  DestValue marker,
1344  NeighborCode3DTwentySix neighborhood)
1345 {
1346  localMaxima3D(src.first, src.second, src.third, dest.first, dest.second,
1347  marker, neighborhood);
1348 }
1349 
1350 template<class SrcIterator, class SrcShape, class SrcAccessor,
1351  class DestIterator, class DestAccessor, class DestValue>
1352 inline void
1353 localMaxima3D(vigra::triple<SrcIterator, SrcShape, SrcAccessor> src,
1354  std::pair<DestIterator, DestAccessor> dest,
1355  DestValue marker)
1356 {
1357  localMaxima3D(src.first, src.second, src.third, dest.first, dest.second,
1358  marker, NeighborCode3DSix());
1359 }
1360 
1361 template<class SrcIterator, class SrcShape, class SrcAccessor,
1362  class DestIterator, class DestAccessor, class DestValue>
1363 inline void
1364 localMaxima3D(triple<SrcIterator, SrcShape, SrcAccessor> src,
1365  pair<DestIterator, DestAccessor> dest,
1366  DestValue marker,
1367  NeighborCode3DSix neighborhood)
1368 {
1369  localMaxima3D(src.first, src.second, src.third, dest.first, dest.second,
1370  marker, neighborhood);
1371 }
1372 
1373 /**************************************************************************/
1374 
1375 /********************************************************/
1376 /* */
1377 /* extendedLocalMinima */
1378 /* */
1379 /********************************************************/
1380 
1381 /** \brief Find local minimal regions in an image or volume.
1382 
1383  Note: the function is not yet implemented for arbitrary dimensional
1384  arrays, but see \ref extendedLocalMinima3D() for 3D.
1385 
1386  This function finds regions of uniform pixel value
1387  whose neighboring regions are all have smaller values
1388  (minimal plateaus of arbitrary size). By default, the pixels
1389  in a plateau have exactly identical values. By passing an <tt>EqualityFunctor</tt>
1390  with tolerance, one can allow for plateaus that are not quite constant
1391  (this is often necessary with float pixel values). Pass
1392  \ref vigra::EightNeighborCode or \ref vigra::FourNeighborCode
1393  to determine the neighborhood where pixel values are compared.
1394 
1395  Minimal regions are
1396  marked in the destination image with the given marker value
1397  (default is 1), all other destination pixels remain unchanged.
1398  <TT>SrcAccessor::value_type</TT> must be equality-comparable and
1399  less-comparable. A pixel or region touching the image border will
1400  never be marked as minimum or minimal plateau. Use localMinima() with the
1401  appropriate options if you need that functionality. Likewise if you want to
1402  apply a threshold onl the fly. In fact, all functionality
1403  except for 'equality with tolerance' can be accessed via that function in
1404  a more readable way, so localMinima() should be preferred.
1405  The function uses accessors.
1406 
1407  <b> Declarations:</b>
1408 
1409  use 3-dimensional arrays:
1410  \code
1411  namespace vigra {
1412  template <class T1, class C1, class T2, class C2,
1413  class Neighborhood>
1414  void
1415  extendedLocalMinima(MultiArrayView<3, T1, C1> src,
1416  MultiArrayView<3, T2, C2> dest,
1417  LocalMinmaxOptions const & options = LocalMinmaxOptions());
1418  \endcode
1419 
1420  pass image iterators explicitly:
1421  \code
1422  namespace vigra {
1423  template <class SrcIterator, class SrcAccessor,
1424  class DestIterator, class DestAccessor,
1425  class DestValue = DestAccessor::value_type,
1426  class Neighborhood = EightNeighborCode,
1427  class EqualityFunctor = std::equal_to<typename SrcAssessor::value_type> >
1428  void
1429  extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1430  DestIterator dul, DestAccessor da,
1431  DestValue marker = NumericTraits<DestValue>::one(),
1432  Neighborhood neighborhood = EightNeighborCode(),
1433  EqualityFunctor equal = EqualityFunctor());
1434  }
1435  \endcode
1436 
1437  use argument objects in conjunction with \ref ArgumentObjectFactories :
1438  \code
1439  namespace vigra {
1440  template <class SrcIterator, class SrcAccessor,
1441  class DestIterator, class DestAccessor,
1442  class DestValue = DestAccessor::value_type,
1443  class Neighborhood = EightNeighborCode,
1444  class EqualityFunctor = std::equal_to<typename SrcAssessor::value_type> >
1445  void
1446  extendedLocalMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1447  pair<DestIterator, DestAccessor> dest,
1448  DestValue marker = NumericTraits<DestValue>::one(),
1449  Neighborhood neighborhood = EightNeighborCode(),
1450  EqualityFunctor equal = EqualityFunctor());
1451  }
1452  \endcode
1453 
1454  <b> Usage:</b>
1455 
1456  <b>\#include</b> <vigra/localminmax.hxx><br>
1457  Namespace: vigra
1458 
1459  \code
1460 
1461  // optional: define an equality functor
1462  template <class T>
1463  struct EqualWithToleranceFunctor
1464  {
1465  EqualWithToleranceFunctor(T tolerance)
1466  : t(tolerance)
1467  {}
1468 
1469  bool operator()(T l, T r) const
1470  {
1471  return vigra::abs(l-r) <= t;
1472  }
1473 
1474  T t;
1475  };
1476 
1477  vigra::BImage src(w,h), minima(w,h);
1478 
1479  // init destiniation image
1480  minima.init(0);
1481 
1482  vigra::extendedLocalMinima(srcImageRange(src), destImage(minima));
1483 
1484  // allow plateaus with tolerance
1485  minima.init(0);
1486  vigra::extendedLocalMinima(srcImageRange(src), destImage(minima), 1.0,
1487  EqualWithToleranceFunctor<unsigned char>(1));
1488  \endcode
1489 
1490  <b> Required Interface:</b>
1491 
1492  \code
1493  SrcImageIterator src_upperleft, src_lowerright;
1494  DestImageIterator dest_upperleft;
1495 
1496  SrcAccessor src_accessor;
1497  DestAccessor dest_accessor;
1498 
1499  SrcAccessor::value_type u = src_accessor(src_upperleft);
1500 
1501  EqualityFunctor equal;
1502  u == u
1503  equal(u, u);
1504  u < u
1505 
1506  DestValue marker;
1507  dest_accessor.set(marker, dest_upperleft);
1508  \endcode
1509 
1510 */
1511 doxygen_overloaded_function(template <...> void extendedLocalMinima)
1512 
1513 template <class SrcIterator, class SrcAccessor,
1514  class DestIterator, class DestAccessor,
1515  class Neighborhood, class EqualityFunctor>
1516 inline void
1517 extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1518  DestIterator dul, DestAccessor da,
1519  typename DestAccessor::value_type marker,
1520  Neighborhood neighborhood, EqualityFunctor equal)
1521 {
1522  typedef typename SrcAccessor::value_type SrcType;
1523 
1524  detail::extendedLocalMinMax(sul, slr, sa, dul, da,
1525  marker, neighborhood,
1526  std::less<SrcType>(), equal,
1528 }
1529 
1530 template <class SrcIterator, class SrcAccessor,
1531  class DestIterator, class DestAccessor,
1532  class Neighborhood>
1533 inline void
1534 extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1535  DestIterator dul, DestAccessor da,
1536  typename DestAccessor::value_type marker,
1537  Neighborhood neighborhood)
1538 {
1539  typedef typename SrcAccessor::value_type SrcType;
1540 
1541  extendedLocalMinima(sul, slr, sa, dul, da,
1542  marker, neighborhood, std::equal_to<SrcType>());
1543 }
1544 
1545 template <class SrcIterator, class SrcAccessor,
1546  class DestIterator, class DestAccessor>
1547 inline void
1548 extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1549  DestIterator dul, DestAccessor da,
1550  typename DestAccessor::value_type marker)
1551 {
1552  typedef typename SrcAccessor::value_type SrcType;
1553 
1554  extendedLocalMinima(sul, slr, sa, dul, da,
1555  marker, EightNeighborCode());
1556 }
1557 
1558 template <class SrcIterator, class SrcAccessor,
1559  class DestIterator, class DestAccessor>
1560 inline void
1561 extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1562  DestIterator dul, DestAccessor da)
1563 {
1564  extendedLocalMinima(sul, slr, sa, dul, da,
1565  NumericTraits<typename DestAccessor::value_type>::one());
1566 }
1567 
1568 template <class SrcIterator, class SrcAccessor,
1569  class DestIterator, class DestAccessor,
1570  class Neighborhood, class EqualityFunctor>
1571 inline void
1572 extendedLocalMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1573  pair<DestIterator, DestAccessor> dest,
1574  typename DestAccessor::value_type marker, Neighborhood neighborhood,
1575  EqualityFunctor equal)
1576 {
1577  extendedLocalMinima(src.first, src.second, src.third,
1578  dest.first, dest.second, marker, neighborhood, equal);
1579 }
1580 
1581 template <class SrcIterator, class SrcAccessor,
1582  class DestIterator, class DestAccessor,
1583  class Neighborhood>
1584 inline void
1585 extendedLocalMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1586  pair<DestIterator, DestAccessor> dest,
1587  typename DestAccessor::value_type marker, Neighborhood neighborhood)
1588 {
1589  extendedLocalMinima(src.first, src.second, src.third,
1590  dest.first, dest.second, marker, neighborhood);
1591 }
1592 
1593 template <class SrcIterator, class SrcAccessor,
1594  class DestIterator, class DestAccessor>
1595 inline void
1596 extendedLocalMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1597  pair<DestIterator, DestAccessor> dest,
1598  typename DestAccessor::value_type marker)
1599 {
1600  extendedLocalMinima(src.first, src.second, src.third,
1601  dest.first, dest.second, marker, EightNeighborCode());
1602 }
1603 
1604 template <class SrcIterator, class SrcAccessor,
1605  class DestIterator, class DestAccessor>
1606 inline void
1607 extendedLocalMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1608  pair<DestIterator, DestAccessor> dest)
1609 {
1610  extendedLocalMinima(src.first, src.second, src.third,
1611  dest.first, dest.second);
1612 }
1613 
1614 /**************************************************************************/
1615 
1616 /********************************************************/
1617 /* */
1618 /* extendedLocalMinima3D */
1619 /* */
1620 /********************************************************/
1621 
1622 /** \brief Find local minimal regions in a volume.
1623 
1624  This function finds regions of uniform pixel value
1625  whose neighboring regions are all have smaller values
1626  (minimal plateaus of arbitrary size). By default, the pixels
1627  in a plateau have exactly identical values. By passing an <tt>EqualityFunctor</tt>
1628  with tolerance, one can allow for plateaus that are not quite constant
1629  (this is often necessary with float pixel values). Pass the neighborhood
1630  where pixel values are compared. See extendedLocalMinima() for more details.
1631 
1632 */
1633 doxygen_overloaded_function(template <...> void extendedLocalMinima3D)
1634 
1635 template<class SrcIterator, class SrcShape, class SrcAccessor,
1636  class DestIterator, class DestAccessor, class Neighborhood,
1637  class EqualityFunctor>
1638 inline void
1639 extendedLocalMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
1640  DestIterator dul, DestAccessor da,
1641  typename DestAccessor::value_type marker,
1642  Neighborhood neighborhood,
1643  EqualityFunctor equal)
1644 {
1645  typedef typename SrcAccessor::value_type SrcType;
1646 
1647  detail::extendedLocalMinMax3D(sul, slr, sa, dul, da, marker, neighborhood,
1648  std::less<SrcType>(), equal,
1650 }
1651 
1652 template<class SrcIterator, class SrcShape, class SrcAccessor,
1653  class DestIterator, class DestAccessor, class Neighborhood>
1654 inline void
1655 extendedLocalMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
1656  DestIterator dul, DestAccessor da,
1657  typename DestAccessor::value_type marker,
1658  Neighborhood neighborhood)
1659 {
1660  typedef typename SrcAccessor::value_type SrcType;
1661 
1662  extendedLocalMinima3D(sul, slr, sa, dul, da, marker, neighborhood,
1663  std::equal_to<SrcType>());
1664 }
1665 
1666 template<class SrcIterator, class SrcShape, class SrcAccessor,
1667  class DestIterator, class DestAccessor>
1668 inline void
1669 extendedLocalMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
1670  DestIterator dul, DestAccessor da)
1671 {
1672  extendedLocalMinima3D(sul, slr, sa, dul, da,
1673  NumericTraits<typename DestAccessor::value_type>::one(),
1674  NeighborCode3DSix());
1675 }
1676 
1677 template<class SrcIterator, class SrcAccessor, class SrcShape,
1678  class DestIterator, class DestAccessor, class Neighborhood>
1679 inline void
1680 extendedLocalMinima3D(triple<SrcIterator, SrcShape, SrcAccessor> src,
1681  pair<DestIterator, DestAccessor> dest,
1682  typename DestAccessor::value_type marker,
1683  Neighborhood neighborhood)
1684 {
1685  extendedLocalMinima3D(src.first, src.second, src.third,
1686  dest.first, dest.second,
1687  marker, neighborhood);
1688 }
1689 
1690 /**************************************************************************/
1691 
1692 /********************************************************/
1693 /* */
1694 /* extendedLocalMaxima */
1695 /* */
1696 /********************************************************/
1697 
1698 /** \brief Find local maximal regions in an image or volume.
1699 
1700  Note: the function is not yet implemented for arbitrary dimensional
1701  arrays, but see \ref extendedLocalMaxima3D() for 3D.
1702 
1703  This function finds regions of uniform pixel value
1704  whose neighboring regions are all have smaller values
1705  (maximal plateaus of arbitrary size). By default, the pixels
1706  in a plateau have exactly identical values. By passing an <tt>EqualityFunctor</tt>
1707  with tolerance, one can allow for plateaus that are not quite constant
1708  (this is often necessary with float pixel values). Pass
1709  \ref vigra::EightNeighborCode or \ref vigra::FourNeighborCode
1710  to determine the neighborhood where pixel values are compared.
1711 
1712  Maximal regions are
1713  marked in the destination image with the given marker value
1714  (default is 1), all other destination pixels remain unchanged.
1715  <TT>SrcAccessor::value_type</TT> must be equality-comparable and
1716  less-comparable. A pixel or region touching the image border will
1717  never be marked as maximum or maximal plateau. Use localMaxima() with the
1718  appropriate options if you need that functionality. Likewise if you want to
1719  apply a threshold onl the fly. In fact, all functionality
1720  except for 'equality with tolerance' can be accessed via that function in
1721  a more readable way, so localMaxima() should be preferred.
1722  The function uses accessors.
1723 
1724  <b> Declarations:</b>
1725 
1726  use 3-dimensional arrays:
1727  \code
1728  namespace vigra {
1729  template <class T1, class C1, class T2, class C2,
1730  class Neighborhood>
1731  void
1732  extendedLocalMaxima(MultiArrayView<3, T1, C1> src,
1733  MultiArrayView<3, T2, C2> dest,
1734  LocalMinmaxOptions const & options = LocalMinmaxOptions());
1735  \endcode
1736 
1737  pass image iterators explicitly:
1738  \code
1739  namespace vigra {
1740  template <class SrcIterator, class SrcAccessor,
1741  class DestIterator, class DestAccessor,
1742  class DestValue = DestAccessor::value_type,
1743  class Neighborhood = EightNeighborCode,
1744  class EqualityFunctor = std::equal_to<typename SrcAssessor::value_type> >
1745  void
1746  extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1747  DestIterator dul, DestAccessor da,
1748  DestValue marker = NumericTraits<DestValue>::one(),
1749  Neighborhood neighborhood = EightNeighborCode(),
1750  EqualityFunctor equal = EqualityFunctor())
1751  }
1752  \endcode
1753 
1754  use argument objects in conjunction with \ref ArgumentObjectFactories :
1755  \code
1756  namespace vigra {
1757  template <class SrcIterator, class SrcAccessor,
1758  class DestIterator, class DestAccessor,
1759  class DestValue = DestAccessor::value_type,
1760  class Neighborhood = EightNeighborCode,
1761  class EqualityFunctor = std::equal_to<typename SrcAssessor::value_type> >
1762  void
1763  extendedLocalMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1764  pair<DestIterator, DestAccessor> dest,
1765  DestValue marker = NumericTraits<DestValue>::one(),
1766  Neighborhood neighborhood = EightNeighborCode(),
1767  EqualityFunctor equal = EqualityFunctor())
1768  }
1769  \endcode
1770 
1771  <b> Usage:</b>
1772 
1773  <b>\#include</b> <vigra/localminmax.hxx><br>
1774  Namespace: vigra
1775 
1776  \code
1777 
1778  // optional: define an equality functor
1779  template <class T>
1780  struct EqualWithToleranceFunctor
1781  {
1782  EqualWithToleranceFunctor(T tolerance)
1783  : t(tolerance)
1784  {}
1785 
1786  bool operator()(T l, T r) const
1787  {
1788  return vigra::abs(l-r) <= t;
1789  }
1790 
1791  T t;
1792  };
1793 
1794  vigra::BImage src(w,h), maxima(w,h);
1795 
1796  // init destiniation image
1797  maxima.init(0);
1798 
1799  vigra::extendedLocalMaxima(srcImageRange(src), destImage(maxima));
1800 
1801  // allow plateaus with tolerance
1802  maxima.init(0);
1803  vigra::extendedLocalMaxima(srcImageRange(src), destImage(maxima), 1.0,
1804  EqualWithToleranceFunctor<unsigned char>(1));
1805  \endcode
1806 
1807  <b> Required Interface:</b>
1808 
1809  \code
1810  SrcImageIterator src_upperleft, src_lowerright;
1811  DestImageIterator dest_upperleft;
1812 
1813  SrcAccessor src_accessor;
1814  DestAccessor dest_accessor;
1815 
1816  SrcAccessor::value_type u = src_accessor(src_upperleft);
1817 
1818  EqualityFunctor equal;
1819  u == u
1820  equal(u, u);
1821  u < u
1822 
1823  DestValue marker;
1824  dest_accessor.set(marker, dest_upperleft);
1825  \endcode
1826 
1827 */
1828 doxygen_overloaded_function(template <...> void extendedLocalMaxima)
1829 
1830 template <class SrcIterator, class SrcAccessor,
1831  class DestIterator, class DestAccessor,
1832  class Neighborhood, class EqualityFunctor>
1833 inline void
1834 extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1835  DestIterator dul, DestAccessor da,
1836  typename DestAccessor::value_type marker,
1837  Neighborhood neighborhood, EqualityFunctor equal)
1838 {
1839  typedef typename SrcAccessor::value_type SrcType;
1840 
1841  detail::extendedLocalMinMax(sul, slr, sa, dul, da,
1842  marker, neighborhood,
1843  std::greater<SrcType>(), equal,
1845 }
1846 
1847 template <class SrcIterator, class SrcAccessor,
1848  class DestIterator, class DestAccessor,
1849  class Neighborhood>
1850 inline void
1851 extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1852  DestIterator dul, DestAccessor da,
1853  typename DestAccessor::value_type marker,
1854  Neighborhood neighborhood)
1855 {
1856  typedef typename SrcAccessor::value_type SrcType;
1857 
1858  extendedLocalMaxima(sul, slr, sa, dul, da,
1859  marker, neighborhood, std::equal_to<SrcType>());
1860 }
1861 
1862 template <class SrcIterator, class SrcAccessor,
1863  class DestIterator, class DestAccessor>
1864 inline void
1865 extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1866  DestIterator dul, DestAccessor da,
1867  typename DestAccessor::value_type marker)
1868 {
1869  typedef typename SrcAccessor::value_type SrcType;
1870 
1871  extendedLocalMaxima(sul, slr, sa, dul, da,
1872  marker, EightNeighborCode());
1873 }
1874 
1875 template <class SrcIterator, class SrcAccessor,
1876  class DestIterator, class DestAccessor>
1877 inline void
1878 extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1879  DestIterator dul, DestAccessor da)
1880 {
1881  extendedLocalMaxima(sul, slr, sa, dul, da,
1882  NumericTraits<typename DestAccessor::value_type>::one());
1883 }
1884 
1885 template <class SrcIterator, class SrcAccessor,
1886  class DestIterator, class DestAccessor,
1887  class Neighborhood, class EqualityFunctor>
1888 inline void
1889 extendedLocalMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1890  pair<DestIterator, DestAccessor> dest,
1891  typename DestAccessor::value_type marker, Neighborhood neighborhood,
1892  EqualityFunctor equal)
1893 {
1894  extendedLocalMaxima(src.first, src.second, src.third,
1895  dest.first, dest.second, marker, neighborhood, equal);
1896 }
1897 
1898 template <class SrcIterator, class SrcAccessor,
1899  class DestIterator, class DestAccessor,
1900  class Neighborhood>
1901 inline void
1902 extendedLocalMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1903  pair<DestIterator, DestAccessor> dest,
1904  typename DestAccessor::value_type marker, Neighborhood neighborhood)
1905 {
1906  extendedLocalMaxima(src.first, src.second, src.third,
1907  dest.first, dest.second, marker, neighborhood);
1908 }
1909 
1910 template <class SrcIterator, class SrcAccessor,
1911  class DestIterator, class DestAccessor>
1912 inline void
1913 extendedLocalMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1914  pair<DestIterator, DestAccessor> dest,
1915  typename DestAccessor::value_type marker)
1916 {
1917  extendedLocalMaxima(src.first, src.second, src.third,
1918  dest.first, dest.second, marker, EightNeighborCode());
1919 }
1920 
1921 template <class SrcIterator, class SrcAccessor,
1922  class DestIterator, class DestAccessor>
1923 inline void
1924 extendedLocalMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1925  pair<DestIterator, DestAccessor> dest)
1926 {
1927  extendedLocalMaxima(src.first, src.second, src.third,
1928  dest.first, dest.second);
1929 }
1930 
1931 /********************************************************/
1932 /* */
1933 /* extendedLocalMaxima3D */
1934 /* */
1935 /********************************************************/
1936 
1937 /** \brief Find local maximal regions in 3D multi array.
1938 
1939  This function finds regions of uniform pixel value
1940  whose neighboring regions are all have smaller values
1941  (maximal plateaus of arbitrary size). By default, the pixels
1942  in a plateau have exactly identical values. By passing an <tt>EqualityFunctor</tt>
1943  with tolerance, one can allow for plateaus that are not quite constant
1944  (this is often necessary with float pixel values). Pass
1945  the neighborhood where pixel values are compared. See extendedLocalMaxima() for more details.
1946  */
1947 
1948 doxygen_overloaded_function(template <...> void extendedLocalMaxima3D)
1949 
1950 template<class SrcIterator, class SrcShape, class SrcAccessor,
1951  class DestIterator, class DestAccessor, class Neighborhood,
1952  class EqualityFunctor>
1953 inline void
1954 extendedLocalMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
1955  DestIterator dul, DestAccessor da,
1956  typename DestAccessor::value_type marker,
1957  Neighborhood neighborhood,
1958  EqualityFunctor equal)
1959 {
1960  typedef typename SrcAccessor::value_type SrcType;
1961 
1962  detail::extendedLocalMinMax3D(sul, slr, sa, dul, da, marker, neighborhood,
1963  std::greater<SrcType>(), equal,
1965 }
1966 
1967 template<class SrcIterator, class SrcShape, class SrcAccessor,
1968  class DestIterator, class DestAccessor, class Neighborhood>
1969 inline void
1970 extendedLocalMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
1971  DestIterator dul, DestAccessor da,
1972  typename DestAccessor::value_type marker,
1973  Neighborhood neighborhood)
1974 {
1975  typedef typename SrcAccessor::value_type SrcType;
1976 
1977  extendedLocalMaxima3D(sul, slr, sa, dul, da,
1978  marker, neighborhood,
1979  std::equal_to<SrcType>());
1980 }
1981 
1982 template<class SrcIterator, class SrcShape, class SrcAccessor,
1983  class DestIterator, class DestAccessor>
1984 inline void
1985 extendedLocalMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
1986  DestIterator dul, DestAccessor da)
1987 {
1988  extendedLocalMaxima3D(sul, slr, sa, dul, da,
1989  NumericTraits<typename DestAccessor::value_type>::one(),
1990  NeighborCode3DSix());
1991 }
1992 
1993 template<class SrcIterator, class SrcShape, class SrcAccessor,
1994  class DestIterator, class DestAccessor, class Neighborhood>
1995 inline void
1996 extendedLocalMaxima3D(triple<SrcIterator, SrcShape, SrcAccessor> src,
1997  pair<DestIterator, DestAccessor> dest,
1998  typename DestAccessor::value_type marker,
1999  Neighborhood neighborhood)
2000 {
2001  extendedLocalMaxima3D(src.first, src.second, src.third,
2002  dest.first, dest.second,
2003  marker, neighborhood);
2004 }
2005 
2006 //@}
2007 
2008 } // namespace vigra
2009 
2010 #endif // VIGRA_LOCALMINMAX_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.8.0 (Wed Sep 26 2012)