$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
by_dilation/union_find.hh
1 // Copyright (C) 2007, 2008, 2009, 2010, 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_RECONSTRUCTION_BY_DILATION_UNION_FIND_HH
28 # define MLN_MORPHO_RECONSTRUCTION_BY_DILATION_UNION_FIND_HH
29 
30 # include <cstdlib>
31 
32 # include <iostream>
33 # include <vector>
34 
35 # include <mln/core/concept/image.hh>
36 # include <mln/core/concept/neighborhood.hh>
37 # include <mln/data/fill.hh>
38 # include <mln/data/compare.hh>
39 # include <mln/data/sort_psites.hh>
40 
41 
42 namespace mln
43 {
44 
45  namespace morpho
46  {
47 
48  namespace reconstruction
49  {
50 
51  namespace by_dilation
52  {
53 
54 
55  template <typename I, typename J, typename N>
56  mln_concrete(I)
57  union_find(const Image<I>& f, const Image<J>& g,
58  const Neighborhood<N>& nbh);
59 
60 
61 # ifndef MLN_INCLUDE_ONLY
62 
63 
64  // Tests.
65 
66  namespace internal
67  {
68 
69  template <typename I, typename J, typename N>
70  inline
71  void
72  union_find_tests(const Image<I>& f_, const Image<J>& g_,
73  const Neighborhood<N>& nbh_)
74  {
75  const I& f = exact(f_);
76  const J& g = exact(g_);
77  const N& nbh = exact(nbh_);
78 
79  mln_precondition(f.is_valid());
80  mln_precondition(g.is_valid());
81  mln_precondition(nbh.is_valid());
82 
83  mln_precondition(f.domain() == g.domain()); // FIXME: Relax?
84  mln_precondition(f <= g);
85 
86  // mlc_equal(mln_value(I), mln_value(J))::check(); // FIXME: Too strong!
87  // FIXME: Also check that we have a total ordering for values.
88 
89  (void) f;
90  (void) g;
91  (void) nbh;
92  }
93 
94 
95 
96  template <typename Par>
97  inline
98  mln_site(Par) find_root(Par& parent, mln_site(Par) x)
99  {
100  if (parent(x) == x)
101  return x;
102  else
103  return parent(x) = find_root(parent, parent(x));
104  }
105 
106 
107  } // end of namespace mln::morpho::reconstruction::by_dilation::internal
108 
109 
110  // Implementations.
111 
112  namespace impl
113  {
114 
115  namespace generic
116  {
117 
118  template <typename I, typename J, typename N>
119  inline
120  mln_concrete(I)
121  union_find(const Image<I>& f_, const Image<J>& g_,
122  const Neighborhood<N>& nbh_)
123  {
124  mln_trace("morpho::reconstruction::by_dilation::impl::generic::union_find");
125 
126  const I& f = exact(f_);
127  const J& g = exact(g_);
128  const N& nbh = exact(nbh_);
129 
130  internal::union_find_tests(f, g, nbh);
131 
132 
133  typedef mln_site(I) P;
134  typedef mln_value(I) V;
135 
136  // Auxiliary data.
137  p_array<P> s;
138  mln_ch_value(I, bool) deja_vu;
139  mln_ch_value(I, P) parent;
140  mln_concrete(I) output;
141 
142  // Initialization.
143  {
144  initialize(output, f);
145  data::fill(output, f);
146  initialize(parent, f);
147  initialize(deja_vu, f);
148  data::fill(deja_vu, false);
149 
151  }
152 
153  // First pass.
154  {
155  for (unsigned i = 0; i < s.nsites(); ++i)
156  {
157  P p = s[i];
158  parent(p) = p; // Make-Set.
159  mln_niter(N) n(nbh, p);
160  for_all(n)
161  {
162 // if (f.domain().has(n))
163 // mln_invariant(deja_vu(n)
164 // ==
165 // (g(n) > g(p) || (g(n) == g(p)
166 // && util::ord_strict(n, p))));
167  if (f.domain().has(n) && deja_vu(n))
168  {
169  // Do-Union.
170  P r = internal::find_root(parent, n);
171  if (r != p)
172  {
173  if (g(r) == g(p) || g(p) >= output(r)) // Equivalence test.
174  {
175  parent(r) = p;
176  if (output(r) > output(p))
177  output(p) = output(r); // Increasing criterion.
178  }
179  else
180  output(p) = mln_max(V);
181  }
182  }
183  }
184  deja_vu(p) = true;
185  }
186  }
187 
188  // Second pass.
189  {
190  for (int i = s.nsites() - 1; i >= 0; --i)
191  {
192  P p = s[i];
193  if (parent(p) == p)
194  {
195  if (output(p) == mln_max(V))
196  output(p) = g(p);
197  }
198  else
199  output(p) = output(parent(p));
200  }
201  }
202 
203  mln_postcondition(output >= f);
204  mln_postcondition(output <= g);
205 
206  return output;
207  }
208 
209 
210  } // end of namespace mln::morpho::reconstruction::by_dilation::impl::generic
211 
212  } // end of namespace mln::morpho::reconstruction::by_dilation::impl
213 
214 
215  // Dispatch.
216 
217  namespace internal
218  {
219 
220  template <typename I, typename J, typename N>
221  inline
222  mln_concrete(I)
223  union_find_dispatch(trait::image::kind::logic,
224  const Image<I>& f, const Image<J>& g,
225  const Neighborhood<N>& nbh)
226  {
227  // FIXME: Not yet implemented.
228  (void) f;
229  (void) g;
230  (void) nbh;
231  std::cerr
232  << __FILE__ << ":" << __LINE__ << ": error:\n"
233  "mln::morpho::reconstruction::by_dilation::internal::\n"
234  " union_find_dispatch(mln::trait::image::kind::logic,\n"
235  " const mln::Image<I>&,\n"
236  " const mln::Image<J>&,\n"
237  " const mln::Neighborhood<N>&)\n"
238  "not implemented."
239  << std::endl;
240  std::abort();
241  }
242 
243  template <typename I, typename J, typename N>
244  inline
245  mln_concrete(I)
246  union_find_dispatch(trait::image::kind::any,
247  const Image<I>& f, const Image<J>& g,
248  const Neighborhood<N>& nbh)
249  {
250  return impl::generic::union_find(f, g, nbh);
251  }
252 
253  template <typename I, typename J, typename N>
254  inline
255  mln_concrete(I)
256  union_find_dispatch(const Image<I>& f, const Image<J>& g,
257  const Neighborhood<N>& nbh)
258  {
259  return union_find_dispatch(mln_trait_image_kind(I)(),
260  f, g, nbh);
261  }
262 
263  } // end of namespace mln::morpho::reconstruction::by_dilation::internal
264 
265 
266  // Facade.
267 
268  template <typename I, typename J, typename N>
269  inline
270  mln_concrete(I)
271  union_find(const Image<I>& f, const Image<J>& g,
272  const Neighborhood<N>& nbh)
273  {
274  mln_trace("morpho::reconstruction::by_dilation::union_find");
275 
276  internal::union_find_tests(f, g, nbh);
277 
278  mln_concrete(I) output;
279  output = internal::union_find_dispatch(f, g, nbh);
280 
281  return output;
282  }
283 
284 # endif // ! MLN_INCLUDE_ONLY
285 
286  } // end of namespace mln::morpho::reconstruction::by_dilation
287 
288  } // end of namespace mln::morpho::reconstruction
289 
290  } // end of namespace mln::morpho
291 
292 } // end of namespace mln
293 
294 
295 #endif // ! MLN_MORPHO_RECONSTRUCTION_BY_DILATION_UNION_FIND_HH