breadth_first_thinning.hh 5.81 KB
Newer Older
1
2
// Copyright (C) 2009, 2010, 2011 EPITA Research and Development
// Laboratory (LRDE)
3
//
4
// This file is part of Olena.
5
//
6
7
8
9
10
// 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,
11
12
13
14
15
// 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
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
22
23
24
25
// 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.
26
27
28
29

#ifndef MLN_TOPO_SKELETON_BREADTH_FIRST_THINNING_HH
# define MLN_TOPO_SKELETON_BREADTH_FIRST_THINNING_HH

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

# include <algorithm>

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

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

41
# include <mln/core/site_set/p_queue_fast.hh>
42
43
44

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

45
46
47
# include <mln/data/fill.hh>


48
49
50
51
52
53
54
55
56
namespace mln
{

  namespace topo
  {

    namespace skeleton
    {

57
      /** \brief Skeleton by Breadth-First Thinning.
58

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

62
63
64
65
66
	  \param input      The input image.
	  \param nbh        The adjacency relation between triangles.
	  \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>.
67
	  \param detach     A function used to detach a cell from \a input.
68
69
			    This functor must provide a method
			    <tt>void set_image(const Image<I>&)</tt>.
70
71
	  \param constraint A constraint on point (site); if it
			    returns \c false for a point, this point
72
73
74
			    will not be removed.

	  Keywords: skeletons, simple points.  */
75
76
77
      template <typename I, typename N, typename F, typename G, typename H>
      mln_concrete(I)
      breadth_first_thinning(const Image<I>& input,
78
			     const Neighborhood<N>& nbh,
79
			     Function_v2b<F>& is_simple,
80
			     G& detach,
81
82
83
84
85
86
			     const Function_v2b<H>& constraint);


      /** \brief Skeleton by Breadth-First Thinning with no constraint.

	  A generic implementation of the computation of a skeleton
87
	  using a breadth-first thinning on a binary image.
88

89
90
91
92
93
	  \param input      The input image.
	  \param nbh        The adjacency relation between triangles.
	  \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>.
94
95
96
97
98
	  \param detach     A function used to detach a cell from \a input.
			    This functor must provide a method
			    <tt>void set_image(const Image<I>&)</tt>.

	  Keywords: skeletons, simple points.  */
99
100
101
102
103
      template <typename I, typename N, typename F, typename G>
      mln_concrete(I)
      breadth_first_thinning(const Image<I>& input,
			     const Neighborhood<N>& nbh,
			     Function_v2b<F>& is_simple,
104
			     G& detach);
105
106
107
108


# ifndef MLN_INCLUDE_ONLY

109
      template <typename I, typename N, typename F, typename G, typename H>
110
      inline
111
112
      mln_concrete(I)
      breadth_first_thinning(const Image<I>& input_,
113
			     const Neighborhood<N>& nbh_,
114
			     Function_v2b<F>& is_simple_,
115
			     G& detach,
116
			     const Function_v2b<H>& constraint_)
117
      {
118
119
	trace::entering("topo::skeleton::breadth_first_thinning");

120
	const I& input = exact(input_);
121
122
	const N& nbh = exact(nbh_);
	F& is_simple = exact(is_simple_);
123
	const H& constraint = exact(constraint_);
124

125
	mln_concrete(I) output = duplicate(input);
126
	// Attach the work image to IS_SIMPLE and DETACH.
127
	is_simple.set_image(output);
128
	detach.set_image(output);
129

130
	// FIFO queue.
131
	typedef mln_psite(I) psite;
132
133
	typedef p_queue_fast<psite> queue_t;
	queue_t queue;
134
135
136
137
138
	// Image showing whether a site has been inserted into the queue.
	mln_ch_value(I, bool) in_queue;
	initialize(in_queue, input);
	data::fill(in_queue, false);

139
	// Populate QUEUE with candidate simple points.
140
141
	mln_piter(I) p(output.domain());
	for_all(p)
142
143
	{
	  if (output(p) && constraint(p) && is_simple(p))
144
145
146
147
	    {
	      queue.push(p);
	      in_queue(p) = true;
	    }
148
149
	}

150
	while (!queue.is_empty())
151
	  {
152
	    psite p = queue.pop_front();
153
 	    in_queue(p) = false;
154
155
	    if (output(p) && constraint(p) && is_simple(p))
	      {
156
		detach(p);
157
158
		mln_niter(N) n(nbh, p);
		for_all(n)
159
		{
160
		  if (output.domain().has(n)
161
162
163
164
165
166
		      && output(n) && constraint(n) && is_simple(n)
		      && !in_queue(n))
		    {
		      queue.push(n);
		      in_queue(n) = true;
		    }
167
		}
168
	      }
169
	  }
170
171

	trace::exiting("topo::skeleton::breadth_first_thinning");
172
173
174
	return output;
      }

175
176
177
178
179
180
181

      template <typename I, typename N, typename F, typename G>
      inline
      mln_concrete(I)
      breadth_first_thinning(const Image<I>& input,
			     const Neighborhood<N>& nbh,
			     Function_v2b<F>& is_simple,
182
			     G& detach)
183
184
185
186
187
      {
	return breadth_first_thinning(input, nbh, is_simple, detach,
				      fun::p2b::tautology());
      }

188
189
190
191
192
193
194
195
196
# 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