$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
video.hh
1 // Copyright (C) 2007, 2008, 2009, 2012, 2013 EPITA Research and
2 // Development 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_VIDEO_HH
28 # define MLN_CANVAS_LABELING_VIDEO_HH
29 
36 
37 # include <mln/core/concept/image.hh>
38 # include <mln/data/fill.hh>
39 # include <mln/literal/zero.hh>
40 # include <mln/extension/adjust_fill.hh>
41 
42 # include <mln/canvas/labeling/internal/tests.hh>
43 # include <mln/canvas/labeling/internal/find_root_fastest.hh>
44 # include <mln/canvas/labeling/generic.hh>
45 
46 namespace mln
47 {
48 
49  namespace canvas
50  {
51 
52  namespace labeling
53  {
54 
60  template <typename I, typename N, typename L, typename F>
61  mln_ch_value(I, L)
62  video(const Image<I>& input, const Neighborhood<N>& nbh,
63  L& nlabels, F& functor);
64 
65 
66 # ifndef MLN_INCLUDE_ONLY
67 
68 
69  // Implementations.
70 
71  namespace impl
72  {
73 
74  template <typename I, typename N, typename L, typename F>
75  mln_ch_value(I, L)
76  video_fastest(const Image<I>& input_,
77  const Neighborhood<N>& nbh_,
78  L& nlabels, F& f)
79  {
80  mln_trace("canvas::impl::video_fastest");
81 
82  // FIXME: Test?!
83 
84  const I& input = exact(input_);
85  const N& nbh = exact(nbh_);
86 
87  extension::adjust(input, nbh);
88 
89  // Auxiliary data.
90  mln_ch_value(I, bool) deja_vu;
91  mln_ch_value(I, unsigned) parent;
92 
93  // Output.
94  mln_ch_value(I, L) output;
95 
96  // Initialization.
97  {
98  initialize(deja_vu, input);
99  mln::data::fill(deja_vu, true);
100  extension::fill(deja_vu, false); // So that the extension is ignored.
101 
102  initialize(parent, input);
103 
104  initialize(output, input);
105  mln::data::fill(output, L(literal::zero));
106  nlabels = 0;
107 
108  f.init_(); // Client initialization.
109  }
110 
111  // First Pass.
112  {
113  util::array<int> dp = positive_offsets_wrt(input, nbh);
114  const unsigned n_nbhs = dp.nelements();
115 
116  mln_bkd_pixter(const I) px(input); // Backward.
117  for_all(px)
118  {
119  unsigned p = px.offset();
120  if (! f.handles_(p))
121  continue;
122 
123  // Make-Set.
124  parent.element(p) = p;
125  f.init_attr_(p);
126  for (unsigned i = 0; i < n_nbhs; ++i)
127  {
128  unsigned n = p + dp[i];
129  if (deja_vu.element(n)) // Only false in the external border.
130  {
131  if (f.equiv_(n, p))
132  {
133  // Do-Union.
134  unsigned r = internal::find_root_fastest(parent, n);
135  if (r != p)
136  {
137  parent.element(r) = p;
138  f.merge_attr_(r, p);
139  }
140  }
141  else
142  f.do_no_union_(n, p);
143  }
144  }
145  }
146  }
147 
148  // Second Pass.
149  {
150  mln_fwd_pixter(const I) px(input); // Forward.
151  for_all(px)
152  {
153  unsigned p = px.offset();
154  if (! f.handles_(p))
155  continue;
156  if (parent.element(p) == p) // if p is root
157  {
158  if (f.labels_(p))
159  {
160  if (nlabels == mln_max(L))
161  {
162  mln_trace_warning("labeling aborted! Too many labels for \
163  this label type: nlabels > \
164  max(label_type).");
165  return output;
166  }
167  output.element(p) = ++nlabels;
168  f.set_new_label_(p, nlabels);
169  }
170  }
171  else
172  {
173  L lbl = output.element(parent.element(p));
174  output.element(p) = lbl;
175  f.set_label_(p, lbl);
176  }
177  }
178  }
179 
180  f.finalize();
181  return output;
182  }
183 
184  } // end of namespace mln::canvas::impl
185 
186 
187 
188  // Dispatch.
189 
190  namespace internal
191  {
192 
193  template <typename I, typename N, typename L, typename F>
194  inline
195  mln_ch_value(I, L)
196  video_dispatch(metal::false_,
197  const Image<I>& input,
198  const Neighborhood<N>& nbh, L& nlabels,
199  F& functor)
200  {
201  return impl::generic::labeling(input, nbh, nlabels,
202  exact(input).domain(), functor);
203  }
204 
205  template <typename I, typename N, typename L, typename F>
206  inline
207  mln_ch_value(I, L)
208  video_dispatch(metal::true_,
209  const Image<I>& input,
210  const Neighborhood<N>& nbh, L& nlabels,
211  F& functor)
212  {
213  return impl::video_fastest(input, nbh, nlabels, functor);
214  }
215 
216  template <typename I, typename N, typename L, typename F>
217  inline
218  mln_ch_value(I, L)
219  video_dispatch(const Image<I>& input,
220  const Neighborhood<N>& nbh, L& nlabels,
221  F& functor)
222  {
223  enum {
224  test = mlc_equal(mln_trait_image_speed(I),
225  trait::image::speed::fastest)::value
226  &&
227  mln_is_simple_neighborhood(N)::value
228  };
229  return video_dispatch(metal::bool_<test>(),
230  input, nbh, nlabels,
231  functor);
232  }
233 
234 
235  } // end of namespace mln::canvas::internal
236 
237 
238 
239  // Facades.
240 
241 
242  template <typename I, typename N, typename L, typename F>
243  inline
244  mln_ch_value(I, L)
245  video(const Image<I>& input, const Neighborhood<N>& nbh,
246  L& nlabels, F& functor)
247  {
248  mln_trace("canvas::video");
249 
250  internal::labeling_tests(input, nbh, nlabels, functor);
251 
252  mln_ch_value(I, L) output;
253  output = internal::video_dispatch(input, nbh, nlabels,
254  functor);
255 
256  return output;
257  }
258 
259 # endif // ! MLN_INCLUDE_ONLY
260 
261  } // end of namespace mln::canvas::labeling
262 
263  } // end of namespace mln::canvas
264 
265 } // end of namespace mln
266 
267 
268 #endif // ! MLN_CANVAS_LABELING_VIDEO_HH