$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
is_simple_2d.hh
1 // Copyright (C) 2008, 2009, 2011, 2012, 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_TOPO_IS_SIMPLE_2D_HH
28 # define MLN_TOPO_IS_SIMPLE_2D_HH
29 
34 
38 
39 
40 #include <mln/core/concept/image.hh>
41 #include <mln/core/concept/neighborhood.hh>
42 
43 #include <mln/core/alias/point2d.hh>
44 #include <mln/core/alias/neighb2d.hh>
45 
46 
47 namespace mln
48 {
49 
50  namespace topo
51  {
52 
63  template<typename I, typename N>
64  inline
65  unsigned
66  connectivity_number_2d(const Image<I>& ima, const Neighborhood<N>& nbh,
67  const mln_psite(I)& p, bool b);
68 
81 
82  template<typename I, typename N>
83  bool
84  is_simple_2d(const Image<I>& ima, const Neighborhood<N>& nbh,
85  const mln_psite(I)& p);
86 
87 
88  template <typename N>
90  {
91 
92  is_simple_2d_t(const Neighborhood<N>& nbh);
93 
94  template <typename I>
95  bool check(const I& ima, const mln_psite(I)& p) const;
96 
97  template <typename I>
98  bool check__(const I& ima, unsigned p) const;
99 
100  template <typename I, typename N2>
101  unsigned nb_connectivity2d(const I&, const N2& nbh,
102  const mln_psite(I)& p, bool object) const;
103  template <typename I, typename N2>
104  unsigned nb_connectivity2d__(const I&, const N2& nbh,
105  unsigned p, bool object) const;
106 
107  protected:
108  const N& nbh_;
109  };
110 
111 
112 
113 # ifndef MLN_INCLUDE_ONLY
114 
115  namespace internal
116  {
117 
118  // Connectivity numbers computed with
119  // tools/compute_local_configurations.cc.
120 
121  static const unsigned char connectivity_number_c8[256] =
122  {
123  0, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1,
124  1, 2, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1,
125  1, 2, 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1,
126  2, 3, 2, 2, 2, 3, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1,
127 
128  1, 2, 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1,
129  1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
130  1, 2, 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1,
131  1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
132 
133  1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2,
134  1, 2, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1,
135  2, 3, 3, 3, 3, 4, 3, 3, 2, 2, 2, 2, 3, 3, 2, 2,
136  2, 3, 2, 2, 2, 3, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1,
137 
138  1, 2, 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1,
139  1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
140  1, 2, 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1,
141  1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
142  };
143 
144 
145  static const unsigned char connectivity_number_c4[256] =
146  {
147  0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1,
148  1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 3, 2, 2, 2, 2, 1,
149  0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1,
150  1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 3, 2, 2, 2, 2, 1,
151 
152  1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 3, 2, 2, 2, 3, 2,
153  2, 2, 3, 3, 2, 2, 2, 2, 3, 3, 4, 3, 3, 3, 3, 2,
154  1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 2, 1,
155  2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 1,
156 
157  0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1,
158  1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 3, 2, 2, 2, 2, 1,
159  0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1,
160  1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 3, 2, 2, 2, 2, 1,
161 
162  1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 3, 2, 2, 2, 3, 2,
163  1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 3, 2, 2, 2, 2, 1,
164  1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 2, 1,
165  1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1
166  };
167 
168  } // end of namespace mln::topo::internal
169 
170 
171 
172  template<typename I, typename N>
173  inline
174  unsigned
175  connectivity_number_2d(const Image<I>& ima_, const Neighborhood<N>& nbh_,
176  const mln_psite(I)& p, bool b)
177  {
178  const I& ima = exact(ima_);
179  const N& nbh = exact(nbh_);
180 
181  unsigned res = 0;
182  unsigned mask = 1;
183  mln_fwd_niter(neighb2d) n(c8(), p);
184  for_all(n)
185  {
186  /* FIXME: The `ima.has(n)' predicate is not meaningful, as the
187  computation below is wrong as soon as `p' has a number of
188  neighbors other than 8. We should instead abort or warn if
189  for any `n' we don't have `ima.has(n)'. */
190  if (ima.has(n) && ima(n) == b)
191  res = res | mask;
192  mask = mask << 1;
193  }
194 
195  unsigned number;
196  if (nbh == c4())
197  number = internal::connectivity_number_c4[res];
198  else if (nbh == c8())
199  number = internal::connectivity_number_c8[res];
200  else
201  abort();
202 
203  return number;
204  }
205 
206  template<typename I, typename N>
207  inline
208  bool
209  is_simple_2d(const Image<I>& ima, const Neighborhood<N>& nbh_,
210  const mln_psite(I)& p)
211  {
212  const N& nbh = exact(nbh_);
213  return
214  connectivity_number_2d(ima, nbh.foreground(), p, true ) == 1 &&
215  connectivity_number_2d(ima, nbh.background(), p, false) == 1;
216  }
217 
218 
219 
220  template <typename N>
221  is_simple_2d_t<N>::is_simple_2d_t(const Neighborhood<N>& nbh)
222  : nbh_(exact(nbh))
223  {
224  mln_precondition(nbh_.is_valid());
225  }
226 
227 
228 
229  template <typename N>
230  template <typename I, typename N2>
231  unsigned
232  is_simple_2d_t<N>::nb_connectivity2d(const I& ima, const N2& nbh,
233  const mln_psite(I)& p, bool b) const
234  {
235  mln_precondition(ima.is_valid());
236  mln_precondition(nbh.is_valid());
237 
238  unsigned res = 0;
239  unsigned mask = 1;
240  // Note: fwd here but bkd in is_simple_point.hh...
241  mln_fwd_niter(N2) n(c8(), p);
242  for_all(n)
243  {
244  /* FIXME: The `ima.has(n)' predicate is not meaningful, as the
245  computation below is wrong as soon as `p' has a number of
246  neighbors other than 8. We should instead abort or warn if
247  for any `n' we don't have `ima.has(n)'. */
248  if (ima.has(n) && ima(n) == b)
249  res = res | mask;
250  mask = mask << 1;
251  }
252 
253  unsigned number;
254  if (nbh == c4())
255  number = internal::connectivity_number_c4[res];
256  else if (nbh == c8())
257  number = internal::connectivity_number_c8[res];
258  else
259  abort();
260 
261  return number;
262  }
263 
264 
265  template <typename N>
266  template <typename I, typename N2>
267  unsigned
268  is_simple_2d_t<N>::nb_connectivity2d__(const I& ima, const N2& nbh,
269  unsigned p, bool b) const
270  {
271  mln_precondition(ima.is_valid());
272  mln_precondition(nbh.is_valid());
273 
274  unsigned res = 0;
275  unsigned mask = 1;
276 
277  static util::array<int>
278  noffset = mln::offsets_wrt(ima, c8());
279 
280  /* FIXME: Warning, this computation is meaningless if
281  noffset.nelements() is not exactly 8, as the connectivity
282  number tables have been computed within an 8-c neighborhood
283  (for both 4-c and 8-c). */
284  for (unsigned i = 0; i < noffset.nelements(); ++i)
285  {
286  if (ima.element(p + noffset[i]) == b)
287  res = res | mask;
288  mask = mask << 1;
289  }
290 
291  unsigned number;
292  if (nbh == c4())
293  number = internal::connectivity_number_c4[res];
294  else if (nbh == c8())
295  number = internal::connectivity_number_c8[res];
296  else
297  abort();
298 
299  return number;
300  }
301 
302 
303  template <typename N>
304  template <typename I>
305  inline
306  bool
307  is_simple_2d_t<N>::check(const I& ima, const mln_psite(I)& p) const
308  {
309  mln_precondition(ima.is_valid());
310  return (nb_connectivity2d(ima, nbh_.foreground(), p, true) == 1) // Consider neighbor.
311  && (nb_connectivity2d(ima, nbh_.background(), p, false) == 1); // Consider complement neighbor.
312  }
313 
314 
315 
316 
317  template <typename N>
318  template <typename I>
319  inline
320  bool
321  is_simple_2d_t<N>::check__(const I& ima, unsigned p) const
322  {
323  mln_precondition(ima.is_valid());
324  return (nb_connectivity2d__(ima, nbh_.foreground(), p, true) == 1) // Consider neighbor
325  && (nb_connectivity2d__(ima, nbh_.background(), p, false) == 1); // Consider complement neighbor.
326  }
327 
328 
329 
330 # endif // MLN_INCLUDE_ONLY
331 
332  } // end of namespace mln::topo
333 
334 } // end of namespace mln
335 
336 #endif // ! MLN_TOPO_IS_SIMPLE_2D_HH