sauvola_threshold_image.hh 7.85 KB
Newer Older
1
2
// Copyright (C) 2009, 2010 EPITA Research and Development 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
//
// 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.

27
28
#ifndef SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_HH
# define SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_HH
29
30
31

/// \file
///
32
/// Compute an image of local threshold using Sauvola algorithm.
33
34
35
36
37
38
39
40
41
42

/// \fixme return type too restrictive!

# include <algorithm>
# include <cmath>

# include <mln/core/image/image2d.hh>
# include <mln/value/int_u.hh>
# include <mln/value/int_u8.hh>

43
# include <scribo/core/init_integral_image.hh>
44
# include <scribo/binarization/internal/compute_sauvola_threshold.hh>
45
46
47



48
49
50
51
52
53
54
55
namespace scribo
{

  namespace binarization
  {

    using namespace mln;

56
    /*! \brief Compute an image of local threshold using Sauvola algorithm.
57
58

      \input[in]  input       An image.
59
      \input[in]  window_size The window size.
60
61
62
63
64
65
66
      \input[out] simple      The sum of all intensities of \p input.
      \input[out] squared     The sum of all squared intensities of \p
                              input.

      \return An image of local thresholds.

     */
67
    template <typename I, typename J>
68
    mln_ch_value(I, value::int_u8)
69
    sauvola_threshold_image(const Image<I>& input, unsigned window_size,
70
			    double K,
71
72
			    Image<J>& simple,
			    Image<J>& squared);
73

74
75
76
77
78
    /// \overload
    template <typename I>
    mln_ch_value(I, value::int_u8)
    sauvola_threshold_image(const Image<I>& input, unsigned window_size,
			    double K);
79
80

    /// \overload
81
    /// K is set to 0.34
82
83
    template <typename I>
    mln_ch_value(I, value::int_u8)
84
    sauvola_threshold_image(const Image<I>& input, unsigned window_size);
85
86
87
88
89
90
91


    /// \overload
    /// The window size is set to 11.
    //
    template <typename I>
    mln_ch_value(I, value::int_u8)
92
    sauvola_threshold_image(const Image<I>& input);
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107



# ifndef MLN_INCLUDE_ONLY


    // Implementation


    namespace impl
    {

      namespace generic
      {

108
	template <typename I, typename J>
109
110
	inline
	mln_concrete(I)
111
	sauvola_threshold_image(const Image<I>& input_, unsigned window_size,
112
				double K,
113
114
				Image<J>& simple_,
				Image<J>& squared_)
115
	{
116
	  trace::entering("scribo::binarization::impl::generic::sauvola_threshold_image");
117

118
119
120
	  const I& input = exact(input_);
	  J& simple = exact(simple_);
	  J& squared = exact(squared_);
121

122
123
124
	  mln_assertion(input.is_valid());
	  mln_assertion(simple.is_valid());
	  mln_assertion(squared.is_valid());
125

126
127
	  typedef mln_value(I) V;
	  typedef mln_site(I) P;
128

129
130
131
132
133
134
135
136
137
#  ifdef SCRIBO_SAUVOLA_DEBUG
	  initialize(internal::debug_mean, input);
	  initialize(internal::debug_stddev, input);
	  initialize(internal::debug_threshold, input);
	  initialize(internal::debug_alpham, input);
	  initialize(internal::debug_alphacond, input);
#  endif // ! SCRIBO_SAUVOLA_DEBUG

	  // Sauvola Algorithm with I.I.
138
139
140
141

	  mln_concrete(I) output;
	  initialize(output, input);

Guillaume Lazzara's avatar
Guillaume Lazzara committed
142
143
144
145
	  const mln::def::coord
	    nrows = static_cast<mln::def::coord>(input.nrows()),
	    ncols = static_cast<mln::def::coord>(input.ncols());

146

Guillaume Lazzara's avatar
Guillaume Lazzara committed
147
148
	  for(mln::def::coord row = 0; row < nrows; ++row)
	    for(mln::def::coord col = 0; col < ncols; ++col)
149
150
151
152
153
154
155
156
157
158
	    {
#  ifdef SCRIBO_SAUVOLA_DEBUG

	      double t = internal::compute_sauvola_threshold(P(row, col), simple,
							     squared, window_size,
							     K,
							     SCRIBO_DEFAULT_SAUVOLA_R);
	      mln::convert::from_to(t, output.at_(row, col));
	      internal::debug_threshold.at_(row, col) = t;
#  else
Guillaume Lazzara's avatar
Guillaume Lazzara committed
159
	      mln::convert::from_to(
160
161
162
163
164
		internal::compute_sauvola_threshold(P(row, col), simple,
						    squared, window_size,
						    K,
						    SCRIBO_DEFAULT_SAUVOLA_R),
		output.at_(row, col));
165
166
#  endif // ! SCRIBO_SAUVOLA_DEBUG
	    }
167
168
169
170
171
172
173
174
175

	  trace::exiting("scribo::binarization::impl::generic::sauvola_threshold");
	  return output;
	}

      } // end of namespace scribo::binarization::impl::generic



176
      template <typename I, typename J>
177
178
      inline
      mln_concrete(I)
179
      sauvola_threshold_image_gl(const I& input, unsigned window_size,
180
181
182
				 double K,
				 Image<J>& simple,
				 Image<J>& squared)
183
      {
184
	return impl::generic::sauvola_threshold_image(input, window_size, K,
185
						      simple, squared);
186
187
188
189
190
191
192
193
194
195
196
197
198
      }


    } // end of namespace scribo::binarization::impl




      // Dispatch

    namespace internal
    {

199
      template <unsigned n, typename I, typename J>
200
201
      inline
      mln_ch_value(I, value::int_u<n>)
202
203
      sauvola_threshold_image_dispatch(const value::int_u<n>&, const I& input,
				       unsigned window_size,
204
				       double K,
205
206
				       J& simple,
				       J& squared)
207
      {
208
209
	return impl::sauvola_threshold_image_gl(input, window_size, K,
						simple, squared);
210
211
212
      }


213
      template <typename I, typename J>
214
215
      inline
      mln_ch_value(I, value::int_u8)
216
217
      sauvola_threshold_image_dispatch(const mln_value(I)&, const I& input,
				       unsigned window_size,
218
				       double K,
219
220
				       J& simple,
				       J& squared)
221
222
223
224
225
226
227
228
229
230
231
232
233
      {
	// No dispatch for this kind of value type.
	mlc_abort(I)::check();

	typedef mln_ch_value(I,bool) output_t;
	return output_t();
      }


    } // end of namespace scribo::binarization::internal



234
    template <typename I, typename J>
235
    mln_ch_value(I, value::int_u8)
236
    sauvola_threshold_image(const Image<I>& input, unsigned window_size,
237
238
239
			    double K,
			    Image<J>& simple,
			    Image<J>& squared)
240
    {
241
      trace::entering("scribo::binarization::sauvola_threshold_image");
242
243
244
245
246
247

      mln_precondition(mln_site_(I)::dim == 2);
      mln_precondition(exact(input).is_valid());

      typedef mln_value(I) value_t;
      mln_ch_value(I, value::int_u8)
248
249
	output = internal::sauvola_threshold_image_dispatch(value_t(),
							    exact(input),
250
							    window_size,
251
							    K,
252
253
							    exact(simple),
							    exact(squared));
254
255
256
257
258
259
260
261
262

      trace::exiting("scribo::text::ppm2pbm");
      return output;
    }


    template <typename I>
    inline
    mln_ch_value(I, value::int_u8)
263
264
    sauvola_threshold_image(const Image<I>& input, unsigned window_size,
			    double K)
265
    {
266
267
268
269
      mln_ch_value(I, double)
	simple = init_integral_image(input, scribo::internal::identity_),
	squared = init_integral_image(input, scribo::internal::square_);

270
271
272
273
      return sauvola_threshold_image(input, window_size,
				     K, simple, squared);
    }

Guillaume Lazzara's avatar
Guillaume Lazzara committed
274

275
276
277
278
279
280
281
    template <typename I>
    inline
    mln_ch_value(I, value::int_u8)
    sauvola_threshold_image(const Image<I>& input, unsigned window_size)
    {
      return sauvola_threshold_image(input, window_size,
				     SCRIBO_DEFAULT_SAUVOLA_K);
282
283
284
285
286
287
    }


    template <typename I>
    inline
    mln_ch_value(I, value::int_u8)
288
    sauvola_threshold_image(const Image<I>& input)
289
    {
290
      return sauvola_threshold_image(input, 11);
291
292
293
294
295
296
297
298
299
300
    }


# endif // ! MLN_INCLUDE_ONLY

    } // end of namespace scribo::binarization

} // end of namespace scribo


301
#endif // ! SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_HH