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