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

multi_labeling.hxx |

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)