
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Update. * icdar/2009/hsc/clean_input.cc: New. * icdar/2009/hsc/clean_input.hh: New. * icdar/2009/hsc/lines_to_boxes.cc: New. * icdar/2009/hsc/line_to_words.hh: Remove blank line. * icdar/2009/hsc/io/icdar/save.hh: Fix warning. * icdar/2009/hsc/ws_to_wsl.hh: Add log. * icdar/2009/hsc/input_to_wsl.cc: Split into... * icdar/2009/hsc/input_to_lines_dat.cc, * icdar/2009/hsc/input_to_ws.hh: ...these new files. * icdar/2009/hsc/line_to_words.cc: Rename as... * icdar/2009/hsc/dummy_input_to_words_dat.cc: ...this. clean_input.cc | 41 +++++++++++++++++ clean_input.hh | 45 +++++++++++++++++++ dummy_input_to_words_dat.cc | 59 ++++++++++++++++++++++++ input_to_lines_dat.cc | 87 ++++++++++++++++++++++++++++++++++++ input_to_ws.hh | 104 +++++++------------------------------------- input_to_wsl.cc | 93 +++++---------------------------------- io/icdar/save.hh | 3 - line_to_words.hh | 1 lines_to_boxes.cc | 54 ++++++++++++++++++++++ ws_to_wsl.hh | 42 +++++++++++++++++ 10 files changed, 360 insertions(+), 169 deletions(-) Index: icdar/2009/hsc/clean_input.cc --- icdar/2009/hsc/clean_input.cc (revision 0) +++ icdar/2009/hsc/clean_input.cc (revision 0) @@ -0,0 +1,41 @@ +#include <sandbox/icdar/2009/hsc/clean_input.hh> + +#include <mln/io/pbm/load.hh> +#include <mln/io/pbm/save.hh> + + + + + + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " input.pbm output.pbm" << std::endl + << " HSC @ ICDAR'2009" << std::endl + << " input.pbm: input 2D binary image (text is black; background is white)" << std::endl + << " output.pbm: cleaned input." << std::endl; + std::abort(); +} + + + +int main(int argc, char* argv[]) +{ + using namespace mln; + using value::int_u8; + + if (argc != 3) + usage(argv); + + + trace::entering("main"); + + + image2d<bool> input; + + io::pbm::load(input, argv[1]); + io::pbm::save(clean_input(input), + argv[2]); + + trace::exiting("main"); +} Index: icdar/2009/hsc/clean_input.hh --- icdar/2009/hsc/clean_input.hh (revision 0) +++ icdar/2009/hsc/clean_input.hh (revision 0) @@ -0,0 +1,45 @@ +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> +#include <mln/value/label_16.hh> + +#include <mln/labeling/background.hh> +#include <mln/labeling/compute.hh> +#include <mln/accu/count.hh> +#include <mln/accu/bbox.hh> + +#include <mln/fun/i2v/array.hh> +#include <mln/level/transform.hh> + + +namespace mln +{ + + image2d<bool> + clean_input(const image2d<bool>& input) + { + int max_col = input.domain().pmax().col(); + + typedef value::label_16 L; + L nlabels; + image2d<L> lab = labeling::background(input, c8(), nlabels); + util::array<unsigned> count = labeling::compute(accu::count<point2d>(), lab, nlabels); + util::array<box2d> box = labeling::compute(accu::bbox<point2d>(), lab, nlabels); + + fun::i2v::array<bool> ok(nlabels.next(), false); // default is text + ok(0) = true; // bg is 'white' + for (L l = 1; l <= nlabels; ++l) + { + if (count[l] <= 3) + { + ok(l) = true; // into bg + continue; + } + int center_col = box[l].center().col(); + if (center_col >= max_col - 3 || + center_col <= 3) + ok(l) = true; + } + return level::transform(lab, ok); + } + +} // mln Index: icdar/2009/hsc/lines_to_boxes.cc --- icdar/2009/hsc/lines_to_boxes.cc (revision 0) +++ icdar/2009/hsc/lines_to_boxes.cc (revision 0) @@ -0,0 +1,54 @@ +#include <mln/labeling/compute.hh> +#include <mln/util/array.hh> + +#include <mln/io/pgm/load.hh> +#include <mln/io/ppm/save.hh> +#include <mln/literal/colors.hh> +#include <mln/level/convert.hh> + +#include <mln/value/label_8.hh> +#include <mln/estim/min_max.hh> +#include <mln/core/image/violent_cast_image.hh> +#include <mln/core/var.hh> + +#include <scribo/draw/bounding_boxes.hh> + + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " input.pgm output.ppm" << std::endl + << " HSC @ ICDAR'2009" << std::endl + << " input.pgm: labeled lines" << std::endl + << " output.ppm: with red boxes" << std::endl; + std::abort(); +} + + + +int main(int argc, char* argv[]) +{ + using namespace mln; + using value::int_u8; + using value::label_8; + using value::rgb8; + + if (argc != 3) + usage(argv); + + image2d<int_u8> input; + io::pgm::load(input, argv[1]); + + int_u8 dummy, n_boxes; + estim::min_max(input, dummy, n_boxes); + + label_8 n = unsigned(n_boxes); + + mln_VAR(input_, violent_cast_image_<label_8>(input)); + util::array<box2d> boxes = labeling::compute(accu::meta::bbox(), + input_, + n); + + image2d<rgb8> out = level::convert(rgb8(), input); + scribo::draw::bounding_boxes(out, boxes, literal::red); + io::ppm::save(out, argv[2]); +} Index: icdar/2009/hsc/line_to_words.hh --- icdar/2009/hsc/line_to_words.hh (revision 3641) +++ icdar/2009/hsc/line_to_words.hh (working copy) @@ -1,4 +1,3 @@ - #include <mln/value/int_u.hh> #include <mln/core/image/image2d.hh> Index: icdar/2009/hsc/dummy_input_to_words_dat.cc --- icdar/2009/hsc/dummy_input_to_words_dat.cc (revision 0) +++ icdar/2009/hsc/dummy_input_to_words_dat.cc (revision 0) @@ -0,0 +1,59 @@ +#include <mln/value/int_u16.hh> +#include <mln/value/rgb8.hh> + +#include <mln/io/pbm/load.hh> +#include <mln/io/ppm/save.hh> +#include <mln/debug/colorize.hh> + +#include <sandbox/icdar/2009/hsc/clean_input.hh> +#include <sandbox/icdar/2009/hsc/line_to_words.hh> +#include <sandbox/icdar/2009/hsc/io/icdar/save.hh> + + + + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " input.pbm output.dat [output.ppm]" << std::endl + << " HSC @ ICDAR'2009" << std::endl + << " input.pbm: a raw binary 2D image (either a line or a page)" << std::endl + << " output.dat: output image where words are labeled (int_u8)" << std::endl + << " 0 is the background label." << std::endl; + std::abort(); +} + + + +int main(int argc, char* argv[]) +{ + using namespace mln; + using value::int_u16; + + if (argc != 3 && argc != 4) + usage(argv); + + + trace::entering("main"); + + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + input = clean_input(input); + + + int_u16 n_words; + image2d<int_u16> output = line_to_words(input, n_words); + + io::icdar::save(output, argv[2]); + + if (argc == 4) + { + io::ppm::save(debug::colorize(value::rgb8(), + output, + n_words), + argv[3]); + } + + trace::exiting("main"); +} Index: icdar/2009/hsc/input_to_lines_dat.cc --- icdar/2009/hsc/input_to_lines_dat.cc (revision 0) +++ icdar/2009/hsc/input_to_lines_dat.cc (revision 0) @@ -0,0 +1,87 @@ +#include <sandbox/icdar/2009/hsc/clean_input.hh> +#include <sandbox/icdar/2009/hsc/input_to_ws.hh> +#include <sandbox/icdar/2009/hsc/ws_to_wsl.hh> +#include <sandbox/icdar/2009/hsc/io/icdar/save.hh> + +#include <mln/world/binary_2d/subsample.hh> + +#include <mln/value/int_u8.hh> +#include <mln/value/label.hh> +#include <mln/value/rgb8.hh> +#include <mln/debug/colorize.hh> +#include <mln/labeling/relabel.hh> + +#include <mln/level/transform.hh> +#include <mln/fun/v2v/enc.hh> + +#include <mln/io/pbm/load.hh> +#include <mln/io/pgm/save.hh> +#include <mln/io/ppm/save.hh> + +#include <mln/core/image/violent_cast_image.hh> + + + + + + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " input.pbm output.dat [output.ppm]" << std::endl + << " HSC @ ICDAR'2009" << std::endl + << " input.pbm: input 2D binary image (text is black; background is white)" << std::endl + << " output.dat: line buffer (int; 0 is bg)." << std::endl; + std::abort(); +} + + + +int main(int argc, char* argv[]) +{ + using namespace mln; + using value::int_u8; + + if (argc != 3 && argc != 4) + usage(argv); + + + trace::entering("main"); + + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + + // First clean. + input = clean_input(input); + + + // Sub-sample. + image2d<int_u8> small = world::binary_2d::subsample(input, 4); + + typedef value::int_u<12> L; + + L n_lines; + image2d<L> + // Get text regions. + ws = input_to_ws(input, small, n_lines), + // Merge regions. + wsl = ws_to_wslines(input, small, ws, n_lines); + + typedef value::label<12> L_; + L_ n_lines_; + image2d<L_> wsl_ = labeling::relabel(violent_cast_image_<L_>(wsl), + n_lines_); + + io::icdar::save(wsl_, argv[2]); + + if (argc == 4) + { + io::ppm::save(debug::colorize(value::rgb8(), + wsl_, + n_lines_), + argv[3]); + } + + trace::exiting("main"); +} Index: icdar/2009/hsc/io/icdar/save.hh --- icdar/2009/hsc/io/icdar/save.hh (revision 3641) +++ icdar/2009/hsc/io/icdar/save.hh (working copy) @@ -69,7 +69,8 @@ { /// Probably too violent... unsigned int value = static_cast<unsigned int>(ima(p)); - fwrite(&value, sizeof (int), 1, f); + int ret = fwrite(&value, sizeof (int), 1, f); + (void)(ret); } fclose(f); Index: icdar/2009/hsc/input_to_ws.hh --- icdar/2009/hsc/input_to_ws.hh (revision 3630) +++ icdar/2009/hsc/input_to_ws.hh (working copy) @@ -1,70 +1,37 @@ -#include <set> -#include <vector> - #include <mln/core/image/image2d.hh> -#include <mln/core/image/image_if.hh> #include <mln/core/alias/neighb2d.hh> -#include <mln/pw/all.hh> #include <mln/data/fill.hh> #include <mln/level/saturate.hh> -#include <mln/level/convert.hh> -#include <mln/arith/revert.hh> #include <mln/value/int_u8.hh> -#include <mln/value/rgb8.hh> -#include <mln/literal/colors.hh> -#include <mln/debug/colorize.hh> - -#include <mln/io/pbm/load.hh> -#include <mln/io/pbm/save.hh> -#include <mln/io/pgm/save.hh> -#include <mln/io/ppm/save.hh> - -#include <mln/world/binary_2d/subsample.hh> #define MLN_FLOAT double #include <sandbox/theo/exec/gaussian_directional_2d.hh> -#include <mln/morpho/closing/structural.hh> -#include <mln/morpho/watershed/flooding.hh> #include <mln/win/rectangle2d.hh> -#include <sandbox/icdar/2009/hsc/ws_to_wsl.hh> - - - +#include <mln/morpho/closing/structural.hh> +#include <mln/morpho/watershed/flooding.hh> -void usage(char* argv[]) +namespace mln { - std::cerr << "usage: " << argv[0] << " input.pbm output.pgm [output.ppm]" << std::endl - << " HSC @ ICDAR'2009" << std::endl - << " input.pbm: input 2D binary image (text is black; background is white)" << std::endl - << " output.pgm: output image where line components are labeled (int_u8)" << std::endl - << " 0 is the background label." << std::endl; - std::abort(); -} - -int main(int argc, char* argv[]) + template <typename L> + image2d<L> + input_to_ws(const image2d<bool>& input, + const image2d<value::int_u8>& small, + L& n_lines) { - using namespace mln; - using value::int_u8; - using value::rgb8; - - if (argc != 3 && argc != 4) - usage(argv); - // Parameters. const unsigned - subsampling_factor = 4, height = 5, - width = 25, - n_min_stats = 1000; + width = 25; + const float h_sigma = 31, v_sigma = 1.3; @@ -72,22 +39,8 @@ // end of Parameters. - trace::entering("main"); - - image2d<bool> input; - io::pbm::load(input, argv[1]); - // Sub-sampling. - image2d<int_u8> - small = world::binary_2d::subsample(input, subsampling_factor), - fuzzy, clo, - ws, - spc; - - -# ifdef LOG - io::pgm::save(small, "tmp_small.pgm"); -# endif + image2d<value::int_u8> fuzzy, clo; // Fuzzifying. @@ -98,38 +51,17 @@ out = linear::gaussian_directional_2d(temp, 1, h_sigma, 0); out = linear::gaussian_directional_2d(out, 0, v_sigma, 0); - fuzzy = level::saturate(int_u8(), out); - -# ifdef LOG - io::pgm::save(fuzzy, "tmp_fuzzy.pgm"); -# endif + fuzzy = level::saturate(value::int_u8(), out); } - + // Closing. clo = morpho::closing::structural(fuzzy, win::rectangle2d(height, width)); -# ifdef LOG - io::pgm::save(clo, "tmp_clo.pgm"); -# endif - - int_u8 n_basins; - ws = morpho::watershed::flooding(clo, c4(), n_basins); + // Watershed transform. + image2d<L> ws = morpho::watershed::flooding(clo, c4(), n_lines); -# ifdef LOG - io::pgm::save(ws, "tmp_ws.pgm"); - io::ppm::save(debug::colorize(rgb8(), ws, n_basins), "tmp_ws.ppm"); -# endif - - - image2d<int_u8> wsl = ws_to_wslines(input, small, ws, n_basins); - - io::pgm::save(wsl, argv[2]); - - if (argc == 4) - { - io::ppm::save(debug::colorize(rgb8(), wsl, n_basins), - argv[3]); + return ws; } - trace::exiting("main"); -} + +} // mln Property changes on: icdar/2009/hsc/input_to_ws.hh ___________________________________________________________________ Added: svn:mergeinfo Index: icdar/2009/hsc/input_to_wsl.cc --- icdar/2009/hsc/input_to_wsl.cc (revision 3641) +++ icdar/2009/hsc/input_to_wsl.cc (working copy) @@ -1,36 +1,16 @@ -#include <set> -#include <vector> +#include <sandbox/icdar/2009/hsc/input_to_ws.hh> +#include <sandbox/icdar/2009/hsc/ws_to_wsl.hh> -#include <mln/core/image/image2d.hh> -#include <mln/core/image/image_if.hh> -#include <mln/core/alias/neighb2d.hh> - -#include <mln/pw/all.hh> -#include <mln/data/fill.hh> -#include <mln/level/saturate.hh> -#include <mln/level/convert.hh> -#include <mln/arith/revert.hh> +#include <mln/world/binary_2d/subsample.hh> #include <mln/value/int_u8.hh> #include <mln/value/rgb8.hh> -#include <mln/literal/colors.hh> #include <mln/debug/colorize.hh> #include <mln/io/pbm/load.hh> -#include <mln/io/pbm/save.hh> #include <mln/io/pgm/save.hh> #include <mln/io/ppm/save.hh> -#include <mln/world/binary_2d/subsample.hh> - -#define MLN_FLOAT double -#include <sandbox/theo/exec/gaussian_directional_2d.hh> - -#include <mln/morpho/closing/structural.hh> -#include <mln/morpho/watershed/flooding.hh> -#include <mln/win/rectangle2d.hh> - -#include <sandbox/icdar/2009/hsc/ws_to_wsl.hh> @@ -58,78 +38,31 @@ usage(argv); - // Parameters. - - const unsigned - subsampling_factor = 4, - height = 5, - width = 25, - n_min_stats = 1000; - const float - h_sigma = 31, - v_sigma = 1.3; - - // end of Parameters. - - trace::entering("main"); + image2d<bool> input; io::pbm::load(input, argv[1]); - // Sub-sampling. - image2d<int_u8> - small = world::binary_2d::subsample(input, subsampling_factor), - fuzzy, clo, - ws, - spc; - -# ifdef LOG - io::pgm::save(small, "tmp_small.pgm"); -# endif - - - // Fuzzifying. - { - image2d<MLN_FLOAT> temp(small.domain()), out; - data::fill(temp, small); - - out = linear::gaussian_directional_2d(temp, 1, h_sigma, 0); - out = linear::gaussian_directional_2d(out, 0, v_sigma, 0); - - fuzzy = level::saturate(int_u8(), out); - -# ifdef LOG - io::pgm::save(fuzzy, "tmp_fuzzy.pgm"); -# endif - } - - - clo = morpho::closing::structural(fuzzy, win::rectangle2d(height, width)); - -# ifdef LOG - io::pgm::save(clo, "tmp_clo.pgm"); -# endif - - int_u8 n_basins; - ws = morpho::watershed::flooding(clo, c4(), n_basins); - -# ifdef LOG - io::pgm::save(ws, "tmp_ws.pgm"); - io::ppm::save(debug::colorize(rgb8(), ws, n_basins), "tmp_ws.ppm"); -# endif + int_u8 n_lines; + image2d<int_u8> + small = world::binary_2d::subsample(input, 4), + ws = input_to_ws(input, small, n_lines), + wsl = ws_to_wslines(input, small, ws, n_lines); - image2d<int_u8> wsl = ws_to_wslines(input, small, ws, n_basins); io::pgm::save(wsl, argv[2]); if (argc == 4) { - io::ppm::save(debug::colorize(rgb8(), wsl, n_basins), + io::ppm::save(debug::colorize(value::rgb8(), + wsl, + n_lines), argv[3]); } + trace::exiting("main"); } Index: icdar/2009/hsc/ws_to_wsl.hh --- icdar/2009/hsc/ws_to_wsl.hh (revision 3641) +++ icdar/2009/hsc/ws_to_wsl.hh (working copy) @@ -25,7 +25,17 @@ #include <mln/morpho/elementary/dilation.hh> +#include <mln/io/pgm/save.hh> +#include <mln/io/ppm/save.hh> +#include <mln/literal/colors.hh> +#include <mln/level/convert.hh> +#include <mln/pw/all.hh> +#include <mln/core/image/image_if.hh> + +#include <mln/fun/i2v/array.hh> +#include <mln/level/transform.hh> +#include <mln/debug/colorize.hh> @@ -296,7 +306,12 @@ & m1 = m[i1], & m2 = m[i2]; - if (m1.n() > 1000 && m2.n() > 1000) +// if (m1.n() != 0 && m2.n() != 0) +// d(e) = dist(m1, m2); +// else +// d(e) = 666.f; + + if (m1.n() > 10 && m2.n() > 10) // FIXME: was 1000 d(e) = dist(m1, m2); else d(e) = 666.f; @@ -379,6 +394,31 @@ } +#ifdef LOG + { + io::pgm::save(small, "tmp_small.pgm"); + io::pgm::save(ws, "tmp_ws.pgm"); + + using value::rgb8; + + image2d<rgb8> small_ws = level::convert(rgb8(), small); + data::fill((small_ws | (pw::value(ws) == pw::cst(0))).rw(), + literal::red); + io::ppm::save(small_ws, "tmp_small_ws.ppm"); + + fun::i2v::array<L> f_relab(n_basins + 1); + f_relab(0) = 0; + for (L l = 1; l <= n_basins; ++l) + f_relab(l) = parent[l]; + + image2d<L> ws_ = level::transform(ws, f_relab); + io::ppm::save(debug::colorize(rgb8(), ws_, n_basins), "tmp_ws.ppm"); + + } +#endif // LOG + + + // Outputing. image2d<L> output(input.domain());