Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
skeleton_constrained.hh
1 // Copyright (C) 2008, 2009, 2011 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_SKELETON_CONSTRAINED_HH
28 # define MLN_MORPHO_SKELETON_CONSTRAINED_HH
29 
36 
37 # include <mln/core/concept/image.hh>
38 # include <mln/core/concept/neighborhood.hh>
39 # include <mln/core/site_set/p_queue_fast.hh>
40 # include <mln/core/site_set/p_priority.hh>
41 # include <mln/extension/adjust_duplicate.hh>
42 # include <mln/extension/adjust_fill.hh>
43 # include <mln/data/fill.hh>
44 
45 # include <mln/util/timer.hh>
46 
47 namespace mln
48 {
49 
50  namespace morpho
51  {
52 
53  template <typename I,
54  typename N, typename F,
55  typename K, typename R>
56  mln_ch_value(I, bool)
57  skeleton_constrained(const Image<I>& input,
58  const Neighborhood<N>& nbh, const F& is_simple,
59  const Image<K>& constraint, const Image<R>& priority);
60 
61 
62 
63 # ifndef MLN_INCLUDE_ONLY
64 
65 
66  namespace impl
67  {
68 
69  namespace generic
70  {
71 
72  template <typename I,
73  typename N, typename F,
74  typename K, typename R>
75  inline
76  mln_ch_value(I, bool)
77  skeleton_constrained(const Image<I>& input_,
78  const Neighborhood<N>& nbh_, const F& is_simple,
79  const Image<K>& constraint_, const Image<R>& priority_)
80  {
81  trace::entering("morpho::skeleton_constrained");
82 
83  const I& input = exact(input_);
84  const N& nbh = exact(nbh_);
85  const K& constraint = exact(constraint_);
86  const R& priority = exact(priority_);
87 
88  mln_precondition(input.is_valid());
89  mln_precondition(nbh.is_valid());
90  mln_precondition(constraint.is_valid());
91  mln_precondition(priority.is_valid());
92 
93  typedef mln_value(I) V;
94  mlc_is(V, bool)::check();
95 
96  extension::adjust_duplicate(input, nbh);
97  extension::adjust_duplicate(constraint, nbh);
98  extension::adjust_duplicate(priority, nbh);
99 
100  // FIXME: Tests!
101 
102  typedef mln_psite(I) P;
103  typedef p_queue_fast<P> Q;
104  p_priority<mln_value(R), Q> q;
105 
106  mln_concrete(I) output;
107 
108  // Initialization.
109  {
110  output = duplicate(input);
111  extension::adjust_duplicate(output, nbh);
112 
113  mln_piter(I) p(input.domain());
114  for_all(p)
115  if (input(p) == false &&
116  is_simple.check(input, p)) // <-- is_simple.check
117  // p is a simple point of the background.
118  {
119  q.push(priority(p), p);
120  }
121  }
122 
123  // Propagation.
124  {
125  P p;
126 
127  mln_niter(N) n(nbh, p);
128  while (! q.is_empty())
129  {
130  p = q.pop_front();
131  for_all(n)
132  if (output.has(n) &&
133  output(n) == true &&
134  constraint(n) == false &&
135  is_simple.check(output, n)) // <-- is_simple.check
136  {
137  output(n) = false; // Remove n from object.
138  q.push(priority(n), n);
139  }
140  }
141  }
142 
143  trace::exiting("morpho::skeleton_constrained");
144  return output;
145  }
146 
147  } // end of namespace mln::morpho::impl::generic
148 
149 
150  template <typename I,
151  typename N, typename F,
152  typename K, typename R>
153  inline
154  mln_ch_value(I, bool)
155  skeleton_constrained_fast(const Image<I>& input_,
156  const Neighborhood<N>& nbh_,
157  const F& is_simple,
158  const Image<K>& constraint_,
159  const Image<R>& priority_)
160  {
161  trace::entering("morpho::skeleton_constrained_fast");
162 
163  const I& input = exact(input_);
164  const N& nbh = exact(nbh_);
165  const K& constraint = exact(constraint_);
166  const R& priority = exact(priority_);
167 
168  mln_precondition(input.is_valid());
169  mln_precondition(nbh.is_valid());
170  mln_precondition(constraint.is_valid());
171  mln_precondition(priority.is_valid());
172 
173  typedef mln_value(I) V;
174  mlc_is(V, bool)::check();
175 
176  // Whatever the value of the extension, results of this fast
177  // version may differ from the generic one. Indeed, we
178  // cannot check whether a site belongs to the image or not,
179  // so we try to not take border site in consideration by
180  // setting their value to false.
181  extension::adjust_fill(input, nbh, false);
182  extension::adjust_fill(constraint, nbh, false);
183 
184  // FIXME: Tests!
185 
186  typedef p_queue_fast<unsigned> Q;
187  p_priority<mln_value(R), Q> q;
188 
189  mln_concrete(I) output;
190 
191  // Initialization.
192  {
193  output = duplicate(input);
194  extension::adjust_fill(output, nbh, false);
195 
196  mln_pixter(const I) p_in(input);
197  for_all(p_in)
198  if (p_in.val() == false &&
199  is_simple.check__(input, p_in)) // <-- is_simple.check
200  // p is a simple point of the background.
201  {
202  q.push(priority.element(p_in.offset()), p_in);
203  }
204  }
205 
206  // Propagation.
207  {
208  util::array<int> dp = offsets_wrt(input, nbh.foreground());
209  const unsigned n_nbhs = dp.nelements();
210  while (! q.is_empty())
211  {
212  unsigned p = q.pop_front();
213 
214  for (unsigned i = 0; i < n_nbhs; ++i)
215  {
216  unsigned n = p + dp[i];
217 
218  if (output.element(n) == true &&
219  constraint.element(n) == false &&
220  is_simple.check__(output, n)) // <-- is_simple.check
221  {
222  output.element(n) = false; // Remove n from object.
223  q.push(priority.element(n), n);
224  }
225  }
226  }
227  }
228 
229  trace::exiting("morpho::skeleton_constrained_fast");
230  return output;
231  }
232 
233 
234  } // end of namespace mln::morpho::impl
235 
236 
237  namespace internal
238  {
239 
240  template <typename I,
241  typename N, typename F,
242  typename K, typename R>
243  inline
244  mln_ch_value(I, bool)
245  skeleton_constrained_dispatch(
246  mln::trait::image::value_access::any,
247  mln::trait::image::value_storage::any,
248  const Image<I>& input,
249  const Neighborhood<N>& nbh,
250  const F& is_simple,
251  const Image<K>& constraint,
252  const Image<R>& priority)
253  {
254  return impl::generic::skeleton_constrained(input, nbh,
255  is_simple,
256  constraint,
257  priority);
258  }
259 
260  template <typename I,
261  typename N, typename F,
262  typename K, typename R>
263  inline
264  mln_ch_value(I, bool)
265  skeleton_constrained_dispatch(
266  mln::trait::image::value_access::direct,
267  mln::trait::image::value_storage::one_block,
268  const Image<I>& input,
269  const Neighborhood<N>& nbh,
270  const F& is_simple,
271  const Image<K>& constraint,
272  const Image<R>& priority)
273  {
274  return impl::skeleton_constrained_fast(input, nbh,
275  is_simple,
276  constraint,
277  priority);
278  }
279 
280 
281  } // end of namespace mln::morpho::internal
282 
283 
284  template <typename I,
285  typename N, typename F,
286  typename K, typename R>
287  inline
288  mln_ch_value(I, bool)
289  skeleton_constrained(const Image<I>& input,
290  const Neighborhood<N>& nbh, const F& is_simple,
291  const Image<K>& constraint, const Image<R>& priority)
292  {
293  trace::entering("morpho::skeleton_constrained");
294 
295  mln_ch_value(I, bool)
296  output = internal::skeleton_constrained_dispatch(
297  mln_trait_image_value_access(I)(),
298  mln_trait_image_value_storage(I)(),
299  input, nbh, is_simple, constraint, priority);
300 
301  trace::exiting("morpho::skeleton_constrained");
302  return output;
303  }
304 
305 # endif // ! MLN_INCLUDE_ONLY
306 
307  } // end of namespace mln::morpho
308 
309 } // end of namespace mln
310 
311 
312 #endif // ! MLN_MORPHO_SKELETON_CONSTRAINED_HH