* scribo/binarization/internal/first_pass_functor.hh,
* scribo/binarization/local_threshold.hh,
* scribo/binarization/sauvola.hh,
* scribo/binarization/sauvola_ms.hh,
* scribo/binarization/sauvola_ms_split.hh,
* scribo/binarization/sauvola_threshold_image.hh,
* scribo/canvas/integral_browsing.hh: Add more parameters to
Sauvola routines.
* scribo/binarization/sauvola_threshold_image_debug.hh: New. New
overload providing debug outputs.
* scribo/debug/usage.hh: Remove a parameter.
* scribo/src/binarization/Makefile.am,
* scribo/src/binarization/pgm_global_threshold_auto.cc,
* scribo/src/binarization/pgm_sauvola.cc,
* scribo/src/binarization/pgm_sauvola_ms.cc,
* scribo/src/binarization/ppm_fg_sauvola_ms.cc,
* scribo/src/binarization/ppm_sauvola.cc,
* scribo/src/binarization/ppm_sauvola_ms.cc,
* scribo/src/binarization/ppm_sauvola_ms_split.cc: Add new
program arguments.
* scribo/src/binarization/fg_sauvola_ms.cc,
* scribo/src/binarization/sauvola.cc,
* scribo/src/binarization/sauvola_ms.cc,
* scribo/src/binarization/sauvola_ms_split.cc,
* scribo/src/binarization/sauvola_debug.cc: New.
---
scribo/ChangeLog | 34 +++
scribo/binarization/internal/first_pass_functor.hh | 22 +-
scribo/binarization/local_threshold.hh | 3 -
scribo/binarization/sauvola.hh | 61 ++++-
scribo/binarization/sauvola_ms.hh | 132 +++++----
scribo/binarization/sauvola_ms_split.hh | 29 ++-
scribo/binarization/sauvola_threshold_image.hh | 128 +++++----
...d_image.hh => sauvola_threshold_image_debug.hh} | 309 ++++++++------------
scribo/canvas/integral_browsing.hh | 13 -
scribo/debug/usage.hh | 13 +-
.../{ppm_fg_sauvola_ms.cc => fg_sauvola_ms.cc} | 15 +-
.../src/binarization/pgm_global_threshold_auto.cc | 3 +-
scribo/src/binarization/pgm_sauvola.cc | 28 ++-
scribo/src/binarization/pgm_sauvola_ms.cc | 53 +++-
scribo/src/binarization/ppm_fg_sauvola_ms.cc | 58 +++--
scribo/src/binarization/ppm_sauvola.cc | 38 ++-
scribo/src/binarization/ppm_sauvola_ms.cc | 57 +++--
scribo/src/binarization/ppm_sauvola_ms_split.cc | 65 +++--
.../binarization/{pgm_sauvola.cc => sauvola.cc} | 39 ++-
scribo/src/binarization/sauvola_debug.cc | 105 +++++++
.../{ppm_sauvola_ms.cc => sauvola_ms.cc} | 64 +++--
...ppm_sauvola_ms_split.cc => sauvola_ms_split.cc} | 71 ++++--
scribo/src/preprocessing/to_pgm.cc | 46 +++
23 files changed, 863 insertions(+), 523 deletions(-)
copy scribo/binarization/{sauvola_threshold_image.hh =>
sauvola_threshold_image_debug.hh} (55%)
copy scribo/src/binarization/{ppm_fg_sauvola_ms.cc => fg_sauvola_ms.cc} (87%)
copy scribo/src/binarization/{pgm_sauvola.cc => sauvola.cc} (68%)
create mode 100644 scribo/src/binarization/sauvola_debug.cc
copy scribo/src/binarization/{ppm_sauvola_ms.cc => sauvola_ms.cc} (61%)
copy scribo/src/binarization/{ppm_sauvola_ms_split.cc => sauvola_ms_split.cc} (64%)
create mode 100644 scribo/src/preprocessing/to_pgm.cc
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 50f9d86..34a258f 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,3 +1,37 @@
+2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Add new Sauvola overloads and update examples.
+
+ * scribo/binarization/internal/first_pass_functor.hh,
+ * scribo/binarization/local_threshold.hh,
+ * scribo/binarization/sauvola.hh,
+ * scribo/binarization/sauvola_ms.hh,
+ * scribo/binarization/sauvola_ms_split.hh,
+ * scribo/binarization/sauvola_threshold_image.hh,
+ * scribo/canvas/integral_browsing.hh: Add more parameters to
+ Sauvola routines.
+
+ * scribo/binarization/sauvola_threshold_image_debug.hh: New. New
+ overload providing debug outputs.
+
+ * scribo/debug/usage.hh: Remove a parameter.
+
+ * scribo/src/binarization/Makefile.am,
+ * scribo/src/binarization/pgm_global_threshold_auto.cc,
+ * scribo/src/binarization/pgm_sauvola.cc,
+ * scribo/src/binarization/pgm_sauvola_ms.cc,
+ * scribo/src/binarization/ppm_fg_sauvola_ms.cc,
+ * scribo/src/binarization/ppm_sauvola.cc,
+ * scribo/src/binarization/ppm_sauvola_ms.cc,
+ * scribo/src/binarization/ppm_sauvola_ms_split.cc: Add new
+ program arguments.
+
+ * scribo/src/binarization/fg_sauvola_ms.cc,
+ * scribo/src/binarization/sauvola.cc,
+ * scribo/src/binarization/sauvola_ms.cc,
+ * scribo/src/binarization/sauvola_ms_split.cc,
+ * scribo/src/binarization/sauvola_debug.cc: New.
+
2010-03-29 Guillaume Lazzara <z(a)lrde.epita.fr>
Add support for various image types in text_in_photo_fast.
diff --git a/scribo/binarization/internal/first_pass_functor.hh
b/scribo/binarization/internal/first_pass_functor.hh
index df4c025..3455060 100644
--- a/scribo/binarization/internal/first_pass_functor.hh
+++ b/scribo/binarization/internal/first_pass_functor.hh
@@ -68,12 +68,12 @@ namespace scribo
unsigned n_nbhs;
util::array<int> dp;
- static const double one_k = 1 - 0.34;
- static const double k_R = 0.34 / 128.0;
+ double K_;
- first_pass_functor(const I& input)
+ first_pass_functor(const I& input, double K)
: input(input),
- pxl(input)
+ pxl(input),
+ K_(K)
{
res = 0;
pxl.start();
@@ -96,17 +96,9 @@ namespace scribo
unsigned p = pxl.offset();
- // Use an inlined and developed version of sauvola's
- // threshold formula.
-// value::int_u8 t_p = mean * (one_k + k_R * stddev);
-
-// std::cout << t_p << ", ";
-
-// std::cout << input.element(p) << " - " << t_p <<
std::endl;
- value::int_u8 t_p = sauvola_threshold_formula(mean, stddev);
-
-// std::cout << input.point_at_index(p)
-// << " - " << sauvola_threshold_formula(mean, stddev);
+ value::int_u8 t_p = sauvola_threshold_formula(mean, stddev,
+ K_,
+ SCRIBO_DEFAULT_SAUVOLA_R);
msk.element(p) = input.element(p) < t_p;
diff --git a/scribo/binarization/local_threshold.hh
b/scribo/binarization/local_threshold.hh
index ea5b34e..aa53664 100644
--- a/scribo/binarization/local_threshold.hh
+++ b/scribo/binarization/local_threshold.hh
@@ -200,9 +200,6 @@ namespace scribo
internal::local_threshold_tests(input, threshold);
-
-
-
mln_ch_value(I, bool)
output = internal::local_threshold_dispatch(input, threshold);
diff --git a/scribo/binarization/sauvola.hh b/scribo/binarization/sauvola.hh
index c3a0cce..6dd812b 100644
--- a/scribo/binarization/sauvola.hh
+++ b/scribo/binarization/sauvola.hh
@@ -55,6 +55,23 @@ namespace scribo
\input[in] input An image.
\input[in] window_size The window size.
+ \input[in] K Sauvola's formulae constant.
+
+ \return A binary image.
+
+ */
+ template <typename I>
+ mln_ch_value(I, bool)
+ sauvola(const Image<I>& input, unsigned window_size, double K);
+
+
+
+ /*! \brief Convert an image into a binary image.
+
+ Sauvola's formulae constant K is set to 0.34.
+
+ \input[in] input An image.
+ \input[in] window_size The window size.
\return A binary image.
@@ -84,7 +101,7 @@ namespace scribo
template <typename I>
mln_ch_value(I, bool)
- sauvola(const Image<I>& input, unsigned window_size)
+ sauvola(const Image<I>& input, unsigned window_size, double K)
{
trace::entering("scribo::binarization::impl::generic::sauvola");
mln_precondition(exact(input).is_valid());
@@ -92,7 +109,8 @@ namespace scribo
mln_ch_value(I, bool)
output = local_threshold(input,
binarization::sauvola_threshold_image(input,
- window_size));
+ window_size,
+ K));
trace::exiting("scribo::binarization::impl::generic::sauvola");
return output;
@@ -103,7 +121,7 @@ namespace scribo
template <typename I>
mln_ch_value(I, bool)
- sauvola_rgb8(const Image<I>& input, unsigned window_size)
+ sauvola_rgb8(const Image<I>& input, unsigned window_size, double K)
{
trace::entering("scribo::binarization::impl::generic::sauvola");
mln_precondition(exact(input).is_valid());
@@ -114,7 +132,8 @@ namespace scribo
mln_ch_value(I, bool)
output = local_threshold(gima,
binarization::sauvola_threshold_image(gima,
- window_size));
+ window_size,
+ K));
trace::exiting("scribo::binarization::impl::generic::sauvola");
return output;
@@ -132,26 +151,29 @@ namespace scribo
template <typename I>
mln_ch_value(I, bool)
sauvola_dispatch(const mln_value(I)&,
- const Image<I>& input, unsigned window_size)
+ const Image<I>& input, unsigned window_size,
+ double K)
{
- return impl::generic::sauvola(input, window_size);
+ return impl::generic::sauvola(input, window_size, K);
}
template <typename I>
mln_ch_value(I, bool)
sauvola_dispatch(const value::rgb8&,
- const Image<I>& input, unsigned window_size)
+ const Image<I>& input, unsigned window_size,
+ double K)
{
- return impl::sauvola_rgb8(input, window_size);
+ return impl::sauvola_rgb8(input, window_size, K);
}
template <typename I>
mln_ch_value(I, bool)
- sauvola_dispatch(const Image<I>& input, unsigned window_size)
+ sauvola_dispatch(const Image<I>& input, unsigned window_size,
+ double K)
{
typedef mln_value(I) V;
- return sauvola_dispatch(V(), input, window_size);
+ return sauvola_dispatch(V(), input, window_size, K);
}
} // end of namespace scribo::binarization::internal
@@ -162,6 +184,22 @@ namespace scribo
template <typename I>
mln_ch_value(I, bool)
+ sauvola(const Image<I>& input, unsigned window_size, double K)
+ {
+ trace::entering("scribo::binarization::sauvola");
+
+ mln_precondition(exact(input).is_valid());
+
+ mln_ch_value(I, bool)
+ output = internal::sauvola_dispatch(input, window_size, K);
+
+ trace::exiting("scribo::binarization::sauvola");
+ return output;
+ }
+
+
+ template <typename I>
+ mln_ch_value(I, bool)
sauvola(const Image<I>& input, unsigned window_size)
{
trace::entering("scribo::binarization::sauvola");
@@ -169,7 +207,8 @@ namespace scribo
mln_precondition(exact(input).is_valid());
mln_ch_value(I, bool)
- output = internal::sauvola_dispatch(input, window_size);
+ output = internal::sauvola_dispatch(input, window_size,
+ SCRIBO_DEFAULT_SAUVOLA_K);
trace::exiting("scribo::binarization::sauvola");
return output;
diff --git a/scribo/binarization/sauvola_ms.hh b/scribo/binarization/sauvola_ms.hh
index 2717770..6e70e04 100644
--- a/scribo/binarization/sauvola_ms.hh
+++ b/scribo/binarization/sauvola_ms.hh
@@ -54,6 +54,9 @@
# include <mln/extension/adjust.hh>
+// FIXME: to be removed later...
+# include <mln/io/pgm/save.hh>
+
# include <scribo/subsampling/integral_single_image.hh>
# include <scribo/core/macros.hh>
@@ -81,6 +84,7 @@ namespace scribo
\param[in] w_1 The window size used to compute stats.
\param[in] s The scale factor used for the first subscaling.
\param[in] lambda_min_1 Size of the objects kept at scale 1.
+ \param[in] K Sauvola's formulae parameter.
\p w_1 and \p lambda_min_1 are expressed according to the image
@@ -90,6 +94,14 @@ namespace scribo
*/
template <typename I>
mln_ch_value(I,bool)
+ sauvola_ms(const Image<I>& input_1_, unsigned w_1,
+ unsigned s, unsigned lambda_min_1, double K);
+
+ /// \overload
+ /// K is set to 0.34.
+ //
+ template <typename I>
+ mln_ch_value(I,bool)
sauvola_ms(const Image<I>& input_1, unsigned w_1,
unsigned s, unsigned lambda_min_1);
@@ -105,6 +117,11 @@ namespace scribo
using namespace mln;
+
+ // FIXME: to be removed later...
+ char* scale_image_output = 0;
+
+
template <typename V>
V my_find_root(image2d<V>& parent, const V& x)
{
@@ -120,7 +137,8 @@ namespace scribo
unsigned lambda_min, unsigned lambda_max,
unsigned s,
unsigned q, unsigned i, unsigned w,
- const image2d<util::couple<double,double> >& integral_sum_sum_2)
+ const image2d<util::couple<double,double> >& integral_sum_sum_2,
+ double K)
{
typedef image2d<int_u8> I;
typedef point2d P;
@@ -133,15 +151,30 @@ namespace scribo
w_local_h = w_local,
w_local_w = w_local;
+ // Make sure the window fits in the image domain.
+ if (w >= static_cast<const unsigned>(integral_sum_sum_2.ncols()))
+ {
+ w_local_w = std::min(integral_sum_sum_2.ncols(), integral_sum_sum_2.nrows()) -
integral_sum_sum_2.border();
+ w_local_h = w_local_w;
+ trace::warning("integral_browsing - Adjusting window width since it was larger
than image width.");
+ }
+ if (w_local_h >= static_cast<const unsigned>(integral_sum_sum_2.nrows()))
+ {
+ w_local_h = std::min(integral_sum_sum_2.nrows(), integral_sum_sum_2.ncols()) -
integral_sum_sum_2.border();
+ w_local_w = w_local_h;
+ trace::warning("integral_browsing - Adjusting window height since it was larger
than image height.");
+ }
+
if (! (w_local % 2))
{
--w_local_w;
++w_local_h;
}
+
// 1st pass
scribo::binarization::internal::first_pass_functor< image2d<int_u8> >
- f(sub);
+ f(sub, K);
scribo::canvas::integral_browsing(integral_sum_sum_2,
ratio,
w_local_w, w_local_h,
@@ -757,7 +790,7 @@ namespace scribo
template <typename I>
mln_ch_value(I,bool)
sauvola_ms(const Image<I>& input_1_, unsigned w_1,
- unsigned s, unsigned lambda_min_1)
+ unsigned s, double K)
{
trace::entering("scribo::binarization::sauvola_ms");
@@ -768,6 +801,8 @@ namespace scribo
dpoint2d none(0, 0);
+ unsigned lambda_min_1 = w_1 / 2;
+
// Number of subscales.
unsigned nb_subscale = 3;
@@ -820,7 +855,7 @@ namespace scribo
// Subsampling to scale 3 and 4.
for (unsigned i = 3; i <= nb_subscale + 1; ++i)
- sub_ima.append(mln::subsampling::antialiased(sub_ima[i - 1], q, none,
+ sub_ima.append(mln::subsampling::antialiased(sub_ima[i - 1], q,
sub_domains[i].first(),
sub_domains[i].second()));
@@ -840,7 +875,8 @@ namespace scribo
mln_max(unsigned),
s,
q, i, w_work,
- integral_sum_sum_2);
+ integral_sum_sum_2,
+ K);
}
// Other scales -> maximum and minimum component size.
@@ -854,7 +890,8 @@ namespace scribo
lambda_max_2 / ratio,
s,
q, i, w_work,
- integral_sum_sum_2);
+ integral_sum_sum_2,
+ K);
}
}
@@ -863,13 +900,17 @@ namespace scribo
t_ima[2] = internal::compute_t_n_and_e_2(sub_ima[2], e_2, 0,
lambda_max_2,
s, 1, 2, w_work,
- integral_sum_sum_2);
+ integral_sum_sum_2,
+ K);
}
// Propagate scale values.
e_2 = transform::influence_zone_geodesic(e_2, c8());
+ // FIXME: Remove or make it better...
+ if (internal::scale_image_output)
+ io::pgm::save(e_2, internal::scale_image_output);
// Binarize
image2d<bool>
@@ -885,7 +926,7 @@ namespace scribo
template <typename I>
mln_ch_value(I,bool)
sauvola_ms_rgb8(const Image<I>& input_1_, unsigned w_1,
- unsigned s, unsigned lambda_min_1)
+ unsigned s, double K)
{
const I& input_1 = exact(input_1_);
@@ -893,54 +934,7 @@ namespace scribo
gima = data::transform(input_1, mln::fun::v2v::rgb_to_int_u<8>());
mln_ch_value(I, bool)
- output = generic::sauvola_ms(gima, w_1, s, lambda_min_1);
-
-
-// typedef mln_ch_value(I,bool) bin_t;
-
-
-// mln_ch_value(I, value::int_u8) r_i, g_i, b_i;
-
-// // Split the rgb8 image into 3 intensity images.
-// mln::data::split(input_1, r_i, g_i, b_i);
-
-// bin_t r_b, g_b, b_b;
-
-// r_b = generic::sauvola_ms(r_i, w_1, s, lambda_min_1);
-// g_b = generic::sauvola_ms(g_i, w_1, s, lambda_min_1);
-// b_b = generic::sauvola_ms(b_i, w_1, s, lambda_min_1);
-
-// border::resize(r_b, input_1.border());
-// border::resize(g_b, input_1.border());
-// border::resize(b_b, input_1.border());
-
-// bin_t output;
-// initialize(output, input_1);
-
-// typedef bool * b_ptr_t;
-// b_ptr_t
-// out_ptr = output.buffer(),
-// r_ptr = r_b.buffer(),
-// g_ptr = g_b.buffer(),
-// b_ptr = b_b.buffer();
-
-// unsigned ntrue;
-// for (unsigned n = 0; n < output.nelements(); ++n)
-// {
-// ntrue = 0;
-// if (*r_ptr)
-// ++ntrue;
-// if (*g_ptr)
-// ++ntrue;
-// if (*b_ptr)
-// ++ntrue;
-
-// *out_ptr++ = ntrue > 1;;
-
-// ++r_ptr;
-// ++g_ptr;
-// ++b_ptr;
-// }
+ output = generic::sauvola_ms(gima, w_1, s, K);
return output;
}
@@ -959,9 +953,9 @@ namespace scribo
mln_ch_value(I,bool)
sauvola_ms_dispatch(const mln_value(I)&,
const Image<I>& input_1, unsigned w_1,
- unsigned s, unsigned lambda_min_1)
+ unsigned s, double K)
{
- return impl::generic::sauvola_ms(input_1, w_1, s, lambda_min_1);
+ return impl::generic::sauvola_ms(input_1, w_1, s, K);
}
@@ -970,19 +964,19 @@ namespace scribo
mln_ch_value(I,bool)
sauvola_ms_dispatch(const value::rgb8&,
const Image<I>& input_1, unsigned w_1,
- unsigned s, unsigned lambda_min_1)
+ unsigned s, double K)
{
- return impl::sauvola_ms_rgb8(input_1, w_1, s, lambda_min_1);
+ return impl::sauvola_ms_rgb8(input_1, w_1, s, K);
}
template <typename I>
mln_ch_value(I,bool)
sauvola_ms_dispatch(const Image<I>& input_1, unsigned w_1,
- unsigned s, unsigned lambda_min_1)
+ unsigned s, double K)
{
typedef mln_value(I) V;
- return sauvola_ms_dispatch(V(), input_1, w_1, s, lambda_min_1);
+ return sauvola_ms_dispatch(V(), input_1, w_1, s, K);
}
@@ -995,20 +989,28 @@ namespace scribo
template <typename I>
mln_ch_value(I,bool)
sauvola_ms(const Image<I>& input_1_, unsigned w_1,
- unsigned s, unsigned lambda_min_1)
+ unsigned s, double K)
{
trace::entering("scribo::binarization::sauvola_ms");
- mln_precondition(input_1.is_valid());
+ mln_precondition(exact(input_1_).is_valid());
mln_ch_value(I,bool)
- output = internal::sauvola_ms_dispatch(input_1_, w_1, s, lambda_min_1);
+ output = internal::sauvola_ms_dispatch(input_1_, w_1, s, K);
trace::exiting("scribo::binarization::sauvola_ms");
return output;
}
+ template <typename I>
+ mln_ch_value(I,bool)
+ sauvola_ms(const Image<I>& input_1, unsigned w_1, unsigned s)
+ {
+ return sauvola_ms(input_1, w_1, s, SCRIBO_DEFAULT_SAUVOLA_K);
+ }
+
+
# endif // ! MLN_INCLUDE_ONLY
diff --git a/scribo/binarization/sauvola_ms_split.hh
b/scribo/binarization/sauvola_ms_split.hh
index cba5d94..de8517c 100644
--- a/scribo/binarization/sauvola_ms_split.hh
+++ b/scribo/binarization/sauvola_ms_split.hh
@@ -61,6 +61,7 @@ namespace scribo
\param[in] min_ntrue A site is set to 'True' in the output if it
is set to 'True' at least \p min_ntrue
components. Possible values: 1, 2, 3.
+ \param[in] K Sauvola's formula parameter.
\p w_1 and \p lambda_min_1 are expressed according to the image
at scale 0, i.e. the original size.
@@ -70,16 +71,27 @@ namespace scribo
template <typename I>
mln_ch_value(I, bool)
sauvola_ms_split(const Image<I>& input_1_, unsigned w_1,
+ unsigned s, unsigned lambda_min_1, unsigned min_ntrue,
+ double K);
+
+
+ /// \overload
+ /// K is set to 0.34.
+ template <typename I>
+ mln_ch_value(I, bool)
+ sauvola_ms_split(const Image<I>& input_1_, unsigned w_1,
unsigned s, unsigned lambda_min_1, unsigned min_ntrue);
+
# ifndef MLN_INCLUDE_ONLY
template <typename I>
mln_ch_value(I, bool)
sauvola_ms_split(const Image<I>& input_1_, unsigned w_1,
- unsigned s, unsigned lambda_min_1, unsigned min_ntrue)
+ unsigned s, unsigned lambda_min_1, unsigned min_ntrue,
+ double K)
{
trace::entering("scribo::binarization::sauvola_ms_split");
@@ -97,9 +109,9 @@ namespace scribo
bin_t r_b, g_b, b_b;
- r_b = impl::generic::sauvola_ms(r_i, w_1, s, lambda_min_1);
- g_b = impl::generic::sauvola_ms(g_i, w_1, s, lambda_min_1);
- b_b = impl::generic::sauvola_ms(b_i, w_1, s, lambda_min_1);
+ r_b = impl::generic::sauvola_ms(r_i, w_1, s, lambda_min_1, K);
+ g_b = impl::generic::sauvola_ms(g_i, w_1, s, lambda_min_1, K);
+ b_b = impl::generic::sauvola_ms(b_i, w_1, s, lambda_min_1, K);
border::resize(r_b, input_1.border());
border::resize(g_b, input_1.border());
@@ -138,6 +150,15 @@ namespace scribo
}
+ template <typename I>
+ mln_ch_value(I, bool)
+ sauvola_ms_split(const Image<I>& input_1, unsigned w_1,
+ unsigned s, unsigned lambda_min_1, unsigned min_ntrue)
+ {
+ return sauvola_ms_split(input_1, w_1, s, lambda_min_1, min_ntrue,
+ SCRIBO_DEFAULT_SAUVOLA_K);
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace scribo::binarization
diff --git a/scribo/binarization/sauvola_threshold_image.hh
b/scribo/binarization/sauvola_threshold_image.hh
index b5bc72d..88b3842 100644
--- a/scribo/binarization/sauvola_threshold_image.hh
+++ b/scribo/binarization/sauvola_threshold_image.hh
@@ -47,10 +47,24 @@
# include <mln/fun/v2v/rgb_to_int_u.hh>
-# include <mln/debug/println.hh>
-
# include <scribo/core/init_integral_image.hh>
+
+
+// Setup default Sauvola's formulae parameters values.
+// These macros may be used in other variant of Sauvola's algorithm.
+//
+// Values are set according to the following reference: "Automatic
+// Evaluation of Document Binarization Results", Badekas and al, 2005
+//
+// Badekas et al. said 0.34 was best.
+# define SCRIBO_DEFAULT_SAUVOLA_K 0.34
+//
+// 128 is best for grayscale documents.
+# define SCRIBO_DEFAULT_SAUVOLA_R 128
+
+
+
namespace scribo
{
@@ -73,11 +87,18 @@ namespace scribo
template <typename I, typename J>
mln_ch_value(I, value::int_u8)
sauvola_threshold_image(const Image<I>& input, unsigned window_size,
+ double K,
Image<J>& simple,
Image<J>& squared);
+ /// \overload
+ template <typename I>
+ mln_ch_value(I, value::int_u8)
+ sauvola_threshold_image(const Image<I>& input, unsigned window_size,
+ double K);
/// \overload
+ /// K is set to 0.34
template <typename I>
mln_ch_value(I, value::int_u8)
sauvola_threshold_image(const Image<I>& input, unsigned window_size);
@@ -113,9 +134,9 @@ namespace scribo
inline
double
sauvola_threshold_formula(const double m_x_y, const double s_x_y,
- const double k, const double R)
+ const double K, const double R)
{
- return m_x_y * (1.0 + k * ((s_x_y / R) - 1.0));
+ return m_x_y * (1.0 + K * ((s_x_y / R) - 1.0));
}
@@ -125,13 +146,9 @@ namespace scribo
double
sauvola_threshold_formula(double m_x_y, double s_x_y)
{
- // Badekas et al. said 0.34 was best.
- const double k = 0.34;
-
- // 128 is best for grayscale documents.
- const double R = 128;
-
- return sauvola_threshold_formula(m_x_y, s_x_y, k, R);
+ return sauvola_threshold_formula(m_x_y, s_x_y,
+ SCRIBO_DEFAULT_SAUVOLA_K,
+ SCRIBO_DEFAULT_SAUVOLA_R);
}
@@ -155,7 +172,7 @@ namespace scribo
compute_sauvola_threshold(const P& p,
const J& simple,
const J& squared,
- int win_width, double k, double R)
+ int win_width, double K, double R)
{
mln_precondition(simple.nrows() == squared.nrows());
mln_precondition(simple.ncols() == squared.ncols());
@@ -191,7 +208,7 @@ namespace scribo
double s_x_y = std::sqrt((s_x_y_tmp - (m_x_y_tmp * m_x_y_tmp) / wh) / (wh - 1.f));
// Thresholding.
- double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, k, R);
+ double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, K, R);
return t_x_y;
}
@@ -201,7 +218,8 @@ namespace scribo
double
compute_sauvola_threshold_single_image(const P& p,
const J& integral,
- int win_width)
+ int win_width,
+ double K, double R)
{
// Window half width.
int w_2 = win_width >> 1;
@@ -234,7 +252,7 @@ namespace scribo
double s_x_y = std::sqrt((s_x_y_tmp - (m_x_y_tmp * m_x_y_tmp) / wh) / (wh - 1.f));
// Thresholding.
- double t_x_y = m_x_y * (1.0 + 0.34 * ((s_x_y / 128) - 1.0));
+ double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, K, R);
return t_x_y;
}
@@ -248,13 +266,9 @@ namespace scribo
const J& squared,
int win_width)
{
- // Badekas et al. said 0.34 was best.
- const double k = 0.34;
-
- // 128 is best for grayscale documents.
- const double R = 128;
-
- return compute_sauvola_threshold(p, simple, squared, win_width, k, R);
+ return compute_sauvola_threshold(p, simple, squared, win_width,
+ SCRIBO_DEFAULT_SAUVOLA_K,
+ SCRIBO_DEFAULT_SAUVOLA_R);
}
@@ -285,6 +299,7 @@ namespace scribo
inline
mln_concrete(I)
sauvola_threshold_image(const Image<I>& input_, unsigned window_size,
+ double K,
Image<J>& simple_,
Image<J>& squared_)
{
@@ -313,7 +328,9 @@ namespace scribo
for(def::coord col = 0; col < ncols; ++col)
output.at_(row, col)
= internal::compute_sauvola_threshold(P(row, col), simple,
- squared, window_size);
+ squared, window_size,
+ K,
+ SCRIBO_DEFAULT_SAUVOLA_R);
trace::exiting("scribo::binarization::impl::generic::sauvola_threshold");
return output;
@@ -327,10 +344,11 @@ namespace scribo
inline
mln_concrete(I)
sauvola_threshold_image_gl(const I& input, unsigned window_size,
- Image<J>& simple,
- Image<J>& squared)
+ double K,
+ Image<J>& simple,
+ Image<J>& squared)
{
- return impl::generic::sauvola_threshold_image(input, window_size,
+ return impl::generic::sauvola_threshold_image(input, window_size, K,
simple, squared);
}
@@ -339,6 +357,7 @@ namespace scribo
inline
mln_ch_value(I, value::int_u8)
sauvola_threshold_image_rgb8(const I& input, unsigned window_size,
+ double K,
Image<J>& simple,
Image<J>& squared)
{
@@ -350,6 +369,7 @@ namespace scribo
mln_ch_value(I, value::int_u8)
output = impl::generic::sauvola_threshold_image(gima, window_size,
+ K,
simple, squared);
trace::exiting("scribo::binarization::impl::sauvola_threshold_image_rgb8");
@@ -372,10 +392,12 @@ namespace scribo
mln_ch_value(I, value::int_u<n>)
sauvola_threshold_image_dispatch(const value::int_u<n>&, const I&
input,
unsigned window_size,
+ double K,
J& simple,
J& squared)
{
- return impl::sauvola_threshold_image_gl(input, window_size, simple, squared);
+ return impl::sauvola_threshold_image_gl(input, window_size, K,
+ simple, squared);
}
template <typename I, typename J>
@@ -383,11 +405,12 @@ namespace scribo
mln_ch_value(I, value::int_u8)
sauvola_threshold_image_dispatch(const value::rgb8&, const I& input,
unsigned window_size,
+ double K,
J& simple,
J& squared)
{
return impl::sauvola_threshold_image_rgb8(input, window_size,
- simple, squared);
+ K, simple, squared);
}
template <typename I, typename J>
@@ -395,6 +418,7 @@ namespace scribo
mln_ch_value(I, value::int_u8)
sauvola_threshold_image_dispatch(const mln_value(I)&, const I& input,
unsigned window_size,
+ double K,
J& simple,
J& squared)
{
@@ -413,37 +437,21 @@ namespace scribo
template <typename I, typename J>
mln_ch_value(I, value::int_u8)
sauvola_threshold_image(const Image<I>& input, unsigned window_size,
- Image<J>& simple,
- Image<J>& squared)
+ double K,
+ Image<J>& simple,
+ Image<J>& squared)
{
trace::entering("scribo::binarization::sauvola_threshold_image");
mln_precondition(mln_site_(I)::dim == 2);
mln_precondition(exact(input).is_valid());
-
-// {
-// J& simple_ = exact(simple);
-// J& squared_ = exact(squared);
-// mln_piter(J) p(simple_.domain());
-// for_all(p)
-// {
-// std::cout << simple_(p) << ", ";
-// }
-// std::cout << std::endl << " ------- " << std::endl;
-// for_all(p)
-// {
-// std::cout << squared_(p) << ", ";
-// }
-// std::cout << std::endl << " ------- " << std::endl;
-// }
-
-
-
typedef mln_value(I) value_t;
mln_ch_value(I, value::int_u8)
- output = internal::sauvola_threshold_image_dispatch(value_t(), exact(input),
+ output = internal::sauvola_threshold_image_dispatch(value_t(),
+ exact(input),
window_size,
+ K,
exact(simple),
exact(squared));
@@ -455,19 +463,25 @@ namespace scribo
template <typename I>
inline
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input, unsigned window_size)
+ sauvola_threshold_image(const Image<I>& input, unsigned window_size,
+ double K)
{
mln_ch_value(I, double)
simple = init_integral_image(input, scribo::internal::identity_),
squared = init_integral_image(input, scribo::internal::square_);
-// debug::println(input);
-// std::cout << "============" << std::endl;
-// // debug::println(simple);
-// // std::cout << "============" << std::endl;
-// // debug::println(squared);
+ return sauvola_threshold_image(input, window_size,
+ K, simple, squared);
+ }
+
- return sauvola_threshold_image(input, window_size, simple, squared);
+ 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);
}
diff --git a/scribo/binarization/sauvola_threshold_image.hh
b/scribo/binarization/sauvola_threshold_image_debug.hh
similarity index 55%
copy from scribo/binarization/sauvola_threshold_image.hh
copy to scribo/binarization/sauvola_threshold_image_debug.hh
index b5bc72d..18216a6 100644
--- a/scribo/binarization/sauvola_threshold_image.hh
+++ b/scribo/binarization/sauvola_threshold_image_debug.hh
@@ -24,8 +24,8 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_HH
-# define SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_HH
+#ifndef SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_DEBUG_HH
+# define SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_DEBUG_HH
/// \file
///
@@ -47,9 +47,23 @@
# include <mln/fun/v2v/rgb_to_int_u.hh>
-# include <mln/debug/println.hh>
-
# include <scribo/core/init_integral_image.hh>
+# include <scribo/binarization/sauvola_threshold_image.hh>
+
+
+// Setup default Sauvola's formulae parameters values.
+// These macros may be used in other variant of Sauvola's algorithm.
+//
+// Values are set according to the following reference: "Automatic
+// Evaluation of Document Binarization Results", Badekas and al, 2005
+//
+// Badekas et al. said 0.34 was best.
+# define SCRIBO_DEFAULT_SAUVOLA_K 0.34
+//
+// 128 is best for grayscale documents.
+# define SCRIBO_DEFAULT_SAUVOLA_R 128
+
+
namespace scribo
{
@@ -72,23 +86,16 @@ namespace scribo
*/
template <typename I, typename J>
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input, unsigned window_size,
- Image<J>& simple,
- Image<J>& squared);
-
+ sauvola_threshold_image_debug(const Image<I>& input, unsigned window_size,
+ double K,
+ Image<J>& simple,
+ Image<J>& squared);
/// \overload
template <typename I>
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input, unsigned window_size);
-
-
- /// \overload
- /// The window size is set to 11.
- //
- template <typename I>
- mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input);
+ sauvola_threshold_image_debug(const Image<I>& input, unsigned window_size,
+ double K);
@@ -98,42 +105,8 @@ namespace scribo
namespace internal
{
- /*! \brief compute Sauvola's threshold applying directly the formula.
-
- \param[in] m_x_y Mean value.
- \param[in] s_x_y Standard deviation.
- \param[in] k Control the threshold value in the local
- window. The higher, the lower the threshold
- form the local mean m(x, y).
- \param[in] R Maximum value of the standard deviation (128
- for grayscale documents).
-
- \return A threshold.
- */
- inline
- double
- sauvola_threshold_formula(const double m_x_y, const double s_x_y,
- const double k, const double R)
- {
- return m_x_y * (1.0 + k * ((s_x_y / R) - 1.0));
- }
-
-
- /// \overload
- //
- inline
- double
- sauvola_threshold_formula(double m_x_y, double s_x_y)
- {
- // Badekas et al. said 0.34 was best.
- const double k = 0.34;
-
- // 128 is best for grayscale documents.
- const double R = 128;
-
- return sauvola_threshold_formula(m_x_y, s_x_y, k, R);
- }
-
+ unsigned mean_debug_factor = 1;
+ unsigned stddev_debug_factor = 10;
/*! \brief Compute a point wise threshold according Sauvola's
binarization.
@@ -150,12 +123,13 @@ namespace scribo
\return A threshold.
*/
- template <typename P, typename J>
+ template <typename P, typename I, typename J>
double
compute_sauvola_threshold(const P& p,
+ I& mean, I& stddev,
const J& simple,
const J& squared,
- int win_width, double k, double R)
+ int win_width, double K, double R)
{
mln_precondition(simple.nrows() == squared.nrows());
mln_precondition(simple.ncols() == squared.ncols());
@@ -182,6 +156,8 @@ namespace scribo
double m_x_y = m_x_y_tmp / wh;
+ mean(p) = m_x_y * mean_debug_factor;
+
// Standard deviation.
double s_x_y_tmp = (squared.at_(row_max, col_max)
+ squared.at_(row_min, col_min)
@@ -190,74 +166,15 @@ namespace scribo
double s_x_y = std::sqrt((s_x_y_tmp - (m_x_y_tmp * m_x_y_tmp) / wh) / (wh - 1.f));
- // Thresholding.
- double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, k, R);
-
- return t_x_y;
- }
-
-
- template <typename P, typename J>
- double
- compute_sauvola_threshold_single_image(const P& p,
- const J& integral,
- int win_width)
- {
- // Window half width.
- int w_2 = win_width >> 1;
-
- int row_min = std::max(0, p.row() - w_2);
- int col_min = std::max(0, p.col() - w_2);
-
- int row_max = std::min(static_cast<int>(integral.nrows()) - 1,
- p.row() + w_2);
- int col_max = std::min(static_cast<int>(integral.ncols()) - 1,
- p.col() + w_2);
-
-
- double wh = (row_max - row_min + 1) * (col_max - col_min + 1);
-
- // Mean.
- double m_x_y_tmp = (integral.at_(row_max, col_max).first()
- + integral.at_(row_min, col_min).first()
- - integral.at_(row_max, col_min).first()
- - integral.at_(row_min, col_max).first());
-
- double m_x_y = m_x_y_tmp / wh;
-
- // Standard deviation.
- double s_x_y_tmp = (integral.at_(row_max, col_max).second()
- + integral.at_(row_min, col_min).second()
- - integral.at_(row_max, col_min).second()
- - integral.at_(row_min, col_max).second());
-
- double s_x_y = std::sqrt((s_x_y_tmp - (m_x_y_tmp * m_x_y_tmp) / wh) / (wh - 1.f));
+ stddev(p) = s_x_y * stddev_debug_factor;
// Thresholding.
- double t_x_y = m_x_y * (1.0 + 0.34 * ((s_x_y / 128) - 1.0));
+ double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, K, R);
return t_x_y;
}
-
- template <typename P, typename J>
- double
- compute_sauvola_threshold(const P& p,
- const J& simple,
- const J& squared,
- int win_width)
- {
- // Badekas et al. said 0.34 was best.
- const double k = 0.34;
-
- // 128 is best for grayscale documents.
- const double R = 128;
-
- return compute_sauvola_threshold(p, simple, squared, win_width, k, R);
- }
-
-
} // end of namespace scribo::binarization::internal
} // end of namespace scribo::binarization
@@ -284,13 +201,18 @@ namespace scribo
template <typename I, typename J>
inline
mln_concrete(I)
- sauvola_threshold_image(const Image<I>& input_, unsigned window_size,
- Image<J>& simple_,
- Image<J>& squared_)
+ sauvola_threshold_image_debug(const Image<I>& input_,
+ unsigned window_size,
+ double K,
+ Image<I>& mean_, Image<I>& stddev_,
+ Image<J>& simple_,
+ Image<J>& squared_)
{
-
trace::entering("scribo::binarization::impl::generic::sauvola_threshold_image");
+
trace::entering("scribo::binarization::impl::generic::sauvola_threshold_image_debug");
const I& input = exact(input_);
+ I& mean = exact(mean_);
+ I& stddev = exact(stddev_);
J& simple = exact(simple_);
J& squared = exact(squared_);
@@ -312,8 +234,11 @@ namespace scribo
for(def::coord row = 0; row < nrows; ++row)
for(def::coord col = 0; col < ncols; ++col)
output.at_(row, col)
- = internal::compute_sauvola_threshold(P(row, col), simple,
- squared, window_size);
+ = internal::compute_sauvola_threshold(P(row, col),
+ mean, stddev,
+ simple, squared,
+ window_size, K,
+ SCRIBO_DEFAULT_SAUVOLA_R);
trace::exiting("scribo::binarization::impl::generic::sauvola_threshold");
return output;
@@ -326,33 +251,43 @@ namespace scribo
template <typename I, typename J>
inline
mln_concrete(I)
- sauvola_threshold_image_gl(const I& input, unsigned window_size,
- Image<J>& simple,
- Image<J>& squared)
+ sauvola_threshold_image_debug_gl(const Image<I>& input,
+ unsigned window_size,
+ double K,
+ Image<I>& mean, Image<I>& stddev,
+ Image<J>& simple,
+ Image<J>& squared)
{
- return impl::generic::sauvola_threshold_image(input, window_size,
- simple, squared);
+ return impl::generic::sauvola_threshold_image_debug(input, window_size,
+ K,
+ mean, stddev,
+ simple, squared);
}
template <typename I, typename J>
inline
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image_rgb8(const I& input, unsigned window_size,
- Image<J>& simple,
- Image<J>& squared)
+ sauvola_threshold_image_debug_rgb8(const Image<I>& input,
+ unsigned window_size,
+ double K,
+ Image<I>& mean, Image<I>& stddev,
+ Image<J>& simple,
+ Image<J>& squared)
{
- trace::entering("scribo::binarization::impl::sauvola_threshold_image_rgb8");
+ trace::entering("scribo::binarization::impl::sauvola_threshold_image_debug_rgb8");
mln_ch_value(I, value::int_u8) gima;
gima = data::transform(input,
mln::fun::v2v::rgb_to_int_u<8>());
mln_ch_value(I, value::int_u8)
- output = impl::generic::sauvola_threshold_image(gima, window_size,
- simple, squared);
+ output = impl::generic::sauvola_threshold_image_debug(gima, window_size,
+ K,
+ mean, stddev,
+ simple, squared);
- trace::exiting("scribo::binarization::impl::sauvola_threshold_image_rgb8");
+ trace::exiting("scribo::binarization::impl::sauvola_threshold_image_debug_rgb8");
return output;
}
@@ -370,33 +305,43 @@ namespace scribo
template <unsigned n, typename I, typename J>
inline
mln_ch_value(I, value::int_u<n>)
- sauvola_threshold_image_dispatch(const value::int_u<n>&, const I&
input,
- unsigned window_size,
- J& simple,
- J& squared)
+ sauvola_threshold_image_debug_dispatch(const value::int_u<n>&,
+ const I& input,
+ unsigned window_size,
+ double K,
+ I& mean, I& stddev,
+ J& simple,
+ J& squared)
{
- return impl::sauvola_threshold_image_gl(input, window_size, simple, squared);
+ return impl::sauvola_threshold_image_debug_gl(input, window_size, K,
+ mean, stddev,
+ simple, squared);
}
template <typename I, typename J>
inline
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image_dispatch(const value::rgb8&, const I& input,
- unsigned window_size,
- J& simple,
- J& squared)
+ sauvola_threshold_image_debug_dispatch(const value::rgb8&, const I& input,
+ unsigned window_size,
+ double K,
+ I& mean, I& stddev,
+ J& simple,
+ J& squared)
{
- return impl::sauvola_threshold_image_rgb8(input, window_size,
- simple, squared);
+ return impl::sauvola_threshold_image_debug_rgb8(input, window_size,
+ K, mean, stddev,
+ simple, squared);
}
template <typename I, typename J>
inline
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image_dispatch(const mln_value(I)&, const I& input,
- unsigned window_size,
- J& simple,
- J& squared)
+ sauvola_threshold_image_debug_dispatch(const mln_value(I)&, const I&
input,
+ I& mean, I& stddev,
+ unsigned window_size,
+ double K,
+ J& simple,
+ J& squared)
{
// No dispatch for this kind of value type.
mlc_abort(I)::check();
@@ -412,40 +357,27 @@ namespace scribo
template <typename I, typename J>
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input, unsigned window_size,
- Image<J>& simple,
- Image<J>& squared)
+ sauvola_threshold_image_debug(const Image<I>& input, unsigned window_size,
+ double K,
+ Image<I>& mean, Image<I>& stddev,
+ Image<J>& simple,
+ Image<J>& squared)
{
- trace::entering("scribo::binarization::sauvola_threshold_image");
+ trace::entering("scribo::binarization::sauvola_threshold_image_debug");
mln_precondition(mln_site_(I)::dim == 2);
mln_precondition(exact(input).is_valid());
-
-// {
-// J& simple_ = exact(simple);
-// J& squared_ = exact(squared);
-// mln_piter(J) p(simple_.domain());
-// for_all(p)
-// {
-// std::cout << simple_(p) << ", ";
-// }
-// std::cout << std::endl << " ------- " << std::endl;
-// for_all(p)
-// {
-// std::cout << squared_(p) << ", ";
-// }
-// std::cout << std::endl << " ------- " << std::endl;
-// }
-
-
-
typedef mln_value(I) value_t;
mln_ch_value(I, value::int_u8)
- output = internal::sauvola_threshold_image_dispatch(value_t(), exact(input),
- window_size,
- exact(simple),
- exact(squared));
+ output = internal::sauvola_threshold_image_debug_dispatch(value_t(),
+ exact(input),
+ window_size,
+ K,
+ exact(mean),
+ exact(stddev),
+ exact(simple),
+ exact(squared));
trace::exiting("scribo::text::ppm2pbm");
return output;
@@ -455,28 +387,17 @@ namespace scribo
template <typename I>
inline
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input, unsigned window_size)
+ sauvola_threshold_image_debug(const Image<I>& input, unsigned window_size,
+ double K,
+ Image<I>& mean, Image<I>& stddev)
{
mln_ch_value(I, double)
simple = init_integral_image(input, scribo::internal::identity_),
squared = init_integral_image(input, scribo::internal::square_);
-// debug::println(input);
-// std::cout << "============" << std::endl;
-// // debug::println(simple);
-// // std::cout << "============" << std::endl;
-// // debug::println(squared);
-
- return sauvola_threshold_image(input, window_size, simple, squared);
- }
-
-
- template <typename I>
- inline
- mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input)
- {
- return sauvola_threshold_image(input, 11);
+ return sauvola_threshold_image_debug(input, window_size, K,
+ mean, stddev,
+ simple, squared);
}
@@ -487,4 +408,4 @@ namespace scribo
} // end of namespace scribo
-#endif // ! SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_HH
+#endif // ! SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_DEBUG_HH
diff --git a/scribo/canvas/integral_browsing.hh b/scribo/canvas/integral_browsing.hh
index 45ff38d..4e55109 100644
--- a/scribo/canvas/integral_browsing.hh
+++ b/scribo/canvas/integral_browsing.hh
@@ -127,19 +127,6 @@ namespace scribo
unsigned s_2 = s * s;
- // Make sure the window fits in the image domain.
- if (w >= static_cast<const unsigned>(ncols))
- {
- w = ncols - 1;
- trace::warning("integral_browsing - Adjusting window width since it was larger than
image width.");
- }
- if (h >= static_cast<const unsigned>(nrows))
- {
- h = nrows - 1;
- trace::warning("integral_browsing - Adjusting window height since it was larger
than image height.");
- }
-
-
// -------------------------------
// T (top)
// -------------------------------
diff --git a/scribo/debug/usage.hh b/scribo/debug/usage.hh
index 6b6c9b7..2c6fa48 100644
--- a/scribo/debug/usage.hh
+++ b/scribo/debug/usage.hh
@@ -26,6 +26,7 @@
#ifndef SCRIBO_DEBUG_USAGE_HH
# define SCRIBO_DEBUG_USAGE_HH
+#include <libgen.h>
#include <iostream>
namespace scribo
@@ -45,7 +46,7 @@ namespace scribo
/// \return Return 1.
//
int usage(char* argv[], const char *desc, const char* args,
- const char*args_desc[][2], const char *out_desc);
+ const char*args_desc[][2]);
# ifndef MLN_INCLUDE_ONLY
@@ -53,21 +54,21 @@ namespace scribo
inline
int
usage(char* argv[], const char *desc, const char* args,
- const char*args_desc[][2], const char *out_desc = 0)
+ const char*args_desc[][2])
{
- std::cout << "Usage: " << argv[0] << " "
<< args
+ std::cout << "Usage: " << basename(argv[0]) << "
" << args
<< std::endl
<< std::endl;
std::cout << "-----------" << std::endl;
std::cout << desc << std::endl
- << std::endl;
+ << std::endl;
for (unsigned i = 0; args_desc[i][0] != 0; ++i)
std::cout << " " << args_desc[i][0] << ": "
<< args_desc[i][1]
<< std::endl;
- if (out_desc)
- std::cout << std::endl << "Output: " << out_desc <<
std::endl;
+// if (out_desc)
+// std::cout << std::endl << "Output: " << out_desc <<
std::endl;
std::cout << "-----------" << std::endl;
std::cout << "EPITA/LRDE - Scribo 2009" << std::endl;
diff --git a/scribo/src/binarization/ppm_fg_sauvola_ms.cc
b/scribo/src/binarization/fg_sauvola_ms.cc
similarity index 87%
copy from scribo/src/binarization/ppm_fg_sauvola_ms.cc
copy to scribo/src/binarization/fg_sauvola_ms.cc
index 5f45470..9c606d6 100644
--- a/scribo/src/binarization/ppm_fg_sauvola_ms.cc
+++ b/scribo/src/binarization/fg_sauvola_ms.cc
@@ -26,7 +26,7 @@
#include <mln/core/image/image2d.hh>
#include <mln/value/rgb8.hh>
-#include <mln/io/ppm/load.hh>
+#include <mln/io/magick/load.hh>
#include <mln/io/pbm/save.hh>
#include <scribo/binarization/sauvola_ms.hh>
@@ -53,7 +53,8 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
- { "input.ppm", "A color image." },
+ { "input.*", "An image." },
+ { "output.pbm", "A binary image." },
{ "lambda", "Lambda used to split bg/fg." },
{ "w", "Window size at scale 1. (Common value: 101)" },
{ "s", "First subsampling ratio (Common value: 3)." },
@@ -71,9 +72,9 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
- "Multi-Scale Binarization of a color image based on Sauvola's algorithm.
Performs a binarization on each component of the color image and merges the
results.",
- "input.ppm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "Multi-Scale Binarization based on Sauvola's algorithm. Performs a
binarization on each component of the color image and merges the results.",
+ "input.* output.pbm w s area_threshold",
+ args_desc);
trace::entering("main");
@@ -90,13 +91,13 @@ int main(int argc, char *argv[])
image2d<value::rgb8> input_1;
- io::ppm::load(input_1, argv[1]);
+ io::magick::load(input_1, argv[1]);
image2d<value::rgb8>
fg = scribo::preprocessing::split_bg_fg(input_1, lambda, 32).first();
image2d<bool>
- output = scribo::binarization::sauvola_ms(fg, w_1, s, lambda_min_1);
+ output = scribo::binarization::sauvola_ms(fg, w_1, s, lambda_min_1,
SCRIBO_DEFAULT_SAUVOLA_K);
io::pbm::save(output, argv[6]);
}
diff --git a/scribo/src/binarization/pgm_global_threshold_auto.cc
b/scribo/src/binarization/pgm_global_threshold_auto.cc
index 7f1dacf..568eba2 100644
--- a/scribo/src/binarization/pgm_global_threshold_auto.cc
+++ b/scribo/src/binarization/pgm_global_threshold_auto.cc
@@ -33,6 +33,7 @@
const char *args_desc[][2] =
{
{ "input.pgm", "A gray level image." },
+ { "output.pbm", "A binary image." },
{0, 0}
};
@@ -46,7 +47,7 @@ int main(int argc, char *argv[])
return scribo::debug::usage(argv,
"Binarization of a gray-level image using an automatic global threshold.",
"input.pgm output.pbm",
- args_desc, "A binary image.");
+ args_desc);
trace::entering("main");
diff --git a/scribo/src/binarization/pgm_sauvola.cc
b/scribo/src/binarization/pgm_sauvola.cc
index 843c355..c6ba643 100644
--- a/scribo/src/binarization/pgm_sauvola.cc
+++ b/scribo/src/binarization/pgm_sauvola.cc
@@ -33,7 +33,9 @@
const char *args_desc[][2] =
{
{ "input.pgm", "A gray level image." },
- { "w", "Window size." },
+ { "output.pbm", "A binary image." },
+ { "w", "Window size (default 51)." },
+ { "k", "Sauvola's formulae parameter (default 0.34)." },
{0, 0}
};
@@ -43,23 +45,35 @@ int main(int argc, char *argv[])
using namespace mln;
using value::int_u8;
- if (argc != 4)
+ if (argc != 5 && argc != 4 && argc != 3)
return scribo::debug::usage(argv,
"Binarization of a gray level image based on Sauvola's algorithm.",
- "input.pgm w output.pbm",
- args_desc, "A binary image.");
+ "input.pgm output.pbm <w> <k>",
+ args_desc);
trace::entering("main");
- unsigned w = atoi(argv[2]);
+ unsigned w;
+ if (argc == 4)
+ w = atoi(argv[3]);
+ else
+ w = 51;
+
+ double k;
+ if (argc == 5)
+ k = atof(argv[4]);
+ else
+ k = 0.34f;
+
+ std::cout << "Using w=" << w << " and k="
<< k << std::endl;
image2d<int_u8> input;
io::pgm::load(input, argv[1]);
- image2d<bool> out = scribo::binarization::sauvola(input, w);
+ image2d<bool> out = scribo::binarization::sauvola(input, w, k);
- io::pbm::save(out, argv[3]);
+ io::pbm::save(out, argv[2]);
trace::exiting("main");
diff --git a/scribo/src/binarization/pgm_sauvola_ms.cc
b/scribo/src/binarization/pgm_sauvola_ms.cc
index d446c3e..fefdd6a 100644
--- a/scribo/src/binarization/pgm_sauvola_ms.cc
+++ b/scribo/src/binarization/pgm_sauvola_ms.cc
@@ -34,16 +34,19 @@
bool check_args(int argc, char * argv[])
{
- if (argc < 5 || argc > 6)
+ if (argc < 3 || argc > 6)
return false;
- int s = atoi(argv[3]);
-
- if (s < 1 || s > 3)
+ if (argc >= 5)
{
- std::cout << "s must be set to 2 or 3."
- << std::endl;
- return false;
+ int s = atoi(argv[4]);
+
+ if (s < 1 || s > 3)
+ {
+ std::cout << "s must be set to 2 or 3."
+ << std::endl;
+ return false;
+ }
}
return true;
@@ -53,9 +56,10 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
{ "input.pgm", "A graylevel image." },
- { "w", "Window size at scale 1. (Common value: 101)" },
- { "s", "First subsampling ratio (Common value: 3)." },
- { "min_area", "Minimum object area at scale 1 (Common value:
67)" },
+ { "out.pbm", "A binary image." },
+ { "w", "Window size at scale 1. (default: 101)" },
+ { "s", "First subsampling ratio (default: 3)." },
+ { "k", "Sauvola's formuale parameter (default: 0.34)" },
{0, 0}
};
@@ -70,28 +74,43 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
"Multi-Scale Binarization of a color image based on Sauvola's
algorithm.",
- "input.pgm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "input.pgm output.pbm <w> <s> <k>",
+ args_desc);
trace::entering("main");
// Window size
- unsigned w_1 = atoi(argv[2]); // Scale 1
+ unsigned w_1;
+ if (argc >= 4)
+ w_1 = atoi(argv[3]); // Scale 1
+ else
+ w_1 = 101u;
// First subsampling scale.
- unsigned s = atoi(argv[3]);
+ unsigned s;
+ if (argc >= 5)
+ s = atoi(argv[4]);
+ else
+ s = 3u;
// Lambda value
- unsigned lambda_min_1 = atoi(argv[4]);
+ unsigned lambda_min_1 = 67; // FIXME: should be adapted to the
+ // window size.
+ double k;
+ if (argc >= 6)
+ k = atof(argv[5]);
+ else
+ k = 0.34f;
image2d<value::int_u8> input_1;
io::pgm::load(input_1, argv[1]);
image2d<bool>
- output = scribo::binarization::sauvola_ms(input_1, w_1, s, lambda_min_1);
+ output = scribo::binarization::sauvola_ms(input_1, w_1, s,
+ lambda_min_1, k);
- io::pbm::save(output, argv[5]);
+ io::pbm::save(output, argv[2]);
}
diff --git a/scribo/src/binarization/ppm_fg_sauvola_ms.cc
b/scribo/src/binarization/ppm_fg_sauvola_ms.cc
index 5f45470..65e8621 100644
--- a/scribo/src/binarization/ppm_fg_sauvola_ms.cc
+++ b/scribo/src/binarization/ppm_fg_sauvola_ms.cc
@@ -35,16 +35,19 @@
bool check_args(int argc, char * argv[])
{
- if (argc != 7)
+ if (argc < 3 || argc > 7)
return false;
- int s = atoi(argv[4]);
-
- if (s < 2 || s > 3)
+ if (argc >= 6)
{
- std::cout << "s must be set to 2 or 3."
- << std::endl;
- return false;
+ int s = atoi(argv[5]);
+
+ if (s < 2 || s > 3)
+ {
+ std::cout << "s must be set to 2 or 3."
+ << std::endl;
+ return false;
+ }
}
return true;
@@ -54,10 +57,11 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
{ "input.ppm", "A color image." },
+ { "output.pbm", "A binary image." },
{ "lambda", "Lambda used to split bg/fg." },
- { "w", "Window size at scale 1. (Common value: 101)" },
- { "s", "First subsampling ratio (Common value: 3)." },
- { "min_area", "Minimum object area at scale 1 (Common value:
67)" },
+ { "w", "Window size at scale 1. (default: 101)" },
+ { "s", "First subsampling ratio. (default: 3)" },
+ { "k", "Sauvola's formula parameter. (default: 0.34)" },
{0, 0}
};
@@ -72,33 +76,49 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
"Multi-Scale Binarization of a color image based on Sauvola's algorithm.
Performs a binarization on each component of the color image and merges the
results.",
- "input.ppm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "input.ppm output.pbm lambda <w> <s> <k>",
+ args_desc);
trace::entering("main");
- unsigned lambda = atoi(argv[2]);
+ unsigned lambda = atoi(argv[3]);
// Window size
- unsigned w_1 = atoi(argv[3]); // Scale 1
+ unsigned w_1;
+ if (argc >= 5)
+ w_1 = atoi(argv[4]); // Scale 1
+ else
+ w_1 = 101u;
// First subsampling scale.
- unsigned s = atoi(argv[4]);
+ unsigned s;
+ if (argc >= 6)
+ s = atoi(argv[5]);
+ else
+ s = 3u;
// Lambda value
- unsigned lambda_min_1 = atoi(argv[5]);
+ unsigned lambda_min_1 = 67; // FIXME: should be adapted to the
+ // window size.
+
+ double k;
+ if (argc >= 7)
+ k = atof(argv[6]);
+ else
+ k = 0.34f;
+
image2d<value::rgb8> input_1;
io::ppm::load(input_1, argv[1]);
image2d<value::rgb8>
- fg = scribo::preprocessing::split_bg_fg(input_1, lambda, 32).first();
+ fg = scribo::preprocessing::split_bg_fg(input_1, lambda, 32).second();
image2d<bool>
- output = scribo::binarization::sauvola_ms(fg, w_1, s, lambda_min_1);
+ output = scribo::binarization::sauvola_ms(fg, w_1, s, lambda_min_1, k);
- io::pbm::save(output, argv[6]);
+ io::pbm::save(output, argv[2]);
}
diff --git a/scribo/src/binarization/ppm_sauvola.cc
b/scribo/src/binarization/ppm_sauvola.cc
index c3ce28a..0b798ae 100644
--- a/scribo/src/binarization/ppm_sauvola.cc
+++ b/scribo/src/binarization/ppm_sauvola.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of Olena.
//
@@ -25,7 +26,6 @@
#include <mln/io/ppm/load.hh>
#include <mln/io/pbm/save.hh>
-#include <mln/value/rgb8.hh>
#include <scribo/binarization/sauvola.hh>
#include <scribo/debug/usage.hh>
@@ -33,7 +33,9 @@
const char *args_desc[][2] =
{
{ "input.ppm", "A color image." },
- { "wsize", "Window size (Common value: 51)." },
+ { "output.pbm", "A binary image." },
+ { "w", "Window size (default 51)." },
+ { "k", "Sauvola's formulae parameter (default 0.34)." },
{0, 0}
};
@@ -41,20 +43,36 @@ const char *args_desc[][2] =
int main(int argc, char *argv[])
{
using namespace mln;
- using value::rgb8;
- if (argc != 4)
+ if (argc != 5 && argc != 4 && argc != 3)
return scribo::debug::usage(argv,
- "Binarization of a color image based on Sauvola's algorithm. First convert
the color image to an intensity image and then run Sauvola.",
- "input.ppm wsize output.pbm",
- args_desc, "A binary image.");
+ "Binarization of a gray level image based on Sauvola's algorithm.",
+ "input.ppm output.pbm <w> <k>",
+ args_desc);
trace::entering("main");
- image2d<rgb8> input;
+ unsigned w;
+ if (argc == 4)
+ w = atoi(argv[3]);
+ else
+ w = 51;
+
+ double k;
+ if (argc == 5)
+ k = atof(argv[4]);
+ else
+ k = 0.34f;
+
+ std::cout << "Using w=" << w << " and k="
<< k << std::endl;
+
+ image2d<value::rgb8> input;
io::ppm::load(input, argv[1]);
- io::pbm::save(scribo::binarization::sauvola(input, atoi(argv[2])), argv[3]);
+ image2d<bool> out = scribo::binarization::sauvola(input, w, k);
+
+
+ io::pbm::save(out, argv[2]);
trace::exiting("main");
diff --git a/scribo/src/binarization/ppm_sauvola_ms.cc
b/scribo/src/binarization/ppm_sauvola_ms.cc
index d8c1c9c..f2cbb6f 100644
--- a/scribo/src/binarization/ppm_sauvola_ms.cc
+++ b/scribo/src/binarization/ppm_sauvola_ms.cc
@@ -25,7 +25,7 @@
// executable file might be covered by the GNU General Public License.
#include <mln/core/image/image2d.hh>
-#include <mln/value/rgb8.hh>
+#include <mln/value/int_u8.hh>
#include <mln/io/ppm/load.hh>
#include <mln/io/pbm/save.hh>
@@ -34,16 +34,19 @@
bool check_args(int argc, char * argv[])
{
- if (argc < 5 || argc > 6)
+ if (argc < 3 || argc > 6)
return false;
- int s = atoi(argv[3]);
-
- if (s < 2 || s > 3)
+ if (argc >= 5)
{
- std::cout << "s must be set to 2 or 3."
- << std::endl;
- return false;
+ int s = atoi(argv[4]);
+
+ if (s < 1 || s > 3)
+ {
+ std::cout << "s must be set to 2 or 3."
+ << std::endl;
+ return false;
+ }
}
return true;
@@ -53,9 +56,10 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
{ "input.ppm", "A color image." },
- { "w", "Window size at scale 1. (Common value: 101)" },
- { "s", "First subsampling ratio (Common value: 3)." },
- { "min_area", "Minimum object area at scale 1 (Common value:
67)" },
+ { "out.pbm", "A binary image." },
+ { "w", "Window size at scale 1. (default: 101)" },
+ { "s", "First subsampling ratio (default: 3)." },
+ { "k", "Sauvola's formuale parameter (default: 0.34)" },
{0, 0}
};
@@ -69,29 +73,44 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
- "Multi-Scale Binarization of a color image based on Sauvola's algorithm.
Performs a binarization on each component of the color image and merges the
results.",
- "input.ppm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "Multi-Scale Binarization of a color image based on Sauvola's
algorithm.",
+ "input.ppm output.pbm <w> <s> <k>",
+ args_desc);
trace::entering("main");
// Window size
- unsigned w_1 = atoi(argv[2]); // Scale 1
+ unsigned w_1;
+ if (argc >= 4)
+ w_1 = atoi(argv[3]); // Scale 1
+ else
+ w_1 = 101u;
// First subsampling scale.
- unsigned s = atoi(argv[3]);
+ unsigned s;
+ if (argc >= 5)
+ s = atoi(argv[4]);
+ else
+ s = 3u;
// Lambda value
- unsigned lambda_min_1 = atoi(argv[4]);
+ unsigned lambda_min_1 = 67; // FIXME: should be adapted to the
+ // window size.
+ double k;
+ if (argc >= 6)
+ k = atof(argv[5]);
+ else
+ k = 0.34f;
image2d<value::rgb8> input_1;
io::ppm::load(input_1, argv[1]);
image2d<bool>
- output = scribo::binarization::sauvola_ms(input_1, w_1, s, lambda_min_1);
+ output = scribo::binarization::sauvola_ms(input_1, w_1, s,
+ lambda_min_1, k);
- io::pbm::save(output, argv[5]);
+ io::pbm::save(output, argv[2]);
}
diff --git a/scribo/src/binarization/ppm_sauvola_ms_split.cc
b/scribo/src/binarization/ppm_sauvola_ms_split.cc
index 3f721db..b1f10ea 100644
--- a/scribo/src/binarization/ppm_sauvola_ms_split.cc
+++ b/scribo/src/binarization/ppm_sauvola_ms_split.cc
@@ -34,16 +34,19 @@
bool check_args(int argc, char * argv[])
{
- if (argc != 7)
+ if (argc < 3 || argc > 7)
return false;
- int s = atoi(argv[3]);
-
- if (s < 1 || s > 3)
+ if (argc >= 5)
{
- std::cout << "s must be set to 2 or 3."
- << std::endl;
- return false;
+ int s = atoi(argv[4]);
+
+ if (s < 1 || s > 3)
+ {
+ std::cout << "s must be set to 2 or 3."
+ << std::endl;
+ return false;
+ }
}
return true;
@@ -53,10 +56,11 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
{ "input.ppm", "A color image." },
- { "w", "Window size at scale 1. (Common value: 101)" },
- { "s", "First subsampling ratio (Common value: 3)." },
- { "min_area", "Minimum object area at scale 1 (Common value:
67)" },
- { "min_ntrue", "The number of components in which a site must be set
to 'True' in order to be set to 'True' in the output (Possible values: 1,
2, 3). (Common value: 2)" },
+ { "output.pbm", "A binary image." },
+ { "w", "Window size at scale 1. (default: 101)" },
+ { "s", "First subsampling ratio (default: 3)." },
+ { "min_ntrue", "The number of components in which a site must be set
to 'True' in order to be set to 'True' in the output (Possible values: 1,
2, 3). (default: 2)" },
+ { "K", "Sauvola's formula parameter (default: 0.34)." },
{0, 0}
};
@@ -71,28 +75,53 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
"Multi-Scale Binarization of a color image based on Sauvola's algorithm.
Performs a binarization on each component of the color image and merges the
results.",
- "input.ppm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "input.ppm output.pbm <w> <s> <min_ntrue> <K>",
+ args_desc);
trace::entering("main");
// Window size
- unsigned w_1 = atoi(argv[2]); // Scale 1
+ unsigned w_1;
+ if (argc >= 4)
+ w_1 = atoi(argv[3]); // Scale 1
+ else
+ w_1 = 101u;
// First subsampling scale.
- unsigned s = atoi(argv[3]);
+ unsigned s;
+ if (argc >= 5)
+ s = atoi(argv[4]);
+ else
+ s = 3u;
+
+ // min_ntrue
+ unsigned min_ntrue;
+ if (argc >= 6)
+ min_ntrue = atoi(argv[5]);
+ else
+ min_ntrue = 2;
// Lambda value
- unsigned lambda_min_1 = atoi(argv[4]);
+ unsigned lambda_min_1 = 67; // FIXME: should be adapted to the
+ // window size.
+
+ double k;
+ if (argc >= 7)
+ k = atof(argv[6]);
+ else
+ k = 0.34f;
+
image2d<value::rgb8> input_1;
io::ppm::load(input_1, argv[1]);
+ std::cout << "Using w=" << w_1 << " - s="
<< s << " - min_ntrue=" << min_ntrue << " -
k=" << k << std::endl;
+
image2d<bool>
- output = scribo::binarization::sauvola_ms_split(input_1, w_1, s, lambda_min_1,
atoi(argv[5]));
+ output = scribo::binarization::sauvola_ms_split(input_1, w_1, s, lambda_min_1,
min_ntrue, k);
- io::pbm::save(output, argv[6]);
+ io::pbm::save(output, argv[2]);
}
diff --git a/scribo/src/binarization/pgm_sauvola.cc b/scribo/src/binarization/sauvola.cc
similarity index 68%
copy from scribo/src/binarization/pgm_sauvola.cc
copy to scribo/src/binarization/sauvola.cc
index 843c355..fb07b0d 100644
--- a/scribo/src/binarization/pgm_sauvola.cc
+++ b/scribo/src/binarization/sauvola.cc
@@ -24,7 +24,7 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#include <mln/io/pgm/load.hh>
+#include <mln/io/magick/load.hh>
#include <mln/io/pbm/save.hh>
#include <scribo/binarization/sauvola.hh>
@@ -32,8 +32,10 @@
const char *args_desc[][2] =
{
- { "input.pgm", "A gray level image." },
- { "w", "Window size." },
+ { "input.*", "An image." },
+ { "output.pbm", "A binary image." },
+ { "w", "Window size (default 51)." },
+ { "k", "Sauvola's formulae parameter (default 0.34)." },
{0, 0}
};
@@ -41,25 +43,36 @@ const char *args_desc[][2] =
int main(int argc, char *argv[])
{
using namespace mln;
- using value::int_u8;
- if (argc != 4)
+ if (argc != 5 && argc != 4 && argc != 3)
return scribo::debug::usage(argv,
- "Binarization of a gray level image based on Sauvola's algorithm.",
- "input.pgm w output.pbm",
- args_desc, "A binary image.");
+ "Binarization based on Sauvola's algorithm.",
+ "input.* output.pbm <w> <k>",
+ args_desc);
trace::entering("main");
- unsigned w = atoi(argv[2]);
+ unsigned w;
+ if (argc >= 4)
+ w = atoi(argv[3]);
+ else
+ w = 51;
- image2d<int_u8> input;
- io::pgm::load(input, argv[1]);
+ double k;
+ if (argc >= 5)
+ k = atof(argv[4]);
+ else
+ k = 0.34f;
- image2d<bool> out = scribo::binarization::sauvola(input, w);
+ std::cout << "Using w=" << w << " and k="
<< k << std::endl;
+ image2d<value::rgb8> input;
+ io::magick::load(input, argv[1]);
- io::pbm::save(out, argv[3]);
+ image2d<bool> out = scribo::binarization::sauvola(input, w, k);
+
+
+ io::pbm::save(out, argv[2]);
trace::exiting("main");
diff --git a/scribo/src/binarization/sauvola_debug.cc
b/scribo/src/binarization/sauvola_debug.cc
new file mode 100644
index 0000000..8bbc19c
--- /dev/null
+++ b/scribo/src/binarization/sauvola_debug.cc
@@ -0,0 +1,105 @@
+// 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.
+
+#include <mln/io/magick/load.hh>
+#include <mln/io/pbm/save.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <scribo/binarization/local_threshold.hh>
+#include <scribo/binarization/sauvola_threshold_image_debug.hh>
+#include <scribo/debug/usage.hh>
+
+const char *args_desc[][2] =
+{
+ { "input.*", "An image." },
+ { "output.pbm", "A binary image." },
+ { "mean.pgm", "The local mean image." },
+ { "stddev.pgm", "The local standard deviation image." },
+ { "mean_factor", "Mean value factor (default 1)." },
+ { "stddev_factor", "Standard deviation value factor (default 10)."
},
+ { "w", "Window size (default 51)." },
+ { "k", "Sauvola's formulae parameter (default 0.34)." },
+ {0, 0}
+};
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using namespace scribo::binarization;
+
+ if (argc < 5 || argc >= 9)
+ return scribo::debug::usage(argv,
+ "Binarization based on Sauvola's algorithm.",
+ "input.* output.pbm mean.pgm stddev.pgm <mean_factor>
<stddev_factor> <w> <k>",
+ args_desc);
+
+ trace::entering("main");
+
+ unsigned w;
+ if (argc >= 8)
+ w = atoi(argv[7]);
+ else
+ w = 51;
+
+ double k;
+ if (argc >= 9)
+ k = atof(argv[8]);
+ else
+ k = 0.34f;
+
+ std::cout << "Using w=" << w << " and k="
<< k << std::endl;
+
+ if (argc >= 6)
+ scribo::binarization::internal::mean_debug_factor = atoi(argv[5]);
+ if (argc >= 7)
+ scribo::binarization::internal::stddev_debug_factor = atoi(argv[6]);
+
+ image2d<value::rgb8> input;
+ io::magick::load(input, argv[1]);
+
+
+ image2d<value::int_u8> mean, stddev;
+ initialize(mean, input);
+ initialize(stddev, input);
+
+ image2d<value::int_u8>
+ gima = data::transform(input,
+ mln::fun::v2v::rgb_to_int_u<8>());
+
+
+ image2d<bool>
+ out = local_threshold(gima,
+ sauvola_threshold_image_debug(gima, w, k,
+ mean, stddev));
+
+
+ io::pbm::save(out, argv[2]);
+ io::pgm::save(mean, argv[3]);
+ io::pgm::save(stddev, argv[4]);
+
+ trace::exiting("main");
+}
diff --git a/scribo/src/binarization/ppm_sauvola_ms.cc
b/scribo/src/binarization/sauvola_ms.cc
similarity index 61%
copy from scribo/src/binarization/ppm_sauvola_ms.cc
copy to scribo/src/binarization/sauvola_ms.cc
index d8c1c9c..3983793 100644
--- a/scribo/src/binarization/ppm_sauvola_ms.cc
+++ b/scribo/src/binarization/sauvola_ms.cc
@@ -25,8 +25,8 @@
// executable file might be covered by the GNU General Public License.
#include <mln/core/image/image2d.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/io/ppm/load.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/magick/load.hh>
#include <mln/io/pbm/save.hh>
#include <scribo/binarization/sauvola_ms.hh>
@@ -34,16 +34,19 @@
bool check_args(int argc, char * argv[])
{
- if (argc < 5 || argc > 6)
+ if (argc < 3 || argc > 7)
return false;
- int s = atoi(argv[3]);
-
- if (s < 2 || s > 3)
+ if (argc >= 5)
{
- std::cout << "s must be set to 2 or 3."
- << std::endl;
- return false;
+ int s = atoi(argv[4]);
+
+ if (s < 1 || s > 3)
+ {
+ std::cout << "s must be set to 2 or 3."
+ << std::endl;
+ return false;
+ }
}
return true;
@@ -52,10 +55,12 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
- { "input.ppm", "A color image." },
- { "w", "Window size at scale 1. (Common value: 101)" },
- { "s", "First subsampling ratio (Common value: 3)." },
- { "min_area", "Minimum object area at scale 1 (Common value:
67)" },
+ { "input.*", "An image." },
+ { "out.pbm", "A binary image." },
+ { "w", "Window size at scale 1. (default: 101)" },
+ { "s", "First subsampling ratio (default: 3)." },
+ { "k", "Sauvola's formuale parameter (default: 0.34)" },
+ { "scale.pgm", "Image of scales used for binarization." },
{0, 0}
};
@@ -69,29 +74,42 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
- "Multi-Scale Binarization of a color image based on Sauvola's algorithm.
Performs a binarization on each component of the color image and merges the
results.",
- "input.ppm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "Multi-Scale Binarization based on Sauvola's algorithm.",
+ "input.* output.pbm <w> <s> <k> <scale.pgm>",
+ args_desc);
trace::entering("main");
// Window size
- unsigned w_1 = atoi(argv[2]); // Scale 1
+ unsigned w_1;
+ if (argc >= 4)
+ w_1 = atoi(argv[3]); // Scale 1
+ else
+ w_1 = 101u;
// First subsampling scale.
- unsigned s = atoi(argv[3]);
+ unsigned s;
+ if (argc >= 5)
+ s = atoi(argv[4]);
+ else
+ s = 3u;
- // Lambda value
- unsigned lambda_min_1 = atoi(argv[4]);
+ double k;
+ if (argc >= 6)
+ k = atof(argv[5]);
+ else
+ k = 0.34f;
+ if (argc >= 7)
+ scribo::binarization::internal::scale_image_output = argv[6];
image2d<value::rgb8> input_1;
- io::ppm::load(input_1, argv[1]);
+ io::magick::load(input_1, argv[1]);
image2d<bool>
- output = scribo::binarization::sauvola_ms(input_1, w_1, s, lambda_min_1);
+ output = scribo::binarization::sauvola_ms(input_1, w_1, s, k);
- io::pbm::save(output, argv[5]);
+ io::pbm::save(output, argv[2]);
}
diff --git a/scribo/src/binarization/ppm_sauvola_ms_split.cc
b/scribo/src/binarization/sauvola_ms_split.cc
similarity index 64%
copy from scribo/src/binarization/ppm_sauvola_ms_split.cc
copy to scribo/src/binarization/sauvola_ms_split.cc
index 3f721db..af8b604 100644
--- a/scribo/src/binarization/ppm_sauvola_ms_split.cc
+++ b/scribo/src/binarization/sauvola_ms_split.cc
@@ -26,7 +26,7 @@
#include <mln/core/image/image2d.hh>
#include <mln/value/rgb8.hh>
-#include <mln/io/ppm/load.hh>
+#include <mln/io/magick/load.hh>
#include <mln/io/pbm/save.hh>
#include <scribo/binarization/sauvola_ms_split.hh>
@@ -34,16 +34,19 @@
bool check_args(int argc, char * argv[])
{
- if (argc != 7)
+ if (argc < 3 || argc > 7)
return false;
- int s = atoi(argv[3]);
-
- if (s < 1 || s > 3)
+ if (argc >= 5)
{
- std::cout << "s must be set to 2 or 3."
- << std::endl;
- return false;
+ int s = atoi(argv[4]);
+
+ if (s < 1 || s > 3)
+ {
+ std::cout << "s must be set to 2 or 3."
+ << std::endl;
+ return false;
+ }
}
return true;
@@ -52,11 +55,12 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
- { "input.ppm", "A color image." },
- { "w", "Window size at scale 1. (Common value: 101)" },
- { "s", "First subsampling ratio (Common value: 3)." },
- { "min_area", "Minimum object area at scale 1 (Common value:
67)" },
- { "min_ntrue", "The number of components in which a site must be set
to 'True' in order to be set to 'True' in the output (Possible values: 1,
2, 3). (Common value: 2)" },
+ { "input.*", "An image." },
+ { "output.pbm", "A binary image." },
+ { "w", "Window size at scale 1. (default: 101)" },
+ { "s", "First subsampling ratio (default: 3)." },
+ { "min_ntrue", "The number of components in which a site must be set
to 'True' in order to be set to 'True' in the output (Possible values: 1,
2, 3). (default: 2)" },
+ { "K", "Sauvola's formula parameter (default: 0.34)." },
{0, 0}
};
@@ -71,28 +75,53 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
"Multi-Scale Binarization of a color image based on Sauvola's algorithm.
Performs a binarization on each component of the color image and merges the
results.",
- "input.ppm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "input.* output.pbm <w> <s> <min_ntrue> <K>",
+ args_desc);
trace::entering("main");
// Window size
- unsigned w_1 = atoi(argv[2]); // Scale 1
+ unsigned w_1;
+ if (argc >= 4)
+ w_1 = atoi(argv[3]); // Scale 1
+ else
+ w_1 = 101u;
// First subsampling scale.
- unsigned s = atoi(argv[3]);
+ unsigned s;
+ if (argc >= 5)
+ s = atoi(argv[4]);
+ else
+ s = 3u;
+
+ // min_ntrue
+ unsigned min_ntrue;
+ if (argc >= 6)
+ min_ntrue = atoi(argv[5]);
+ else
+ min_ntrue = 2;
// Lambda value
- unsigned lambda_min_1 = atoi(argv[4]);
+ unsigned lambda_min_1 = 67; // FIXME: should be adapted to the
+ // window size.
+
+ double k;
+ if (argc >= 7)
+ k = atof(argv[6]);
+ else
+ k = 0.34f;
+
image2d<value::rgb8> input_1;
- io::ppm::load(input_1, argv[1]);
+ io::magick::load(input_1, argv[1]);
+
+ std::cout << "Using w=" << w_1 << " - s="
<< s << " - min_ntrue=" << min_ntrue << " -
k=" << k << std::endl;
image2d<bool>
- output = scribo::binarization::sauvola_ms_split(input_1, w_1, s, lambda_min_1,
atoi(argv[5]));
+ output = scribo::binarization::sauvola_ms_split(input_1, w_1, s, lambda_min_1,
min_ntrue, k);
- io::pbm::save(output, argv[6]);
+ io::pbm::save(output, argv[2]);
}
diff --git a/scribo/src/preprocessing/to_pgm.cc b/scribo/src/preprocessing/to_pgm.cc
new file mode 100644
index 0000000..974e03f
--- /dev/null
+++ b/scribo/src/preprocessing/to_pgm.cc
@@ -0,0 +1,46 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/io/magick/load.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <scribo/debug/usage.hh>
+
+
+const char *args_desc[][2] =
+{
+ { "input.*", "A color image." },
+ { "output.pgm", "A graylevel image." },
+ {0, 0}
+};
+
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+
+ if (argc != 3)
+ return scribo::debug::usage(argv,
+ "Convert a color image using the minimum RGB component value as
intensity.",
+ "input.* output.pgm",
+ args_desc);
+
+
+ typedef image2d<value::rgb8> I;
+ I ima;
+ io::magick::load(ima, argv[1]);
+
+ image2d<value::int_u8> out;
+ initialize(out, ima);
+
+ value::rgb8 v;
+ mln_piter_(I) p(ima.domain());
+ for_all(p)
+ {
+ v = ima(p);
+ out(p) = std::min(v.red(), std::min(v.green(), v.blue()));
+ }
+
+ io::pgm::save(out, argv[2]);
+}
--
1.5.6.5