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