Commit 5cb4a2bf authored by Guillaume Lazzara's avatar Guillaume Lazzara
Browse files

Several small fixes.

	* scribo/estim/font_color.hh: Fix namespace ambiguities.

	* src/binarization/Makefile.am: Add kim as target.

	* src/binarization/kim.cc: Cleanup code.

	* src/binarization/niblack.cc: Fix reverse video.

	* src/binarization/sauvola_ms.cc: Handle several k values.
parent 1e63053d
2012-08-23 Guillaume Lazzara <z@lrde.epita.fr>
Several small fixes.
* scribo/estim/font_color.hh: Fix namespace ambiguities.
* src/binarization/Makefile.am: Add kim as target.
* src/binarization/kim.cc: Cleanup code.
* src/binarization/niblack.cc: Fix reverse video.
* src/binarization/sauvola_ms.cc: Handle several k values.
2012-08-23 Guillaume Lazzara <z@lrde.epita.fr>
Improve documentation.
......
......@@ -83,7 +83,7 @@ namespace scribo
mln_ch_value(I,value::int_u8)
lbl = labeling::blobs(skel, c8(), nlabels);
util::array<algebra::vec<3u, float> > res =
mln::util::array<algebra::vec<3u, float> > res =
labeling::compute(accu::meta::stat::mean(), text_ima, lbl, nlabels);
accu::stat::median_h<value::int_u12> m_red;
......@@ -131,7 +131,7 @@ namespace scribo
value::int_u8 nlabels = 0;
mln_ch_value(J,value::int_u8) lbl = labeling::blobs(skel, c8(), nlabels);
util::array<algebra::vec<3u, float> > res =
mln::util::array<algebra::vec<3u, float> > res =
labeling::compute(accu::meta::stat::mean(), text_ima, lbl, nlabels);
accu::stat::median_h<value::int_u12> m_val;
......
......@@ -30,6 +30,7 @@ if HAVE_MAGICKXX
sauvola_ms_debug
utilexec_PROGRAMS = \
kim \
niblack \
otsu \
sauvola \
......@@ -66,6 +67,12 @@ if HAVE_MAGICKXX
sauvola_ms_fg_LDFLAGS = $(AM_LDFLAGS) \
$(MAGICKXX_LDFLAGS)
kim_SOURCES = kim.cc
kim_CPPFLAGS = $(AM_CPPFLAGS) \
$(MAGICKXX_CPPFLAGS)
kim_LDFLAGS = $(AM_LDFLAGS) \
$(MAGICKXX_LDFLAGS)
sauvola_SOURCES = sauvola.cc
sauvola_CPPFLAGS = $(AM_CPPFLAGS) \
$(MAGICKXX_CPPFLAGS)
......
......@@ -77,6 +77,47 @@ static const scribo::debug::opt_data opt_desc[] =
double
compute_thres(const mln::image2d<mln::util::couple<double,double> >& integral_sum_sum_2,
int row, int col, unsigned win_size,
const scribo::binarization::internal::sauvola_formula& formula)
{
point2d
tl(row - win_size - 1,
col - win_size - 1),
br(row + win_size,
col + win_size);
box2d b(tl, br);
b.crop_wrt(integral_sum_sum_2.domain());
point2d tr = b.pmax();
tr.row() = b.pmin().row();
point2d bl = b.pmin();
bl.row() = b.pmax().row();
unsigned card_min = b.nsites() - b.height() - b.width() + 1;
const mln::util::couple<double,double>&
D = integral_sum_sum_2(b.pmax()),
B = integral_sum_sum_2(tr),
C = integral_sum_sum_2(bl),
A = integral_sum_sum_2(b.pmin());
double sum = D.first() - B.first() - C.first() + A.first();
double sum_2 = D.second() - B.second() - C.second() + A.second();
double mean = sum / card_min;
double num = (sum_2 - sum * sum / card_min);
double stddev;
if (num > 0)
stddev = std::sqrt(num / (card_min - 1));
else
stddev = 0;
return formula(mean, stddev);
}
int main(int argc, char *argv[])
......@@ -202,97 +243,43 @@ int main(int argc, char *argv[])
if (!lines(i).is_textline())
continue;
math::round<double> round;
double
win_min = thickness(lines(i).id()),
win_max = lines(i).bbox().height(),
card_min,
card_max;
win_max = lines(i).bbox().height();;
mln_assertion(win_min != 0);
mln_assertion(win_max != 0);
binarization::internal::sauvola_formula compute_thres;
point2d tl, br;
scribo::binarization::internal::sauvola_formula formula;
mln_piter(L) p(lines(i).bbox());
for_all(p)
for (int row = lines(i).bbox().pmin().row();
row <= lines(i).bbox().pmax().row();
++row)
{
bool* out_ptr = &output.at_(row, lines(i).bbox().pmin().col());
value::int_u8* in_ptr = &input_1_gl.at_(row, lines(i).bbox().pmin().col());
for (int col = lines(i).bbox().pmin().col();
col <= lines(i).bbox().pmax().col();
++col)
{
// Min case
double T_min = compute_thres(integral_sum_sum_2, row, col, win_min, formula);
// Min case
tl.row() = (p.row() - win_min - 1);
tl.col() = (p.col() - win_min - 1);
br.row() = (p.row() + win_min);
br.col() = (p.col() + win_min);
box2d b(tl, br);
b.crop_wrt(integral_sum_sum_2.domain());
point2d tr = b.pmax();
tr.row() = b.pmin().row();
point2d bl = b.pmin();
bl.row() = b.pmax().row();
card_min = b.nsites() - b.height() - b.width() + 1;
double sum = integral_sum_sum_2(b.pmax()).first() - integral_sum_sum_2(tr).first() - integral_sum_sum_2(bl).first() + integral_sum_sum_2(b.pmin()).first();
double sum_2 = integral_sum_sum_2(b.pmax()).second() - integral_sum_sum_2(tr).second() - integral_sum_sum_2(bl).second() + integral_sum_sum_2(b.pmin()).second();
double mean = sum / card_min;
double num = (sum_2 - sum * sum / card_min);
double stddev = 0;
if (num > 0)
stddev = std::sqrt(num / (card_min - 1));
else
stddev = 0;
double T_min = compute_thres(mean, stddev);
// Max case
tl.row() = (p.row() - win_max - 1);
tl.col() = (p.col() - win_max - 1);
br.row() = (p.row() + win_max);
br.col() = (p.col() + win_max);
b = box2d(tl, br);
b.crop_wrt(integral_sum_sum_2.domain());
tr = b.pmax();
tr.row() = b.pmin().row();
bl = b.pmin();
bl.row() = b.pmax().row();
card_max = b.nsites() - b.height() - b.width() + 1;
sum = integral_sum_sum_2(b.pmax()).first() - integral_sum_sum_2(tr).first() - integral_sum_sum_2(bl).first() + integral_sum_sum_2(b.pmin()).first();
sum_2 = integral_sum_sum_2(b.pmax()).second() - integral_sum_sum_2(tr).second() - integral_sum_sum_2(bl).second() + integral_sum_sum_2(b.pmin()).second();
mean = sum / card_max;
num = (sum_2 - sum * sum / card_max);
stddev = 0;
if (num > 0)
stddev = std::sqrt(num / (card_max - 1));
else
stddev = 0;
double T_max = compute_thres(mean, stddev);
// Final threshold
// Max case
double T_max = compute_thres(integral_sum_sum_2, row, col, win_max, formula);
double teta = 0.3;
double T = teta * T_max + (1 - teta) * T_min;
// Final threshold
double teta = 0.3; // Good results from 0.1 to 0.3 according
// to the paper.
double T = teta * T_max + (1 - teta) * T_min;
mln_assertion(T_min <= 255);
mln_assertion(T_max <= 255);
mln_assertion(T <= 255);
mln_assertion(T_min <= 255);
mln_assertion(T_max <= 255);
mln_assertion(T <= 255);
output(p) = input_1_gl(p) <= T;
*out_ptr++ = *in_ptr++ <= T;
}
}
}
lt.stop();
......
......@@ -29,6 +29,8 @@
#include <mln/io/pbm/save.hh>
#include <mln/data/transform.hh>
#include <mln/fun/v2v/rgb_to_luma.hh>
#include <mln/arith/revert.hh>
#include <mln/logical/not.hh>
#include <scribo/binarization/niblack.hh>
#include <scribo/debug/option_parser.hh>
......@@ -98,8 +100,9 @@ int main(int argc, char *argv[])
image2d<value::int_u8>
input_1_gl = data::transform(input, mln::fun::v2v::rgb_to_luma<value::int_u8>());
arith::revert_inplace(input_1_gl);
image2d<bool> out = scribo::binarization::niblack(input_1_gl, w, k);
logical::not_inplace(out);
io::pbm::save(out, options.arg("output.pbm"));
trace::exiting("main");
......
......@@ -109,15 +109,24 @@ int main(int argc, char *argv[])
unsigned s = atoi(options.opt_value("s").c_str());
double k = atof(options.opt_value("k").c_str());
if (options.is_set("k"))
{
binarization::internal::k2 = k;
binarization::internal::k3 = k;
binarization::internal::k4 = k;
}
else
{
binarization::internal::k2 = atof(options.opt_value("k2").c_str());
binarization::internal::k3 = atof(options.opt_value("k3").c_str());
binarization::internal::k4 = atof(options.opt_value("k4").c_str());
}
if (verbose)
std::cout << "Using w_1=" << w_1 << " - s=" << s
<< " - k=" << k << std::endl;
binarization::internal::k2 = atof(options.opt_value("k2").c_str());
binarization::internal::k3 = atof(options.opt_value("k3").c_str());
binarization::internal::k4 = atof(options.opt_value("k4").c_str());
// Load
image2d<value::rgb8> input_1;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment