$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
union.hh
1 // Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
31 
32 #ifndef SCRIBO_PRIMITIVE_EXTRACT_INTERNAL_UNION_HH
33 # define SCRIBO_PRIMITIVE_EXTRACT_INTERNAL_UNION_HH
34 
35 # include <mln/core/image/image2d.hh>
36 # include <mln/border/fill.hh>
37 
38 
39 namespace scribo
40 {
41 
42  namespace primitive
43  {
44 
45  namespace extract
46  {
47 
48  namespace internal
49  {
50 
51  using namespace mln;
52 
53 
54  unsigned find_root(image2d<unsigned>& parent, unsigned x);
55 
56 
57  void union_find(const image2d<bool>& input, bool lab,
59  unsigned& max_area);
60 
61 
62 # ifndef MLN_INCLUDE_ONLY
63 
64  inline
65  unsigned find_root(image2d<unsigned>& parent, unsigned x)
66  {
67  if (parent.element(x) == x)
68  return x;
69  return parent.element(x) = find_root(parent, parent.element(x));
70  }
71 
72 
73  inline
74  void union_find(const image2d<bool>& input,
75  bool lab,
76  // output:
77  image2d<unsigned>& parent,
79  unsigned& max_area)
80  {
81  const unsigned nrows = input.nrows(), ncols = input.ncols();
82 
83  unsigned op, on, delta = input.delta_offset(dpoint2d(1, 0));
84 
85  data::fill(parent, 0);
86  max_area = 0;
87 
88  {
89 
90  // row == 0 and col == 0
91 
92  op = input.offset_of_point(point2d(0,0));
93  if (input.element(op) == lab)
94  {
95  area.element(op) = 1;
96  parent.element(op) = op;
97  }
98 
99 
100  // row = 0
101 
102  for (unsigned col = 1; col < ncols; ++col)
103  {
104  on = op;
105  ++op;
106 
107  if (input.element(op) != lab)
108  continue;
109 
110  if (input.element(on) == lab)
111  {
112  unsigned& par_p = parent.element(op);
113  par_p = find_root(parent, on);
114  ++area.element(par_p);
115  if (area.element(par_p) > max_area)
116  max_area = area.element(par_p);
117  }
118  else
119  {
120  area.element(op) = 1;
121  parent.element(op) = op;
122  }
123 
124  }
125  }
126 
127 
128  for (unsigned row = 1; row < nrows; ++row)
129  {
130 
131  {
132  // col == 0
133 
134  op = input.offset_of_point(point2d(row, 0));
135  on = op - delta;
136 
137  if (input.element(op) == lab)
138  {
139  if (input.element(on) == lab)
140  {
141  unsigned& par_p = parent.element(op);
142  par_p = find_root(parent, on);
143  ++area.element(par_p);
144  if (area.element(par_p) > max_area)
145  max_area = area.element(par_p);
146  }
147  else
148  {
149  area.element(op) = 1;
150  parent.element(op) = op;
151  }
152  }
153 
154  }
155 
156  for (unsigned col = 1; col < ncols; ++col)
157  {
158  ++op;
159  ++on;
160 
161  if (input.element(op) != lab)
162  continue;
163 
164  bool merge_ = false;
165 
166  // up
167 
168  if (input.element(on) == lab)
169  {
170  unsigned& par_p = parent.element(op);
171  par_p = find_root(parent, on);
172  ++area.element(par_p);
173  if (area.element(par_p) > max_area)
174  max_area = area.element(par_p);
175  merge_ = true;
176  }
177 
178 
179  // left
180 
181  unsigned ol = op - 1;
182 
183  if (input.element(ol) == lab)
184  {
185  if (merge_)
186  {
187  if (input.element(on - 1) != lab) // not already merged
188  {
189  unsigned r_op = parent.element(op), r_ol = find_root(parent, ol);
190  if (r_op != r_ol)
191  {
192  // do-union
193  if (r_op < r_ol)
194  {
195  parent.element(r_ol) = r_op;
196  area.element(r_op) += area.element(r_ol);
197  if (area.element(r_op) > max_area)
198  max_area = area.element(r_op);
199  }
200  else
201  {
202  parent.element(r_op) = r_ol;
203  area.element(r_ol) += area.element(r_op);
204  if (area.element(r_ol) > max_area)
205  max_area = area.element(r_ol);
206  }
207  }
208  }
209  } // end of "if (merge)
210  else
211  {
212  unsigned& par_p = parent.element(op);
213  par_p = find_root(parent, ol);
214  ++area.element(par_p);
215  if (area.element(par_p) > max_area)
216  max_area = area.element(par_p);
217  merge_ = true;
218  }
219  }
220 
221 
222  // finalization
223 
224  if (merge_ == false)
225  {
226  parent.element(op) = op;
227  area.element(op) = 1;
228  }
229 
230  }
231  }
232 
233  } // end of 'union_find'
234 
235 # endif // ! MLN_INCLUDE_ONLY
236 
237  } // end of namespace scribo::primivite::extract::internal
238 
239  } // end of namespace scribo::primitive::extract
240 
241  } // end of namespace scribo::primitive
242 
243 } // end of namespace scribo
244 
245 
246 #endif // ! SCRIBO_PRIMITIVE_EXTRACT_INTERNAL_UNION_HH