$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
sorted.hh
1 // Copyright (C) 2009, 2012, 2013 EPITA Research and Development
2 // Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_CANVAS_LABELING_SORTED_HH
28 # define MLN_CANVAS_LABELING_SORTED_HH
29 
33 
34 
35 # include <mln/core/concept/image.hh>
36 # include <mln/data/fill.hh>
37 # include <mln/literal/zero.hh>
38 # include <mln/extension/adjust_fill.hh>
39 
40 # include <mln/data/sort_psites.hh>
41 # include <mln/data/sort_offsets.hh>
42 
43 # include <mln/canvas/labeling/generic.hh>
44 # include <mln/canvas/labeling/internal/tests.hh>
45 # include <mln/canvas/labeling/internal/find_root_fastest.hh>
46 
47 
48 
49 namespace mln
50 {
51 
52  namespace canvas
53  {
54 
55  namespace labeling
56  {
57 
63  template <typename I, typename N, typename L, typename F>
64  inline
65  mln_ch_value(I, L)
66  sorted(const Image<I>& input, const Neighborhood<N>& nbh,
67  L& nlabels, F& functor, bool increasing);
68 
69 
70 # ifndef MLN_INCLUDE_ONLY
71 
72 
73  // Implementations.
74 
75  namespace impl
76  {
77 
78  // Fastest sorted version
79 
80  template <typename I, typename N, typename L,
81  typename S, typename F>
82  mln_ch_value(I, L)
83  sorted_fastest(const Image<I>& input_,
84  const Neighborhood<N>& nbh_, L& nlabels,
85  const S& s, F& f)
86  {
87  mln_trace("canvas::impl::labeling::sorted_fastest");
88 
89  // FIXME: Test?!
90 
91  const I& input = exact(input_);
92  const N& nbh = exact(nbh_);
93 
94  extension::adjust(input, nbh);
95 
96  // Local type.
97  typedef mln_psite(I) P;
98 
99  // Auxiliary data.
100  mln_ch_value(I, bool) deja_vu;
101  mln_ch_value(I, unsigned) parent;
102 
103  // Output.
104  mln_ch_value(I, L) output;
105 
106  // Initialization.
107  {
108  initialize(deja_vu, input);
109  mln::data::fill(deja_vu, false);
110  extension::fill(deja_vu, false); // So that the extension is ignored.
111 
112  initialize(parent, input);
113 
114  initialize(output, input);
115  mln::data::fill(output, L(literal::zero));
116  nlabels = 0;
117 
118  f.init_(); // Client initialization.
119  }
120 
121  util::array<int> dp = offsets_wrt(input, nbh);
122  const unsigned n_nbhs = dp.nelements();
123 
124  const unsigned n_points = s.nelements();
125 
126  // First Pass.
127  {
128  for (int i = n_points - 1; i >=0; --i) // Backward.
129  {
130  unsigned p = s[i];
131  if (! f.handles_(p))
132  continue;
133 
134  // Make-Set.
135  parent.element(p) = p;
136  f.init_attr_(p);
137 
138  for (unsigned j = 0; j < n_nbhs; ++j)
139  {
140  unsigned n = p + dp[j];
141  if (! deja_vu.element(n))
142  continue;
143 
144  if (f.equiv_(n, p))
145  {
146  // Do-Union.
147  unsigned r = internal::find_root_fastest(parent, n);
148  if (r != p)
149  {
150  parent.element(r) = p;
151  f.merge_attr_(r, p);
152  }
153  }
154  else
155  f.do_no_union_(n, p);
156  }
157  deja_vu.element(p) = true;
158  }
159  }
160 
161  // Second Pass.
162  {
163  for (unsigned i = 0; i < n_points; ++i) // Forward.
164  {
165  unsigned p = s[i];
166  if (! f.handles_(p))
167  continue;
168 
169  if (parent.element(p) == p) // if p is root
170  {
171  if (f.labels_(p))
172  {
173  if (nlabels == mln_max(L))
174  {
175  mln_trace_warning("labeling aborted! Too many labels \
176  for this label type: nlabels > \
177  max(label_type).");
178  return output;
179  }
180  output.element(p) = ++nlabels;
181  }
182  }
183  else
184  output.element(p) = output.element(parent.element(p));
185  }
186  }
187 
188  return output;
189  }
190 
191  } // end of namespace mln::canvas::impl
192 
193 
194  // Dispatch.
195 
196  namespace internal
197  {
198 
199  template <typename I, typename N, typename L, typename F>
200  inline
201  mln_ch_value(I, L)
202  sorted_dispatch(metal::false_,
203  const Image<I>& input,
204  const Neighborhood<N>& nbh, L& nlabels,
205  F& functor, bool increasing)
206  {
207  p_array<mln_psite(I)> s =
208  increasing ?
211  return impl::generic::labeling(input, nbh, nlabels, s,
212  functor);
213  }
214 
215  template <typename I, typename N, typename L, typename F>
216  inline
217  mln_ch_value(I, L)
218  sorted_dispatch(metal::true_,
219  const Image<I>& input,
220  const Neighborhood<N>& nbh, L& nlabels,
221  F& functor, bool increasing)
222  {
223  util::array<unsigned> s =
224  increasing ?
226  data::sort_offsets_decreasing(input);
227  return impl::sorted_fastest(input, nbh, nlabels, s,
228  functor);
229  }
230 
231  template <typename I, typename N, typename L, typename F>
232  inline
233  mln_ch_value(I, L)
234  sorted_dispatch(const Image<I>& input,
235  const Neighborhood<N>& nbh, L& nlabels,
236  F& functor, bool increasing)
237  {
238  enum {
239  test = mlc_equal(mln_trait_image_speed(I),
240  trait::image::speed::fastest)::value
241  &&
242  mln_is_simple_neighborhood(N)::value
243  };
244  return sorted_dispatch(metal::bool_<test>(),
245  input, nbh, nlabels,
246  functor, increasing);
247  }
248 
249 
250  } // end of namespace mln::canvas::internal
251 
252 
253 
254  // Facades.
255 
256 
257  template <typename I, typename N, typename L, typename F>
258  inline
259  mln_ch_value(I, L)
260  sorted(const Image<I>& input, const Neighborhood<N>& nbh,
261  L& nlabels, F& functor, bool increasing)
262  {
263  mln_trace("canvas::labeling::sorted");
264 
265  internal::labeling_tests(input, nbh, nlabels, functor);
266 
267  mln_ch_value(I, L) output;
268  output = internal::sorted_dispatch(input, nbh, nlabels,
269  functor, increasing);
270 
271  return output;
272  }
273 
274 
275 # endif // ! MLN_INCLUDE_ONLY
276 
277  } // end of namespace mln::canvas::labeling
278 
279  } // end of namespace mln::canvas
280 
281 } // end of namespace mln
282 
283 
284 #endif // ! MLN_CANVAS_LABELING_SORTED_HH