$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
dual_hqueue.hh
1 // Copyright (C) 2008, 2009, 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_MORPHO_TREE_IMPL_COMPUTE_PARENT_DUAL_HQUEUE_HH
28 # define MLN_MORPHO_TREE_IMPL_COMPUTE_PARENT_DUAL_HQUEUE_HH
29 
46 
47 # include <mln/data/sort_psites.hh>
48 # include <mln/data/fill.hh>
49 
50 # include <mln/geom/nsites.hh>
51 # include <mln/geom/translate.hh>
52 
53 # include <mln/morpho/tree/data.hh>
54 
55 # include <mln/util/hqueues.hh>
56 # include <mln/util/ord.hh>
57 
58 # include <mln/value/value_array.hh>
59 # include <mln/value/set.hh>
60 
61 # include <mln/util/timer.hh>
62 
63 namespace mln
64 {
65 
66  namespace morpho
67  {
68 
69  namespace tree
70  {
71 
72  namespace impl
73  {
74 
83  template <typename I, typename N>
84  inline
86  dual_hqueue(const Image<I>& f,
87  const Image<I>& m,
88  const Neighborhood<N>& nbh);
89 
90  } // end of namespace mln::morpho::tree::impl
91 
92 
93 # ifndef MLN_INCLUDE_ONLY
94 
95  namespace internal
96  {
97 
98  template <typename I, typename N, class E>
99  struct shared_flood_args
100  {
101  typedef mln_psite(I) P;
102  typedef mln_value(I) V;
103  typedef p_array<P> S;
104 
105  const I& f;
106  const I& m;
107  const N& nbh;
108  mln_ch_value(I, P)& parent;
109 
110  // Aux data
111  util::hqueues<P, V>& hqueues;
112  const E& extend; // site -> site functor.
113  value::value_array<V, bool> is_node_at_level;
114  value::value_array<V, P> node_at_level;
115  mln_ch_value(I, bool) deja_vu;
116  const value::set<V>& vset;
117 
118  shared_flood_args(const I& f_,
119  const I& m_,
120  const N& neigb_,
121  mln_ch_value(I, P)& parent_,
122  util::hqueues<mln_psite(I), V>& hqueues_,
123  const E& extend_)
124  : f (f_),
125  m (m_),
126  nbh (neigb_),
127  parent (parent_),
128  hqueues (hqueues_),
129  extend (extend_),
130  is_node_at_level (false),
131  vset (hqueues.vset())
132  {
133  initialize(deja_vu, f);
134  mln::data::fill(deja_vu, false);
135  }
136  };
137 
138  template <typename I>
139  inline
141  compute_histo(const I& f, const I& m, mln_value(I)& hmin, mln_psite(I)& pmin)
142  {
145 
146  { // Retrieve hmin.
147  unsigned i = 0;
148  while (hm[i] == 0)
149  ++i;
150  hmin = hm.vset()[i];
151  }
152 
153  // Merge histograms.
154  for (unsigned i = 0; i < hm.nvalues(); ++i)
155  hm[i] += hf[i];
156 
157  // Retrieve pmin.
158  mln_piter(I) p(m.domain());
159  for (p.start(); m(p) != hmin; p.next())
160  ;
161  mln_assertion(p.is_valid());
162  pmin = p;
163 
164  return hm;
165  }
166 
167  // Site -> site functor: give for all p in Domain(f), its
168  // equivalence in the extended domain.
169  // TODO: make it generic. It works only on boxed domain.
170  template <typename I>
171  struct extend
172  {
173  extend(const mln_psite(I)::delta& dp)
174  : dp_ (dp)
175  {
176  }
177 
178  mln_psite(I) operator() (const mln_psite(I)& p) const
179  {
180  return p + dp_;
181  }
182 
183  private:
184  const mln_psite(I)::delta dp_;
185  };
186 
187  } // end of namespace mln::morpho::tree::internal
188 
189  namespace impl
190  {
191 
192  template <typename I, typename N, typename E>
193  unsigned
194  flood(internal::shared_flood_args<I, N, E>& args, const unsigned h_idx)
195  {
196  mln_assertion(args.is_node_at_level[h_idx]);
197 
198  while (!args.hqueues[h_idx].empty())
199  {
200  mln_psite(I) p = args.hqueues[h_idx].pop_front();
201  unsigned p_idx = args.vset.index_of(args.f(p));
202 
203  if (p_idx != h_idx)
204  { // Intensity mismatch: irregular case.
205  mln_psite(I) pext = args.extend(p);
206  args.parent(pext) = args.node_at_level[h_idx];
207 
208  if (p_idx > h_idx) // Singleton with parent at h.
209  args.parent(p) = args.node_at_level[h_idx];
210  else
211  {
212  if (!args.is_node_at_level[p_idx])
213  {
214  args.is_node_at_level[p_idx] = true;
215  args.node_at_level[p_idx] = p;
216  }
217  }
218  }
219 
220  if (p_idx <= h_idx)
221  {
222  if (!args.f.domain().has(args.node_at_level[p_idx]) ||
223  util::ord_strict(p, args.node_at_level[p_idx]))
224  { // Regular case but a representative provided by the extension.
225  args.parent(args.node_at_level[p_idx]) = p;
226  args.node_at_level[p_idx] = p;
227  //args.parent(p) = p;
228  }
229  args.parent(p) = args.node_at_level[p_idx];
230  }
231 
232 
233  // Process the neighbors
234  mln_niter(N) n(args.nbh, p);
235  for_all(n)
236  if (args.f.domain().has(n) && !args.deja_vu(n))
237  {
238  unsigned mn = args.vset.index_of(args.m(n));
239  unsigned fn = args.vset.index_of(args.f(n));
240  args.hqueues[mn].push(n);
241  args.deja_vu(n) = true;
242 
243  mln_psite(I) ext = args.extend(n);
244  // Create a node at c.
245  {
246  mln_psite(I) node = (fn == mn) ? n : ext;
247  if (!args.is_node_at_level[mn])
248  {
249  args.is_node_at_level[mn] = true;
250  args.node_at_level[mn] = node;
251  }
252  }
253 
254  while (mn > h_idx)
255  mn = flood(args, mn);
256  }
257  }
258 
259  // Retrieve dad.
260  args.is_node_at_level[h_idx] = false;
261  unsigned c = h_idx;
262  while (c > 0 && !args.is_node_at_level[c])
263  --c;
264 
265  mln_psite(I) x = args.node_at_level[h_idx];
266  if (c > 0)
267  args.parent(x) = args.node_at_level[c];
268  else
269  args.parent(x) = x;
270 
271  return c;
272  }
273 
274  template <typename I, typename N>
275  inline
276  data< I, p_array<mln_psite(I)> >
277  dual_hqueue(const Image<I>& f_,
278  const Image<I>& m_,
279  const Neighborhood<N>& neibh_)
280  {
281  mln_trace("mln::morpho::tree::impl::dual_hqueue");
282 
283  const I& f = exact(f_);
284  const I& m = exact(m_);
285  const N& nbh = exact(neibh_);
286 
287  typedef mln_psite(I) P;
288  typedef p_array<mln_psite(I)> S;
289 
290  util::timer tm;
291  tm.start();
292 
293  // Histo.
294  mln_psite(I) pmin;
295  mln_value(I) hmin;
296  const histo::array<mln_value(I)> histo = internal::compute_histo(f, m, hmin, pmin);
297  util::hqueues<P, mln_value(I)> hqueues(histo);
298 
299  mln_psite(I)::delta dp(literal::zero);
300  mln_domain(I) d_ext = f.domain();
301  mln_domain(I) d = f.domain();
302 
303  // Extend the domain.
304  dp[0] = d.pmax()[0] - d.pmin()[0] + 1;
305  d.pmax() += dp;
306  d_ext.pmin() += dp;
307  d_ext.pmax() += dp;
308 
309  // Data.
310  mln_concrete(I) fext;
311  mln_ch_value(I, P) parent;
312  p_array<mln_psite(I)> s;
313 
314  // Initialization.
315  fext = geom::translate(m, dp.to_vec(), f, d);
316  initialize(parent, fext);
317  s.reserve(geom::nsites(fext));
318 
319  // Process.
320  internal::extend<I> extend(dp);
321  internal::shared_flood_args< I, N, internal::extend<I> >
322  args(f, m, nbh, parent, hqueues, extend);
323 
324  unsigned r = args.vset.index_of(hmin);
325  args.deja_vu(pmin) = true;
326  args.hqueues[r].push(pmin);
327  args.node_at_level[r] = (f(pmin) == hmin) ? pmin : extend(pmin);
328  args.is_node_at_level[r] = true;
329  flood(args, r);
330 
331  // Attach the nodes under hmin.
332  unsigned i = r;
333  do
334  {
335  if (args.is_node_at_level[i])
336  {
337  parent(args.node_at_level[r]) = args.node_at_level[i];
338  r = i;
339  }
340  }
341  while (i-- > 0);
342  parent(args.node_at_level[r]) = args.node_at_level[r]; //root
343 
344  // Canonization and make tree site set.
345  {
346  mln_ch_value(I, bool) deja_vu(d_ext);
347  mln::data::fill(deja_vu, false);
348 
349  p_array<mln_psite(I)> s_f = mln::data::sort_psites_increasing(f);
350  mln_fwd_piter(S) p(s_f); // Forward.
351  for_all(p)
352  {
353  P x = p;
354  P q = parent(p);
355 
356  // Case: l: m <---- m <---- f
357  // Or
358  // Case l1: m <----- f impossible.
359  // |
360  // l2: m
361  mln_assertion(!(d_ext.has(q) && fext(p) == fext(q) && d_ext.has(parent(q)) && q != parent(q)));
362 
363  while (d_ext.has(q) && !deja_vu(q) && (fext(q) != fext(parent(q)) || q == parent(q)))
364  {
365  s.append(q);
366  deja_vu(q) = true;
367  x = q;
368  q = parent(q);
369  }
370 
371  if (d_ext.has(q) && fext(q) == fext(parent(q)) && q != parent(q))
372  {
373  q = (parent(x) = parent(q));
374  mln_assertion(f.domain().has(q));
375  }
376 
377  if (fext(q) == fext(parent(q)))
378  parent(x) = parent(q);
379 
380  s.append(p);
381 
382  mln_assertion((q = parent(p)) == parent(q) || fext(q) != fext(parent(q)));
383  }
384 
385  }
386 
387  data<I, S> tree(fext, parent, s);
388 
389 
390  return tree;
391  }
392 
393  } // end of namespace mln::morpho::tree::impl
394 
395 # endif // ! MLN_INCLUDE_ONLY
396 
397  } // end of namespace mln::morpho::tree
398 
399  } // end of namespace mln::morpho
400 
401 } // end of namespace mln
402 
403 #endif // !MLN_MORPHO_TREE_COMPUTE_PARENT_DUAL_HQUEUE_HH
404 
405 
406