last-svn-commit-48-g65c1cd1 Add and update examples.

* src/Makefile.am, * src/binarization/Makefile.am, * src/preprocessing/Makefile.am: Add new targets. * src/preprocessing/denoising.cc: New. * src/preprocessing/split_bg_fg.cc: Fix usage. * src/text_in_article.cc, * src/text_in_photo_ppm_fast.cc: Update code according last changes in core classes. * src/text_in_photo_ppm_fast_2.cc: New example. --- scribo/ChangeLog | 18 + scribo/src/Makefile.am | 26 ++ scribo/src/binarization/Makefile.am | 2 + scribo/src/preprocessing/Makefile.am | 2 + .../denoising.cc} | 71 +++- scribo/src/preprocessing/split_bg_fg.cc | 2 +- scribo/src/text_in_article.cc | 459 +++++++++++++------- scribo/src/text_in_photo_ppm_fast.cc | 215 +++++----- ...oto_ppm_fast.cc => text_in_photo_ppm_fast_2.cc} | 259 +++-------- 9 files changed, 589 insertions(+), 465 deletions(-) copy scribo/src/{filter/objects_large.cc => preprocessing/denoising.cc} (55%) copy scribo/src/{text_in_photo_ppm_fast.cc => text_in_photo_ppm_fast_2.cc} (71%) diff --git a/scribo/ChangeLog b/scribo/ChangeLog index 7af1c38..13deec7 100644 --- a/scribo/ChangeLog +++ b/scribo/ChangeLog @@ -1,5 +1,23 @@ 2010-02-19 Guillaume Lazzara <z@lrde.epita.fr> + Add and update examples. + + * src/Makefile.am, + * src/binarization/Makefile.am, + * src/preprocessing/Makefile.am: Add new targets. + + * src/preprocessing/denoising.cc: New. + + * src/preprocessing/split_bg_fg.cc: Fix usage. + + * src/text_in_article.cc, + * src/text_in_photo_ppm_fast.cc: Update code according last + changes in core classes. + + * src/text_in_photo_ppm_fast_2.cc: New example. + +2010-02-19 Guillaume Lazzara <z@lrde.epita.fr> + Small fixes. * binarization/sauvola_ms.hh: Remove a useless include. diff --git a/scribo/src/Makefile.am b/scribo/src/Makefile.am index 6cc4229..a206e04 100644 --- a/scribo/src/Makefile.am +++ b/scribo/src/Makefile.am @@ -31,13 +31,19 @@ SUBDIRS = \ text bin_PROGRAMS = \ + pbm_lines_in_doc \ text_in_photo \ text_in_photo_ppm \ + text_in_photo_ppm_fast \ + text_in_photo_ppm_fast_2 \ text_in_photo_invert +pbm_lines_in_doc_SOURCES = pbm_lines_in_doc.cc text_in_photo_SOURCES = text_in_photo.cc text_in_photo_ppm_SOURCES = text_in_photo_ppm.cc +text_in_photo_ppm_fast_SOURCES = text_in_photo_ppm_fast.cc +text_in_photo_ppm_fast_2_SOURCES = text_in_photo_ppm_fast_2.cc text_in_photo_invert_SOURCES = text_in_photo_invert.cc @@ -65,5 +71,25 @@ if HAVE_TIFF $(TIFF_LDFLAGS) \ -lpthread -lhpdf + bin_PROGRAMS += text_in_article + text_in_article_CPPFLAGS = $(AM_CPPFLAGS) \ + $(TESSERACT_CPPFLAGS) \ + $(TIFF_CPPFLAGS) + text_in_article_LDFLAGS = $(AM_LDFLAGS) \ + $(TESSERACT_LDFLAGS) \ + $(TIFF_LDFLAGS) \ + -lpthread +# -lhpdf + text_in_article_SOURCES = text_in_article.cc + + + text_in_photo_ppm_fast_CPPFLAGS = $(AM_CPPFLAGS) \ + $(TESSERACT_CPPFLAGS) \ + $(TIFF_CPPFLAGS) + text_in_photo_ppm_fast_LDFLAGS = $(AM_LDFLAGS) \ + $(TESSERACT_LDFLAGS) \ + $(TIFF_LDFLAGS) \ + -lpthread + endif HAVE_TIFF endif HAVE_TESSERACT diff --git a/scribo/src/binarization/Makefile.am b/scribo/src/binarization/Makefile.am index 531d4cf..2c47ea1 100644 --- a/scribo/src/binarization/Makefile.am +++ b/scribo/src/binarization/Makefile.am @@ -22,11 +22,13 @@ include $(top_srcdir)/scribo/scribo.mk bin_PROGRAMS = \ sauvola \ sauvola_ms \ + sauvola_ms_slow \ sauvola_pgm \ simple sauvola_SOURCES = sauvola.cc sauvola_ms_SOURCES = sauvola_ms.cc +sauvola_ms_slow_SOURCES = sauvola_ms_slow.cc sauvola_pgm_SOURCES = sauvola_pgm.cc simple_SOURCES = simple.cc diff --git a/scribo/src/preprocessing/Makefile.am b/scribo/src/preprocessing/Makefile.am index 086a70f..2422d87 100644 --- a/scribo/src/preprocessing/Makefile.am +++ b/scribo/src/preprocessing/Makefile.am @@ -20,11 +20,13 @@ include $(top_srcdir)/scribo/scribo.mk bin_PROGRAMS = \ + denoising \ preprocess \ split_bg_fg \ split_bg_fg_ms \ unskew +denoising_SOURCES = denoising.cc preprocess_SOURCES = preprocess.cc split_bg_fg_SOURCES = split_bg_fg.cc split_bg_fg_ms_SOURCES = split_bg_fg_ms.cc diff --git a/scribo/src/filter/objects_large.cc b/scribo/src/preprocessing/denoising.cc similarity index 55% copy from scribo/src/filter/objects_large.cc copy to scribo/src/preprocessing/denoising.cc index a665032..769f75b 100644 --- a/scribo/src/filter/objects_large.cc +++ b/scribo/src/preprocessing/denoising.cc @@ -27,18 +27,20 @@ #include <mln/core/alias/neighb2d.hh> #include <mln/data/convert.hh> #include <mln/io/pbm/all.hh> +#include <mln/value/label.hh> +#include <mln/accu/math/count.hh> +#include <mln/labeling/relabel.hh> +#include <mln/labeling/compute.hh> +#include <mln/labeling/foreground.hh> -#include <mln/value/label_16.hh> - -#include <scribo/filter/objects_large.hh> #include <scribo/debug/usage.hh> const char *args_desc[][2] = { { "input.pbm", "A binary image. 'True' for objects, 'False'\ for the background." }, - { "max_area", "The maximum object area value. Objects with an area greater\ -than this value are removed." }, + { "nbh", "Select the neighborhood used for checking neighbors. '4' will use C4, '8' will use C8." }, + { "n_nbh", "The minimum neighbor count to be set to true." }, {0, 0} }; @@ -46,10 +48,10 @@ int main(int argc, char *argv[]) { using namespace mln; - if (argc != 4) + if (argc != 5) return scribo::debug::usage(argv, - "Filter too large objects", - "input.pbm max_area output.pbm", + "Remove noise.", + "input.pbm nbh min_nbh output.pbm", args_desc, "A binary image."); @@ -59,13 +61,54 @@ int main(int argc, char *argv[]) I input; io::pbm::load(input, argv[1]); - value::label_16 nobjects; - typedef object_image(mln_ch_value_(I,value::label_16)) obj_ima_t; - obj_ima_t objects - = scribo::primitive::extract::objects(input, c8(), nobjects); + typedef value::label<30> V; + + neighb2d nbh; + if (atoi(argv[2]) == 4) + nbh = c4(); + else if (atoi(argv[2]) == 8) + nbh = c8(); + else + { + std::cout << "Error: nbh must be set to '4' or '8'!" << std::endl; + return 1; + } + + unsigned min_nbh = atoi(argv[3]); + + + V nlabels; + image2d<V> lbl = labeling::foreground(input, nbh, nlabels); + std::cout << nlabels << std::endl; + + + util::array<unsigned> result = labeling::compute(accu::meta::math::count(), lbl, nlabels); + + fun::i2v::array<bool> f(static_cast<unsigned>(nlabels) + 1, true); + for (unsigned i = 1; i <= nlabels; ++i) + if (result(i) < min_nbh) + f(i) = false; + + labeling::relabel_inplace(lbl, nlabels, f); + std::cout << nlabels << std::endl; + + +// mln_piter_(I) p(input.domain()); +// mln_niter_(neighb2d) n(nbh, p); +// unsigned n_nbh; +// for_all(p) +// if (input(p)) +// { +// n_nbh = 0; +// for_all(n) +// if (input(n)) +// ++n_nbh; + +// if (n_nbh < min_nbh) +// input(p) = false; +// } - obj_ima_t filtered = scribo::filter::objects_large(objects, atoi(argv[2])); - io::pbm::save(data::convert(bool(), filtered), argv[3]); + io::pbm::save(data::convert(bool(), lbl), argv[4]); trace::exiting("main"); diff --git a/scribo/src/preprocessing/split_bg_fg.cc b/scribo/src/preprocessing/split_bg_fg.cc index a1aab52..0d7ba8a 100644 --- a/scribo/src/preprocessing/split_bg_fg.cc +++ b/scribo/src/preprocessing/split_bg_fg.cc @@ -49,7 +49,7 @@ int main(int argc, char *argv[]) if (argc != 6) return scribo::debug::usage(argv, "Split background and foreground.", - "input.pbm bg.ppm fg.ppm", + "input.pbm lambda delta bg.ppm fg.ppm", args_desc, "The foreground image."); typedef image2d<value::rgb8> I; diff --git a/scribo/src/text_in_article.cc b/scribo/src/text_in_article.cc index d140719..876eba5 100644 --- a/scribo/src/text_in_article.cc +++ b/scribo/src/text_in_article.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,6 +26,7 @@ #include <libgen.h> +#include <fstream> #include <iostream> #include <mln/core/image/image2d.hh> @@ -32,6 +34,7 @@ #include <mln/io/pbm/all.hh> #include <mln/io/ppm/save.hh> +#include <mln/io/dump/save.hh> #include <mln/math/min.hh> @@ -43,43 +46,58 @@ #include <mln/draw/box.hh> #include <mln/draw/line.hh> +#include <mln/data/convert.hh> + #include <mln/extension/adjust.hh> #include <mln/accu/stat/median_h.hh> -#include <scribo/draw/bounding_boxes.hh> +#include <mln/labeling/colorize.hh> +#include <mln/labeling/relabel.hh> + +//#include <scribo/draw/bounding_boxes.hh> +#include <scribo/draw/bounding_box_links.hh> -#include <scribo/primitive/extract/objects.hh> +#include <scribo/primitive/extract/components.hh> #include <scribo/primitive/link/merge_double_link.hh> #include <scribo/primitive/link/with_single_left_link_dmax_ratio.hh> #include <scribo/primitive/link/with_single_right_link_dmax_ratio.hh> #include <scribo/primitive/group/apply.hh> -#include <scribo/primitive/group/from_double_link.hh> +// #include <scribo/primitive/group/from_double_link.hh> #include <scribo/primitive/group/from_single_link.hh> #include <scribo/filter/object_links_bbox_h_ratio.hh> #include <scribo/filter/objects_small.hh> -#include <scribo/filter/objects_thin.hh> -#include <scribo/filter/objects_thick.hh> +// #include <scribo/filter/objects_thin.hh> +// #include <scribo/filter/objects_thick.hh> + +// #include <scribo/filter/object_groups_small.hh> -#include <scribo/filter/object_groups_small.hh> +// #include <scribo/debug/decision_image.hh> +// #include <scribo/debug/save_bboxes_image.hh> +// #include <scribo/debug/save_bboxes_image.hh> +// #include <scribo/debug/save_linked_bboxes_image.hh> + +#include <scribo/core/line_set.hh> +#include <scribo/io/xml/save_text_lines.hh> -#include <scribo/debug/decision_image.hh> -#include <scribo/debug/save_bboxes_image.hh> -#include <scribo/debug/save_bboxes_image.hh> -#include <scribo/debug/save_linked_bboxes_image.hh> #include <scribo/debug/usage.hh> #include <scribo/make/debug_filename.hh> +//#include <scribo/text/recognition.hh> + +#include <scribo/text/merging.hh> + + const char *args_desc[][2] = { - { "input.pbm", "A binary image. 'False' for objects, 'True'\ + { "input.pbm", "A binary image. 'False' for object, 'True'\ for the background." }, { "debug_dir", "Output directory for debug image" }, {0, 0} @@ -105,223 +123,340 @@ int main(int argc, char* argv[]) image2d<bool> input; - io::pbm::load(input, argv[1]); - - typedef image2d<value::label_16> L; + mln::io::pbm::load(input, argv[1]); - /// Finding objects. - std::cout << "Finding objects..." << std::endl; - value::label_16 nobjects; - object_image(L) - objects = scribo::primitive::extract::objects(input, - c8(), - nobjects); + typedef value::label_16 V; + typedef image2d<V> L; + /// Finding components. + std::cout << "Finding components..." << std::endl; + V ncomponents; + component_set<L> + components = scribo::primitive::extract::components(input, + c8(), + ncomponents); /// First filtering. - std::cout << "Filtering objects..." << std::endl; - object_image(L) filtered_objects - = scribo::filter::objects_small(objects, 6); + std::cout << "Filtering components..." << std::endl; + component_set<L> filtered_components + = scribo::filter::components_small(components, 6); + + { + unsigned none = 0, ignored = 0; + for_all_comps(i, filtered_components) + { + if (filtered_components.info(i).tag() == component::Ignored) + ++ignored; + else + ++none; + } + std::cout << "stats - none = " << none << " - ignored = " << ignored << std::endl; + + } /// Linking potential objects std::cout << "Linking objects..." << std::endl; object_links<L> left_link - = primitive::link::with_single_left_link_dmax_ratio(filtered_objects); + = primitive::link::with_single_left_link_dmax_ratio(filtered_components, 2); object_links<L> right_link - = primitive::link::with_single_right_link_dmax_ratio(filtered_objects); - + = primitive::link::with_single_right_link_dmax_ratio(filtered_components, 2); // Validating left and right links. object_links<L> - merged_links = primitive::link::merge_double_link(filtered_objects, + merged_links = primitive::link::merge_double_link(filtered_components, left_link, right_link); -#ifndef NOUT - if (argc == 4) - { - image2d<value::rgb8> output = data::convert(value::rgb8(), input); - scribo::draw::bounding_box_links(output, - merged_links, - literal::green); - - util::array<bool> drawn(objects.nlabels(), 0); - for_all_components(i, objects.bboxes()) - if (merged_links[i] == i && ! drawn(i)) - { - mln::draw::box(output, objects.bbox(i), literal::orange); - drawn[i] = true; - } - else - { - mln::draw::box(output, objects.bbox(i), literal::blue); - mln::draw::box(output, objects.bbox(merged_links[i]), literal::blue); - drawn[i] = true; - drawn[merged_links[i]] = true; - } - - io::ppm::save(output, scribo::make::debug_filename("links.ppm")); - } -#endif +// #ifndef NOUT +// if (argc == 4) +// { +// image2d<value::rgb8> output = data::convert(value::rgb8(), input); +// scribo::draw::bounding_box_links(output, +// merged_links, +// literal::green); +// mln::util::array<bool> drawn(static_cast<unsigned>(filtered_components.nelements()) + 1, 0); +// for_all_comps(i, filtered_components) +// if (filtered_components(i).tag() != component::Ignored) +// { +// if (merged_links[i] == i && ! drawn(i)) +// { +// mln::draw::box(output, filtered_components(i).bbox(), literal::orange); +// drawn[i] = true; +// } +// else +// { +// mln::draw::box(output, filtered_components(i).bbox(), literal::blue); +// mln::draw::box(output, filtered_components(merged_links[i]).bbox(), literal::blue); +// drawn[i] = true; +// drawn[merged_links[i]] = true; +// } +// } + +// mln::io::ppm::save(output, scribo::make::debug_filename("links.ppm")); +// } +// #endif // Remove links if bboxes have too different sizes. object_links<L> hratio_filtered_links - = filter::object_links_bbox_h_ratio(filtered_objects, + = filter::object_links_bbox_h_ratio(filtered_components, merged_links, - 2.0f); + 2.5f); -#ifndef NOUT - if (argc == 4) - { - image2d<value::rgb8> - hratio_decision_image = scribo::debug::decision_image(input, - merged_links, - hratio_filtered_links); - io::ppm::save(hratio_decision_image, - scribo::make::debug_filename("hratio_links_decision_image.ppm")); - } -#endif +// #ifndef NOUT +// if (argc == 4) +// { +// image2d<value::rgb8> +// hratio_decision_image = scribo::debug::decision_image(input, +// merged_links, +// hratio_filtered_links); +// io::ppm::save(hratio_decision_image, +// scribo::make::debug_filename("hratio_links_decision_image.ppm")); +// } +// #endif - // FIXME: from_single_link should return a packed object_groups? - // - //###### +// // FIXME: from_single_link should return a packed object_groups? +// // +// //###### object_groups<L> - groups = primitive::group::from_single_link(filtered_objects, + groups = primitive::group::from_single_link(filtered_components, hratio_filtered_links); - value::label_16 n_groups; - mln::fun::i2v::array<value::label_16> - groups_packed = mln::make::relabelfun(groups, - filtered_objects.nlabels(), - n_groups); - //###### +// value::label_16 n_groups; +// mln::fun::i2v::array<value::label_16> +// groups_packed = mln::make::relabelfun(groups, +// filtered_objects.nlabels(), +// n_groups); +// //###### - std::cout << "Grouping objects..." << std::endl; - object_image(L) - grouped_objects = primitive::group::apply(filtered_objects, groups); +// mln::util::array<line_stats_extra> line_stats; + line_set<L> + lines = scribo::make::line_set(hratio_filtered_links, groups); - // Compute min_row/max_row median - std::cout << "Preparing output" << std::endl; + + + // Bboxes image. { image2d<value::rgb8> output = data::convert(value::rgb8(), input); -// scribo::draw::bounding_box_links(output, -// filtered_objects.bboxes(), -// hratio_filtered_links, -// literal::green); - - typedef mln::value::int_u<10> median_t; - typedef mln::accu::stat::median_h<median_t> accu_t; - util::array<accu_t> - med_min_row(static_cast<unsigned>(grouped_objects.nlabels()) + 1), - med_max_row(static_cast<unsigned>(grouped_objects.nlabels()) + 1); + for_all_lines(l, lines) + if (lines(l).tag() != line::Ignored) + mln::draw::box(output, lines(l).bbox(), literal::red); -// std::cout << "Find median min/max rows" << std::endl; - for_all_components(i, filtered_objects.bboxes()) - { - if (groups_packed(i) != 0) - { - med_min_row(groups_packed(i)).take(filtered_objects.bbox(i).pmin().row() - grouped_objects.bbox(groups_packed(i)).pmin().row()); + mln::io::ppm::save(output, + scribo::make::debug_filename("step1_bboxes.ppm")); + } - med_max_row(groups_packed(i)).take(grouped_objects.bbox(groups_packed(i)).pmax().row() - filtered_objects.bbox(i).pmax().row()); - } - } + // Bboxes enlarged + { + image2d<value::rgb8> output = data::convert(value::rgb8(), input); - // Output - std::cout << "Drawing bboxes" << std::endl; - util::array<bool> drawn(static_cast<unsigned>(filtered_objects.nlabels()) + 1, 0); - util::array<bool> single(static_cast<unsigned>(grouped_objects.nlabels()) + 1); - for_all_components(i, filtered_objects.bboxes()) - if (hratio_filtered_links[i] == i && ! drawn(i)) + for_all_lines(l, lines) + if (lines(l).tag() != line::Ignored) { - mln::draw::box(output, filtered_objects.bbox(i), literal::orange); - drawn[i] = true; - single(groups_packed(i)) = true; + if (text::internal::looks_like_a_text_line(lines(l))) + { + box2d + b = text::internal::enlarge(lines(l).bbox(), + text::internal::delta_of_line(lines(l))); + b.crop_wrt(input.domain()); + mln::draw::box(output, b, literal::green); + } + else + mln::draw::box(output, lines(l).bbox(), literal::red); } - else + + mln::io::ppm::save(output, + scribo::make::debug_filename("step1_bboxes_enlarged.ppm")); + } + + // Looks like a text line + { + image2d<value::rgb8> output = data::convert(value::rgb8(), input); + + for_all_lines(l, lines) + if (lines(l).tag() != line::Ignored) { - mln::draw::box(output, filtered_objects.bbox(i), literal::blue); - mln::draw::box(output, filtered_objects.bbox(hratio_filtered_links[i]), - literal::blue); - drawn[i] = true; - drawn[hratio_filtered_links[i]] = true; - single(groups_packed(i)) = false; + if (text::internal::looks_like_a_text_line(lines(l))) + mln::draw::box(output, lines(l).bbox(), literal::green); + else + mln::draw::box(output, lines(l).bbox(), literal::red); } -// std::cout << "Drawing median lines" << std::endl; - for_all_components(i, grouped_objects.bboxes()) - { - if (! single(i)) + mln::io::ppm::save(output, + scribo::make::debug_filename("step1_looks_like_a_text_line.ppm")); + } + + + // Bboxes + line infos + { + std::ofstream file(scribo::make::debug_filename("step1_bboxes_100p.txt").c_str()); + std::ofstream file_50p(scribo::make::debug_filename("step1_bboxes_50p.txt").c_str()); + + for_all_lines(l, lines) + if (lines(l).tag() != line::Merged + && lines(l).tag() != line::Ignored + && lines(l).tag() != line::Pathological) { - point2d - b_top(grouped_objects.bbox(i).pmin().row() + med_min_row(i).to_result(), grouped_objects.bbox(i).pmin().col()), - e_top(grouped_objects.bbox(i).pmin().row() + med_min_row(i).to_result(), grouped_objects.bbox(i).pmax().col()), - b_bot(grouped_objects.bbox(i).pmax().row() - med_max_row(i).to_result(), grouped_objects.bbox(i).pmin().col()), - e_bot(grouped_objects.bbox(i).pmax().row() - med_max_row(i).to_result(), grouped_objects.bbox(i).pmax().col()); - - mln::draw::box(output, grouped_objects.bbox(i), literal::purple); - mln::draw::line(output, b_top, e_top, literal::cyan); - mln::draw::line(output, b_bot, e_bot, literal::cyan); + file << lines(l).bbox().pmin().row() << " " + << lines(l).bbox().pmin().col() << " " + << lines(l).bbox().pmax().row() << " " + << lines(l).bbox().pmax().col() << " " + << lines(l).card() << " " + << lines(l).baseline() << " " + << lines(l).x_height() << " " + << lines(l).median() << " " + << lines(l).d_height() << " " + << lines(l).a_height() << " " + << lines(l).char_space() << " " + << lines(l).char_width() << std::endl; + + file_50p << lines(l).bbox().pmin().row() / 2 << " " + << lines(l).bbox().pmin().col() / 2 << " " + << lines(l).bbox().pmax().row() / 2 << " " + << lines(l).bbox().pmax().col() / 2 << std::endl; } - } - io::ppm::save(output, argv[2]); + file.close(); + file_50p.close(); } + std::cout << "Merging lines..." << std::endl; + lines = scribo::text::merging(input.domain(), lines); - // Display median character space. + // Median and base lines. { image2d<value::rgb8> output = data::convert(value::rgb8(), input); - typedef mln::value::int_u<8> median_t; - typedef mln::accu::stat::median_h<median_t> accu_t; - util::array<accu_t> - lspace_med(static_cast<unsigned>(grouped_objects.nlabels()) + 1); - for_all_components(i, filtered_objects.bboxes()) - if (groups_packed(i) != 0) + for_all_lines(l, lines) + { + if (lines(l).tag() == line::Pathological) + mln::draw::box(output, lines(l).bbox(), literal::orange); + else if (lines(l).tag() != line::Merged) { - if (hratio_filtered_links(i) != i) + if (lines(l).card() > 1) { - unsigned - space = filtered_objects.bbox(i).pmin().col() - filtered_objects.bbox(hratio_filtered_links(i)).pmax().col(); + point2d + b_top(lines(l).baseline() - lines(l).median(), lines(l).bbox().pmin().col()), + e_top(lines(l).baseline() - lines(l).median(), lines(l).bbox().pmax().col()), + b_bot(lines(l).baseline(), lines(l).bbox().pmin().col()), + e_bot(lines(l).baseline(), lines(l).bbox().pmax().col()); - lspace_med(groups_packed(i)).take(space); + mln::draw::line(output, b_top, e_top, literal::blue); + mln::draw::line(output, b_bot, e_bot, literal::cyan); +// std::cout << lines(l) << std::endl; } + mln::draw::box(output, lines(l).bbox(), literal::purple); } + } - std::cout << "Drawing median character space" << std::endl; - for_all_components(i, filtered_objects.bboxes()) - if (groups_packed(i) != 0 && lspace_med(groups_packed(i)).card() > 1) - { - unsigned med = lspace_med(groups_packed(i)).to_result(); + mln::io::ppm::save(output, scribo::make::debug_filename("step2_x_height.ppm")); + } - mln::draw::box(output, grouped_objects.bbox(groups_packed(i)), - literal::purple); - point2d - beg = filtered_objects.bbox(i).pmax(), - end = beg; - beg.row() = filtered_objects.bbox(i).pmin().row(); - mln::draw::line(output, beg, end, literal::cyan); - beg.col() += med; - end.col() += med; - mln::draw::line(output, beg, end, literal::cyan); + // Bboxes image. + { + image2d<value::rgb8> output = data::convert(value::rgb8(), input); + for_all_lines(l, lines) + if (lines(l).tag() != line::Merged + && lines(l).tag() != line::Ignored + && lines(l).tag() != line::Pathological) + { + mln::draw::box(output, lines(l).bbox(), literal::red); } - io::ppm::save(output, "median_wspace.ppm"); - + mln::io::ppm::save(output, argv[2]); } - trace::exiting("main"); + +// // line label image. +// { +// util::array<V> +// f(static_cast<unsigned>(filtered_components.nelements()) + 1, 0); +// for_all_lines(l, lines) +// if (lines(l).tag() != line::Merged +// && lines(l).tag() != line::Ignored +// && lines(l).tag() != line::Pathological) +// { +// for_all_elements(c, lines(l).components()) +// f(lines(l).components()[c]) = l; +// } +// L line_label = duplicate(filtered_components.labeled_image()); +// V nlbl = filtered_components.nelements(); +// mln::labeling::relabel_inplace(line_label, nlbl, f); + +// mln::io::ppm::save(labeling::colorize(value::rgb8(), line_label), +// scribo::make::debug_filename("labeled_lines.ppm")); +// mln::io::dump::save(line_label, scribo::make::debug_filename("labeled_lines.dump")); +// } + + + +// scribo::io::xml::save_text_lines(argv[1], lines, "out.xml"); + + + + + + + +// scribo::text::recognition(lines, "fra", "out.txt"); + + +// // Display median character space. +// { +// image2d<value::rgb8> output = data::convert(value::rgb8(), input); +// typedef mln::value::int_u<8> median_t; +// typedef mln::accu::stat::median_h<median_t> accu_t; +// util::array<accu_t> +// lspace_med(static_cast<unsigned>(grouped_objects.nlabels()) + 1); + +// for_all_components(i, filtered_objects.bboxes()) +// if (groups_packed(i) != 0) +// { +// if (hratio_filtered_links(i) != i) +// { +// unsigned +// space = filtered_objects.bbox(i).pmin().col() - filtered_objects.bbox(hratio_filtered_links(i)).pmax().col(); + +// lspace_med(groups_packed(i)).take(space); + +// } +// } + +// std::cout << "Drawing median character space" << std::endl; +// for_all_components(i, filtered_objects.bboxes()) +// if (groups_packed(i) != 0 && lspace_med(groups_packed(i)).card() > 1) +// { +// unsigned med = lspace_med(groups_packed(i)).to_result(); + +// mln::draw::box(output, grouped_objects.bbox(groups_packed(i)), +// literal::purple); + +// point2d +// beg = filtered_objects.bbox(i).pmax(), +// end = beg; +// beg.row() = filtered_objects.bbox(i).pmin().row(); +// mln::draw::line(output, beg, end, literal::cyan); +// beg.col() += med; +// end.col() += med; +// mln::draw::line(output, beg, end, literal::cyan); + +// } + +// io::ppm::save(output, "median_wspace.ppm"); + +// } + +// trace::exiting("main"); } diff --git a/scribo/src/text_in_photo_ppm_fast.cc b/scribo/src/text_in_photo_ppm_fast.cc index 4a7562f..e4ddd48 100644 --- a/scribo/src/text_in_photo_ppm_fast.cc +++ b/scribo/src/text_in_photo_ppm_fast.cc @@ -58,7 +58,7 @@ #include <scribo/binarization/sauvola_ms.hh> #include <scribo/binarization/sauvola.hh> -#include <scribo/primitive/extract/objects.hh> +#include <scribo/primitive/extract/components.hh> #include <scribo/primitive/link/merge_double_link.hh> #include <scribo/primitive/link/with_single_left_link.hh> @@ -95,6 +95,9 @@ #include <scribo/src/afp/link.hh> #include <scribo/src/afp/regroup.hh> +#include <scribo/core/line_set.hh> +#include <scribo/text/recognition.hh> + const char *args_desc[][2] = { { "input.ppm", "A color image." }, @@ -137,20 +140,22 @@ namespace mln template <typename I, typename L> mln_concrete(I) compute_highlight_image(const I& input_rgb, - const object_image<L>& objects) + const scribo::component_set<L>& components) { mln_ch_value(I, bool) mask; initialize(mask, input_rgb); data::fill(mask, false); - for_all_components(i, objects.bboxes()) - data::fill((mask | objects.bbox(i)).rw(), true); + for_all_comps(i, components) + if (components(i).is_valid()) + data::fill((mask | components(i).bbox()).rw(), true); mask_non_text f(mask); mln_concrete(I) output = data::transform(input_rgb, f); - for_all_components(i, objects.bboxes()) - mln::draw::box(output, objects.bbox(i), literal::red); + for_all_components(i, components) + if (components(i).is_valid()) + mln::draw::box(output, components(i).bbox(), literal::red); return output; } @@ -158,17 +163,17 @@ namespace mln template <typename I, typename L> mln_concrete(I) compute_text_image(const I& input_rgb, - const object_image<L>& grouped_objects) + const scribo::component_set<L>& grouped_objects) { - const util::array<mln_domain(L)>& bboxes = grouped_objects.bboxes(); - unsigned shift = 5; float height = 1, width = 0; - for_all_components(i, bboxes) - { - height += bboxes(i).nrows() + shift; - width = math::max(static_cast<float>(bboxes(i).ncols()), width); - } + for_all_comps(i, grouped_objects) + if (grouped_objects(i).is_valid()) + { + height += grouped_objects(i).bbox().nrows() + shift; + width = math::max(static_cast<float>(grouped_objects(i).bbox().ncols()), + width); + } if (width == 0) width = 1; @@ -178,21 +183,23 @@ namespace mln algebra::vec<2, float> dv; dv[0] = 0; dv[1] = 0; - for_all_ncomponents(i, grouped_objects.nlabels()) - { - mln_VAR(tmp, duplicate(input_rgb | grouped_objects.bbox(i))); + for_all_comps(i, grouped_objects) + if (grouped_objects(i).is_valid()) + { + mln_VAR(tmp, duplicate(input_rgb | grouped_objects(i).bbox())); - typedef fun::x2x::translation<mln_site_(I)::dim, float> trans_t; - trans_t trans(dv - grouped_objects.bbox(i).pmin().to_vec()); + typedef fun::x2x::translation<mln_site_(I)::dim, float> trans_t; + trans_t trans(dv - grouped_objects(i).bbox().pmin().to_vec()); - mln_domain(I) tr_box(grouped_objects.bbox(i).pmin().to_vec() + trans.t(), - grouped_objects.bbox(i).pmax().to_vec() + trans.t()); + mln_domain(I) + tr_box(grouped_objects(i).bbox().pmin().to_vec() + trans.t(), + grouped_objects(i).bbox().pmax().to_vec() + trans.t()); - tr_image<mln_domain(I), tmp_t, trans_t> tr_ima(tr_box, tmp, trans); + tr_image<mln_domain(I), tmp_t, trans_t> tr_ima(tr_box, tmp, trans); - data::paste(tr_ima, output); - dv[0] += grouped_objects.bbox(i).nrows() + shift; - } + data::paste(tr_ima, output); + dv[0] += grouped_objects(i).bbox().nrows() + shift; + } return output; } @@ -237,7 +244,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", std::cout << "Using lambda = " << lambda << std::endl; image2d<value::int_u8> intensity_ima; - util::timer timer_, global_t_; + mln::util::timer timer_, global_t_; float t_; global_t_.start(); @@ -284,12 +291,12 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", if (argc > 4 && atoi(argv[4]) != 0) { std::cout << "** Using sauvola_ms with w_1 = " << w << std::endl; - input = binarization::sauvola_ms(intensity_ima, w, 3, 67); + input = scribo::binarization::sauvola_ms(intensity_ima, w, 3, 67); } else { std::cout << "** Using sauvola with w_1 = " << w << std::endl; - input = binarization::sauvola(intensity_ima, w); + input = scribo::binarization::sauvola(intensity_ima, w); } #ifndef NOUT if (debug) @@ -310,45 +317,44 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", typedef image2d<value::label_16> L; - /// Finding objects. + /// Finding components. timer_.restart(); - typedef object_image(L) Obj; - Obj filtered_objects; + typedef component_set<L> Obj; + Obj filtered_components; { - util::array<box2d> bboxes; - util::array<point2d> mass_centers; + mln::util::array<std::pair<box2d, std::pair<point2d, unsigned> > > attribs; - value::label_16 nobjects; - L components = extract_components(input, nobjects, bboxes, mass_centers); + value::label_16 ncomponents; + L components = extract_components(input, ncomponents, attribs); - filtered_objects = Obj(components, nobjects, bboxes, mass_centers); + filtered_components = Obj(components, ncomponents, attribs); } t_ = timer_; - std::cout << "Object extracted " << t_ << " - " << filtered_objects.nlabels() << " objects" << std::endl; + std::cout << "Object extracted " << t_ << " - " << filtered_components.nelements() << " components" << std::endl; // if (debug) -// io::pgm::save(data::stretch(value::int_u8(), filtered_objects), "ref_objects.pgm"); +// io::pgm::save(data::stretch(value::int_u8(), filtered_components), "ref_components.pgm"); - /// linking potential objects + /// linking potential components timer_.restart(); - util::couple<object_links<L>, object_links<L> > - links = primitive::link::left_right(filtered_objects); + mln::util::couple<object_links<L>, object_links<L> > + links = primitive::link::left_right(filtered_components); object_links<L>& left_link = links.first(); object_links<L>& right_link = links.second(); // object_links<L> left_link -// = primitive::link::with_single_left_link(filtered_objects, 30); +// = primitive::link::with_single_left_link(filtered_components, 30); // t_ = timer_; // std::cout << "Left Link done " << t_ << std::endl; // timer_.restart(); // object_links<L> right_link -// = primitive::link::with_single_right_link(filtered_objects, 30); +// = primitive::link::with_single_right_link(filtered_components, 30); t_ = timer_; std::cout << "Link done " << t_ << std::endl; @@ -357,9 +363,9 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", #ifndef NOUT if (debug) { - std::cerr << "BEFORE - nobjects = " << filtered_objects.nlabels() << std::endl; + std::cerr << "BEFORE - ncomponents = " << filtered_components.nelements() << std::endl; scribo::debug::save_linked_bboxes_image(input, - filtered_objects, + filtered_components, left_link, right_link, literal::red, literal::cyan, literal::yellow, @@ -373,7 +379,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", // Validating left and right links. timer_.restart(); object_links<L> - merged_links = primitive::link::merge_double_link(filtered_objects, + merged_links = primitive::link::merge_double_link(filtered_components, left_link, right_link); t_ = timer_; @@ -383,7 +389,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", // Remove links if bboxes have too different sizes. timer_.restart(); object_links<L> - hratio_filtered_links = filter::object_links_bbox_h_ratio(filtered_objects, + hratio_filtered_links = filter::object_links_bbox_h_ratio(filtered_components, merged_links, 1.50f); @@ -407,7 +413,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", //Remove links if bboxes overlap too much. object_links<L> overlap_filtered_links - = filter::object_links_bbox_overlap(filtered_objects, + = filter::object_links_bbox_overlap(filtered_components, hratio_filtered_links, 0.80f); @@ -428,39 +434,43 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", t_ = timer_; - std::cout << "Objects links filtered. " << t_ << std::endl; + std::cout << "Components links filtered. " << t_ << std::endl; timer_.restart(); object_groups<L> - groups = primitive::group::from_single_link(filtered_objects, + groups = primitive::group::from_single_link(filtered_components, overlap_filtered_links); // Apply grouping in a temporary image (for debug purpose). #ifndef NOUT - object_image(L) - raw_group_image = primitive::group::apply(filtered_objects, + component_set<L> + raw_group_image = primitive::group::apply(filtered_components, groups); #endif // !NOUT t_ = timer_; - std::cout << "Objects grouped. " << t_ << std::endl; + std::cout << "Components grouped. " << t_ << std::endl; #ifndef NOUT if (debug) { - image2d<value::rgb8> decision_image = data::convert(value::rgb8(), input); + image2d<value::rgb8> + decision_image = data::convert(value::rgb8(), input); - scribo::draw::bounding_boxes(decision_image, filtered_objects, literal::green); - scribo::draw::bounding_boxes(decision_image, raw_group_image, literal::blue); + scribo::draw::bounding_boxes(decision_image, + filtered_components, literal::green); + scribo::draw::bounding_boxes(decision_image, + raw_group_image, literal::blue); io::ppm::save(decision_image, scribo::make::debug_filename("group_and_object_image.ppm")); decision_image = data::convert(value::rgb8(), input); - scribo::draw::bounding_boxes(decision_image, raw_group_image, literal::blue); + scribo::draw::bounding_boxes(decision_image, + raw_group_image, literal::blue); io::ppm::save(decision_image, scribo::make::debug_filename("group_image.ppm")); } @@ -469,10 +479,10 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", std::cout << "Filtering groups..." << std::endl; - util::timer g_timer; + mln::util::timer g_timer; timer_.restart(); - // Remove objects part of groups with strictly less than 3 objects. + // Remove components part of groups with strictly less than 3 components. g_timer.start(); object_groups<L> filtered_small_groups; @@ -489,18 +499,19 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", #ifndef NOUT - object_image(L) debug_image; + component_set<L> debug_image; image2d<value::rgb8> decision_image; if (debug) { decision_image = data::convert(value::rgb8(), input); - object_image(L) - grouped_objects = primitive::group::apply(filtered_objects, + component_set<L> + grouped_objects = primitive::group::apply(filtered_components, filtered_small_groups); - for_all_components(i, filtered_objects.bboxes()) - if (filtered_small_groups(i) != 0) - mln::draw::box(decision_image, filtered_objects.bbox(i), literal::green); + for_all_components(i, filtered_components) + if (filtered_components(i).is_valid() + && filtered_small_groups(i) != 0) + mln::draw::box(decision_image, filtered_components(i).bbox(), literal::green); scribo::draw::bounding_boxes(decision_image, raw_group_image, literal::red); scribo::draw::bounding_boxes(decision_image, grouped_objects, literal::blue); @@ -512,7 +523,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", - // Remove objects part of groups having a mean thickness lower than 8. + // Remove components part of groups having a mean thickness lower than 8. g_timer.restart(); object_groups<L> filtered_thin_groups; if (argc > 7 && atoi(argv[7]) != 0) @@ -532,22 +543,21 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", { decision_image = data::convert(value::rgb8(), input); - object_image(L) - grouped_objects = primitive::group::apply(filtered_objects, - filtered_thin_groups); + component_set<L> + grouped_components = primitive::group::apply(filtered_components, + filtered_thin_groups); - for_all_components(i, filtered_objects.bboxes()) - { - if (filtered_thin_groups(i) != 0) - mln::draw::box(decision_image, filtered_objects.bbox(i), literal::green); - } + for_all_components(i, filtered_components) + if (filtered_components(i).is_valid() + && filtered_thin_groups(i) != 0) + mln::draw::box(decision_image, filtered_components(i).bbox(), literal::green); scribo::draw::bounding_boxes(decision_image, debug_image, literal::red); - scribo::draw::bounding_boxes(decision_image, grouped_objects, literal::blue); + scribo::draw::bounding_boxes(decision_image, grouped_components, literal::blue); io::ppm::save(decision_image, scribo::make::debug_filename("thin_groups_filter.ppm")); - debug_image = grouped_objects; + debug_image = grouped_components; } #endif @@ -556,32 +566,32 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", /// Apply grouping in the object image. g_timer.restart(); -// groups = primitive::group::regroup_left(filtered_objects, +// groups = primitive::group::regroup_left(filtered_components, // filtered_thin_groups, // 30); - object_image(L) - grouped_objects = primitive::group::apply(filtered_objects, - filtered_thin_groups); + component_set<L> + grouped_components = primitive::group::apply(filtered_components, + filtered_thin_groups); t_ = g_timer; std::cout << "Group applied to object image " << t_ << std::endl; - /// Objects have been grouped. We try to link groups together. - /// This time a single link is enough since non-wanted objects have + /// Components have been grouped. We try to link groups together. + /// This time a single link is enough since non-wanted components have /// been removed. g_timer.restart(); - left_link = primitive::link::left(grouped_objects, 30); + left_link = primitive::link::left(grouped_components, 30); // left_link -// = primitive::link::with_single_left_link(grouped_objects, 30); +// = primitive::link::with_single_left_link(grouped_components, 30); /// Grouping groups. - groups = primitive::group::from_single_link(grouped_objects, left_link); + groups = primitive::group::from_single_link(grouped_components, left_link); -// object_image(L) - grouped_objects = primitive::group::apply(grouped_objects, groups); +// component_set<L> + grouped_components = primitive::group::apply(grouped_components, groups); t_ = g_timer; std::cout << "Link and group again " << t_ << std::endl; @@ -590,21 +600,21 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", // if (debug) // io::ppm::save(mln::labeling::colorize(value::rgb8(), -// grouped_objects, -// grouped_objects.nlabels()), +// grouped_components, +// grouped_components.nelements()), // scribo::make::debug_filename("out_raw.ppm")); timer_.resume(); -// io::pgm::save(data::wrap(value::int_u8(), grouped_objects.labeled_image_()), "lbl_to_be_filtered.pgm"); +// io::pgm::save(data::wrap(value::int_u8(), grouped_components.labeled_image_()), "lbl_to_be_filtered.pgm"); g_timer.restart(); /// Filter grouped objects not having enough background components. if (argc > 5 && atoi(argv[5]) != 0) { std::cout << "** Using objects_with_two_holes" << std::endl; - grouped_objects = scribo::filter::objects_with_two_holes(grouped_objects, 5); + grouped_components = scribo::filter::components_with_two_holes(grouped_components, 5); t_ = g_timer; std::cout << "Objects_with_holes " << t_ << std::endl; } @@ -623,36 +633,41 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", decision_image = data::convert(value::rgb8(), input); scribo::draw::bounding_boxes(decision_image, debug_image, literal::red); - scribo::draw::bounding_boxes(decision_image, grouped_objects, literal::blue); + scribo::draw::bounding_boxes(decision_image, grouped_components, literal::blue); io::ppm::save(decision_image, scribo::make::debug_filename("group_with_holes_filter.ppm")); - std::cerr << "AFTER - nobjects = " << grouped_objects.nlabels() << std::endl; + std::cerr << "AFTER - nobjects = " << grouped_components.nelements() << std::endl; } #endif timer_.restart(); std::cout << "Saving result..." << std::endl; io::ppm::save(mln::labeling::colorize(value::rgb8(), - grouped_objects, - grouped_objects.nlabels()), + grouped_components.labeled_image(), + grouped_components.nelements()), argv[2]); #ifndef NOUT -// scribo::debug::save_bboxes_image(input_rgb, grouped_objects.bboxes(), +// scribo::debug::save_bboxes_image(input_rgb, grouped_components.bboxes(), // literal::red, // scribo::make::debug_filename("orig_with_bboxes.ppm")); #endif - io::ppm::save(compute_highlight_image(input_rgb, grouped_objects), + io::ppm::save(compute_highlight_image(input_rgb, grouped_components), out_base_dir + "_input_with_bboxes.ppm"); - io::ppm::save(compute_text_image(input_rgb, grouped_objects), + io::ppm::save(compute_text_image(input_rgb, grouped_components), out_base_dir + "_out_text.ppm"); t_ = timer_; std::cout << "Output saved " << t_ << std::endl; - std::cout << "# objects = " << grouped_objects.nlabels() << std::endl; + std::cout << "# objects = " << grouped_components.nelements() << std::endl; + + + scribo::line_set<L> + lines = scribo::line_set<L>(filtered_components, filtered_thin_groups); + text::recognition(lines, "fra", "out.txt"); trace::exiting("main"); - return grouped_objects.nlabels() != 0; + return grouped_components.nelements() != 0; } diff --git a/scribo/src/text_in_photo_ppm_fast.cc b/scribo/src/text_in_photo_ppm_fast_2.cc similarity index 71% copy from scribo/src/text_in_photo_ppm_fast.cc copy to scribo/src/text_in_photo_ppm_fast_2.cc index 4a7562f..bb24a11 100644 --- a/scribo/src/text_in_photo_ppm_fast.cc +++ b/scribo/src/text_in_photo_ppm_fast_2.cc @@ -207,19 +207,16 @@ int main(int argc, char* argv[]) if (argc < 3 || argc > 10) return scribo::debug::usage(argv, - "Find text in a photo.\n\n\ -Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", - "input.ppm output.ppm <bg/fg enabled> <sauvola_ms enabled> <Bg comp filter enabled> <small group filter enabled> <thin group filter enabled> [debug_output_dir] [lambda]", + "Find text in a photo.", + "input.ppm output.ppm [bg/fg enabled] [sauvola_ms enabled] [Bg comp filter enabled] [small group filter enabled] [thin group filter enabled] [debug_output_dir] [lambda]", args_desc, "A color image where the text is highlighted."); - std::string out_base_dir; bool debug = false; if (argc > 8) { scribo::make::internal::debug_filename_prefix = argv[8]; debug = true; - out_base_dir = argv[8]; } trace::entering("main"); @@ -229,12 +226,11 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", unsigned lambda; - if (argc == 10) + if (argc == 6) lambda = atoi(argv[9]); else lambda = 1.2 * (input_rgb.nrows() + input_rgb.ncols()); - std::cout << "Using lambda = " << lambda << std::endl; image2d<value::int_u8> intensity_ima; util::timer timer_, global_t_; @@ -254,14 +250,6 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", intensity_ima = data::transform(fg, mln::fun::v2v::rgb_to_int_u<8>()); t_ = timer_; std::cout << "Foreground extracted. " << t_ << std::endl; - -#ifndef NOUT - if (debug) - { - io::ppm::save(fg, scribo::make::debug_filename("foreground.ppm")); - } - -#endif // !NOUT } else { @@ -291,14 +279,6 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", std::cout << "** Using sauvola with w_1 = " << w << std::endl; input = binarization::sauvola(intensity_ima, w); } -#ifndef NOUT - if (debug) - { - io::pbm::save(input, - scribo::make::debug_filename("binarization.pbm")); - } - -#endif // !NOUT // if (debug) @@ -354,19 +334,19 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", -#ifndef NOUT - if (debug) - { - std::cerr << "BEFORE - nobjects = " << filtered_objects.nlabels() << std::endl; - scribo::debug::save_linked_bboxes_image(input, - filtered_objects, - left_link, right_link, - literal::red, literal::cyan, - literal::yellow, - literal::green, - scribo::make::debug_filename("links.ppm")); - } -#endif +// #ifndef NOUT +// if (argc > 4) +// { +// std::cerr << "BEFORE - nobjects = " << filtered_objects.nlabels() << std::endl; +// scribo::debug::save_linked_bboxes_image(input, +// filtered_objects, +// left_link, right_link, +// literal::red, literal::cyan, +// literal::yellow, +// literal::green, +// scribo::make::debug_filename("links.ppm")); +// } +// #endif @@ -390,17 +370,17 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", -#ifndef NOUT - if (debug) - { - image2d<value::rgb8> - hratio_decision_image = scribo::debug::decision_image(input, - merged_links, - hratio_filtered_links); - io::ppm::save(hratio_decision_image, - scribo::make::debug_filename("hratio_links_decision_image.ppm")); - } -#endif +// #ifndef NOUT +// if (argc > 4) +// { +// image2d<value::rgb8> +// hratio_decision_image = scribo::debug::decision_image(input, +// merged_links, +// hratio_filtered_links); +// io::ppm::save(hratio_decision_image, +// scribo::make::debug_filename("hratio_links_decision_image.ppm")); +// } +// #endif @@ -414,17 +394,17 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", -#ifndef NOUT - if (debug) - { - image2d<value::rgb8> overlap_decision_image - = scribo::debug::decision_image(input, - hratio_filtered_links, - overlap_filtered_links); - io::ppm::save(overlap_decision_image, - scribo::make::debug_filename("overlap_links_decision_image.ppm")); - } -#endif +// #ifndef NOUT +// if (argc > 4) +// { +// image2d<value::rgb8> overlap_decision_image +// = scribo::debug::decision_image(input, +// hratio_filtered_links, +// overlap_filtered_links); +// io::ppm::save(overlap_decision_image, +// scribo::make::debug_filename("overlap_links_decision_image.ppm")); +// } +// #endif t_ = timer_; @@ -437,39 +417,45 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", -// Apply grouping in a temporary image (for debug purpose). -#ifndef NOUT - object_image(L) - raw_group_image = primitive::group::apply(filtered_objects, - groups); -#endif // !NOUT + /// Apply grouping in a temporary image (for debug purpose). +// #ifndef NOUT +// object_image(L) +// raw_group_image = primitive::group::apply(filtered_objects, +// filter::object_groups_small(groups, 2)); +// #endif // !NOUT t_ = timer_; std::cout << "Objects grouped. " << t_ << std::endl; -#ifndef NOUT - if (debug) - { - image2d<value::rgb8> decision_image = data::convert(value::rgb8(), input); + util::timer g_timer; - scribo::draw::bounding_boxes(decision_image, filtered_objects, literal::green); - scribo::draw::bounding_boxes(decision_image, raw_group_image, literal::blue); + object_image(L) + grouped_objects = primitive::group::apply(filtered_objects, + groups); - io::ppm::save(decision_image, - scribo::make::debug_filename("group_and_object_image.ppm")); + t_ = g_timer; + std::cout << "Group applied to object image " << t_ << std::endl; - decision_image = data::convert(value::rgb8(), input); - scribo::draw::bounding_boxes(decision_image, raw_group_image, literal::blue); - io::ppm::save(decision_image, - scribo::make::debug_filename("group_image.ppm")); - } -#endif // !NOUT + /// Objects have been grouped. We try to link groups together. + /// This time a single link is enough since non-wanted objects have + /// been removed. + g_timer.restart(); + left_link = primitive::link::left(grouped_objects, 30); +// left_link +// = primitive::link::with_single_left_link(grouped_objects, 30); - std::cout << "Filtering groups..." << std::endl; - util::timer g_timer; + /// Grouping groups. + groups = primitive::group::from_single_link(grouped_objects, left_link); + +// object_image(L) + grouped_objects = primitive::group::apply(grouped_objects, groups); + + + + std::cout << "Filtering groups..." << std::endl; timer_.restart(); // Remove objects part of groups with strictly less than 3 objects. @@ -488,30 +474,6 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", -#ifndef NOUT - object_image(L) debug_image; - image2d<value::rgb8> decision_image; - if (debug) - { - decision_image = data::convert(value::rgb8(), input); - object_image(L) - grouped_objects = primitive::group::apply(filtered_objects, - filtered_small_groups); - - for_all_components(i, filtered_objects.bboxes()) - if (filtered_small_groups(i) != 0) - mln::draw::box(decision_image, filtered_objects.bbox(i), literal::green); - scribo::draw::bounding_boxes(decision_image, raw_group_image, literal::red); - scribo::draw::bounding_boxes(decision_image, grouped_objects, literal::blue); - - io::ppm::save(decision_image, - scribo::make::debug_filename("small_groups_filter.ppm")); - debug_image = grouped_objects; - } -#endif - - - // Remove objects part of groups having a mean thickness lower than 8. g_timer.restart(); object_groups<L> filtered_thin_groups; @@ -527,78 +489,15 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", std::cout << "Groups too thin " << t_ << std::endl; -#ifndef NOUT - if (debug) - { - decision_image = data::convert(value::rgb8(), input); - - object_image(L) - grouped_objects = primitive::group::apply(filtered_objects, - filtered_thin_groups); - - for_all_components(i, filtered_objects.bboxes()) - { - if (filtered_thin_groups(i) != 0) - mln::draw::box(decision_image, filtered_objects.bbox(i), literal::green); - } - - scribo::draw::bounding_boxes(decision_image, debug_image, literal::red); - scribo::draw::bounding_boxes(decision_image, grouped_objects, literal::blue); - - io::ppm::save(decision_image, - scribo::make::debug_filename("thin_groups_filter.ppm")); - debug_image = grouped_objects; - } -#endif - - - - /// Apply grouping in the object image. - g_timer.restart(); - -// groups = primitive::group::regroup_left(filtered_objects, -// filtered_thin_groups, -// 30); - - object_image(L) - grouped_objects = primitive::group::apply(filtered_objects, - filtered_thin_groups); - - t_ = g_timer; - std::cout << "Group applied to object image " << t_ << std::endl; - - /// Objects have been grouped. We try to link groups together. - /// This time a single link is enough since non-wanted objects have - /// been removed. - g_timer.restart(); - - left_link = primitive::link::left(grouped_objects, 30); -// left_link -// = primitive::link::with_single_left_link(grouped_objects, 30); - - - /// Grouping groups. - groups = primitive::group::from_single_link(grouped_objects, left_link); - -// object_image(L) - grouped_objects = primitive::group::apply(grouped_objects, groups); t_ = g_timer; std::cout << "Link and group again " << t_ << std::endl; timer_.stop(); -// if (debug) -// io::ppm::save(mln::labeling::colorize(value::rgb8(), -// grouped_objects, -// grouped_objects.nlabels()), -// scribo::make::debug_filename("out_raw.ppm")); - timer_.resume(); -// io::pgm::save(data::wrap(value::int_u8(), grouped_objects.labeled_image_()), "lbl_to_be_filtered.pgm"); - g_timer.restart(); /// Filter grouped objects not having enough background components. if (argc > 5 && atoi(argv[5]) != 0) @@ -609,27 +508,16 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", std::cout << "Objects_with_holes " << t_ << std::endl; } - t_ = timer_; std::cout << "Objects groups filtered. " << t_ << std::endl; +// object_image(L) + grouped_objects = primitive::group::apply(grouped_objects, groups); + t_ = global_t_; std::cout << "*** Result computed " << t_ << std::endl; -#ifndef NOUT - if (debug) - { - decision_image = data::convert(value::rgb8(), input); - - scribo::draw::bounding_boxes(decision_image, debug_image, literal::red); - scribo::draw::bounding_boxes(decision_image, grouped_objects, literal::blue); - io::ppm::save(decision_image, scribo::make::debug_filename("group_with_holes_filter.ppm")); - - std::cerr << "AFTER - nobjects = " << grouped_objects.nlabels() << std::endl; - } -#endif - timer_.restart(); std::cout << "Saving result..." << std::endl; io::ppm::save(mln::labeling::colorize(value::rgb8(), @@ -637,16 +525,11 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1", grouped_objects.nlabels()), argv[2]); -#ifndef NOUT -// scribo::debug::save_bboxes_image(input_rgb, grouped_objects.bboxes(), -// literal::red, -// scribo::make::debug_filename("orig_with_bboxes.ppm")); -#endif io::ppm::save(compute_highlight_image(input_rgb, grouped_objects), - out_base_dir + "_input_with_bboxes.ppm"); + scribo::make::debug_filename("orig_with_bboxes.ppm")); io::ppm::save(compute_text_image(input_rgb, grouped_objects), - out_base_dir + "_out_text.ppm"); + scribo::make::debug_filename("out_text.ppm")); t_ = timer_; std::cout << "Output saved " << t_ << std::endl; -- 1.5.6.5
participants (1)
-
Guillaume Lazzara