priority_driven_thinning.hh 6.75 KB
Newer Older
1
// Copyright (C) 2009, 2010, 2011, 2013 EPITA Research and Development
2
// Laboratory (LRDE)
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
//
// This file is part of Olena.
//
// 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,
// 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 Olena.  If not, see <http://www.gnu.org/licenses/>.
//
// As a special exception, you may use this file as part of a free
// software project 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_PRIORITY_DRIVEN_THINNING_HH
# define MLN_TOPO_SKELETON_PRIORITY_DRIVEN_THINNING_HH

/// \file
/// \brief Computing a skeleton by using priority-driven thinning on a
/// binary image.
33
34
35
36
37
38
39
40
///
/// Careful: The meaning of the `constraint' is inversed with respect
/// to the definitions used in
///
///   Gilles Bertrand and Michel Couprie: Transformations topologiques
///   discrtes.  In David Coeurjolly, Annick Montanvert and Jean-Marc
///   Chassery, eds.: Gomtrie discrte et images numriques.  Hermes
///   Sciences Publications (2007), pages 187--209.
41
42
43
44
45
46
47
48
49

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

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

# include <mln/core/site_set/p_queue_fast.hh>
# include <mln/core/site_set/p_priority.hh>

50
# include <mln/topo/no_constraint.hh>
51

52
53
54
# include <mln/data/fill.hh>


55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
namespace mln
{

  namespace topo
  {

    namespace skeleton
    {

      /** \brief Skeleton by Priority-Driven Thinning.

	  A generic implementation of the computation of a skeleton
	  using a priority-driven thinning on a binary image.

	  \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>.
	  \param detach     A function used to detach a cell from \a input.
75
76
			    This functor must provide a method
			    <tt>void set_image(const Image<I>&)</tt>.
77
78
79
	  \param priority   A priority function expressed as an image.
	  \param constraint A constraint on point (site); if it
			    returns \c false for a point, this point
80
81
82
			    will not be removed.

	  Keywords: skeletons, simple points.  */
83
84
85
86
87
88
      template <typename I, typename N, typename F, typename G, typename J,
		typename H>
      mln_concrete(I)
      priority_driven_thinning(const Image<I>& input,
			       const Neighborhood<N>& nbh,
			       Function_v2b<F>& is_simple,
89
			       G& detach,
90
91
92
93
94
95
96
97
98
99
100
101
102
103
			       const Image<J>& priority,
			       const Function_v2b<H>& constraint);


      /** \brief Skeleton by Priority-Driven Thinning with no constraint.

	  A generic implementation of the computation of a skeleton
	  using a priority-driven thinning on a binary image.

	  \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>.
104
105
106
107
108
109
	  \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>.
	  \param priority   A priority function expressed as an image.

	  Keywords: skeletons, simple points.  */
110
111
112
113
114
      template <typename I, typename N, typename F, typename G, typename J>
      mln_concrete(I)
      priority_driven_thinning(const Image<I>& input,
			       const Neighborhood<N>& nbh,
			       Function_v2b<F>& is_simple,
115
			       G& detach,
116
117
118
119
120
121
122
123
124
125
126
127
			       const Image<J>& priority);


# ifndef MLN_INCLUDE_ONLY

      template <typename I, typename N, typename F, typename G, typename J,
		typename H>
      inline
      mln_concrete(I)
      priority_driven_thinning(const Image<I>& input_,
			       const Neighborhood<N>& nbh_,
			       Function_v2b<F>& is_simple_,
128
			       G& detach,
129
130
131
			       const Image<J>& priority_,
			       const Function_v2b<H>& constraint_)
      {
132
	mln_trace("topo::skeleton::priority_driven_thinning");
133
134
135
136
137
138
139
140

	const I& input = exact(input_);
	const N& nbh = exact(nbh_);
	F& is_simple = exact(is_simple_);
	const J& priority = exact(priority_);
	const H& constraint = exact(constraint_);

	mln_concrete(I) output = duplicate(input);
141
	// Attach the work image to IS_SIMPLE and DETACH.
142
	is_simple.set_image(output);
143
	detach.set_image(output);
144

145
	// Priority queue.
146
147
	typedef mln_psite(I) psite;
	typedef p_queue_fast<psite> queue_t;
148
149
	typedef p_priority<mln_value(J), queue_t> priority_queue_t;
	priority_queue_t queue;
150
151
152
153
154
	// 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);

155
	// Populate QUEUE with candidate simple points.
156
157
	mln_piter(I) p(output.domain());
	for_all(p)
158
159
	{
	  if (output(p) && constraint(p) && is_simple(p))
160
161
162
163
	    {
	      queue.push(priority(p), p);
	      in_queue(p) = true;
	    }
164
165
	}

166
	while (!queue.is_empty())
167
	  {
168
	    psite p = queue.pop_front();
169
 	    in_queue(p) = false;
170
171
	    if (output(p) && constraint(p) && is_simple(p))
	      {
172
		detach(p);
173
174
		mln_niter(N) n(nbh, p);
		for_all(n)
175
176
		{
		  if (output.domain().has(n)
177
178
179
180
181
182
		      && output(n) && constraint(n) && is_simple(n)
		      && !in_queue(n))
		    {
		      queue.push(priority(n), n);
		      in_queue(n) = true;
		    }
183
184
185
186
187
188
189
190
191
192
193
194
195
196
		}
	      }
	  }

	return output;
      }


      template <typename I, typename N, typename F, typename G, typename J>
      inline
      mln_concrete(I)
      priority_driven_thinning(const Image<I>& input,
			       const Neighborhood<N>& nbh,
			       Function_v2b<F>& is_simple,
197
			       G& detach,
198
199
			       const Image<J>& priority)
      {
200
201
202
	// mln::topo::no_constraint is a dummy functor always
	// returning `true'.
	no_constraint constraint;
203
	return priority_driven_thinning(input, nbh, is_simple, detach,
204
					priority, constraint);
205
206
207
208
209
210
211
212
213
214
215
      }

# endif // MLN_INCLUDE_ONLY

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

  } // end of namespace mln::topo

} // end of namespace mln

#endif // ! MLN_TOPO_SKELETON_PRIORITY_DRIVEN_THINNING_HH