priority_driven_thinning.hh 5.74 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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory (LRDE)
//
// 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.

# include <algorithm>

# 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>

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

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.
	  \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
			    will not be removed.  */
      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,
75
			       G& detach,
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
			       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>.
	  \param detach     A function used to detach a cell from
			    \a input.
	  \param priority   A priority function expressed as an image.  */
      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,
98
			       G& detach,
99
100
101
102
103
104
105
106
107
108
109
110
			       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_,
111
			       G& detach,
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
			       const Image<J>& priority_,
			       const Function_v2b<H>& constraint_)
      {
	trace::entering("topo::skeleton::priority_driven_thinning");

	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);
	// Attach the work image to IS_SIMPLE.
	is_simple.set_image(output);

	typedef mln_psite(I) psite;
	typedef p_queue_fast<psite> queue_t;
129
130
131
	typedef p_priority<mln_value(J), queue_t> priority_queue_t;
	priority_queue_t queue;
	// Populate QUEUE with candidate simple points.
132
133
	mln_piter(I) p(output.domain());
	for_all(p)
134
135
	{
	  if (output(p) && constraint(p) && is_simple(p))
136
	    queue.push(priority(p), p);
137
138
	}

139
	while (!queue.is_empty())
140
	  {
141
	    psite p = queue.pop_front();
142
143
144
	    if (output(p) && constraint(p) && is_simple(p))
	      {
		detach(p, output);
145
146
		mln_niter(N) n(nbh, p);
		for_all(n)
147
148
149
		{
		  if (output.domain().has(n)
		      && output(n) && constraint(n) && is_simple(n))
150
		    queue.push(priority(n), n);
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
		}
	      }
	  }

	trace::exiting("topo::skeleton::priority_driven_thinning");
	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,
166
			       G& detach,
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
			       const Image<J>& priority)
      {
	return priority_driven_thinning(input, nbh, is_simple, detach,
					priority, fun::p2b::tautology());
      }

# 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