$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
by_erosion/union_find.hh
1 // Copyright (C) 2007, 2008, 2009, 2010, 2011, 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_MORPHO_RECONSTRUCTION_BY_EROSION_UNION_FIND_HH
28 # define MLN_MORPHO_RECONSTRUCTION_BY_EROSION_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_erosion
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_erosion::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_erosion::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  typedef mln_site(I) P;
133  typedef mln_value(I) V;
134 
135  // Auxiliary data.
136  p_array<P> s;
137  mln_ch_value(I, bool) deja_vu;
138  mln_ch_value(I, P) parent;
139  mln_concrete(I) output;
140 
141  // Initialization.
142  {
143  initialize(output, f);
144  data::fill(output, f);
145  initialize(parent, f);
146  initialize(deja_vu, f);
147  data::fill(deja_vu, false);
148 
150  }
151 
152  // First pass.
153  {
154  for (unsigned i = 0; i < s.nsites(); ++i)
155  {
156  P p = s[i];
157  parent(p) = p; // Make-Set.
158  mln_niter(N) n(nbh, p);
159  for_all(n)
160  {
161 // if (f.domain().has(n))
162 // mln_invariant(deja_vu(n)
163 // ==
164 // (g(n) > g(p) || (g(n) == g(p)
165 // && util::ord_strict(n, p))));
166  if (f.domain().has(n) && deja_vu(n))
167  {
168  // Do-Union.
169  P r = internal::find_root(parent, n);
170  if (r != p)
171  {
172  if (g(r) == g(p) || g(p) <= output(r)) // Equivalence test.
173  {
174  parent(r) = p;
175  if (output(r) < output(p))
176  output(p) = output(r); // Increasing criterion.
177  }
178  else
179  output(p) = mln_min(V);
180  }
181  }
182  }
183  deja_vu(p) = true;
184  }
185  }
186 
187  // Second pass.
188  {
189  for (int i = s.nsites() - 1; i >= 0; --i)
190  {
191  P p = s[i];
192  if (parent(p) == p)
193  {
194  if (output(p) == mln_min(V))
195  output(p) = g(p);
196  }
197  else
198  output(p) = output(parent(p));
199  }
200  }
201 
202  mln_postcondition(output >= f);
203  mln_postcondition(output >= g);
204 
205  return output;
206  }
207 
208  } // end of namespace mln::morpho::reconstruction::by_erosion::impl::generic
209 
210  } // end of namespace mln::morpho::reconstruction::by_erosion::impl
211 
212 
213  // Dispatch.
214 
215  namespace internal
216  {
217 
218  template <typename I, typename J, typename N>
219  inline
220  mln_concrete(I)
221  union_find_dispatch(trait::image::kind::logic,
222  const Image<I>& f, const Image<J>& g,
223  const Neighborhood<N>& nbh)
224  {
225  // FIXME: Not yet implemented.
226  (void) f;
227  (void) g;
228  (void) nbh;
229  std::cerr
230  << __FILE__ << ":" << __LINE__ << ": error:\n"
231  "mln::morpho::reconstruction::by_erosion::internal::\n"
232  " union_find_dispatch(mln::trait::image::kind::logic,\n"
233  " const mln::Image<I>&,\n"
234  " const mln::Image<J>&,\n"
235  " const mln::Neighborhood<N>&)\n"
236  "not implemented."
237  << std::endl;
238  std::abort();
239  }
240 
241  template <typename I, typename J, typename N>
242  inline
243  mln_concrete(I)
244  union_find_dispatch(trait::image::kind::any,
245  const Image<I>& f, const Image<J>& g,
246  const Neighborhood<N>& nbh)
247  {
248  return impl::generic::union_find(f, g, nbh);
249  }
250 
251  template <typename I, typename J, typename N>
252  inline
253  mln_concrete(I)
254  union_find_dispatch(const Image<I>& f, const Image<J>& g,
255  const Neighborhood<N>& nbh)
256  {
257  return union_find_dispatch(mln_trait_image_kind(I)(),
258  f, g, nbh);
259  }
260 
261  } // end of namespace mln::morpho::reconstruction::by_erosion::internal
262 
263 
264  // Facade.
265 
266  template <typename I, typename J, typename N>
267  inline
268  mln_concrete(I)
269  union_find(const Image<I>& f, const Image<J>& g,
270  const Neighborhood<N>& nbh)
271  {
272  mln_trace("morpho::reconstruction::by_erosion::union_find");
273 
274  internal::union_find_tests(f, g, nbh);
275 
276  mln_concrete(I) output;
277  output = internal::union_find_dispatch(f, g, nbh);
278 
279  return output;
280  }
281 
282 # endif // ! MLN_INCLUDE_ONLY
283 
284  } // end of namespace mln::morpho::reconstruction::by_erosion
285 
286  } // end of namespace mln::morpho::reconstruction
287 
288  } // end of namespace mln::morpho
289 
290 } // end of namespace mln
291 
292 
293 #endif // ! MLN_MORPHO_RECONSTRUCTION_BY_EROSION_UNION_FIND_HH