breadth_first_thinning.hh 5.19 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Olena Library.  This library is free
// software; you can redistribute it and/or modify it under the terms
// of the GNU General Public License version 2 as published by the
// Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this library; see the file COPYING.  If not, write to
// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
// Boston, MA 02111-1307, USA.
//
// As a special exception, you may use this file as part of a free
// software library without restriction.  Specifically, if other files
// instantiate templates or use macros or inline functions from this
// file, or you compile this file and link it with other files to
// produce an executable, this file does not by itself cause the
// resulting executable to be covered by the GNU General Public
// License.  This exception does not however invalidate any other
// reasons why the executable file might be covered by the GNU General
// Public License.

#ifndef MLN_TOPO_SKELETON_BREADTH_FIRST_THINNING_HH
# define MLN_TOPO_SKELETON_BREADTH_FIRST_THINNING_HH

/// \file mln/topo/skeleton/breadth_first_thinning.hh
/// \brief Computing a skeleton by using breadth-first thinning on a
/// binary image.

# include <algorithm>

# include <mln/core/routine/duplicate.hh>

39
40
41
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>

42
43
44
45
46
47
48
49
50
51
52
53
54
# include <mln/core/site_set/p_set.hh>

# include <mln/fun/p2b/tautology.hh>

namespace mln
{

  namespace topo
  {

    namespace skeleton
    {

55
      /** \brief Skeleton by Breadth-First Thinning.
56

57
58
	  A generic implementation of the computation of a skeleton
	  using a breadth-first thinning on a binary.
59
60
61

          \param input      The input image.
          \param nbh        The adjacency relation between triangles.
62
63
64
65
          \param is_simple  The predicate on the simplicity of points
                            (sites).  This functor must provide a method
                            <tt>void set_image(const Image<I>&)</tt>.
	  \param detach     A function used to detach a cell from \a input.
66
67
68
          \param constraint A constraint on point (site); if it
       	                    returns \c false for a point, this point
                            will not be removed.  */
69
70
71
      template <typename I, typename N, typename F, typename G, typename H>
      mln_concrete(I)
      breadth_first_thinning(const Image<I>& input,
72
			     const Neighborhood<N>& nbh,
73
			     Function_v2b<F>& is_simple,
74
			     G detach,
75
			     const Function_v2b<H>& constraint =
76
77
78
79
80
			       fun::p2b::tautology());


# ifndef MLN_INCLUDE_ONLY

81
      template <typename I, typename N, typename F, typename G, typename H>
82
      inline
83
84
      mln_concrete(I)
      breadth_first_thinning(const Image<I>& input_,
85
			     const Neighborhood<N>& nbh_,
86
			     Function_v2b<F>& is_simple_,
87
			     G detach,
88
			     const Function_v2b<H>& constraint_)
89
      {
90
	const I& input = exact(input_);
91
92
	const N& nbh = exact(nbh_);
	F& is_simple = exact(is_simple_);
93
	const H& constraint = exact(constraint_);
94
95
96
97
98

	I output = duplicate(input);
	// Attach the work image to IS_SIMPLE.
	is_simple.set_image(output);

99
	typedef mln_psite(I) psite;
100
101
	typedef p_set<psite> set_t;
	set_t set;
102
	// Populate SET with candidate simple points.
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
	mln_piter(I) p_(output.domain());
	for_all(p_)
	{
	  /* CONSTRAINTS and IS_SIMPLE are site-to-boolean (p2b)
	     predicate functors; passing an iterator as argument might
	     not be possible (C++ cannot resolve template routines if
	     an implicit conversion of the argument is needed).  Help
	     the compiler and pass an actual, explicit psite.  */
	  psite p = p_;
	  if (output(p) && constraint(p) && is_simple(p))
	    set.insert(p);
	}

	while (!set.is_empty())
	  {
	    set_t next_set;
119
120
121
122
123
124
125
126
127
128
129
130

	    /* FIXME: Using the following code does not work (it does
	       compiles, but does not behave like the code using a
	       hand-made loop).  There must be a bug somewhere in
	       p_set or p_indexed_psite. */
# if 0
	    mln_piter(set_t) ps(set);
	    for_all(ps);
	    {
	      // Same remark as above.
	      psite p = p_;
# endif
131
132
133
	    for (unsigned i = 0; i < set.nsites(); ++i)
	      {
		psite p = set[i];
134
135
136
137
138

		/* FIXME: We compute the cell and attachment of P twice:
		   during the call to is_simple() and within detach().
		   How could we reuse this elegantly, without breaking
		   the genericity of the skeleton algorithm?  */
139
140
		if (constraint(p) && is_simple(p))
		  {
141
		    detach(p, output);
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
		    mln_niter(N) n(nbh, p);
		    for_all(n)
		      if (output.domain().has(n)
			  && output(n) && constraint(p) && is_simple(n))
			next_set.insert(n);
		  }
	      }
	    set.clear();
	    std::swap(set, next_set);
	  }
	return output;
      }

# endif // MLN_INCLUDE_ONLY

    } // end of namespace mln::topo::skeleton

  } // end of namespace mln::topo

} // end of namespace mln

#endif // ! MLN_TOPO_SKELETON_BREADTH_FIRST_THINNING_HH