3645: Add a document-to-words routine based on lines.

https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Add a document-to-words routine based on lines. * icdar/2009/hsc/input_to_lines.hh (tau): New. * icdar/2009/hsc/input_to_lines_dat.cc: Update. * icdar/2009/hsc/input_to_words_dat.cc: New. * icdar/2009/hsc/line_to_words.hh (black_on_white, reduce): New. * icdar/2009/hsc/get_line_images.hh: Fix 1st elt, at index 0. get_line_images.hh | 13 +++++++-- input_to_lines.hh | 5 ++- input_to_lines_dat.cc | 2 - input_to_words_dat.cc | 64 ++++++++++++++++++++++++++++++++++++++++----- line_to_words.hh | 71 +++++++++++++++++++++++++++++++++++++++++++------- 5 files changed, 134 insertions(+), 21 deletions(-) Index: icdar/2009/hsc/input_to_lines.hh --- icdar/2009/hsc/input_to_lines.hh (revision 3644) +++ icdar/2009/hsc/input_to_lines.hh (working copy) @@ -16,7 +16,8 @@ template <typename L> image2d<L> - input_to_lines(const image2d<bool>& raw_input, L& n_lines) + input_to_lines(const image2d<bool>& raw_input, L& n_lines, + float tau) { // First clean. image2d<bool> input = clean_input(raw_input); @@ -35,7 +36,7 @@ wsl = ws_to_wslines(input, small, ws, n_reg); // Clean lines - wsl = clean_lines(input, wsl, 0.7f); + wsl = clean_lines(input, wsl, tau); return labeling::relabel(violent_cast_image_<L>(wsl), n_lines); Index: icdar/2009/hsc/input_to_words_dat.cc --- icdar/2009/hsc/input_to_words_dat.cc (revision 3644) +++ icdar/2009/hsc/input_to_words_dat.cc (working copy) @@ -4,12 +4,34 @@ #include <mln/io/pbm/load.hh> #include <mln/io/ppm/save.hh> #include <mln/debug/colorize.hh> +#include <mln/estim/min_max.hh> -#include <sandbox/icdar/2009/hsc/clean_input.hh> +#include <sandbox/icdar/2009/hsc/input_to_lines.hh> #include <sandbox/icdar/2009/hsc/line_to_words.hh> +#include <sandbox/icdar/2009/hsc/get_line_images.hh> #include <sandbox/icdar/2009/hsc/io/icdar/save.hh> +namespace mln +{ + + template <typename L> + void + paste_words(image2d<L>& output, + const image2d<L>& words, + L l_1st) + { + mln_piter(box2d) p(words.domain()); + for_all(p) + { + if (words(p) == 0) + continue; + output(p) = l_1st.to_enc() + words(p).to_enc(); + } + } + +} // mln + void usage(char* argv[]) @@ -27,7 +49,6 @@ int main(int argc, char* argv[]) { using namespace mln; - using value::int_u16; if (argc != 3 && argc != 4) usage(argv); @@ -35,15 +56,46 @@ trace::entering("main"); + typedef image2d<bool> I_bw; - image2d<bool> input; + I_bw input; io::pbm::load(input, argv[1]); - input = clean_input(input); + typedef value::label<12> Ll; + Ll n_lines; + image2d<Ll> lines = input_to_lines(input, n_lines, 0.501); // with majoritary + + // std::cout << "n lines = " << n_lines << std::endl; + + typedef value::int_u16 L; - int_u16 n_words; - image2d<int_u16> output = line_to_words(input, n_words); + image2d<L> output(input.domain()); + data::fill(output, 0); + + util::array<I_bw> line_ = get_line_images(lines, n_lines, 51); + + L n_words = 0; + for (unsigned l = 1; l <= n_lines; ++l) + { + I_bw line = line_[l]; // A line image. + + L n_line_words = 0; + image2d<L> words = line_to_words(line, n_line_words, false); + paste_words(output, words, /* 1st label is */ n_words); + + // std::cout << "line = " << l + // << " n_words = " << n_line_words << std::endl; + + n_words += n_line_words; + } + + { + // L l_min, l_max; + // estim::min_max(output, l_min, l_max); + // if (l_max != n_words) + // std::cout << "oops: " << l_max << ' ' << n_words << std::endl; + } io::icdar::save(output, argv[2]); Property changes on: icdar/2009/hsc/input_to_words_dat.cc ___________________________________________________________________ Added: svn:mergeinfo Index: icdar/2009/hsc/line_to_words.hh --- icdar/2009/hsc/line_to_words.hh (revision 3644) +++ icdar/2009/hsc/line_to_words.hh (working copy) @@ -12,20 +12,25 @@ #include <mln/morpho/elementary/dilation.hh> #include <mln/morpho/watershed/flooding.hh> +#include <mln/io/pbm/save.hh> +#include <mln/io/pgm/save.hh> +#include <mln/io/ppm/save.hh> +#include <mln/labeling/wrap.hh> namespace mln { - - image2d<bool> // Fwd decl. - reduce_negate(const image2d<bool>& input); + // Fwd decl. + image2d<bool> reduce (const image2d<bool>& input); + image2d<bool> reduce_negate(const image2d<bool>& input); template <typename L> image2d<L> - line_to_words(const image2d<bool>& input, L& n_words) + line_to_words(const image2d<bool>& input, L& n_words, + bool black_on_white = true) { // Parameters. @@ -37,12 +42,20 @@ // end of Parameters. - image2d<bool> - sub = reduce_negate(input), + image2d<bool> sub, clo; + + if (black_on_white) + sub = reduce_negate(input); + else + sub = reduce(input); + clo = morpho::closing::structural(sub, win::rectangle2d(height, width)); + // io::pbm::save(sub, "tmp_sub.pbm"); + // io::pbm::save(clo, "tmp_clo.pbm"); + int ww[] = { 00, 11, 0, 11, 0, 11, 7, 5, 7, 11, 00, 5, 0, 5, 0, @@ -56,11 +69,21 @@ mln_max(int_u12)), dmap_ = morpho::closing::area(dmap, c4(), l_area); - image2d<L> ws = morpho::elementary::dilation(morpho::watershed::flooding(dmap_, + + // io::pgm::save(labeling::wrap(dmap), "tmp_dmap.pgm"); + // io::pgm::save(labeling::wrap(dmap_), "tmp_dmap_.pgm"); + + + image2d<L> ws_ = morpho::watershed::flooding(dmap_, c4(), - n_words), + n_words); + image2d<L> ws = morpho::elementary::dilation(ws_, c4()); + // io::pgm::save(labeling::wrap(ws), "tmp_ws.pgm"); + // io::pgm::save(labeling::wrap(ws_), "tmp_ws_.pgm"); + + image2d<L> output(input.domain()); { @@ -70,13 +93,43 @@ mln_piter_(box2d) p(input.domain()); for_all(p) - if (input(p)) + if (input(p) == black_on_white) output(p) = 0; else output(p) = ws.at_((p.row() - min_row) / 2, (p.col() - min_col) / 2); } + // io::pgm::save(labeling::wrap(output), "tmp_output.pgm"); + + return output; + } + + + + image2d<bool> + reduce(const image2d<bool>& input) + { + const int + min_row = input.domain().pmin().row(), + min_col = input.domain().pmin().col(), + max_row = input.domain().pmax().row(), + max_col = input.domain().pmax().col(); + + image2d<bool> output(input.nrows() / 2, + input.ncols() / 2); + + for (int row = min_row; row <= max_row; row += 2) + for (int col = min_col; col <= max_col; col += 2) + { + unsigned count = 0; + if (input.at_(row, col) == true) ++count; + if (input.at_(row, col + 1) == true) ++count; + if (input.at_(row + 1, col) == true) ++count; + if (input.at_(row + 1, col + 1) == true) ++count; + output.at_((row - min_row) / 2, + (col - min_col) / 2) = (count >= 2); + } return output; } Index: icdar/2009/hsc/input_to_lines_dat.cc --- icdar/2009/hsc/input_to_lines_dat.cc (revision 3644) +++ icdar/2009/hsc/input_to_lines_dat.cc (working copy) @@ -37,7 +37,7 @@ typedef value::label<12> L; L n_lines; - image2d<L> output = input_to_lines(input, n_lines); + image2d<L> output = input_to_lines(input, n_lines, 0.7); // with 70% io::icdar::save(output, argv[2]); Index: icdar/2009/hsc/get_line_images.hh --- icdar/2009/hsc/get_line_images.hh (revision 3644) +++ icdar/2009/hsc/get_line_images.hh (working copy) @@ -39,14 +39,21 @@ util::array<box<mln_site(L)> > bboxes = labeling::compute(accu::meta::bbox(), lines, nlines); - util::array<mln_ch_value(L,bool)> result; + typedef mln_ch_value(L,bool) line_t; + util::array<line_t> result; - for (unsigned i = 1; i < nlines; ++i) { - typedef mln_ch_value(L,bool) line_t; + // Skipping index 0: + line_t dummy(1,1); + result.append(dummy); + } + + for (unsigned i = 1; i <= nlines; ++i) + { box<mln_site(L)> b = bboxes[i]; b.enlarge(bbox_line_enlarge); line_t line(b); + data::fill(line, false); data::fill(((line | bboxes[i]).rw() | (pw::value(lines) == i)).rw(), true); result.append(line);
participants (1)
-
Thierry Geraud