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

multi_labeling.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2012-2013 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_MULTI_LABELING_HXX
37 #define VIGRA_MULTI_LABELING_HXX
38 
39 #include "multi_array.hxx"
40 #include "multi_gridgraph.hxx"
41 #include "union_find.hxx"
42 
43 namespace vigra{
44 
45 /** \addtogroup Labeling
46 */
47 //@{
48 
49 namespace lemon_graph {
50 
51 template <class Graph, class T1Map, class T2Map, class Equal>
52 typename T2Map::value_type
53 labelGraph(Graph const & g,
54  T1Map const & data,
55  T2Map & labels,
56  Equal const & equal)
57 {
58  typedef typename Graph::NodeIt graph_scanner;
59  typedef typename Graph::OutBackArcIt neighbor_iterator;
60  typedef typename T2Map::value_type LabelType;
61 
62  vigra::detail::UnionFindArray<LabelType> regions;
63 
64  // pass 1: find connected components
65  for (graph_scanner node(g); node != INVALID; ++node)
66  {
67  typename T1Map::value_type center = data[*node];
68 
69  // define tentative label for current node
70  LabelType currentLabel = regions.nextFreeLabel();
71 
72  for (neighbor_iterator arc(g, node); arc != INVALID; ++arc)
73  {
74  // merge regions if colors are equal
75  if(equal(center, data[g.target(*arc)]))
76  {
77  LabelType neighborLabel = regions[labels[g.target(*arc)]];
78  currentLabel = regions.makeUnion(neighborLabel, currentLabel);
79  }
80  }
81  // set label of current node
82  labels[*node] = regions.finalizeLabel(currentLabel);
83  }
84 
85  LabelType count = regions.makeContiguous();
86 
87  // pass 2: make component labels contiguous
88  for (graph_scanner node(g); node != INVALID; ++node)
89  {
90  labels[*node] = regions[labels[*node]];
91  }
92  return count;
93 }
94 
95 template <class Graph, class T1Map, class T2Map, class Equal>
96 typename T2Map::value_type
97 labelGraphWithBackground(Graph const & g,
98  T1Map const & data,
99  T2Map & labels,
100  typename T1Map::value_type backgroundValue,
101  Equal const & equal)
102 {
103  typedef typename Graph::NodeIt graph_scanner;
104  typedef typename Graph::OutBackArcIt neighbor_iterator;
105  typedef typename T2Map::value_type LabelType;
106 
107  vigra::detail::UnionFindArray<LabelType> regions;
108 
109  // pass 1: find connected components
110  for (graph_scanner node(g); node != INVALID; ++node)
111  {
112  typename T1Map::value_type center = data[*node];
113 
114  // background always gets label zero
115  if(equal(center, backgroundValue))
116  {
117  labels[*node] = 0;
118  continue;
119  }
120 
121  // define tentative label for current node
122  LabelType currentLabel = regions.nextFreeLabel();
123 
124  for (neighbor_iterator arc(g, node); arc != INVALID; ++arc)
125  {
126  // merge regions if colors are equal
127  if(equal(center, data[g.target(*arc)]))
128  {
129  LabelType neighborLabel = regions[labels[g.target(*arc)]];
130  currentLabel = regions.makeUnion(neighborLabel, currentLabel);
131  }
132  }
133  // set label of current node
134  labels[*node] = regions.finalizeLabel(currentLabel);
135  }
136 
137  LabelType count = regions.makeContiguous();
138 
139  // pass 2: make component labels contiguous
140  for (graph_scanner node(g); node != INVALID; ++node)
141  {
142  labels[*node] = regions[labels[*node]];
143  }
144  return count;
145 }
146 
147 } // namespace lemon_graph
148 
149 /********************************************************/
150 /* */
151 /* labelMultiArray */
152 /* */
153 /********************************************************/
154 
155 /** \brief Find the connected components of a MultiArray with arbitrary many dimensions.
156 
157  <b> Declaration:</b>
158 
159  \code
160  namespace vigra {
161 
162  template <unsigned int N, class T, class S1,
163  class Label, class S2,
164  class EqualityFunctor = std::equal_to<T> >
165  Label
166  labelMultiArray(MultiArrayView<N, T, S1> const & data,
167  MultiArrayView<N, Label, S2> labels,
168  NeighborhoodType neighborhood = DirectNeighborhood,
169  EqualityFunctor equal = std::equal_to<T>())
170 
171  }
172  \endcode
173 
174  Connected components are defined as regions with uniform values.
175  Thus, the value type <tt>T</tt> of the input array \a data either
176  must be equality comparable, or an EqualityFunctor must be
177  provided that realizes the desired predicate. The destination
178  array's value type <tt>Label</tt> should be large enough to hold
179  the labels without overflow. Region numbers will form a consecutive
180  sequence starting at <b>one</b> and ending with the region number
181  returned by the function (inclusive).
182 
183  Argument \a neighborhood specifies the type of connectivity used. It can
184  take the values <tt>DirectNeighborhood</tt> (which corresponds to
185  4-neighborhood in 2D and 6-neighborhood in 3D, default) or
186  <tt>IndirectNeighborhood</tt> (which corresponds to
187  8-neighborhood in 2D and 26-neighborhood in 3D).
188 
189  Return: the number of regions found (= highest region label, because labeling starts at 1)
190 
191  <b> Usage:</b>
192 
193  <b>\#include</b> <vigra/multi_labeling.hxx><br>
194  Namespace: vigra
195 
196  \code
197  MultiArray<3,int> src(Shape3(w,h,d));
198  MultiArray<3,int> dest(Shape3(w,h,d));
199 
200  // find 6-connected regions
201  int max_region_label = labelMultiArray(src, dest);
202 
203  // find 26-connected regions
204  max_region_label = labelMultiArray(src, dest, IndirectNeighborhood);
205  \endcode
206 
207  <b> Required Interface:</b>
208 
209  \code
210  T t;
211  t == t // T is equality comparable
212 
213  EqualityFunctor equal; // or a suitable functor is supplied
214  equal(t, t)
215  \endcode
216 */
217 doxygen_overloaded_function(template <...> unsigned int labelMultiArray)
218 
219 template <unsigned int N, class T, class S1,
220  class Label, class S2,
221  class Equal>
222 inline Label
223 labelMultiArray(MultiArrayView<N, T, S1> const & data,
224  MultiArrayView<N, Label, S2> labels,
225  NeighborhoodType neighborhood,
226  Equal equal)
227 {
228  vigra_precondition(data.shape() == labels.shape(),
229  "labelMultiArray(): shape mismatch between input and output.");
230 
231  GridGraph<N, undirected_tag> graph(data.shape(), neighborhood);
232  return lemon_graph::labelGraph(graph, data, labels, equal);
233 }
234 
235 template <unsigned int N, class T, class S1,
236  class Label, class S2>
237 inline Label
238 labelMultiArray(MultiArrayView<N, T, S1> const & data,
239  MultiArrayView<N, Label, S2> labels,
240  NeighborhoodType neighborhood = DirectNeighborhood)
241 {
242  return labelMultiArray(data, labels, neighborhood, std::equal_to<T>());
243 }
244 
245 /********************************************************/
246 /* */
247 /* labelMultiArrayWithBackground */
248 /* */
249 /********************************************************/
250 
251 /** \brief Find the connected components of a MultiArray with arbitrary many dimensions,
252  excluding the background from labeling.
253 
254  <b> Declaration:</b>
255 
256  \code
257  namespace vigra {
258 
259  template <unsigned int N, class T, class S1,
260  class Label, class S2
261  class Equal = std::equal<T> >
262  Label
263  labelMultiArrayWithBackground(MultiArrayView<N, T, S1> const & data,
264  MultiArrayView<N, Label, S2> labels,
265  NeighborhoodType neighborhood = DirectNeighborhood,
266  T backgroundValue = T(),
267  Equal equal = std::equal<T>());
268 
269  }
270  \endcode
271 
272  This function is the same as \ref labelMultiArray(), except for
273  the additional parameter \a backgroundValue. Points in the input
274  array \a data with this value (which default to zero) are ignored
275  during labeling, and their output label is automatically set to
276  zero. Region numbers will be a consecutive sequence starting at
277  zero (when background was present) or at one (when no background
278  was present) and ending with the region number returned by the
279  function (inclusive).
280 
281  Return: the number of non-background regions found (= highest region label,
282  because background has label 0)
283 
284  <b> Usage:</b>
285 
286  <b>\#include</b> <vigra/multi_labeling.hxx><br>
287  Namespace: vigra
288 
289  \code
290  MultiArray<3, int> src(Shape3(w,h,d));
291  MultiArray<3, int> dest(Shape3(w,h,d));
292 
293  // find 6-connected regions, ignoring background value zero (the default)
294  int max_region_label = labelMultiArrayWithBackground(src, dest);
295 
296  // find 26-connected regions, using -1 as the background value
297  max_region_label = labelMultiArrayWithBackground(src, dest, IndirectNeighborhood, -1);
298  \endcode
299 
300  <b> Required Interface:</b>
301 
302  \code
303  T t, backgroundValue;
304  t == backgroundValue // T is equality comparable
305 
306  EqualityFunctor equal; // or a suitable functor is supplied
307  equal(t, backgroundValue)
308  \endcode
309 */
310 doxygen_overloaded_function(template <...> unsigned int labelMultiArrayWithBackground)
311 
312 template <unsigned int N, class T, class S1,
313  class Label, class S2,
314  class Equal>
315 inline Label
316 labelMultiArrayWithBackground(MultiArrayView<N, T, S1> const & data,
317  MultiArrayView<N, Label, S2> labels,
318  NeighborhoodType neighborhood,
319  T backgroundValue,
320  Equal equal)
321 {
322  vigra_precondition(data.shape() == labels.shape(),
323  "labelMultiArrayWithBackground(): shape mismatch between input and output.");
324 
325  GridGraph<N, undirected_tag> graph(data.shape(), neighborhood);
326  return lemon_graph::labelGraphWithBackground(graph, data, labels, backgroundValue, equal);
327 }
328 
329 template <unsigned int N, class T, class S1,
330  class Label, class S2>
331 inline Label
332 labelMultiArrayWithBackground(MultiArrayView<N, T, S1> const & data,
333  MultiArrayView<N, Label, S2> labels,
334  NeighborhoodType neighborhood = DirectNeighborhood,
335  T backgroundValue = T())
336 {
337  return labelMultiArrayWithBackground(data, labels, neighborhood, backgroundValue, std::equal_to<T>());
338 }
339 
340 //@}
341 
342 } // namespace vigra
343 
344 #endif //VIGRA_MULTI_LABELING_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.10.0 (Mon Nov 18 2013)