Commit 21af64ad authored by Guillaume Lazzara's avatar Guillaume Lazzara
Browse files

Improve debug outputs in Sauvola and make binarization tools compile again.

	* binarization/internal/first_pass_functor.hh,
	* binarization/sauvola_ms.hh,
	* binarization/sauvola_threshold_image.hh: Add debug outputs if
	SCRIBO_SAUVOLA_DEBUG flag is set.

	* binarization/sauvola_ms_split.hh: Remove lambda argument.

	* binarization/sauvola_threshold_image_debug.hh: Add the threshold
	image as debug output.

	* src/binarization/Makefile.am: Add sauvola_ms_debug.
	* src/binarization/sauvola_ms_debug.cc: New.

	* src/binarization/fg_sauvola_ms.cc,
	* src/binarization/pgm_sauvola_ms.cc,
	* src/binarization/ppm_fg_sauvola_ms.cc,
	* src/binarization/ppm_sauvola_ms.cc,
	* src/binarization/ppm_sauvola_ms_split.cc,
	* src/binarization/sauvola_debug.cc,
	* src/binarization/sauvola_ms.cc,
	* src/binarization/sauvola_ms_split.cc: Make compile again.
parent 24e4f689
2010-05-25 Guillaume Lazzara <z@lrde.epita.fr>
Improve debug outputs in Sauvola and make binarization tools
compile again.
* binarization/internal/first_pass_functor.hh,
* binarization/sauvola_ms.hh,
* binarization/sauvola_threshold_image.hh: Add debug outputs if
SCRIBO_SAUVOLA_DEBUG flag is set.
* binarization/sauvola_ms_split.hh: Remove lambda argument.
* binarization/sauvola_threshold_image_debug.hh: Add the threshold
image as debug output.
* src/binarization/Makefile.am: Add sauvola_ms_debug.
* src/binarization/sauvola_ms_debug.cc: New.
* src/binarization/fg_sauvola_ms.cc,
* src/binarization/pgm_sauvola_ms.cc,
* src/binarization/ppm_fg_sauvola_ms.cc,
* src/binarization/ppm_sauvola_ms.cc,
* src/binarization/ppm_sauvola_ms_split.cc,
* src/binarization/sauvola_debug.cc,
* src/binarization/sauvola_ms.cc,
* src/binarization/sauvola_ms_split.cc: Make compile again.
2010-05-04 Guillaume Lazzara <z@lrde.epita.fr>
Small fixes for Nuxeo/XWiki.
......
......@@ -42,6 +42,13 @@ namespace scribo
namespace internal
{
# ifdef SCRIBO_SAUVOLA_DEBUG
// Global debug images.
extern image2d<value::int_u8> debug_k;
extern image2d<float> debug_s_n;
extern image2d<float> debug_k_l;
# endif // ! SCRIBO_SAUVOLA_DEBUG
using namespace mln;
......@@ -81,6 +88,13 @@ namespace scribo
initialize(t_sub, input);
initialize(parent, input);
initialize(msk, input);
# ifdef SCRIBO_SAUVOLA_DEBUG
initialize(debug_k, input);
initialize(debug_s_n, input);
initialize(debug_k_l, input);
# endif // ! SCRIBO_SAUVOLA_DEBUG
extension::fill(msk, false);
initialize(card, input);
......@@ -96,9 +110,20 @@ namespace scribo
unsigned p = pxl.offset();
value::int_u8 t_p = sauvola_threshold_formula(mean, stddev,
K_,
SCRIBO_DEFAULT_SAUVOLA_R);
# ifdef SCRIBO_SAUVOLA_DEBUG
value::int_u8
t_p = sauvola_threshold_formula(mean, stddev,
K_,
SCRIBO_DEFAULT_SAUVOLA_R,
debug_k.element(p),
debug_s_n.element(p),
debug_k_l.element(p));
# else
value::int_u8
t_p = sauvola_threshold_formula(mean, stddev,
K_,
SCRIBO_DEFAULT_SAUVOLA_R);
# endif // SCRIBO_SAUVOLA_DEBUG
msk.element(p) = input.element(p) < t_p;
......
......@@ -54,9 +54,6 @@
# 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>
......@@ -66,6 +63,14 @@
# include <scribo/canvas/integral_browsing.hh>
# ifdef SCRIBO_SAUVOLA_DEBUG
# include <mln/io/pgm/save.hh>
# include <mln/data/saturate.hh>
# include <mln/data/convert.hh>
# include <mln/arith/times.hh>
# endif // ! SCRIBO_SAUVOLA_DEBUG
namespace scribo
{
......@@ -116,9 +121,12 @@ namespace scribo
using namespace mln;
// FIXME: to be removed later...
# ifdef SCRIBO_SAUVOLA_DEBUG
char* scale_image_output = 0;
char* k_image_output = 0;
char* s_n_image_output = 0;
char* k_l_image_output = 0;
# endif // ! SCRIBO_SAUVOLA_DEBUG
template <typename V>
V my_find_root(image2d<V>& parent, const V& x)
......@@ -906,9 +914,10 @@ namespace scribo
// Propagate scale values.
e_2 = transform::influence_zone_geodesic(e_2, c8());
// FIXME: Remove or make it better...
# ifdef SCRIBO_SAUVOLA_DEBUG
if (internal::scale_image_output)
io::pgm::save(e_2, internal::scale_image_output);
# endif // ! SCRIBO_SAUVOLA_DEBUG
// Binarize
image2d<bool>
......@@ -921,67 +930,9 @@ namespace scribo
} // end of namespace scribo::binarization::impl::generic
template <typename I>
mln_ch_value(I,bool)
sauvola_ms_rgb8(const Image<I>& input_1_, unsigned w_1,
unsigned s, double K)
{
const I& input_1 = exact(input_1_);
mln_ch_value(I, value::int_u8) gima;
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, K);
return output;
}
} // end of namespace scribo::binarization::impl
// Dispatch
namespace internal
{
template <typename I>
mln_ch_value(I,bool)
sauvola_ms_dispatch(const mln_value(I)&,
const Image<I>& input_1, unsigned w_1,
unsigned s, double K)
{
return impl::generic::sauvola_ms(input_1, w_1, s, K);
}
template <typename I>
mln_ch_value(I,bool)
sauvola_ms_dispatch(const value::rgb8&,
const Image<I>& input_1, unsigned w_1,
unsigned s, double K)
{
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, double K)
{
typedef mln_value(I) V;
return sauvola_ms_dispatch(V(), input_1, w_1, s, K);
}
} // end of namespace scribo::binarization::internal
// Facade
template <typename I>
......@@ -992,9 +943,26 @@ namespace scribo
trace::entering("scribo::binarization::sauvola_ms");
mln_precondition(exact(input_1_).is_valid());
// Gray level images ONLY.
mlc_is_not_a(mln_value(I), value::Vectorial)::check();
mlc_is_not(mln_value(I), bool)::check();
mln_ch_value(I,bool)
output = internal::sauvola_ms_dispatch(input_1_, w_1, s, K);
output = impl::generic::sauvola_ms(exact(input_1_), w_1, s, K);
# ifdef SCRIBO_SAUVOLA_DEBUG
if (internal::k_image_output)
io::pgm::save(internal::debug_k, internal::k_image_output);
if (internal::s_n_image_output)
io::pgm::save(data::saturate(value::int_u8(), internal::debug_s_n * 100),
internal::s_n_image_output);
if (internal::k_l_image_output)
io::pgm::save(data::saturate(value::int_u8(), internal::debug_k_l * 10),
internal::k_l_image_output);
# endif // ! SCRIBO_SAUVOLA_DEBUG
trace::exiting("scribo::binarization::sauvola_ms");
return output;
......
......@@ -54,24 +54,23 @@ namespace scribo
/*! \brief Binarize a color image merging the binarization of each
component using Sauvola's algorithm.
\param[in] input_1 A grayscale or a color image.
\param[in] input_1 A color image.
\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] 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.
\p w_1 is expressed according to the image at scale 0, i.e. the
original size.
\return A Boolean image.
*/
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 min_ntrue,
double K);
......@@ -80,7 +79,7 @@ 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);
unsigned s, unsigned min_ntrue);
......@@ -90,7 +89,7 @@ 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,
unsigned s, unsigned min_ntrue,
double K)
{
trace::entering("scribo::binarization::sauvola_ms_split");
......@@ -109,9 +108,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, 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);
r_b = impl::generic::sauvola_ms(r_i, w_1, s, K);
g_b = impl::generic::sauvola_ms(g_i, w_1, s, K);
b_b = impl::generic::sauvola_ms(b_i, w_1, s, K);
border::resize(r_b, input_1.border());
border::resize(g_b, input_1.border());
......@@ -153,9 +152,9 @@ 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)
unsigned s, unsigned min_ntrue)
{
return sauvola_ms_split(input_1, w_1, s, lambda_min_1, min_ntrue,
return sauvola_ms_split(input_1, w_1, s, min_ntrue,
SCRIBO_DEFAULT_SAUVOLA_K);
}
......
......@@ -119,6 +119,15 @@ namespace scribo
namespace internal
{
# ifdef SCRIBO_SAUVOLA_DEBUG
// Declare debug images.
image2d<value::int_u8> debug_k;
image2d<float> debug_s_n;
image2d<float> debug_k_l;
# endif // ! SCRIBO_SAUVOLA_DEBUG
/*! \brief compute Sauvola's threshold applying directly the formula.
\param[in] m_x_y Mean value.
......@@ -131,12 +140,96 @@ namespace scribo
\return A threshold.
*/
# ifdef SCRIBO_SAUVOLA_DEBUG
inline
double
sauvola_threshold_formula(const double m_x_y, const double s_x_y,
const double K, const double R,
value::int_u8& dbg_k, float& dbg_s_n,
float& dbg_k_l)
# else
inline
double
sauvola_threshold_formula(const double m_x_y, const double s_x_y,
const double K, const double R)
# endif // ! SCRIBO_SAUVOLA_DEBUG
{
return m_x_y * (1.0 + K * ((s_x_y / R) - 1.0));
// double s_N = s_x_y / 256;
double K_2 = K;
// double K_2 = exp(K * log(s_x_y / 256));
// if (s_x_y < 30)
// K_2 = 0.01;
// else if (s_x_y < 80)
// K_2 = 0.1;
// else if (s_x_y > 80)
// K_2 = K;
// Results_0.1_0.34
//
// if (s_N < 0.1f)
// {
// K_2 = 0.1f;
// dbg_k = 0;
// dbg_s_n = s_N;
// }
// else if (s_N > 0.34)
// {
// K_2 = 0.34;
// dbg_k = 255;
// dbg_s_n = s_N;
// }
// else
// {
// K_2 = s_N;
// dbg_k = 150;
// dbg_s_n = s_N;
// }
// const double k_min = 0.1f;
// const double k_max = 1.0f;
// const double s_1 = 0.05f;
// const double s_2 = 0.50f;
// double k_b = (k_max - k_min) / (double)(s_2 - s_1);
// double k_a = 0.1f - s_1 * k_b;
// K_2 = k_a + k_b * s_N;
// dbg_s_n = s_N;
// if (K_2 < k_min)
// dbg_k = 0;
// else if (K_2 > k_max)
// dbg_k = 255;
// else
// dbg_k = 150;
// if (s_N < 0.1f)
// {
// K_2 = 0.1f;
// dbg_k = 0;
// dbg_s_n = s_N;
// dbg_k_l = 0.1;
// }
// else
// {
// // double K_L = ((long int)((s_N * 11) + 0.49999)) * s_N;
// double K_L = s_N * K / 3.0f;
// // K_2 = std::min(K_L, (double) 1.0);
// K_2 = K_L;
// if (K_L > 1.0f)
// dbg_k = 255;
// else
// dbg_k = 150;
// dbg_s_n = s_N;
// dbg_k_l = K_L;
// }
return m_x_y * (1.0 + K_2 * ((s_x_y / R) - 1.0));
}
......@@ -146,9 +239,15 @@ namespace scribo
double
sauvola_threshold_formula(double m_x_y, double s_x_y)
{
return sauvola_threshold_formula(m_x_y, s_x_y,
SCRIBO_DEFAULT_SAUVOLA_K,
SCRIBO_DEFAULT_SAUVOLA_R);
# ifdef SCRIBO_SAUVOLA_DEBUG
# warning "This overload of sauvola_threshold_formula is disabled in debug mode!"
std::cout << "This overload of sauvola_threshold_formula is disabled in debug mode!" << std::endl;
return 0;
# else
return sauvola_threshold_formula(m_x_y, s_x_y,
SCRIBO_DEFAULT_SAUVOLA_K,
SCRIBO_DEFAULT_SAUVOLA_R);
# endif // !SCRIBO_SAUVOLA_DEBUG
}
......@@ -208,7 +307,11 @@ 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.
# ifdef SCRIBO_SAUVOLA_DEBUG
double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, K, R, debug_k(p), debug_s_n(p), debug_k_l(p));
# else
double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, K, R);
# endif // ! SCRIBO_SAUVOLA_DEBUG
return t_x_y;
}
......@@ -252,7 +355,11 @@ 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.
# ifdef SCRIBO_SAUVOLA_DEBUG
double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, K, R, debug_k(p), debug_s_n(p), debug_k_l(p));
# else
double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, K, R);
# endif // !SCRIBO_SAUVOLA_DEBUG
return t_x_y;
}
......
......@@ -126,7 +126,7 @@ namespace scribo
template <typename P, typename M, typename J>
double
compute_sauvola_threshold(const P& p,
M& mean, M& stddev,
M& mean, M& stddev, M& thres,
const J& simple,
const J& squared,
int win_width, double K, double R)
......@@ -171,6 +171,8 @@ namespace scribo
// Thresholding.
double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, K, R);
thres(p) = t_x_y;
return t_x_y;
}
......@@ -205,6 +207,7 @@ namespace scribo
unsigned window_size,
double K,
Image<M>& mean_, Image<M>& stddev_,
Image<M>& thres_,
Image<J>& simple_,
Image<J>& squared_)
{
......@@ -213,6 +216,7 @@ namespace scribo
const I& input = exact(input_);
M& mean = exact(mean_);
M& stddev = exact(stddev_);
M& thres = exact(thres_);
J& simple = exact(simple_);
J& squared = exact(squared_);
......@@ -235,7 +239,7 @@ namespace scribo
for(def::coord col = 0; col < ncols; ++col)
output.at_(row, col)
= internal::compute_sauvola_threshold(P(row, col),
mean, stddev,
mean, stddev, thres,
simple, squared,
window_size, K,
SCRIBO_DEFAULT_SAUVOLA_R);
......@@ -255,12 +259,13 @@ namespace scribo
unsigned window_size,
double K,
Image<M>& mean, Image<M>& stddev,
Image<M>& thres,
Image<J>& simple,
Image<J>& squared)
{
return impl::generic::sauvola_threshold_image_debug(input, window_size,
K,
mean, stddev,
mean, stddev, thres,
simple, squared);
}
......@@ -272,6 +277,7 @@ namespace scribo
unsigned window_size,
double K,
Image<M>& mean, Image<M>& stddev,
Image<M>& thres,
Image<J>& simple,
Image<J>& squared)
{
......@@ -284,7 +290,7 @@ namespace scribo
mln_ch_value(I, value::int_u8)
output = impl::generic::sauvola_threshold_image_debug(gima, window_size,
K,
mean, stddev,
mean, stddev, thres,
simple, squared);
trace::exiting("scribo::binarization::impl::sauvola_threshold_image_debug_rgb8");
......@@ -309,12 +315,12 @@ namespace scribo
const I& input,
unsigned window_size,
double K,
M& mean, M& stddev,
M& mean, M& stddev, M& thres,
J& simple,
J& squared)
{
return impl::sauvola_threshold_image_debug_gl(input, window_size, K,
mean, stddev,
mean, stddev, thres,
simple, squared);
}
......@@ -324,7 +330,7 @@ namespace scribo
sauvola_threshold_image_debug_dispatch(const value::rgb8&, const I& input,
unsigned window_size,
double K,
M& mean, M& stddev,
M& mean, M& stddev, M& thres,
J& simple,
J& squared)
{
......@@ -337,7 +343,7 @@ namespace scribo
inline
mln_ch_value(I, value::int_u8)
sauvola_threshold_image_debug_dispatch(const mln_value(I)&, const I& input,
M& mean, M& stddev,
M& mean, M& stddev, M& thres,
unsigned window_size,
double K,
J& simple,
......@@ -360,6 +366,7 @@ namespace scribo
sauvola_threshold_image_debug(const Image<I>& input, unsigned window_size,
double K,
Image<M>& mean, Image<M>& stddev,
Image<M>& thres,
Image<J>& simple,
Image<J>& squared)
{
......@@ -376,6 +383,7 @@ namespace scribo
K,
exact(mean),
exact(stddev),
exact(thres),
exact(simple),
exact(squared));
......@@ -389,14 +397,15 @@ namespace scribo
mln_ch_value(I, value::int_u8)
sauvola_threshold_image_debug(const Image<I>& input, unsigned window_size,
double K,
Image<M>& mean, Image<M>& stddev)
Image<M>& mean, Image<M>& stddev,
Image<M>& thres)
{
mln_ch_value(I, double)
simple = init_integral_image(input, scribo::internal::identity_),
squared = init_integral_image(input, scribo::internal::square_);
return sauvola_threshold_image_debug(input, window_size, K,
mean, stddev,
mean, stddev, thres,
simple, squared);
}
......
# 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.
#
......@@ -43,7 +44,7 @@ if HAVE_MAGICKXX
sauvola \
sauvola_debug \
sauvola_ms \
sauvola_ms_static \
sauvola_ms_debug \
sauvola_ms_split
fg_sauvola_ms_SOURCES = fg_sauvola_ms.cc
......@@ -71,6 +72,12 @@ if HAVE_MAGICKXX
sauvola_ms_LDFLAGS = $(AM_LDFLAGS) \
$(MAGICKXX_LDFLAGS)
sauvola_ms_debug_SOURCES = sauvola_ms_debug.cc
sauvola_ms_debug_CPPFLAGS = $(AM_CPPFLAGS) -DSCRIBO_SAUVOLA_DEBUG \
$(MAGICKXX_CPPFLAGS)
sauvola_ms_debug_LDFLAGS = $(AM_LDFLAGS) \
$(MAGICKXX_LDFLAGS)