36 #ifndef VIGRA_BLOCKWISE_WATERSHEDS_HXX
37 #define VIGRA_BLOCKWISE_WATERSHEDS_HXX
39 #include "multi_array.hxx"
40 #include "multi_gridgraph.hxx"
41 #include "blockify.hxx"
42 #include "blockwise_labeling.hxx"
43 #include "overlapped_blocks.hxx"
54 namespace blockwise_watersheds_detail
57 template <
class DataArray,
class DirectionsBlocksIterator>
58 void prepareBlockwiseWatersheds(
const Overlaps<DataArray>& overlaps,
59 DirectionsBlocksIterator directions_blocks_begin,
62 static const unsigned int N = DataArray::actual_dimension;
63 typedef typename MultiArrayShape<N>::type Shape;
64 typedef typename DirectionsBlocksIterator::value_type DirectionsBlock;
65 Shape shape = overlaps.shape();
66 vigra_assert(shape == directions_blocks_begin.shape(),
"");
68 MultiCoordinateIterator<N> it(shape);
69 MultiCoordinateIterator<N> end = it.getEndIterator();
70 for( ; it != end; ++it)
72 DirectionsBlock directions_block = directions_blocks_begin[*it];
73 OverlappingBlock<DataArray> data_block = overlaps[*it];
75 typedef GridGraph<N, undirected_tag> Graph;
76 typedef typename Graph::NodeIt GraphScanner;
77 typedef typename Graph::OutArcIt NeighborIterator;
79 Graph graph(data_block.block.shape(), neighborhood);
80 for(GraphScanner node(graph); node != lemon::INVALID; ++node)
82 if(within(*node, data_block.inner_bounds))
84 typedef typename DataArray::value_type Data;
85 Data lowest_neighbor = data_block.block[*node];
87 typedef typename DirectionsBlock::value_type
Direction;
88 Direction lowest_neighbor_direction = std::numeric_limits<unsigned short>::max();
90 for(NeighborIterator arc(graph, *node); arc != lemon::INVALID; ++arc)
92 Shape neighbor_coordinates = graph.target(*arc);
93 Data neighbor_data = data_block.block[neighbor_coordinates];
94 if(neighbor_data < lowest_neighbor)
96 lowest_neighbor = neighbor_data;
97 lowest_neighbor_direction = arc.neighborIndex();
100 directions_block[*node - data_block.inner_bounds.first] = lowest_neighbor_direction;
106 template <
unsigned int N>
107 struct UnionFindWatershedsEquality
111 GridGraph<N, undirected_tag>* graph;
113 template <
class Shape>
114 bool operator()(
unsigned short u,
const unsigned short v,
const Shape& diff)
const
116 static const unsigned short plateau_id = std::numeric_limits<unsigned short>::max();
117 return (u == plateau_id && v == plateau_id) ||
118 (u != plateau_id && graph->neighborOffset(u) == diff) ||
119 (v != plateau_id && graph->neighborOffset(graph->oppositeIndex(v)) == diff);
128 template <
unsigned int N,
class Data,
class S1,
129 class Label,
class S2>
130 Label unionFindWatershedsBlockwise(MultiArrayView<N, Data, S1> data,
131 MultiArrayView<N, Label, S2> labels,
133 const typename MultiArrayView<N, Data, S1>::difference_type& block_shape =
134 typename MultiArrayView<N, Data, S1>::difference_type(128))
136 using namespace blockwise_watersheds_detail;
138 typedef typename MultiArrayView<N, Data, S1>::difference_type Shape;
139 Shape shape = data.shape();
140 vigra_precondition(shape == labels.shape(),
"shapes of data and labels do not match");
142 MultiArray<N, unsigned short> directions(shape);
144 MultiArray<N, MultiArrayView<N, unsigned short> > directions_blocks = blockify(directions, block_shape);
146 Overlaps<MultiArrayView<N, Data, S1> > overlaps(data, block_shape, Shape(1), Shape(1));
147 prepareBlockwiseWatersheds(overlaps, directions_blocks.begin(), neighborhood);
148 GridGraph<N, undirected_tag> graph(data.shape(), neighborhood);
149 UnionFindWatershedsEquality<N> equal = {&graph};
150 return labelMultiArrayBlockwise(directions, labels, LabelOptions().neighborhood(neighborhood).blockShape(block_shape), equal);
204 template <
unsigned int N,
class Data,
class Label>
205 Label unionFindWatershedsBlockwise(
const ChunkedArray<N, Data>& data,
206 ChunkedArray<N, Label>& labels,
208 ChunkedArray<N, unsigned short>& directions)
210 using namespace blockwise_watersheds_detail;
212 typedef typename ChunkedArray<N, Data>::shape_type Shape;
213 Shape shape = data.shape();
214 vigra_precondition(shape == labels.shape() && shape == directions.shape(),
"shapes of data and labels do not match");
215 Shape chunk_shape = data.chunkShape();
216 vigra_precondition(chunk_shape == labels.chunkShape() && chunk_shape == directions.chunkShape(),
"chunk shapes do not match");
218 Overlaps<ChunkedArray<N, Data> > overlaps(data, data.chunkShape(), Shape(1), Shape(1));
220 prepareBlockwiseWatersheds(overlaps, directions.chunk_begin(Shape(0), shape), neighborhood);
222 GridGraph<N, undirected_tag> graph(shape, neighborhood);
223 UnionFindWatershedsEquality<N> equal = {&graph};
224 return labelMultiArrayBlockwise(directions, labels, LabelOptions().neighborhood(neighborhood), equal);
227 template <
unsigned int N,
class Data,
230 unionFindWatershedsBlockwise(
const ChunkedArray<N, Data>& data,
231 ChunkedArray<N, Label>& labels,
234 ChunkedArrayLazy<N, unsigned short> directions(data.shape(), data.chunkShape());
235 return unionFindWatershedsBlockwise(data, labels, neighborhood, directions);
242 #endif // VIGRA_BLOCKWISE_WATERSHEDS_HXX