breadth_first_thinning.hh 5.04 KB
Newer Older
1
2
// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
//
3
// This file is part of Olena.
4
//
5
6
7
8
9
// Olena is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, version 2 of the License.
//
// Olena is distributed in the hope that it will be useful,
10
11
12
13
14
// 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
15
// along with Olena.  If not, see <http://www.gnu.org/licenses/>.
16
17
//
// As a special exception, you may use this file as part of a free
18
// software project without restriction.  Specifically, if other files
19
// instantiate templates or use macros or inline functions from this
20
21
22
23
24
// 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.
25
26
27
28

#ifndef MLN_TOPO_SKELETON_BREADTH_FIRST_THINNING_HH
# define MLN_TOPO_SKELETON_BREADTH_FIRST_THINNING_HH

29
/// \file
30
31
32
33
34
35
36
/// \brief Computing a skeleton by using breadth-first thinning on a
/// binary image.

# include <algorithm>

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

37
38
39
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>

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

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

namespace mln
{

  namespace topo
  {

    namespace skeleton
    {

53
      /** \brief Skeleton by Breadth-First Thinning.
54

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

          \param input      The input image.
          \param nbh        The adjacency relation between triangles.
60
61
62
63
          \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.
64
65
66
          \param constraint A constraint on point (site); if it
       	                    returns \c false for a point, this point
                            will not be removed.  */
67
68
69
      template <typename I, typename N, typename F, typename G, typename H>
      mln_concrete(I)
      breadth_first_thinning(const Image<I>& input,
70
			     const Neighborhood<N>& nbh,
71
			     Function_v2b<F>& is_simple,
72
			     G detach,
73
			     const Function_v2b<H>& constraint =
74
75
76
77
78
			       fun::p2b::tautology());


# ifndef MLN_INCLUDE_ONLY

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

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

97
	typedef mln_psite(I) psite;
98
99
	typedef p_set<psite> set_t;
	set_t set;
100
	// Populate SET with candidate simple points.
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
	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;
117
118
119
120
121
122
123
124
125
126
127
128

	    /* 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
129
130
131
	    for (unsigned i = 0; i < set.nsites(); ++i)
	      {
		psite p = set[i];
132
133
134
135
136

		/* 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?  */
137
138
		if (constraint(p) && is_simple(p))
		  {
139
		    detach(p, output);
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
		    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