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

seededregiongrowing3d.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_SEEDEDREGIONGROWING_3D_HXX
38 #define VIGRA_SEEDEDREGIONGROWING_3D_HXX
39 
40 #include <vector>
41 #include <stack>
42 #include <queue>
43 #include "utilities.hxx"
44 #include "stdimage.hxx"
45 #include "stdimagefunctions.hxx"
46 #include "seededregiongrowing.hxx"
47 #include "multi_shape.hxx"
48 #include "multi_pointoperators.hxx"
49 #include "voxelneighborhood.hxx"
50 
51 namespace vigra {
52 
53 namespace detail {
54 
55 template <class COST, class Diff_type>
56 class SeedRgVoxel
57 {
58 public:
59  Diff_type location_, nearest_;
60  COST cost_;
61  int count_;
62  int label_;
63  int dist_;
64 
65  SeedRgVoxel()
66  //: location_(0,0,0), nearest_(0,0,0), cost_(0), count_(0), label_(0)
67  {
68  location_ = Diff_type(0,0,0);
69  nearest_ = Diff_type(0,0,0);
70  cost_ = 0;
71  count_ = 0;
72  label_ = 0;
73  }
74 
75  SeedRgVoxel(Diff_type const & location, Diff_type const & nearest,
76  COST const & cost, int const & count, int const & label)
77  : location_(location), nearest_(nearest),
78  cost_(cost), count_(count), label_(label)
79  {
80  int dx = location_[0] - nearest_[0];
81  int dy = location_[1] - nearest_[1];
82  int dz = location_[2] - nearest_[2];
83  dist_ = dx * dx + dy * dy + dz * dz;
84  }
85 
86  void set(Diff_type const & location, Diff_type const & nearest,
87  COST const & cost, int const & count, int const & label)
88  {
89  location_ = location;
90  nearest_ = nearest;
91  cost_ = cost;
92  count_ = count;
93  label_ = label;
94 
95  int dx = location_[0] - nearest_[0];
96  int dy = location_[1] - nearest_[1];
97  int dz = location_[2] - nearest_[2];
98  dist_ = dx * dx + dy * dy + dz * dz;
99  }
100 
101  struct Compare
102  {
103  // must implement > since priority_queue looks for largest element
104  bool operator()(SeedRgVoxel const & l,
105  SeedRgVoxel const & r) const
106  {
107  if(r.cost_ == l.cost_)
108  {
109  if(r.dist_ == l.dist_) return r.count_ < l.count_;
110 
111  return r.dist_ < l.dist_;
112  }
113 
114  return r.cost_ < l.cost_;
115  }
116  bool operator()(SeedRgVoxel const * l,
117  SeedRgVoxel const * r) const
118  {
119  if(r->cost_ == l->cost_)
120  {
121  if(r->dist_ == l->dist_) return r->count_ < l->count_;
122 
123  return r->dist_ < l->dist_;
124  }
125 
126  return r->cost_ < l->cost_;
127  }
128  };
129 
130  struct Allocator
131  {
132  ~Allocator()
133  {
134  while(!freelist_.empty())
135  {
136  delete freelist_.top();
137  freelist_.pop();
138  }
139  }
140 
141  SeedRgVoxel * create(Diff_type const & location, Diff_type const & nearest,
142  COST const & cost, int const & count, int const & label)
143  {
144  if(!freelist_.empty())
145  {
146  SeedRgVoxel * res = freelist_.top();
147  freelist_.pop();
148  res->set(location, nearest, cost, count, label);
149  return res;
150  }
151 
152  return new SeedRgVoxel(location, nearest, cost, count, label);
153  }
154 
155  void dismiss(SeedRgVoxel * p)
156  {
157  freelist_.push(p);
158  }
159 
160  std::stack<SeedRgVoxel<COST,Diff_type> *> freelist_;
161  };
162 };
163 
164 } // namespace detail
165 
166 /** \addtogroup Superpixels
167 */
168 //@{
169 
170 /********************************************************/
171 /* */
172 /* seededRegionGrowing3D */
173 /* */
174 /********************************************************/
175 
176 /** \brief Three-dimensional Region Segmentation by means of Seeded Region Growing.
177 
178  This algorithm implements seeded region growing as described in
179 
180  The seed image is a partly segmented multi-dimensional array which contains uniquely
181  labeled regions (the seeds) and unlabeled voxels (the candidates, label 0).
182  Seed regions can be as large as you wish and as small as one voxel. If
183  there are no candidates, the algorithm will simply copy the seed array
184  into the output array. Otherwise it will aggregate the candidates into
185  the existing regions so that a cost function is minimized.
186  Candidates are taken from the neighborhood of the already assigned pixels,
187  where the type of neighborhood is determined by parameter <tt>neighborhood</tt>
188  which can take the values <tt>NeighborCode3DSix()</tt> (the default)
189  or <tt>NeighborCode3DTwentySix()</tt>. The algorithm basically works as follows
190  (illustrated for 6-neighborhood, but 26-neighborhood works in the same way):
191 
192  <ol>
193 
194  <li> Find all candidate pixels that are 6-adjacent to a seed region.
195  Calculate the cost for aggregating each candidate into its adjacent region
196  and put the candidates into a priority queue.
197 
198  <li> While( priority queue is not empty)
199 
200  <ol>
201 
202  <li> Take the candidate with least cost from the queue. If it has not
203  already been merged, merge it with it's adjacent region.
204 
205  <li> Put all candidates that are 4-adjacent to the pixel just processed
206  into the priority queue.
207 
208  </ol>
209 
210  </ol>
211 
212  <tt>SRGType</tt> can take the following values:
213 
214  <DL>
215  <DT><tt>CompleteGrow</tt> <DD> produce a complete tesselation of the volume (default).
216  <DT><tt>KeepContours</tt> <DD> keep a 1-voxel wide unlabeled contour between all regions.
217  <DT><tt>StopAtThreshold</tt> <DD> stop when the boundary indicator values exceed the
218  threshold given by parameter <tt>max_cost</tt>.
219  <DT><tt>KeepContours | StopAtThreshold</tt> <DD> keep 1-voxel wide contour and stop at given <tt>max_cost</tt>.
220  </DL>
221 
222  The cost is determined jointly by the source array and the
223  region statistics functor. The source array contains feature values for each
224  pixel which will be used by the region statistics functor to calculate and
225  update statistics for each region and to calculate the cost for each
226  candidate. The <TT>RegionStatisticsArray</TT> must be compatible to the
227  \ref ArrayOfRegionStatistics functor and contains an <em> array</em> of
228  statistics objects for each region. The indices must correspond to the
229  labels of the seed regions. The statistics for the initial regions must have
230  been calculated prior to calling <TT>seededRegionGrowing3D()</TT>
231 
232  For each candidate
233  <TT>x</TT> that is adjacent to region <TT>i</TT>, the algorithm will call
234  <TT>stats[i].cost(as(x))</TT> to get the cost (where <TT>x</TT> is a <TT>SrcImageIterator</TT>
235  and <TT>as</TT> is
236  the SrcAccessor). When a candidate has been merged with a region, the
237  statistics are updated by calling <TT>stats[i].operator()(as(x))</TT>. Since
238  the <TT>RegionStatisticsArray</TT> is passed by reference, this will overwrite
239  the original statistics.
240 
241  If a candidate could be merged into more than one regions with identical
242  cost, the algorithm will favour the nearest region. If <tt>StopAtThreshold</tt> is active,
243  and the cost of the current candidate at any point in the algorithm exceeds the optional
244  <tt>max_cost</tt> value (which defaults to <tt>NumericTraits<double>::max()</tt>),
245  region growing is aborted, and all voxels not yet assigned to a region remain unlabeled.
246 
247  In some cases, the cost only depends on the feature value of the current
248  voxel. Then the update operation will simply be a no-op, and the <TT>cost()</TT>
249  function returns its argument. This behavior is implemented by the
250  \ref SeedRgDirectValueFunctor.
251 
252  <b> Declarations:</b>
253 
254  pass 3D array views:
255  \code
256  namespace vigra {
257  template <class T1, class S1,
258  class TS, class AS,
259  class T2, class S2,
260  class RegionStatisticsArray, class Neighborhood>
261  void
262  seededRegionGrowing3D(MultiArrayView<3, T1, S1> const & src,
263  MultiArrayView<3, TS, AS> const & seeds,
264  MultiArrayView<3, T2, S2> labels,
265  RegionStatisticsArray & stats,
266  SRGType srgType = CompleteGrow,
267  Neighborhood neighborhood = NeighborCode3DSix(),
268  double max_cost = NumericTraits<double>::max());
269  }
270  \endcode
271 
272  \deprecatedAPI{seededRegionGrowing3D}
273  pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors :
274  \code
275  namespace vigra {
276  template <class SrcImageIterator, class Shape, class SrcAccessor,
277  class SeedImageIterator, class SeedAccessor,
278  class DestImageIterator, class DestAccessor,
279  class RegionStatisticsArray, class Neighborhood>
280  void
281  seededRegionGrowing3D(SrcImageIterator srcul, Shape shape, SrcAccessor as,
282  SeedImageIterator seedsul, SeedAccessor aseeds,
283  DestImageIterator destul, DestAccessor ad,
284  RegionStatisticsArray & stats,
285  SRGType srgType = CompleteGrow,
286  Neighborhood neighborhood = NeighborCode3DSix(),
287  double max_cost = NumericTraits<double>::max());
288  }
289  \endcode
290  use argument objects in conjunction with \ref ArgumentObjectFactories :
291  \code
292  namespace vigra {
293  template <class SrcImageIterator, class Shape, class SrcAccessor,
294  class SeedImageIterator, class SeedAccessor,
295  class DestImageIterator, class DestAccessor,
296  class RegionStatisticsArray, class Neighborhood>
297  void
298  seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> src,
299  pair<SeedImageIterator, SeedAccessor> seeds,
300  pair<DestImageIterator, DestAccessor> dest,
301  RegionStatisticsArray & stats,
302  SRGType srgType = CompleteGrow,
303  Neighborhood neighborhood = NeighborCode3DSix(),
304  double max_cost = NumericTraits<double>::max());
305  }
306  \endcode
307  \deprecatedEnd
308 
309  <b> Usage:</b>
310 
311  <b>\#include</b> <vigra/seededregiongrowing3d.hxx><br>
312  Namespace: vigra
313 
314  See \ref seededRegionGrowing() for an example
315 */
317 
318 template <class SrcImageIterator, class Diff_type, class SrcAccessor,
319  class SeedImageIterator, class SeedAccessor,
320  class DestImageIterator, class DestAccessor,
321  class RegionStatisticsArray, class Neighborhood>
322 void
323 seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, SrcAccessor as,
324  SeedImageIterator seedsul, SeedAccessor aseeds,
325  DestImageIterator destul, DestAccessor ad,
326  RegionStatisticsArray & stats,
327  SRGType srgType,
328  Neighborhood,
329  double max_cost)
330 {
331  //SrcImageIterator srclr = srcul + shape;
332  //int w = srclr.x - srcul.x;
333  int w = shape[0];
334  //int h = srclr.y - srcul.y;
335  int h = shape[1];
336  //int d = srclr.z - srcul.z;
337  int d = shape[2];
338  int count = 0;
339 
340  SrcImageIterator isy = srcul, isx = srcul, isz = srcul; // iterators for the src image
341 
342  typedef typename RegionStatisticsArray::value_type RegionStatistics;
343  typedef typename PromoteTraits<typename RegionStatistics::cost_type, double>::Promote CostType;
344  typedef detail::SeedRgVoxel<CostType, Diff_type> Voxel;
345 
346  typename Voxel::Allocator allocator;
347 
348  typedef std::priority_queue< Voxel *,
349  std::vector<Voxel *>,
350  typename Voxel::Compare > SeedRgVoxelHeap;
351  typedef MultiArray<3, int> IVolume;
352  typedef IVolume::traverser Traverser;
353 
354  // copy seed image in an image with border
355  Diff_type regionshape = shape + Diff_type(2,2,2);
356  IVolume regions(regionshape);
357  Traverser ir = regions.traverser_begin();
358  ir = ir + Diff_type(1,1,1);
359 
360  //IVolume::Iterator iry, irx, irz;
361  Traverser iry, irx, irz;
362 
363  //initImageBorder(destImageRange(regions), 1, SRGWatershedLabel);
364  initMultiArrayBorder(destMultiArrayRange(regions), 1, SRGWatershedLabel);
365 
366  copyMultiArray(seedsul, Diff_type(w,h,d), aseeds, ir, AccessorTraits<int>::default_accessor());
367 
368  // allocate and init memory for the results
369 
370  SeedRgVoxelHeap pheap;
371  int cneighbor;
372 
373  typedef typename Neighborhood::Direction Direction;
374  int directionCount = Neighborhood::DirectionCount;
375 
376  Diff_type pos(0,0,0);
377 
378  for(isz=srcul, irz=ir, pos[2]=0; pos[2]<d;
379  pos[2]++, isz.dim2()++, irz.dim2()++)
380  {
381  //std::cerr << "Z = " << pos[2] << std::endl;
382 
383  for(isy=isz, iry=irz, pos[1]=0; pos[1]<h;
384  pos[1]++, isy.dim1()++, iry.dim1()++)
385  {
386  //std::cerr << "Y = " << pos[1] << std::endl;
387 
388  for(isx=isy, irx=iry, pos[0]=0; pos[0]<w;
389  pos[0]++, isx.dim0()++, irx.dim0()++)
390  {
391  //std::cerr << "X = " << pos[0] << std::endl;
392 
393  if(*irx == 0)
394  {
395  // find candidate pixels for growing and fill heap
396  for(int i=0; i<directionCount; i++)
397  {
398  cneighbor = *(irx + Neighborhood::diff((Direction)i));
399  if(cneighbor > 0)
400  {
401  CostType cost = stats[cneighbor].cost(as(isx));
402 
403  Voxel * voxel =
404  allocator.create(pos, pos+Neighborhood::diff((Direction)i), cost, count++, cneighbor);
405  pheap.push(voxel);
406  }
407  }
408  }
409  }
410  }
411  }
412 
413  // perform region growing
414  while(pheap.size() != 0)
415  {
416  Voxel * voxel = pheap.top();
417  pheap.pop();
418 
419  Diff_type pos = voxel->location_;
420  Diff_type nearest = voxel->nearest_;
421  int lab = voxel->label_;
422  CostType cost = voxel->cost_;
423 
424  allocator.dismiss(voxel);
425 
426  if((srgType & StopAtThreshold) != 0 && cost > max_cost)
427  break;
428 
429  irx = ir + pos;
430  isx = srcul + pos;
431 
432  if(*irx) // already labelled region / watershed?
433  continue;
434 
435  if((srgType & KeepContours) != 0)
436  {
437  for(int i=0; i<directionCount; i++)
438  {
439  cneighbor = * (irx + Neighborhood::diff((Direction)i));
440  if((cneighbor>0) && (cneighbor != lab))
441  {
442  lab = SRGWatershedLabel;
443  break;
444  }
445  }
446  }
447 
448  *irx = lab;
449 
450  if((srgType & KeepContours) == 0 || lab > 0)
451  {
452  // update statistics
453  stats[*irx](as(isx));
454 
455  // search neighborhood
456  // second pass: find new candidate pixels
457  for(int i=0; i<directionCount; i++)
458  {
459  if(*(irx + Neighborhood::diff((Direction)i)) == 0)
460  {
461  CostType cost = stats[lab].cost(as(isx, Neighborhood::diff((Direction)i)));
462 
463  Voxel * new_voxel =
464  allocator.create(pos+Neighborhood::diff((Direction)i), nearest, cost, count++, lab);
465  pheap.push(new_voxel);
466  }
467  }
468  }
469  }
470 
471  // free temporary memory
472  while(pheap.size() != 0)
473  {
474  allocator.dismiss(pheap.top());
475  pheap.pop();
476  }
477 
478  // write result
479  transformMultiArray(ir, Diff_type(w,h,d), AccessorTraits<int>::default_accessor(),
480  destul, ad, detail::UnlabelWatersheds());
481 }
482 
483 template <class SrcImageIterator, class Diff_type, class SrcAccessor,
484  class SeedImageIterator, class SeedAccessor,
485  class DestImageIterator, class DestAccessor,
486  class RegionStatisticsArray, class Neighborhood >
487 inline void
488 seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, SrcAccessor as,
489  SeedImageIterator seedsul, SeedAccessor aseeds,
490  DestImageIterator destul, DestAccessor ad,
491  RegionStatisticsArray & stats, SRGType srgType, Neighborhood n)
492 {
493  seededRegionGrowing3D( srcul, shape, as, seedsul, aseeds,
494  destul, ad, stats, srgType, n, NumericTraits<double>::max());
495 }
496 
497 template <class SrcImageIterator, class Diff_type, class SrcAccessor,
498  class SeedImageIterator, class SeedAccessor,
499  class DestImageIterator, class DestAccessor,
500  class RegionStatisticsArray >
501 inline void
502 seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, SrcAccessor as,
503  SeedImageIterator seedsul, SeedAccessor aseeds,
504  DestImageIterator destul, DestAccessor ad,
505  RegionStatisticsArray & stats, SRGType srgType)
506 {
507  seededRegionGrowing3D( srcul, shape, as, seedsul, aseeds,
508  destul, ad, stats, srgType, NeighborCode3DSix());
509 }
510 
511 template <class SrcImageIterator, class Diff_type, class SrcAccessor,
512  class SeedImageIterator, class SeedAccessor,
513  class DestImageIterator, class DestAccessor,
514  class RegionStatisticsArray >
515 inline void
516 seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, SrcAccessor as,
517  SeedImageIterator seedsul, SeedAccessor aseeds,
518  DestImageIterator destul, DestAccessor ad,
519  RegionStatisticsArray & stats)
520 {
521  seededRegionGrowing3D( srcul, shape, as, seedsul, aseeds, destul, ad,
522  stats, CompleteGrow);
523 }
524 
525 template <class SrcImageIterator, class Shape, class SrcAccessor,
526  class SeedImageIterator, class SeedAccessor,
527  class DestImageIterator, class DestAccessor,
528  class RegionStatisticsArray, class Neighborhood>
529 inline void
530 seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1,
531  pair<SeedImageIterator, SeedAccessor> img3,
532  pair<DestImageIterator, DestAccessor> img4,
533  RegionStatisticsArray & stats,
534  SRGType srgType, Neighborhood n, double max_cost)
535 {
536  seededRegionGrowing3D(img1.first, img1.second, img1.third,
537  img3.first, img3.second,
538  img4.first, img4.second,
539  stats, srgType, n, max_cost);
540 }
541 
542 template <class SrcImageIterator, class Shape, class SrcAccessor,
543  class SeedImageIterator, class SeedAccessor,
544  class DestImageIterator, class DestAccessor,
545  class RegionStatisticsArray, class Neighborhood>
546 inline void
547 seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1,
548  pair<SeedImageIterator, SeedAccessor> img3,
549  pair<DestImageIterator, DestAccessor> img4,
550  RegionStatisticsArray & stats,
551  SRGType srgType, Neighborhood n)
552 {
553  seededRegionGrowing3D(img1.first, img1.second, img1.third,
554  img3.first, img3.second,
555  img4.first, img4.second,
556  stats, srgType, n, NumericTraits<double>::max());
557 }
558 
559 template <class SrcImageIterator, class Shape, class SrcAccessor,
560  class SeedImageIterator, class SeedAccessor,
561  class DestImageIterator, class DestAccessor,
562  class RegionStatisticsArray>
563 inline void
564 seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1,
565  pair<SeedImageIterator, SeedAccessor> img3,
566  pair<DestImageIterator, DestAccessor> img4,
567  RegionStatisticsArray & stats, SRGType srgType)
568 {
569  seededRegionGrowing3D(img1.first, img1.second, img1.third,
570  img3.first, img3.second,
571  img4.first, img4.second,
572  stats, srgType, NeighborCode3DSix());
573 }
574 
575 template <class SrcImageIterator, class Shape, class SrcAccessor,
576  class SeedImageIterator, class SeedAccessor,
577  class DestImageIterator, class DestAccessor,
578  class RegionStatisticsArray>
579 inline void
580 seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1,
581  pair<SeedImageIterator, SeedAccessor> img3,
582  pair<DestImageIterator, DestAccessor> img4,
583  RegionStatisticsArray & stats)
584 {
585  seededRegionGrowing3D(img1.first, img1.second, img1.third,
586  img3.first, img3.second,
587  img4.first, img4.second,
588  stats);
589 }
590 
591 template <class T1, class S1,
592  class TS, class AS,
593  class T2, class S2,
594  class RegionStatisticsArray, class Neighborhood>
595 inline void
596 seededRegionGrowing3D(MultiArrayView<3, T1, S1> const & img1,
597  MultiArrayView<3, TS, AS> const & img3,
598  MultiArrayView<3, T2, S2> img4,
599  RegionStatisticsArray & stats,
600  SRGType srgType, Neighborhood n, double max_cost)
601 {
602  vigra_precondition(img1.shape() == img3.shape(),
603  "seededRegionGrowing3D(): shape mismatch between input and output.");
604  seededRegionGrowing3D(srcMultiArrayRange(img1),
605  srcMultiArray(img3),
606  destMultiArray(img4),
607  stats, srgType, n, max_cost);
608 }
609 
610 template <class T1, class S1,
611  class TS, class AS,
612  class T2, class S2,
613  class RegionStatisticsArray, class Neighborhood>
614 inline void
615 seededRegionGrowing3D(MultiArrayView<3, T1, S1> const & img1,
616  MultiArrayView<3, TS, AS> const & img3,
617  MultiArrayView<3, T2, S2> img4,
618  RegionStatisticsArray & stats,
619  SRGType srgType, Neighborhood n)
620 {
621  vigra_precondition(img1.shape() == img3.shape(),
622  "seededRegionGrowing3D(): shape mismatch between input and output.");
623  seededRegionGrowing3D(srcMultiArrayRange(img1),
624  srcMultiArray(img3),
625  destMultiArray(img4),
626  stats, srgType, n, NumericTraits<double>::max());
627 }
628 
629 template <class T1, class S1,
630  class TS, class AS,
631  class T2, class S2,
632  class RegionStatisticsArray>
633 inline void
634 seededRegionGrowing3D(MultiArrayView<3, T1, S1> const & img1,
635  MultiArrayView<3, TS, AS> const & img3,
636  MultiArrayView<3, T2, S2> img4,
637  RegionStatisticsArray & stats, SRGType srgType)
638 {
639  vigra_precondition(img1.shape() == img3.shape(),
640  "seededRegionGrowing3D(): shape mismatch between input and output.");
641  seededRegionGrowing3D(srcMultiArrayRange(img1),
642  srcMultiArray(img3),
643  destMultiArray(img4),
644  stats, srgType, NeighborCode3DSix());
645 }
646 
647 template <class T1, class S1,
648  class TS, class AS,
649  class T2, class S2,
650  class RegionStatisticsArray>
651 inline void
652 seededRegionGrowing3D(MultiArrayView<3, T1, S1> const & img1,
653  MultiArrayView<3, TS, AS> const & img3,
654  MultiArrayView<3, T2, S2> img4,
655  RegionStatisticsArray & stats)
656 {
657  vigra_precondition(img1.shape() == img3.shape(),
658  "seededRegionGrowing3D(): shape mismatch between input and output.");
659  seededRegionGrowing3D(srcMultiArrayRange(img1),
660  srcMultiArray(img3),
661  destMultiArray(img4),
662  stats);
663 }
664 
665 } // namespace vigra
666 
667 #endif // VIGRA_SEEDEDREGIONGROWING_HXX
668 
void initMultiArrayBorder(...)
Write values to the specified border values in the array.
SRGType
Definition: seededregiongrowing.hxx:176
void seededRegionGrowing3D(...)
Three-dimensional Region Segmentation by means of Seeded Region Growing.
NeighborCode::Direction Direction
Definition: pixelneighborhood.hxx:321
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
void copyMultiArray(...)
Copy a multi-dimensional array.
Neighborhood3DSix::NeighborCode3D NeighborCode3DSix
Definition: voxelneighborhood.hxx:490
void transformMultiArray(...)
Transform a multi-dimensional array with a unary function or functor.

© 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.11.1 (Fri May 19 2017)