$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
canvas/distance_front.hh
1 // Copyright (C) 2008, 2009, 2012 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_DISTANCE_FRONT_HH
28 # define MLN_CANVAS_DISTANCE_FRONT_HH
29 
33 
34 # include <vector>
35 # include <mln/core/concept/image.hh>
36 # include <mln/core/concept/neighborhood.hh>
37 # include <mln/core/concept/weighted_window.hh>
38 # include <mln/data/fill.hh>
39 # include <mln/accu/stat/max.hh>
40 # include <mln/extension/adjust_fill.hh>
41 
42 
43 namespace mln
44 {
45 
46  namespace canvas
47  {
48 
54  template <typename I,
55  typename N, typename W, typename D,
56  typename F>
57  mln_ch_value(I, D)
58  distance_front(const Image<I>& input,
59  const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win, D max,
60  F& functor);
61 
62 
63 
64 # ifndef MLN_INCLUDE_ONLY
65 
66 
67  // Tests.
68 
69  namespace internal
70  {
71 
72  template <typename I,
73  typename N, typename W, typename D,
74  typename F>
75  void
76  distance_front_tests(const Image<I>& input_,
77  const Neighborhood<N>& nbh_,
78  const Weighted_Window<W>& w_win_,
79  D max,
80  F& functor)
81  {
82  const I& input = exact(input_);
83  const N& nbh = exact(nbh_);
84  const W& w_win = exact(w_win_);
85 
86  mln_precondition(input.is_valid());
87  mln_precondition(nbh.is_valid());
88 
89  (void) input;
90  (void) nbh;
91  (void) max;
92  (void) functor;
93  (void) w_win;
94  }
95 
96 
97  } // of namespace mln::canvas::internal
98 
99 
100 
101  // Implementations.
102 
103  namespace impl
104  {
105 
106  namespace generic
107  {
108 
109  template <typename I,
110  typename N, typename W, typename D,
111  typename F>
112  mln_ch_value(I, D)
113  distance_front(const Image<I>& input_,
114  const Neighborhood<N>& nbh_,
115  const Weighted_Window<W>& w_win_,
116  D max,
117  F& functor)
118  {
119  mln_trace("canvas::impl::generic::distance_front");
120 
121  const I& input = exact(input_);
122  const N& nbh = exact(nbh_);
123  const W& w_win = exact(w_win_);
124 
125  mln_precondition(input.is_valid());
126  mln_precondition(w_win.is_valid());
127 
128  typedef mln_site(I) P;
129  typedef std::vector<P> bucket_t;
130 
131  // Distance map.
132  mln_ch_value(I, D) dmap;
133  initialize(dmap, input);
134  data::fill(dmap, max);
135 
136  // Mod determination.
137  unsigned mod;
138  {
139  accu::stat::max<unsigned> m;
140  for (unsigned i = 0; i < w_win.size(); ++i)
141  m.take(w_win.w(i));
142  mod = unsigned(m) + 1;
143  }
144 
145  // Aux data.
146  std::vector<bucket_t> bucket(mod);
147  unsigned bucket_size = 0;
148 
149  // Initialization.
150  {
151  functor.init(input); // <-- init
152  mln_piter(I) p(input.domain());
153  mln_niter(N) n(nbh, p);
154  for_all(p)
155  if (functor.inqueue_p_wrt_input_p(input(p))) // <-- inqueue_p_wrt_input_p
156  {
157  dmap(p) = 0;
158  for_all(n)
159  if (input.domain().has(n) &&
160  functor.inqueue_p_wrt_input_n(input(n))) // <-- inqueue_p_wrt_input_n
161  {
162  bucket[0].push_back(p);
163  ++bucket_size;
164  break;
165  }
166  }
167  } // end of Initialization.
168 
169  // Propagation.
170  {
171  P p;
172  mln_qiter(W) q(w_win, p);
173  for (unsigned d = 0; bucket_size != 0; ++d)
174  {
175  bucket_t& bucket_d = bucket[d % mod];
176  for (unsigned i = 0; i < bucket_d.size(); ++i)
177  {
178  p = bucket_d[i];
179 
180  if (dmap(p) == max)
181  {
182  // Saturation so stop.
183  bucket_size = bucket_d.size(); // So at end bucket_size == 0.
184  break;
185  }
186 
187  if (dmap(p) < d)
188  // p has already been processed, having a distance less than d.
189  continue;
190 
191  for_all(q)
192  if (dmap.domain().has(q) && dmap(q) > d)
193  {
194  unsigned d_ = d + q.w();
195  if (d_ < dmap(q))
196  {
197  dmap(q) = d_;
198  functor.process(p, q); // <- process
199  bucket[d_ % mod].push_back(q);
200  ++bucket_size;
201  }
202  }
203  }
204  bucket_size -= bucket_d.size();
205  bucket_d.clear();
206  }
207  } // end of Propagation.
208 
209  return dmap;
210  }
211 
212  } // of namespace mln::canvas::impl::generic
213 
214 
215 
216  // Fastest version.
217 
218  template <typename I,
219  typename N, typename W, typename D,
220  typename F>
221  mln_ch_value(I, D)
222  distance_front_fastest(const Image<I>& input_,
223  const Neighborhood<N>& nbh_,
224  const Weighted_Window<W>& w_win_,
225  D max, F& functor)
226  {
227  mln_trace("canvas::impl::distance_front_fastest");
228 
229  const I& input = exact(input_);
230  const N& nbh = exact(nbh_);
231  const W& w_win = exact(w_win_);
232 
233  mln_precondition(input.is_valid());
234  mln_precondition(w_win.is_valid());
235 
236  // Handling w_win.
237  extension::adjust(input, w_win);
238  const unsigned n_ws = w_win.size();
239  util::array<int> dp = offsets_wrt(input, w_win.win());
240  mln_invariant(dp.nelements() == n_ws);
241 
242  // Distance map.
243  mln_ch_value(I, D) dmap;
244  initialize(dmap, input);
245  data::fill(dmap, max);
246 
247  // Mod determination.
248  unsigned mod;
249  {
250  accu::stat::max<unsigned> m;
251  for (unsigned i = 0; i < w_win.size(); ++i)
252  m.take(w_win.w(i));
253  mod = unsigned(m) + 1;
254  }
255 
256  // Aux data.
257  typedef std::vector<unsigned> bucket_t;
258  std::vector<bucket_t> bucket(mod);
259  unsigned bucket_size = 0;
260 
261  // Initialization.
262  {
263  functor.init_(input); // <-- init
264 
265  // For the extension to be ignored:
266  extension::fill(input, true);
267  extension::fill(dmap, D(0));
268 
269  mln_pixter(const I) p(input);
270  mln_nixter(const I, N) n(p, nbh);
271  for_all(p)
272  if (functor.inqueue_p_wrt_input_p_(p.val())) // <-- inqueue_p_wrt_input_p
273  {
274  dmap.element(p.offset()) = 0;
275  for_all(n)
276  if (functor.inqueue_p_wrt_input_n_(n.val())) // <-- inqueue_p_wrt_input_n
277  {
278  bucket[0].push_back(p.offset());
279  ++bucket_size;
280  break;
281  }
282  }
283  } // end of Initialization.
284 
285  // Propagation.
286  {
287  unsigned p;
288 
289  for (unsigned d = 0; bucket_size != 0; ++d)
290  {
291  bucket_t& bucket_d = bucket[d % mod];
292  for (unsigned i = 0; i < bucket_d.size(); ++i)
293  {
294  p = bucket_d[i];
295 
296  if (dmap.element(p) == max)
297  {
298  // Saturation so stop.
299  bucket_size = bucket_d.size(); // So at end bucket_size == 0.
300  break;
301  }
302 
303  if (dmap.element(p) < d)
304  // p has already been processed, having a distance less than d.
305  continue;
306 
307  for (unsigned i = 0; i < n_ws; ++i)
308  {
309  unsigned q = p + dp[i];
310  if (dmap.element(q) > d)
311  {
312  unsigned d_ = d + w_win.w(i);
313  if (d_ < dmap.element(q))
314  {
315  dmap.element(q) = d_;
316  functor.process_(p, q); // <- process
317  bucket[d_ % mod].push_back(q);
318  ++bucket_size;
319  }
320  }
321  }
322  }
323  bucket_size -= bucket_d.size();
324  bucket_d.clear();
325  }
326  } // end of Propagation.
327 
328  return dmap;
329  }
330 
331 
332  } // of namespace mln::canvas::impl
333 
334 
335 
336  // Dispatch.
337 
338  namespace internal
339  {
340 
341  template <typename I,
342  typename N, typename W, typename D,
343  typename F>
344  inline
345  mln_ch_value(I, D)
346  distance_front_dispatch(metal::false_,
347  const Image<I>& input,
348  const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win,
349  D max, F& functor)
350  {
351  return impl::generic::distance_front(input, nbh, w_win, max, functor);
352  }
353 
354  template <typename I,
355  typename N, typename W, typename D,
356  typename F>
357  inline
358  mln_ch_value(I, D)
359  distance_front_dispatch(metal::true_,
360  const Image<I>& input,
361  const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win,
362  D max, F& functor)
363  {
364  return impl::distance_front_fastest(input, nbh, w_win, max, functor);
365  }
366 
367  template <typename I,
368  typename N, typename W, typename D,
369  typename F>
370  inline
371  mln_ch_value(I, D)
372  distance_front_dispatch(const Image<I>& input,
373  const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win,
374  D max, F& functor)
375  {
376  enum {
377  test = mlc_equal(mln_trait_image_speed(I),
378  trait::image::speed::fastest)::value
379  &&
380  mln_is_simple_neighborhood(N)::value
381  &&
382  mln_is_simple_weighted_window(W)::value
383  };
384  return distance_front_dispatch(metal::bool_<test>(),
385  input, nbh, w_win, max, functor);
386  }
387 
388 
389  } // of namespace mln::canvas::internal
390 
391 
392 
393  // Facade.
394 
395  template <typename I,
396  typename N, typename W, typename D,
397  typename F>
398  inline
399  mln_ch_value(I, D)
400  distance_front(const Image<I>& input,
401  const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win,
402  D max, F& functor)
403  {
404  mln_trace("canvas::distance_front");
405 
406  internal::distance_front_tests(input, nbh, w_win, max, functor);
407 
408  mln_ch_value(I,D) output;
409  output = internal::distance_front_dispatch(input, nbh, w_win, max, functor);
410 
411  return output;
412  }
413 
414 
415 # endif // ! MLN_INCLUDE_ONLY
416 
417  } // end of namespace mln::canvas
418 
419 } // end of namespace mln
420 
421 
422 #endif // ! MLN_CANVAS_DISTANCE_FRONT_HH