36 #ifndef VIGRA_BLOCKWISE_WATERSHEDS_HXX
37 #define VIGRA_BLOCKWISE_WATERSHEDS_HXX
39 #include "threadpool.hxx"
40 #include "multi_array.hxx"
41 #include "multi_gridgraph.hxx"
42 #include "blockify.hxx"
43 #include "blockwise_labeling.hxx"
44 #include "metaprogramming.hxx"
45 #include "overlapped_blocks.hxx"
56 namespace blockwise_watersheds_detail
59 template <
class DataArray,
class DirectionsBlocksIterator>
60 void prepareBlockwiseWatersheds(
const Overlaps<DataArray>& overlaps,
61 DirectionsBlocksIterator directions_blocks_begin,
62 BlockwiseLabelOptions
const & options)
64 static const unsigned int N = DataArray::actual_dimension;
66 typedef typename MultiArrayShape<DataArray::actual_dimension>::type Shape;
67 typedef typename DirectionsBlocksIterator::value_type DirectionsBlock;
68 Shape shape = overlaps.shape();
69 vigra_assert(shape == directions_blocks_begin.shape(),
"");
71 MultiCoordinateIterator<DataArray::actual_dimension> itBegin(shape);
72 MultiCoordinateIterator<DataArray::actual_dimension> end = itBegin.getEndIterator();
73 typedef typename MultiCoordinateIterator<DataArray::actual_dimension>::value_type Coordinate;
77 [&](
const int ,
const Coordinate iterVal){
79 DirectionsBlock directions_block = directions_blocks_begin[iterVal];
80 OverlappingBlock<DataArray> data_block = overlaps[iterVal];
82 typedef GridGraph<DataArray::actual_dimension, undirected_tag> Graph;
83 typedef typename Graph::NodeIt GraphScanner;
84 typedef typename Graph::OutArcIt NeighborIterator;
86 Graph graph(data_block.block.shape(), options.getNeighborhood());
87 for(GraphScanner node(graph); node != lemon::INVALID; ++node)
89 if(within(*node, data_block.inner_bounds))
91 typedef typename DataArray::value_type Data;
92 Data lowest_neighbor = data_block.block[*node];
94 typedef typename DirectionsBlock::value_type
Direction;
95 Direction lowest_neighbor_direction = std::numeric_limits<unsigned short>::max();
97 for(NeighborIterator arc(graph, *node); arc != lemon::INVALID; ++arc)
99 Shape neighbor_coordinates = graph.target(*arc);
100 Data neighbor_data = data_block.block[neighbor_coordinates];
101 if(neighbor_data < lowest_neighbor)
103 lowest_neighbor = neighbor_data;
104 lowest_neighbor_direction = arc.neighborIndex();
107 directions_block[*node - data_block.inner_bounds.first] = lowest_neighbor_direction;
114 template <
unsigned int N>
115 struct UnionFindWatershedsEquality
119 GridGraph<N, undirected_tag>* graph;
121 template <
class Shape>
122 bool operator()(
unsigned short u,
const unsigned short v,
const Shape& diff)
const
124 static const unsigned short plateau_id = std::numeric_limits<unsigned short>::max();
125 return (u == plateau_id && v == plateau_id) ||
126 (u != plateau_id && graph->neighborOffset(u) == diff) ||
127 (v != plateau_id && graph->neighborOffset(graph->oppositeIndex(v)) == diff);
200 template <
unsigned int N,
class Data,
class S1,
201 class Label,
class S2>
203 MultiArrayView<N, Label, S2> labels,
204 BlockwiseLabelOptions
const & options = BlockwiseLabelOptions())
206 using namespace blockwise_watersheds_detail;
208 typedef typename MultiArrayView<N, Data, S1>::difference_type Shape;
209 Shape shape = data.shape();
210 vigra_precondition(shape == labels.shape(),
"shapes of data and labels do not match");
212 MultiArray<N, unsigned short> directions(shape);
213 Shape block_shape = options.getBlockShapeN<N>();
215 MultiArray<N, MultiArrayView<N, unsigned short> > directions_blocks = blockify(directions, block_shape);
217 Overlaps<MultiArrayView<N, Data, S1> > overlaps(data, block_shape, Shape(1), Shape(1));
218 prepareBlockwiseWatersheds(overlaps, directions_blocks.begin(), options);
219 GridGraph<N, undirected_tag> graph(data.shape(), options.getNeighborhood());
220 UnionFindWatershedsEquality<N> equal = {&graph};
224 template <
unsigned int N,
class Data,
class Label>
226 ChunkedArray<N, Label>& labels,
227 BlockwiseLabelOptions
const & options,
228 ChunkedArray<N, unsigned short>& directions)
230 using namespace blockwise_watersheds_detail;
232 typedef typename ChunkedArray<N, Data>::shape_type Shape;
233 Shape shape = data.shape();
234 vigra_precondition(shape == labels.shape() && shape == directions.shape(),
235 "unionFindWatershedsBlockwise(): shapes of data and labels do not match");
236 Shape chunk_shape = data.chunkShape();
237 vigra_precondition(chunk_shape == labels.chunkShape() && chunk_shape == directions.chunkShape(),
238 "unionFindWatershedsBlockwise(): chunk shapes do not match");
240 Overlaps<ChunkedArray<N, Data> > overlaps(data, data.chunkShape(), Shape(1), Shape(1));
242 prepareBlockwiseWatersheds(overlaps, directions.chunk_begin(Shape(0), shape), options);
244 GridGraph<N, undirected_tag> graph(shape, options.getNeighborhood());
245 UnionFindWatershedsEquality<N> equal = {&graph};
249 template <
unsigned int N,
class Data,
253 ChunkedArray<N, Label>& labels,
254 BlockwiseLabelOptions
const & options = BlockwiseLabelOptions())
256 ChunkedArrayLazy<N, unsigned short> directions(data.shape(), data.chunkShape());
264 #endif // VIGRA_BLOCKWISE_WATERSHEDS_HXX
NeighborCode::Direction Direction
Definition: pixelneighborhood.hxx:321
unsigned int labelMultiArrayBlockwise(...)
Connected components labeling for MultiArrays and ChunkedArrays.
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
void parallel_foreach(...)
Apply a functor to all items in a range in parallel.
unsigned int unionFindWatershedsBlockwise(...)
Blockwise union-find watersheds transform for MultiArrays and ChunkedArrays.