36 #ifndef VIGRA_watersheds3D_HXX
37 #define VIGRA_watersheds3D_HXX
39 #include "voxelneighborhood.hxx"
40 #include "multi_array.hxx"
41 #include "multi_localminmax.hxx"
42 #include "labelvolume.hxx"
43 #include "seededregiongrowing3d.hxx"
44 #include "watersheds.hxx"
49 template <
class SrcIterator,
class SrcAccessor,
class SrcShape,
50 class DestIterator,
class DestAccessor,
class Neighborhood3D>
51 int preparewatersheds3D( SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa,
52 DestIterator d_Iter, DestAccessor da, Neighborhood3D)
55 int w = srcShape[0], h = srcShape[1], d = srcShape[2];
56 int x,y,z, local_min_count=0;
59 SrcIterator zs = s_Iter;
64 DestIterator zd = d_Iter;
66 for(z = 0; z != d; ++z, ++zs.dim2(), ++zd.dim2())
71 for(y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1())
76 for(x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0())
79 typename SrcAccessor::value_type v = sa(xs);
84 typename SrcAccessor::value_type my_v = v;
87 NeighborhoodCirculator<SrcIterator, Neighborhood3D> c(xs), cend(c);
95 else if(sa(c) == my_v && my_v == v)
97 o = o | c.directionBit();
104 RestrictedNeighborhoodCirculator<SrcIterator, Neighborhood3D> c(xs, atBorder), cend(c);
109 o = c.directionBit();
111 else if(sa(c) == my_v && my_v == v)
113 o = o | c.directionBit();
118 if (o==0) local_min_count++;
123 return local_min_count;
126 template <
class SrcIterator,
class SrcAccessor,
class SrcShape,
127 class DestIterator,
class DestAccessor,
128 class Neighborhood3D>
129 unsigned int watershedLabeling3D( SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa,
130 DestIterator d_Iter, DestAccessor da,
133 typedef typename DestAccessor::value_type LabelType;
136 int w = srcShape[0], h = srcShape[1], d = srcShape[2];
140 SrcIterator zs = s_Iter;
141 DestIterator zd = d_Iter;
144 detail::UnionFindArray<LabelType> labels;
147 NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhood3D::CausalFirst);
148 NeighborOffsetCirculator<Neighborhood3D> nce(Neighborhood3D::CausalLast);
163 for(z = 0; z != d; ++z, ++zs.dim2(), ++zd.dim2())
166 DestIterator yd = zd;
168 for(y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1())
171 DestIterator xd = yd;
173 for(x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0())
175 LabelType currentLabel = labels.nextFreeLabel();
184 nc = NeighborOffsetCirculator<Neighborhood3D>(Neighborhood3D::CausalFirst);
190 if((sa(xs) & nc.directionBit()) || (sa(xs,*nc) & nc.oppositeDirectionBit()))
192 currentLabel = labels.makeUnion(da(xd,*nc), currentLabel);
200 nc = NeighborOffsetCirculator<Neighborhood3D>(Neighborhood3D::nearBorderDirectionsCausal(atBorder,0));
202 while(nc.direction() != Neighborhood3D::Error)
206 if((sa(xs) & nc.directionBit()) || (sa(xs,*nc) & nc.oppositeDirectionBit()))
208 currentLabel = labels.makeUnion(da(xd,*nc), currentLabel);
210 nc.turnTo(Neighborhood3D::nearBorderDirectionsCausal(atBorder,++j));
213 da.set(labels.finalizeLabel(currentLabel), xd);
218 unsigned int count = labels.makeContiguous();
223 for(z=0; z != d; ++z, ++zd.dim2())
227 for(y=0; y != h; ++y, ++yd.dim1())
231 for(x = 0; x != w; ++x, ++xd.dim0())
233 da.set(labels[da(xd)], xd);
307 template <
unsigned int N,
class T1,
class C1,
class T2,
class C2>
310 generateWatershedSeeds3D(MultiArrayView<N, T1, C1> in, MultiArrayView<N, T2, C2> out,
311 Neighborhood neighborhood,
312 SeedOptions const & options = SeedOptions())
314 using namespace functor;
316 vigra_precondition(in.shape() == out.shape(),
317 "generateWatershedSeeds3D(): Shape mismatch between input and output.");
319 vigra_precondition(options.mini != SeedOptions::LevelSets ||
320 options.thresholdIsValid<SrcType>(),
321 "generateWatershedSeeds3D(): SeedOptions.levelSets() must be specified with threshold.");
323 MultiArray<N, UInt8> seeds(in.shape());
325 if(options.mini == SeedOptions::LevelSets)
328 ifThenElse(Arg1() <= Param(options.thresh), Param(1), Param(0)));
333 LocalMinmaxOptions().neighborhood(Neighborhood::DirectionCount)
335 .threshold(options.thresh)
337 .allowPlateaus(options.mini == SeedOptions::ExtendedMinima));
344 template <
class SrcIterator,
class SrcAccessor,
345 class DestIterator,
class DestAccessor>
348 DestIterator upperleftd, DestAccessor da,
349 SeedOptions
const & options = SeedOptions())
355 template <
class SrcIterator,
class SrcAccessor,
356 class DestIterator,
class DestAccessor,
360 pair<DestIterator, DestAccessor> dest,
361 Neighborhood neighborhood,
362 SeedOptions
const & options = SeedOptions())
365 dest.first, dest.second,
366 neighborhood, options);
369 template <
class SrcIterator,
class SrcAccessor,
370 class DestIterator,
class DestAccessor>
373 pair<DestIterator, DestAccessor> dest,
374 SeedOptions
const & options = SeedOptions())
377 dest.first, dest.second,
508 doxygen_overloaded_function(template <...>
unsigned int watersheds3D)
510 template <
class SrcIterator,
class SrcAccessor,
class SrcShape,
511 class DestIterator,
class DestAccessor,
512 class Neighborhood3D>
513 unsigned int watersheds3D( SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa,
514 DestIterator d_Iter, DestAccessor da, Neighborhood3D neighborhood3D)
517 if ((
int)Neighborhood3D::DirectionCount>7){
521 preparewatersheds3D( s_Iter, srcShape, sa,
522 destMultiArray(orientationVolume).first, destMultiArray(orientationVolume).second,
525 return watershedLabeling3D( srcMultiArray(orientationVolume).first, srcShape, srcMultiArray(orientationVolume).second,
533 preparewatersheds3D( s_Iter, srcShape, sa,
534 destMultiArray(orientationVolume).first, destMultiArray(orientationVolume).second,
537 return watershedLabeling3D( srcMultiArray(orientationVolume).first, srcShape, srcMultiArray(orientationVolume).second,
543 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
544 class DestIterator,
class DestAccessor>
545 inline unsigned int watersheds3DSix( vigra::triple<SrcIterator, SrcShape, SrcAccessor> src,
546 vigra::pair<DestIterator, DestAccessor> dest)
551 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
552 class DestIterator,
class DestAccessor>
553 inline unsigned int watersheds3DTwentySix( vigra::triple<SrcIterator, SrcShape, SrcAccessor> src,
554 vigra::pair<DestIterator, DestAccessor> dest)
561 #endif //VIGRA_watersheds3D_HXX
AtImageBorder AtVolumeBorder
Encode whether a voxel is near the volume border.
Definition: voxelneighborhood.hxx:72
unsigned int watersheds3D(...)
Region Segmentation by means of the watershed algorithm.
Neighborhood3DTwentySix::NeighborCode3D NeighborCode3DTwentySix
Definition: voxelneighborhood.hxx:1602
void localMinima(...)
Find local minima in an image or multi-dimensional array.
Main MultiArray class containing the memory management.
Definition: multi_array.hxx:595
AtVolumeBorder isAtVolumeBorderCausal(int x, int y, int z, int width, int height, int)
Find out whether a voxel is at a scan-order relevant volume border. This function checks if x == 0 or...
Definition: voxelneighborhood.hxx:112
AtVolumeBorder isAtVolumeBorder(int x, int y, int z, int width, int height, int depth)
Find out whether a voxel is at the volume border.
Definition: voxelneighborhood.hxx:82
unsigned int labelVolumeWithBackground(...)
Find the connected components of a segmented volume, excluding the background from labeling...
Neighborhood3DSix::NeighborCode3D NeighborCode3DSix
Definition: voxelneighborhood.hxx:468
unsigned int generateWatershedSeeds3D(...)
Generate seeds for watershed computation and seeded region growing.
unsigned int generateWatershedSeeds(...)
Generate seeds for watershed computation and seeded region growing.
void transformMultiArray(...)
Transform a multi-dimensional array with a unary function or functor.
Definition: pixelneighborhood.hxx:70
EightNeighborhood::NeighborCode EightNeighborCode
Definition: pixelneighborhood.hxx:644