* src/preprocessing/Makefile.am, * src/filter/Makefile.am, * src/debug/Makefile.am: Add new targets. * src/debug/show_info_median_inter_characters.cc, * src/debug/show_info_x_height.cc, * src/debug/show_links_single_down.cc, * src/debug/show_links_single_down_left_aligned.cc, * src/debug/show_links_single_down_right_aligned.cc, * src/debug/show_links_single_up.cc, * src/debug/show_links_single_up_left_aligned.cc, * src/debug/show_links_single_up_right_aligned.cc, * src/filter/objects_with_holes.cc, * src/filter/objects_with_holes_pgm.cc, * src/pbm_lines_in_doc.cc, * src/preprocessing/split_bg_fg_ms.cc, * src/text_in_article.cc, * src/text_in_photo_ppm_fast.cc: New tools. * src/debug/show_left_right_links_validation.cc: Rename as... * src/debug/show_links_left_right_links_validation.cc: ...this. * src/debug/show_links_bbox_h_ratio.cc: Add a missing argument. --- scribo/ChangeLog | 28 + scribo/src/debug/Makefile.am | 20 +- .../src/debug/show_info_median_inter_characters.cc | 256 ++++++++ scribo/src/debug/show_info_x_height.cc | 281 +++++++++ .../src/debug/show_left_right_links_validation.cc | 122 ---- scribo/src/debug/show_links_bbox_h_ratio.cc | 2 +- .../show_links_left_right_links_validation.cc | 122 ++++ scribo/src/debug/show_links_single_down.cc | 157 +++++ .../debug/show_links_single_down_left_aligned.cc | 99 +++ .../debug/show_links_single_down_right_aligned.cc | 99 +++ scribo/src/debug/show_links_single_up.cc | 157 +++++ .../src/debug/show_links_single_up_left_aligned.cc | 100 +++ .../debug/show_links_single_up_right_aligned.cc | 98 +++ scribo/src/filter/Makefile.am | 6 +- scribo/src/filter/objects_with_holes.cc | 70 ++ scribo/src/filter/objects_with_holes_pgm.cc | 71 +++ scribo/src/pbm_lines_in_doc.cc | 299 +++++++++ scribo/src/preprocessing/Makefile.am | 2 + scribo/src/preprocessing/split_bg_fg_ms.cc | 109 ++++ scribo/src/text_in_article.cc | 327 ++++++++++ scribo/src/text_in_photo_ppm_fast.cc | 658 ++++++++++++++++++++ 21 files changed, 2957 insertions(+), 126 deletions(-) create mode 100644 scribo/src/debug/show_info_median_inter_characters.cc create mode 100644 scribo/src/debug/show_info_x_height.cc delete mode 100644 scribo/src/debug/show_left_right_links_validation.cc create mode 100644 scribo/src/debug/show_links_left_right_links_validation.cc create mode 100644 scribo/src/debug/show_links_single_down.cc create mode 100644 scribo/src/debug/show_links_single_down_left_aligned.cc create mode 100644 scribo/src/debug/show_links_single_down_right_aligned.cc create mode 100644 scribo/src/debug/show_links_single_up.cc create mode 100644 scribo/src/debug/show_links_single_up_left_aligned.cc create mode 100644 scribo/src/debug/show_links_single_up_right_aligned.cc create mode 100644 scribo/src/filter/objects_with_holes.cc create mode 100644 scribo/src/filter/objects_with_holes_pgm.cc create mode 100644 scribo/src/pbm_lines_in_doc.cc create mode 100644 scribo/src/preprocessing/split_bg_fg_ms.cc create mode 100644 scribo/src/text_in_article.cc create mode 100644 scribo/src/text_in_photo_ppm_fast.cc diff --git a/scribo/ChangeLog b/scribo/ChangeLog index ee8e03c..f7a0e58 100644 --- a/scribo/ChangeLog +++ b/scribo/ChangeLog @@ -1,5 +1,33 @@ 2010-02-19 Guillaume Lazzara <z@lrde.epita.fr> + Add new tools in Scribo. + + * src/preprocessing/Makefile.am, + * src/filter/Makefile.am, + * src/debug/Makefile.am: Add new targets. + + * src/debug/show_info_median_inter_characters.cc, + * src/debug/show_info_x_height.cc, + * src/debug/show_links_single_down.cc, + * src/debug/show_links_single_down_left_aligned.cc, + * src/debug/show_links_single_down_right_aligned.cc, + * src/debug/show_links_single_up.cc, + * src/debug/show_links_single_up_left_aligned.cc, + * src/debug/show_links_single_up_right_aligned.cc, + * src/filter/objects_with_holes.cc, + * src/filter/objects_with_holes_pgm.cc, + * src/pbm_lines_in_doc.cc, + * src/preprocessing/split_bg_fg_ms.cc, + * src/text_in_article.cc, + * src/text_in_photo_ppm_fast.cc: New tools. + + * src/debug/show_left_right_links_validation.cc: Rename as... + * src/debug/show_links_left_right_links_validation.cc: ...this. + + * src/debug/show_links_bbox_h_ratio.cc: Add a missing argument. + +2010-02-19 Guillaume Lazzara <z@lrde.epita.fr> + * scribo/src/text_in_photo_ppm.cc: Improve output. 2010-02-19 Guillaume Lazzara <z@lrde.epita.fr> diff --git a/scribo/src/debug/Makefile.am b/scribo/src/debug/Makefile.am index 28839dc..bb55bfb 100644 --- a/scribo/src/debug/Makefile.am +++ b/scribo/src/debug/Makefile.am @@ -20,7 +20,9 @@ include $(top_srcdir)/scribo/scribo.mk bin_PROGRAMS = \ - show_left_right_links_validation \ + show_info_x_height \ + show_info_median_inter_characters \ + show_links_left_right_links_validation \ show_links_bbox_h_ratio \ show_links_bbox_overlap \ show_links_bottom_aligned \ @@ -28,10 +30,16 @@ bin_PROGRAMS = \ show_links_non_h_aligned \ show_links_several_right \ show_links_several_right_overlap \ + show_links_single_down \ + show_links_single_down_left_aligned \ + show_links_single_down_right_aligned \ show_links_single_left \ show_links_single_left_dmax_ratio \ show_links_single_right \ show_links_single_right_dmax_ratio \ + show_links_single_up \ + show_links_single_up_left_aligned \ + show_links_single_up_right_aligned \ show_links_top_aligned \ show_objects_large \ show_objects_large_small \ @@ -40,7 +48,9 @@ bin_PROGRAMS = \ show_objects_thin -show_left_right_links_validation_SOURCES = show_left_right_links_validation.cc +show_info_x_height_SOURCES = show_info_x_height.cc +show_info_median_inter_characters_SOURCES = show_info_median_inter_characters.cc +show_links_left_right_links_validation_SOURCES = show_links_left_right_links_validation.cc show_links_bbox_h_ratio_SOURCES = show_links_bbox_h_ratio.cc show_links_bbox_overlap_SOURCES = show_links_bbox_overlap.cc show_links_bottom_aligned_SOURCES = show_links_bottom_aligned.cc @@ -48,10 +58,16 @@ show_links_center_aligned_SOURCES = show_links_center_aligned.cc show_links_non_h_aligned_SOURCES = show_links_non_h_aligned.cc show_links_several_right_SOURCES = show_links_several_right.cc show_links_several_right_overlap_SOURCES = show_links_several_right_overlap.cc +show_links_single_down_SOURCES = show_links_single_down.cc +show_links_single_down_left_aligned_SOURCES = show_links_single_down_left_aligned.cc +show_links_single_down_right_aligned_SOURCES = show_links_single_down_right_aligned.cc show_links_single_left_SOURCES = show_links_single_left.cc show_links_single_left_dmax_ratio_SOURCES = show_links_single_left_dmax_ratio.cc show_links_single_right_SOURCES = show_links_single_right.cc show_links_single_right_dmax_ratio_SOURCES = show_links_single_right_dmax_ratio.cc +show_links_single_up_SOURCES = show_links_single_up.cc +show_links_single_up_left_aligned_SOURCES = show_links_single_up_left_aligned.cc +show_links_single_up_right_aligned_SOURCES = show_links_single_up_right_aligned.cc show_links_top_aligned_SOURCES = show_links_top_aligned.cc show_objects_large_SOURCES = show_objects_large.cc show_objects_large_small_SOURCES = show_objects_large_small.cc diff --git a/scribo/src/debug/show_info_median_inter_characters.cc b/scribo/src/debug/show_info_median_inter_characters.cc new file mode 100644 index 0000000..e28ad96 --- /dev/null +++ b/scribo/src/debug/show_info_median_inter_characters.cc @@ -0,0 +1,256 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + + +#include <libgen.h> +#include <iostream> + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/io/pbm/all.hh> +#include <mln/io/ppm/save.hh> + +#include <mln/math/min.hh> + +#include <mln/literal/colors.hh> +#include <mln/value/rgb8.hh> +#include <mln/value/label_16.hh> +#include <mln/value/int_u16.hh> + +#include <mln/draw/box.hh> +#include <mln/draw/line.hh> + +#include <mln/extension/adjust.hh> + +#include <mln/accu/stat/median_h.hh> + +#include <scribo/draw/bounding_boxes.hh> + +#include <scribo/primitive/extract/objects.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_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/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/debug/usage.hh> + +#include <scribo/make/debug_filename.hh> + + +const char *args_desc[][2] = +{ + { "input.pbm", "A binary image. 'False' for objects, 'True'\ +for the background." }, + { "debug_dir", "Output directory for debug image" }, + {0, 0} +}; + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace mln; + + if (argc != 3 && argc != 4) + return scribo::debug::usage(argv, + "Find text lines using left/right validation and display x-height in a binarized article.", + "input.pbm out.ppm <debug_dir>", + args_desc, + "A color image. The following colors are used : dark blue for object bboxes, orange for single object bboxes, purple for group bboxes and light blue for x-height."); + + if (argc == 4) + scribo::make::internal::debug_filename_prefix = argv[3]; + + trace::entering("main"); + + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + typedef image2d<value::label_16> L; + + /// Finding objects. + std::cout << "Finding objects..." << std::endl; + value::label_16 nobjects; + object_image(L) + objects = scribo::primitive::extract::objects(input, + c8(), + nobjects); + + + /// First filtering. + std::cout << "Filtering objects..." << std::endl; + object_image(L) filtered_objects + = scribo::filter::objects_small(objects, 6); + + /// Linking potential objects + std::cout << "Linking objects..." << std::endl; + object_links<L> left_link + = primitive::link::with_single_left_link_dmax_ratio(filtered_objects); + object_links<L> right_link + = primitive::link::with_single_right_link_dmax_ratio(filtered_objects); + + + // Validating left and right links. + object_links<L> + merged_links = primitive::link::merge_double_link(filtered_objects, + 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 + + + // Remove links if bboxes have too different sizes. + object_links<L> hratio_filtered_links + = filter::object_links_bbox_h_ratio(filtered_objects, + merged_links, + 2.0f); + + + + +#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? + // + //###### + object_groups<L> + groups = primitive::group::from_single_link(filtered_objects, + 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); + //###### + + + std::cout << "Grouping objects..." << std::endl; + object_image(L) + grouped_objects = primitive::group::apply(filtered_objects, groups); + + + + // 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); + + } + } + + 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, argv[2]); + + } + + trace::exiting("main"); +} diff --git a/scribo/src/debug/show_info_x_height.cc b/scribo/src/debug/show_info_x_height.cc new file mode 100644 index 0000000..e0c84a6 --- /dev/null +++ b/scribo/src/debug/show_info_x_height.cc @@ -0,0 +1,281 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + + +#include <libgen.h> +#include <iostream> + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/io/pbm/all.hh> +#include <mln/io/ppm/save.hh> + +#include <mln/math/min.hh> + +#include <mln/literal/colors.hh> +#include <mln/value/rgb8.hh> +#include <mln/value/label_16.hh> +#include <mln/value/int_u16.hh> + +#include <mln/draw/box.hh> +#include <mln/draw/line.hh> + +#include <mln/extension/adjust.hh> + +#include <mln/accu/stat/median_h.hh> + +#include <scribo/draw/bounding_boxes.hh> + +#include <scribo/primitive/extract/objects.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_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/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/debug/usage.hh> + +#include <scribo/make/debug_filename.hh> + + +const char *args_desc[][2] = +{ + { "input.pbm", "A binary image. 'False' for objects, 'True'\ +for the background." }, + { "debug_dir", "Output directory for debug image" }, + {0, 0} +}; + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace mln; + + if (argc != 3 && argc != 4) + return scribo::debug::usage(argv, + "Find text lines using left/right validation and display x-height in a binarized article.", + "input.pbm out.ppm <debug_dir>", + args_desc, + "A color image. The following colors are used : dark blue for object bboxes, orange for single object bboxes, purple for group bboxes and light blue for x-height."); + + if (argc == 4) + scribo::make::internal::debug_filename_prefix = argv[3]; + + trace::entering("main"); + + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + typedef image2d<value::label_16> L; + + /// Finding objects. + std::cout << "Finding objects..." << std::endl; + value::label_16 nobjects; + object_image(L) + objects = scribo::primitive::extract::objects(input, + c8(), + nobjects); + + + /// First filtering. + std::cout << "Filtering objects..." << std::endl; + object_image(L) filtered_objects + = scribo::filter::objects_small(objects, 6); + + /// Linking potential objects + std::cout << "Linking objects..." << std::endl; + object_links<L> left_link + = primitive::link::with_single_left_link_dmax_ratio(filtered_objects); + object_links<L> right_link + = primitive::link::with_single_right_link_dmax_ratio(filtered_objects); + + + // Validating left and right links. + object_links<L> + merged_links = primitive::link::merge_double_link(filtered_objects, + left_link, + right_link); + +#ifndef NOUT + if (argc == 4) + { + image2d<value::rgb8> output = data::convert(value::rgb8(), input); + scribo::draw::bounding_box_links(output, + filtered_objects.bboxes(), + 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 + + + // Remove links if bboxes have too different sizes. + object_links<L> hratio_filtered_links + = filter::object_links_bbox_h_ratio(filtered_objects, + merged_links, + 2.0f); + + + + +#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? + // + //###### + object_groups<L> + groups = primitive::group::from_single_link(filtered_objects, + 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); + //###### + + + std::cout << "Grouping objects..." << std::endl; + object_image(L) + grouped_objects = primitive::group::apply(filtered_objects, groups); + + + + // Compute min_row/max_row median + std::cout << "Preparing output" << std::endl; + { + 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); + +// 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()); + + med_max_row(groups_packed(i)).take(grouped_objects.bbox(groups_packed(i)).pmax().row() - filtered_objects.bbox(i).pmax().row()); + } + } + + // 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)) + { + mln::draw::box(output, filtered_objects.bbox(i), literal::orange); + drawn[i] = true; + single(groups_packed(i)) = true; + } + else + { + 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; + } + +// std::cout << "Drawing median lines" << std::endl; + for_all_components(i, grouped_objects.bboxes()) + { + if (! single(i)) + { + 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); + } + } + + io::ppm::save(output, argv[2]); + } + + trace::exiting("main"); +} diff --git a/scribo/src/debug/show_left_right_links_validation.cc b/scribo/src/debug/show_left_right_links_validation.cc deleted file mode 100644 index bb23dd5..0000000 --- a/scribo/src/debug/show_left_right_links_validation.cc +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) -// -// This file is part of Olena. -// -// Olena is free software: you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation, version 2 of the License. -// -// Olena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Olena. If not, see <http://www.gnu.org/licenses/>. -// -// As a special exception, you may use this file as part of a free -// software project without restriction. Specifically, if other files -// instantiate templates or use macros or inline functions from this -// file, or you compile this file and link it with other files to produce -// an executable, this file does not by itself cause the resulting -// executable to be covered by the GNU General Public License. This -// exception does not however invalidate any other reasons why the -// executable file might be covered by the GNU General Public License. - -#include <iostream> - -#include <mln/core/image/image2d.hh> -#include <mln/labeling/colorize.hh> -#include <mln/debug/println.hh> -#include <mln/data/convert.hh> -#include <mln/util/array.hh> -#include <mln/literal/colors.hh> -#include <mln/io/pbm/load.hh> -#include <mln/io/ppm/save.hh> -#include <mln/core/alias/neighb2d.hh> -#include <mln/value/label_16.hh> - -#include <scribo/core/object_links.hh> -#include <scribo/core/object_image.hh> - -#include <scribo/primitive/extract/objects.hh> - -#include <scribo/primitive/link/with_single_left_link.hh> -#include <scribo/primitive/link/with_single_right_link.hh> -#include <scribo/primitive/link/merge_double_link.hh> - -#include <scribo/draw/bounding_boxes.hh> -#include <scribo/draw/bounding_box_links.hh> - -#include <scribo/debug/usage.hh> - - - -const char *args_desc[][2] = -{ - { "input.pbm", "A binary image. 'True' for objects, 'False'\ -for the background." }, - { "hlmax", "Maximum distance between two grouped objects while browsing on the left." }, - { "hrmax", "Maximum distance between two grouped objects while browsing on the right." }, - {0, 0} -}; - -int main(int argc, char *argv[]) -{ - using namespace scribo; - using namespace mln; - - if (argc != 5) - return scribo::debug::usage(argv, - "Display double validated (left and right) links between objects", - "<input.pbm> <hlmax> <hrmax> <output.ppm>", - args_desc, - "A color image. Validated links are drawn in green."); - - image2d<bool> input; - io::pbm::load(input, argv[1]); - - // Finding objects. - value::label_16 nbboxes; - typedef image2d<value::label_16> L; - object_image(L) objects = primitive::extract::objects(input, c8(), nbboxes); - - // Left links. - object_links<L> left_link - = primitive::link::with_single_left_link(objects, atoi(argv[2])); - - // Right links. - object_links<L> right_link - = primitive::link::with_single_right_link(objects, atoi(argv[3])); - - // Validation. - object_links<L> - links = primitive::link::merge_double_link(objects, left_link, right_link); - - - // Saving result. - image2d<value::rgb8> output = data::convert(value::rgb8(), input); - -// scribo::draw::bounding_boxes(output, objects, literal::blue); - scribo::draw::bounding_box_links(output, - objects.bboxes(), - links, - literal::green); - - util::array<bool> drawn(objects.nlabels(), 0); - for_all_components(i, objects.bboxes()) - if (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(links[i]), literal::blue); - drawn[i] = true; - drawn[links[i]] = true; - } - - io::ppm::save(output, argv[4]); -} diff --git a/scribo/src/debug/show_links_bbox_h_ratio.cc b/scribo/src/debug/show_links_bbox_h_ratio.cc index 86841c6..4377b41 100644 --- a/scribo/src/debug/show_links_bbox_h_ratio.cc +++ b/scribo/src/debug/show_links_bbox_h_ratio.cc @@ -92,7 +92,7 @@ int main(int argc, char* argv[]) image2d<value::rgb8> hratio_decision_image = scribo::debug::links_decision_image(input, right_links, - hratio_filtered_links); + hratio_filtered_links, 200); io::ppm::save(hratio_decision_image, argv[3]); } diff --git a/scribo/src/debug/show_links_left_right_links_validation.cc b/scribo/src/debug/show_links_left_right_links_validation.cc new file mode 100644 index 0000000..3c5d1bf --- /dev/null +++ b/scribo/src/debug/show_links_left_right_links_validation.cc @@ -0,0 +1,122 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#include <iostream> + +#include <mln/core/image/image2d.hh> +#include <mln/labeling/colorize.hh> +#include <mln/debug/println.hh> +#include <mln/data/convert.hh> +#include <mln/util/array.hh> +#include <mln/literal/colors.hh> +#include <mln/io/pbm/load.hh> +#include <mln/io/ppm/save.hh> +#include <mln/core/alias/neighb2d.hh> +#include <mln/value/label_16.hh> + +#include <scribo/core/object_links.hh> +#include <scribo/core/object_image.hh> + +#include <scribo/primitive/extract/objects.hh> + +#include <scribo/primitive/link/with_single_left_link.hh> +#include <scribo/primitive/link/with_single_right_link.hh> +#include <scribo/primitive/link/merge_double_link.hh> + +#include <scribo/draw/bounding_boxes.hh> +#include <scribo/draw/bounding_box_links.hh> + +#include <scribo/debug/usage.hh> + + + +const char *args_desc[][2] = +{ + { "input.pbm", "A binary image. 'True' for objects, 'False'\ +for the background." }, + { "hlmax", "Maximum distance between two grouped objects while browsing on the left." }, + { "hrmax", "Maximum distance between two grouped objects while browsing on the right." }, + {0, 0} +}; + +int main(int argc, char *argv[]) +{ + using namespace scribo; + using namespace mln; + + if (argc != 5) + return scribo::debug::usage(argv, + "Display double validated (left and right) links between objects", + "<input.pbm> <hlmax> <hrmax> <output.ppm>", + args_desc, + "A color image. Validated links are drawn in green."); + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + // Finding objects. + value::label_16 nbboxes; + typedef image2d<value::label_16> L; + object_image(L) objects = primitive::extract::objects(input, c8(), nbboxes); + + // Left links. + object_links<L> left_link + = primitive::link::with_single_left_link(objects, atoi(argv[2])); + + // Right links. + object_links<L> right_link + = primitive::link::with_single_right_link(objects, atoi(argv[3])); + + // Validation. + object_links<L> + links = primitive::link::merge_double_link(objects, left_link, right_link); + + + // Saving result. + image2d<value::rgb8> output = data::convert(value::rgb8(), input); + +// scribo::draw::bounding_boxes(output, objects, literal::blue); + scribo::draw::bounding_box_links(output, + objects.bboxes(), + links, + literal::green); + + util::array<bool> drawn(static_cast<unsigned>(objects.nlabels()) + 1, 0); + for_all_components(i, objects.bboxes()) + if (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(links[i]), literal::blue); + drawn[i] = true; + drawn[links[i]] = true; + } + + io::ppm::save(output, argv[4]); +} diff --git a/scribo/src/debug/show_links_single_down.cc b/scribo/src/debug/show_links_single_down.cc new file mode 100644 index 0000000..37325d2 --- /dev/null +++ b/scribo/src/debug/show_links_single_down.cc @@ -0,0 +1,157 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#include <iostream> + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/data/convert.hh> + +#include <mln/value/rgb8.hh> +#include <mln/value/label_16.hh> +#include <mln/literal/colors.hh> + +#include <mln/io/pbm/load.hh> +#include <mln/io/ppm/save.hh> + +#include <mln/draw/line.hh> + +#include <scribo/primitive/extract/objects.hh> +#include <scribo/primitive/link/internal/link_ms_dmax_base.hh> +#include <scribo/primitive/link/compute.hh> + +#include <scribo/draw/bounding_boxes.hh> + +#include <scribo/debug/save_linked_bboxes_image.hh> +#include <scribo/debug/usage.hh> + + +namespace scribo +{ + + template <typename I, typename L> + struct single_down_link_debug_functor + : primitive::link::internal::link_ms_dmax_base<L, + single_down_link_debug_functor<I, L> > + { + typedef single_down_link_debug_functor<I, L> self_t; + typedef + primitive::link::internal::link_ms_dmax_base<L, self_t> super_; + + public: + typedef mln_site(L) P; + + single_down_link_debug_functor(const I& input, + const object_image(L)& objects, + float dmax) + : super_(objects, dmax, 0) + { + output_ = data::convert(value::rgb8(), input); + scribo::draw::bounding_boxes(output_, objects, literal::blue); + mln_postcondition(output_.is_valid()); + } + + void validate_link_(unsigned current_object, + const P& start_point, + const P& p, + anchor::Type anchor) + { + mln::draw::line(output_, start_point, p, literal::green); + + super_::validate_link_(current_object, start_point, p, anchor); + } + + + + void invalidate_link_(unsigned current_object, + const P& start_point, + const P& p, + anchor::Type anchor) + { + if (output_.domain().has(p)) + mln::draw::line(output_, start_point, p, literal::red); + else + { + P tmp = p; + --tmp.row(); + mln::draw::line(output_, start_point, tmp, literal::red); + } + + super_::invalidate_link_(current_object, start_point, p, anchor); + } + + + + void compute_next_site_(P& p) + { + ++p.row(); + } + + + image2d<value::rgb8> output_; + }; + + +} + + +const char *args_desc[][2] = +{ + { "input.pbm", "A binary image. True for objects and False for the background." }, + { "max_nbh_dist", "The maximum lookup distance. (common value : 30)" }, + {0, 0} +}; + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace scribo::primitive::internal; + using namespace mln; + + if (argc != 4) + return scribo::debug::usage(argv, + "Show sucessful/unsuccessful down links between components.", + "input.pbm max_nbh_dist output.ppm", + args_desc, + "A color image. Valid links are drawn in green, invalid ones in red."); + + typedef image2d<bool> I; + I input; + io::pbm::load(input, argv[1]); + + // Finding objects. + value::label_16 nbboxes; + typedef image2d<value::label_16> L; + object_image(L) objects + = scribo::primitive::extract::objects(input, c8(), nbboxes); + + // Write debug image. + single_down_link_debug_functor<I, L> functor(input, objects, atof(argv[2])); + primitive::link::compute(functor); + + io::ppm::save(functor.output_, argv[3]); +} diff --git a/scribo/src/debug/show_links_single_down_left_aligned.cc b/scribo/src/debug/show_links_single_down_left_aligned.cc new file mode 100644 index 0000000..b094d6e --- /dev/null +++ b/scribo/src/debug/show_links_single_down_left_aligned.cc @@ -0,0 +1,99 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#include <iostream> + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/data/convert.hh> + +#include <mln/value/rgb8.hh> +#include <mln/value/label_16.hh> +#include <mln/literal/colors.hh> + +#include <mln/io/pbm/load.hh> +#include <mln/io/ppm/save.hh> + +#include <mln/math/pi.hh> + +#include <mln/draw/line.hh> + +#include <scribo/primitive/extract/objects.hh> +#include <scribo/primitive/link/with_single_down_link.hh> +#include <scribo/primitive/link/compute.hh> +#include <scribo/filter/object_links_left_aligned.hh> + +#include <scribo/draw/bounding_boxes.hh> + +#include <scribo/debug/save_linked_bboxes_image.hh> +#include <scribo/debug/usage.hh> + + +const char *args_desc[][2] = +{ + { "input.pbm", "A binary image. True for objects and False for the background." }, + { "dmax", "The maximum lookup distance. (common value : 300)" }, + {0, 0} +}; + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace scribo::primitive::internal; + using namespace mln; + + if (argc != 4) + return scribo::debug::usage(argv, + "Show sucessful/unsuccessful down links between components.", + "input.pbm dmax output.ppm", + args_desc, + "A color image. Valid links are drawn in green, invalid ones in red."); + + typedef image2d<bool> I; + I input; + io::pbm::load(input, argv[1]); + + // Finding objects. + value::label_16 nbboxes; + typedef image2d<value::label_16> L; + object_image(L) objects + = scribo::primitive::extract::objects(input, c8(), nbboxes); + + + object_links<L> + down_links = primitive::link::with_single_down_link(objects, + atof(argv[2]), + anchor::Left); + + // Filtering. + down_links = filter::object_links_left_aligned(objects, down_links, 5); + + + scribo::debug::save_linked_bboxes_image(input, objects, down_links, + literal::blue, literal::green, + argv[3], anchor::ActualLeft); +} diff --git a/scribo/src/debug/show_links_single_down_right_aligned.cc b/scribo/src/debug/show_links_single_down_right_aligned.cc new file mode 100644 index 0000000..9a12c0d --- /dev/null +++ b/scribo/src/debug/show_links_single_down_right_aligned.cc @@ -0,0 +1,99 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#include <iostream> + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/data/convert.hh> + +#include <mln/value/rgb8.hh> +#include <mln/value/label_16.hh> +#include <mln/literal/colors.hh> + +#include <mln/io/pbm/load.hh> +#include <mln/io/ppm/save.hh> + +#include <mln/math/pi.hh> + +#include <mln/draw/line.hh> + +#include <scribo/primitive/extract/objects.hh> +#include <scribo/primitive/link/with_single_down_link.hh> +#include <scribo/primitive/link/compute.hh> +#include <scribo/filter/object_links_right_aligned.hh> + +#include <scribo/draw/bounding_boxes.hh> + +#include <scribo/debug/save_linked_bboxes_image.hh> +#include <scribo/debug/usage.hh> + + +const char *args_desc[][2] = +{ + { "input.pbm", "A binary image. True for objects and False for the background." }, + { "dmax", "The maximum lookup distance. (common value : 300)" }, + {0, 0} +}; + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace scribo::primitive::internal; + using namespace mln; + + if (argc != 4) + return scribo::debug::usage(argv, + "Show sucessful/unsuccessful down links between components.", + "input.pbm dmax output.ppm", + args_desc, + "A color image. Valid links are drawn in green, invalid ones in red."); + + typedef image2d<bool> I; + I input; + io::pbm::load(input, argv[1]); + + // Finding objects. + value::label_16 nbboxes; + typedef image2d<value::label_16> L; + object_image(L) objects + = scribo::primitive::extract::objects(input, c8(), nbboxes); + + + object_links<L> + down_links = primitive::link::with_single_down_link(objects, + atof(argv[2]), + anchor::Right); + + // Filtering. + down_links = filter::object_links_right_aligned(objects, down_links, 5); + + + scribo::debug::save_linked_bboxes_image(input, objects, down_links, + literal::blue, literal::green, + argv[3], anchor::ActualRight); +} diff --git a/scribo/src/debug/show_links_single_up.cc b/scribo/src/debug/show_links_single_up.cc new file mode 100644 index 0000000..59c8ce5 --- /dev/null +++ b/scribo/src/debug/show_links_single_up.cc @@ -0,0 +1,157 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#include <iostream> + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/data/convert.hh> + +#include <mln/value/rgb8.hh> +#include <mln/value/label_16.hh> +#include <mln/literal/colors.hh> + +#include <mln/io/pbm/load.hh> +#include <mln/io/ppm/save.hh> + +#include <mln/draw/line.hh> + +#include <scribo/primitive/extract/objects.hh> +#include <scribo/primitive/link/internal/link_ms_dmax_base.hh> +#include <scribo/primitive/link/compute.hh> + +#include <scribo/draw/bounding_boxes.hh> + +#include <scribo/debug/save_linked_bboxes_image.hh> +#include <scribo/debug/usage.hh> + + +namespace scribo +{ + + template <typename I, typename L> + struct single_up_link_debug_functor + : primitive::link::internal::link_ms_dmax_base<L, + single_up_link_debug_functor<I, L> > + { + typedef single_up_link_debug_functor<I, L> self_t; + typedef + primitive::link::internal::link_ms_dmax_base<L, self_t> super_; + + public: + typedef mln_site(L) P; + + single_up_link_debug_functor(const I& input, + const object_image(L)& objects, + float dmax) + : super_(objects, dmax) + { + output_ = data::convert(value::rgb8(), input); + scribo::draw::bounding_boxes(output_, objects, literal::blue); + mln_postcondition(output_.is_valid()); + } + + void validate_link_(unsigned current_object, + const P& start_point, + const P& p, + anchor::Type anchor) + { + mln::draw::line(output_, start_point, p, literal::green); + + super_::validate_link_(current_object, start_point, p, anchor); + } + + + + void invalidate_link_(unsigned current_object, + const P& start_point, + const P& p, + anchor::Type anchor) + { + if (output_.domain().has(p)) + mln::draw::line(output_, start_point, p, literal::red); + else + { + P tmp = p; + ++tmp.row(); + mln::draw::line(output_, start_point, tmp, literal::red); + } + + super_::invalidate_link_(current_object, start_point, p, anchor); + } + + + + void compute_next_site_(P& p) + { + --p.row(); + } + + + image2d<value::rgb8> output_; + }; + + +} + + +const char *args_desc[][2] = +{ + { "input.pbm", "A binary image. True for objects and False for the background." }, + { "max_nbh_dist", "The maximum lookup distance. (common value : 30)" }, + {0, 0} +}; + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace scribo::primitive::internal; + using namespace mln; + + if (argc != 4) + return scribo::debug::usage(argv, + "Show sucessful/unsuccessful up links between components.", + "input.pbm max_nbh_dist output.ppm", + args_desc, + "A color image. Valid links are drawn in green, invalid ones in red."); + + typedef image2d<bool> I; + I input; + io::pbm::load(input, argv[1]); + + // Finding objects. + value::label_16 nbboxes; + typedef image2d<value::label_16> L; + object_image(L) objects + = scribo::primitive::extract::objects(input, c8(), nbboxes); + + // Write debug image. + single_up_link_debug_functor<I, L> functor(input, objects, atof(argv[2])); + primitive::link::compute(functor); + + io::ppm::save(functor.output_, argv[3]); +} diff --git a/scribo/src/debug/show_links_single_up_left_aligned.cc b/scribo/src/debug/show_links_single_up_left_aligned.cc new file mode 100644 index 0000000..5239619 --- /dev/null +++ b/scribo/src/debug/show_links_single_up_left_aligned.cc @@ -0,0 +1,100 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#include <iostream> + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/data/convert.hh> + +#include <mln/value/rgb8.hh> +#include <mln/value/label_16.hh> +#include <mln/literal/colors.hh> + +#include <mln/io/pbm/load.hh> +#include <mln/io/ppm/save.hh> + +#include <mln/math/pi.hh> + +#include <mln/draw/line.hh> + +#include <scribo/primitive/extract/objects.hh> +#include <scribo/primitive/link/with_single_up_link.hh> +#include <scribo/primitive/link/compute.hh> +#include <scribo/filter/object_links_left_aligned.hh> + +#include <scribo/draw/bounding_boxes.hh> + +#include <scribo/debug/save_linked_bboxes_image.hh> +#include <scribo/debug/usage.hh> + + +const char *args_desc[][2] = +{ + { "input.pbm", "A binary image. True for objects and False for the background." }, + { "dmax", "The maximum lookup distance. (common value : 300)" }, + {0, 0} +}; + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace scribo::primitive::internal; + using namespace mln; + + if (argc != 4) + return scribo::debug::usage(argv, + "Show sucessful/unsuccessful up links between components.", + "input.pbm dmax output.ppm", + args_desc, + "A color image. Valid links are drawn in green, invalid ones in red."); + + typedef image2d<bool> I; + I input; + io::pbm::load(input, argv[1]); + + // Finding objects. + value::label_16 nbboxes; + typedef image2d<value::label_16> L; + object_image(L) objects + = scribo::primitive::extract::objects(input, c8(), nbboxes); + + + object_links<L> + up_links = primitive::link::with_single_up_link(objects, + atof(argv[2]), + anchor::Left); + + + // Filtering. + up_links = filter::object_links_left_aligned(objects, up_links, 5); + + + scribo::debug::save_linked_bboxes_image(input, objects, up_links, + literal::blue, literal::green, + argv[3], anchor::ActualLeft); +} diff --git a/scribo/src/debug/show_links_single_up_right_aligned.cc b/scribo/src/debug/show_links_single_up_right_aligned.cc new file mode 100644 index 0000000..8c1841e --- /dev/null +++ b/scribo/src/debug/show_links_single_up_right_aligned.cc @@ -0,0 +1,98 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#include <iostream> + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/data/convert.hh> + +#include <mln/value/rgb8.hh> +#include <mln/value/label_16.hh> +#include <mln/literal/colors.hh> + +#include <mln/io/pbm/load.hh> +#include <mln/io/ppm/save.hh> + +#include <mln/math/pi.hh> + +#include <mln/draw/line.hh> + +#include <scribo/primitive/extract/objects.hh> +#include <scribo/primitive/link/with_single_up_link.hh> +#include <scribo/primitive/link/compute.hh> +#include <scribo/filter/object_links_right_aligned.hh> + +#include <scribo/draw/bounding_boxes.hh> + +#include <scribo/debug/save_linked_bboxes_image.hh> +#include <scribo/debug/usage.hh> + + +const char *args_desc[][2] = +{ + { "input.pbm", "A binary image. True for objects and False for the background." }, + { "dmax", "The maximum lookup distance. (common value : 300)" }, + {0, 0} +}; + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace scribo::primitive::internal; + using namespace mln; + + if (argc != 4) + return scribo::debug::usage(argv, + "Show sucessful/unsuccessful up links between components.", + "input.pbm dmax output.ppm", + args_desc, + "A color image. Valid links are drawn in green, invalid ones in red."); + + typedef image2d<bool> I; + I input; + io::pbm::load(input, argv[1]); + + // Finding objects. + value::label_16 nbboxes; + typedef image2d<value::label_16> L; + object_image(L) objects + = scribo::primitive::extract::objects(input, c8(), nbboxes); + + object_links<L> + up_links = primitive::link::with_single_up_link(objects, + atof(argv[2]), + anchor::Right); + + // Filtering. + up_links = filter::object_links_right_aligned(objects, up_links, 5); + + + scribo::debug::save_linked_bboxes_image(input, objects, up_links, + literal::blue, literal::green, + argv[3], anchor::ActualRight); +} diff --git a/scribo/src/filter/Makefile.am b/scribo/src/filter/Makefile.am index e8a2b9c..98f8371 100644 --- a/scribo/src/filter/Makefile.am +++ b/scribo/src/filter/Makefile.am @@ -23,9 +23,13 @@ bin_PROGRAMS = \ objects_large \ objects_small \ objects_thick \ - objects_thin + objects_thin \ + objects_with_holes \ + objects_with_holes_pgm objects_large_SOURCES = objects_large.cc objects_small_SOURCES = objects_small.cc objects_thick_SOURCES = objects_thick.cc objects_thin_SOURCES = objects_thin.cc +objects_with_holes_SOURCES = objects_with_holes.cc +objects_with_holes_pgm_SOURCES = objects_with_holes_pgm.cc diff --git a/scribo/src/filter/objects_with_holes.cc b/scribo/src/filter/objects_with_holes.cc new file mode 100644 index 0000000..0ebf89f --- /dev/null +++ b/scribo/src/filter/objects_with_holes.cc @@ -0,0 +1,70 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> +#include <mln/data/convert.hh> +#include <mln/io/pbm/all.hh> +#include <mln/value/label_16.hh> + +#include <scribo/filter/objects_with_holes.hh> +#include <scribo/debug/usage.hh> + +const char *args_desc[][2] = +{ + { "input.pbm", "A binary image. 'True' for objects, 'False'\ +for the background." }, + { "min_holes_count", "The minimum holes per objects." }, + {0, 0} +}; + +int main(int argc, char *argv[]) +{ + using namespace mln; + + if (argc != 4) + return scribo::debug::usage(argv, + "Filter objects with holes", + "input.pbm min_holes_count output.pbm", + args_desc, + "A binary image."); + + trace::entering("main"); + + typedef image2d<bool> I; + 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); + + obj_ima_t filtered = scribo::filter::objects_with_holes(objects, atoi(argv[2])); + io::pbm::save(data::convert(bool(), filtered), argv[3]); + + trace::exiting("main"); + +} diff --git a/scribo/src/filter/objects_with_holes_pgm.cc b/scribo/src/filter/objects_with_holes_pgm.cc new file mode 100644 index 0000000..c834538 --- /dev/null +++ b/scribo/src/filter/objects_with_holes_pgm.cc @@ -0,0 +1,71 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> +#include <mln/data/convert.hh> +#include <mln/data/compute.hh> +#include <mln/io/pbm/save.hh> +#include <mln/io/pgm/load.hh> +#include <mln/value/label_8.hh> +#include <mln/accu/stat/max.hh> + +#include <scribo/filter/objects_with_holes.hh> +#include <scribo/debug/usage.hh> + +const char *args_desc[][2] = +{ + { "input.pgm", "A label image. 'True' for objects, 'False'\ +for the background." }, + { "min_holes_count", "The minimum holes per objects." }, + {0, 0} +}; + +int main(int argc, char *argv[]) +{ + using namespace mln; + + if (argc != 4) + return scribo::debug::usage(argv, + "Filter objects with holes", + "input.pgm min_holes_count output.pbm", + args_desc, + "A binary image."); + + trace::entering("main"); + + typedef image2d<value::label_8> I; + I input; + io::pgm::load(input, argv[1]); + + value::label_8 nobjects = data::compute(accu::meta::stat::max(), input); + object_image(I) objects(input, nobjects); + + object_image(I) filtered = scribo::filter::objects_with_holes(objects, atoi(argv[2])); + io::pbm::save(data::convert(bool(), filtered), argv[3]); + + trace::exiting("main"); + +} diff --git a/scribo/src/pbm_lines_in_doc.cc b/scribo/src/pbm_lines_in_doc.cc new file mode 100644 index 0000000..8363b61 --- /dev/null +++ b/scribo/src/pbm_lines_in_doc.cc @@ -0,0 +1,299 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + + +#include <libgen.h> +#include <iostream> +#include <fstream> + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/logical/not.hh> + +#include <mln/labeling/colorize.hh> + +#include <mln/io/pbm/all.hh> +#include <mln/io/ppm/save.hh> +#include <mln/io/dump/save.hh> + +#include <mln/math/min.hh> + +#include <mln/literal/colors.hh> +#include <mln/value/rgb8.hh> +#include <mln/value/label_16.hh> + +#include <mln/draw/box.hh> + +#include <mln/extension/adjust.hh> + +#include <scribo/table/erase.hh> + +#include <scribo/draw/bounding_boxes.hh> + +#include <scribo/primitive/extract/objects.hh> +#include <scribo/primitive/extract/lines_h_discontinued.hh> +#include <scribo/primitive/extract/lines_v_discontinued.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_single_link.hh> + +#include <scribo/filter/object_links_bottom_aligned.hh> +#include <scribo/filter/object_links_bbox_h_ratio.hh> +#include <scribo/filter/object_links_bbox_overlap.hh> + +#include <scribo/filter/objects_large.hh> +#include <scribo/filter/objects_small.hh> +#include <scribo/filter/objects_thin.hh> +#include <scribo/filter/objects_thick.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/debug/usage.hh> + +#include <scribo/make/debug_filename.hh> + + +const char *args_desc[][2] = +{ + { "input.pbm", "A binary image. 'False' for objects, 'True'\ +for the background." }, + { "out.ppm", "Show the text found in the input." }, + { "object_label.dump", "Object labeled image." }, + { "line_label.dump", "Text lines labeled image." }, + { "bbox_100p.txt", "Text file containing pmin and pmax of text line bounding boxes." }, + { "bbox_50p.txt", "Text file containing pmin and pmax of text line bounding boxes." }, + { "output_dir", "Output directory for debug image" }, + {0, 0} +}; + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace mln; + + if (argc != 7 && argc != 8) + return scribo::debug::usage(argv, + "Find text lines in a document", + "input.pbm out.ppm object_label.dump line_label.dump bbox_100p.txt bbox_50p.txt [output_dir]", + args_desc, + "Debug outputs. The recognized text is printed in the standard output."); + + if (argc == 8) + scribo::make::internal::debug_filename_prefix = argv[7]; + + trace::entering("main"); + + + bool enable_debug = (argc == 5); + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + typedef image2d<value::label_16> L; + + /// Finding objects. + std::cout << "Finding objects..." << std::endl; + value::label_16 nobjects; + object_image(L) + objects = scribo::primitive::extract::objects(input, + c8(), + nobjects); + + + /// First filtering. + std::cout << "Filtering objects..." << std::endl; + object_image(L) filtered_objects + = scribo::filter::objects_small(objects, 6); + + + filtered_objects + = scribo::filter::objects_large(filtered_objects, + math::min(input.ncols(), input.nrows()) + * math::min(input.ncols(), input.nrows()) / 5); + + + + /// Linking potential objects + std::cout << "Linking objects..." << std::endl; + object_links<L> left_link + = primitive::link::with_single_left_link_dmax_ratio(filtered_objects); + object_links<L> right_link + = primitive::link::with_single_right_link_dmax_ratio(filtered_objects); + + +#ifndef NOUT + if (enable_debug) + { + std::cerr << "BEFORE - nobjects = " << nobjects << 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 + + + // Validating left and right links. + object_links<L> + merged_links = primitive::link::merge_double_link(filtered_objects, + left_link, + right_link); + + + + + // Remove links if bboxes have too different sizes. + object_links<L> hratio_filtered_links + = filter::object_links_bbox_h_ratio(filtered_objects, + merged_links, + 2.0f); + + + + +#ifndef NOUT + if (enable_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 + + + + + //Remove links if bboxes overlap too much. + object_links<L> overlap_filtered_links + = filter::object_links_bbox_overlap(filtered_objects, + hratio_filtered_links, + 0.8f); + + + + +#ifndef NOUT + if (enable_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 + + + + + object_groups<L> + groups = primitive::group::from_single_link(filtered_objects, + overlap_filtered_links); + + + std::cout << "Grouping objects..." << std::endl; + object_image(L) + grouped_objects = primitive::group::apply(filtered_objects, groups); + + + + std::cout << "Saving line bboxes..." << std::endl; + + // 100p bboxes + { + std::ofstream out; + out.open(argv[5], std::ios_base::trunc); + + if (! out) + { + std::cout << "Can't create output file!" << std::endl; + return 1; + } + + for_all_ncomponents(i, grouped_objects.nlabels()) + { + out << grouped_objects.bbox(i).pmin().row() << " " + << grouped_objects.bbox(i).pmin().col() + << " " + << grouped_objects.bbox(i).pmax().row() << " " + << grouped_objects.bbox(i).pmax().col() + << std::endl; + } + out.close(); + + } + + // 50p bboxes + { + std::ofstream out; + out.open(argv[6], std::ios_base::trunc); + + if (! out) + { + std::cout << "Can't create output file!" << std::endl; + return 1; + } + + for_all_ncomponents(i, grouped_objects.nlabels()) + { + out << grouped_objects.bbox(i).pmin().row() / 2 << " " + << grouped_objects.bbox(i).pmin().col() / 2 + << " " + << grouped_objects.bbox(i).pmax().row() / 2 << " " + << grouped_objects.bbox(i).pmax().col() / 2 + << std::endl; + } + out.close(); + + } + + scribo::debug::save_bboxes_image(input, grouped_objects.bboxes(), + literal::red, + argv[2]); + + io::dump::save(filtered_objects, argv[3]); + io::dump::save(grouped_objects, argv[4]); + + trace::exiting("main"); +} diff --git a/scribo/src/preprocessing/Makefile.am b/scribo/src/preprocessing/Makefile.am index 8c1cd80..086a70f 100644 --- a/scribo/src/preprocessing/Makefile.am +++ b/scribo/src/preprocessing/Makefile.am @@ -22,8 +22,10 @@ include $(top_srcdir)/scribo/scribo.mk bin_PROGRAMS = \ preprocess \ split_bg_fg \ + split_bg_fg_ms \ unskew preprocess_SOURCES = preprocess.cc split_bg_fg_SOURCES = split_bg_fg.cc +split_bg_fg_ms_SOURCES = split_bg_fg_ms.cc unskew_SOURCES = unskew.cc diff --git a/scribo/src/preprocessing/split_bg_fg_ms.cc b/scribo/src/preprocessing/split_bg_fg_ms.cc new file mode 100644 index 0000000..4c0180a --- /dev/null +++ b/scribo/src/preprocessing/split_bg_fg_ms.cc @@ -0,0 +1,109 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#include <mln/core/image/image2d.hh> +#include <mln/io/ppm/all.hh> + +#include <mln/debug/filename.hh> + +#include <mln/subsampling/subsampling.hh> + +#include <scribo/preprocessing/split_bg_fg.hh> +#include <scribo/debug/usage.hh> + + +const char *args_desc[][2] = +{ + { "input.pbm", "A color image." }, + { "lambda", "Lambda value. (FIX Description)" }, + { "delta", "Delta value. (FIX Description)" }, + { "lambda_sub2", "Lambda value. (FIX Description)" }, + { "delta_sub2", "Delta value. (FIX Description)" }, + { "lambda_sub4", "Lambda value. (FIX Description)" }, + { "delta_sub4", "Delta value. (FIX Description)" }, + {0, 0} +}; + + + +int main(int argc, char *argv[]) +{ + mln::trace::entering("main"); + using namespace mln; + dpoint2d none(0, 0); + + if (argc != 9) + return scribo::debug::usage(argv, + "Split background and foreground.", + "input.pbm lambda delta lambda_sub2 delta_sub2 lambda_sub3 delta_sub3 output_prefix", + args_desc, "The background and foreground images."); + + mln::debug::internal::filename_prefix = argv[8]; + + typedef image2d<value::rgb8> I; + I input; + io::ppm::load(input, argv[1]); + + util::couple<I,I> + bg_fg = scribo::preprocessing::split_bg_fg(input, + atoi(argv[2]), + atoi(argv[3])); + + io::ppm::save(bg_fg.first(), mln::debug::filename("out_bg.ppm")); + io::ppm::save(bg_fg.second(), mln::debug::filename("out_fg.ppm")); + + + { + // 1/2 + std::cout << "1/2" << std::endl; + I input_sub2x = mln::subsampling::subsampling(input, none, 2); + + util::couple<I,I> + bg_fg = scribo::preprocessing::split_bg_fg(input_sub2x, + atoi(argv[4]), + atoi(argv[5])); + + + io::ppm::save(bg_fg.first(), mln::debug::filename("out_bg_sub2x.ppm")); + io::ppm::save(bg_fg.second(), mln::debug::filename("out_fg_sub2x.ppm")); + } + + { + // 1/4 + std::cout << "1/4" << std::endl; + I input_sub4x = mln::subsampling::subsampling(input, none, 4); + + util::couple<I,I> + bg_fg = scribo::preprocessing::split_bg_fg(input_sub4x, + atoi(argv[6]), + atoi(argv[7])); + + + io::ppm::save(bg_fg.first(), mln::debug::filename("out_bg_sub4x.ppm")); + io::ppm::save(bg_fg.second(), mln::debug::filename("out_fg_sub4x.ppm")); + } + + mln::trace::exiting("main"); +} diff --git a/scribo/src/text_in_article.cc b/scribo/src/text_in_article.cc new file mode 100644 index 0000000..d140719 --- /dev/null +++ b/scribo/src/text_in_article.cc @@ -0,0 +1,327 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + + +#include <libgen.h> +#include <iostream> + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/io/pbm/all.hh> +#include <mln/io/ppm/save.hh> + +#include <mln/math/min.hh> + +#include <mln/literal/colors.hh> +#include <mln/value/rgb8.hh> +#include <mln/value/label_16.hh> +#include <mln/value/int_u16.hh> + +#include <mln/draw/box.hh> +#include <mln/draw/line.hh> + +#include <mln/extension/adjust.hh> + +#include <mln/accu/stat/median_h.hh> + +#include <scribo/draw/bounding_boxes.hh> + +#include <scribo/primitive/extract/objects.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_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/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/debug/usage.hh> + +#include <scribo/make/debug_filename.hh> + + +const char *args_desc[][2] = +{ + { "input.pbm", "A binary image. 'False' for objects, 'True'\ +for the background." }, + { "debug_dir", "Output directory for debug image" }, + {0, 0} +}; + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace mln; + + if (argc != 3 && argc != 4) + return scribo::debug::usage(argv, + "Find text lines using left/right validation and display x-height in a binarized article.", + "input.pbm out.ppm <debug_dir>", + args_desc, + "A color image. The following colors are used : dark blue for object bboxes, orange for single object bboxes, purple for group bboxes and light blue for x-height."); + + if (argc == 4) + scribo::make::internal::debug_filename_prefix = argv[3]; + + trace::entering("main"); + + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + typedef image2d<value::label_16> L; + + /// Finding objects. + std::cout << "Finding objects..." << std::endl; + value::label_16 nobjects; + object_image(L) + objects = scribo::primitive::extract::objects(input, + c8(), + nobjects); + + + /// First filtering. + std::cout << "Filtering objects..." << std::endl; + object_image(L) filtered_objects + = scribo::filter::objects_small(objects, 6); + + /// Linking potential objects + std::cout << "Linking objects..." << std::endl; + object_links<L> left_link + = primitive::link::with_single_left_link_dmax_ratio(filtered_objects); + object_links<L> right_link + = primitive::link::with_single_right_link_dmax_ratio(filtered_objects); + + + // Validating left and right links. + object_links<L> + merged_links = primitive::link::merge_double_link(filtered_objects, + 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 + + + // Remove links if bboxes have too different sizes. + object_links<L> hratio_filtered_links + = filter::object_links_bbox_h_ratio(filtered_objects, + merged_links, + 2.0f); + + + + +#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? + // + //###### + object_groups<L> + groups = primitive::group::from_single_link(filtered_objects, + 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); + //###### + + + std::cout << "Grouping objects..." << std::endl; + object_image(L) + grouped_objects = primitive::group::apply(filtered_objects, groups); + + + + // Compute min_row/max_row median + std::cout << "Preparing output" << std::endl; + { + 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); + +// 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()); + + med_max_row(groups_packed(i)).take(grouped_objects.bbox(groups_packed(i)).pmax().row() - filtered_objects.bbox(i).pmax().row()); + } + } + + // 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)) + { + mln::draw::box(output, filtered_objects.bbox(i), literal::orange); + drawn[i] = true; + single(groups_packed(i)) = true; + } + else + { + 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; + } + +// std::cout << "Drawing median lines" << std::endl; + for_all_components(i, grouped_objects.bboxes()) + { + if (! single(i)) + { + 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); + } + } + + io::ppm::save(output, argv[2]); + } + + + + // 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 new file mode 100644 index 0000000..4a7562f --- /dev/null +++ b/scribo/src/text_in_photo_ppm_fast.cc @@ -0,0 +1,658 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to produce +// an executable, this file does not by itself cause the resulting +// executable to be covered by the GNU General Public License. This +// exception does not however invalidate any other reasons why the +// executable file might be covered by the GNU General Public License. + +#include <libgen.h> +#include <iostream> + +#include <mln/core/image/image2d.hh> +#include <mln/core/image/imorph/tr_image.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/labeling/colorize.hh> + +#include <mln/data/stretch.hh> + +#include <mln/io/pbm/all.hh> +#include <mln/io/ppm/save.hh> + +#include <mln/math/min.hh> + +#include <mln/logical/not.hh> + +#include <mln/literal/colors.hh> +#include <mln/value/rgb8.hh> +#include <mln/value/label_16.hh> + +#include <mln/fun/v2v/rgb_to_int_u.hh> + +#include <mln/data/wrap.hh> + +#include <mln/draw/box.hh> + +#include <mln/geom/translate.hh> + +#include <scribo/draw/bounding_boxes.hh> + +#include <scribo/binarization/sauvola_ms.hh> +#include <scribo/binarization/sauvola.hh> + +#include <scribo/primitive/extract/objects.hh> + +#include <scribo/primitive/link/merge_double_link.hh> +#include <scribo/primitive/link/with_single_left_link.hh> +#include <scribo/primitive/link/with_single_right_link.hh> + +#include <scribo/primitive/group/apply.hh> +#include <scribo/primitive/group/from_double_link.hh> +#include <scribo/primitive/group/from_single_link.hh> + +#include <scribo/filter/objects_with_holes.hh> +#include <scribo/filter/object_links_bbox_h_ratio.hh> +#include <scribo/filter/object_links_bbox_overlap.hh> + +#include <scribo/filter/common/objects_photo.hh> + +#include <scribo/filter/object_groups_small.hh> +#include <scribo/filter/object_groups_v_thickness.hh> + +#include <scribo/debug/decision_image.hh> +#include <scribo/debug/save_bboxes_image.hh> +#include <scribo/debug/save_linked_bboxes_image.hh> + +#include <scribo/debug/usage.hh> + +#include <scribo/preprocessing/split_bg_fg.hh> + +#include <scribo/make/debug_filename.hh> + +#include <mln/util/timer.hh> +#include <mln/core/var.hh> + + +#include <scribo/src/afp/components.hh> +#include <scribo/src/afp/link.hh> +#include <scribo/src/afp/regroup.hh> + +const char *args_desc[][2] = +{ + { "input.ppm", "A color image." }, + { "debug_output_dir", "Directory were debug images will be saved" }, + { "lambda", "Lambda value used for foreground extraction" }, + {0, 0} +}; + + +namespace mln +{ + + struct mask_non_text : Function_v2v<mask_non_text> + { + typedef value::rgb8 result; + typedef image2d<bool> I; + + mask_non_text(const image2d<bool>& mask) + : mask_(mask), p_(mask_) + { + p_.start(); + } + + result operator()(const result& v) const + { + bool b = p_.val(); + p_.next(); + if (!b) + return v / 2; + else + return v; + + } + + I mask_; + mutable mln_pixter_(I) p_; + }; + + + template <typename I, typename L> + mln_concrete(I) + compute_highlight_image(const I& input_rgb, + const object_image<L>& objects) + { + 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); + + 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); + + return output; + } + + template <typename I, typename L> + mln_concrete(I) + compute_text_image(const I& input_rgb, + const object_image<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); + } + if (width == 0) + width = 1; + + I output(height, width); + data::fill(output, literal::black); + + 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))); + + typedef fun::x2x::translation<mln_site_(I)::dim, float> trans_t; + trans_t trans(dv - grouped_objects.bbox(i).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()); + + 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; + } + + return output; + } + +} // end of namespace mln + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace mln; + + 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]", + 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"); + + image2d<value::rgb8> input_rgb; + io::ppm::load(input_rgb, argv[1]); + + + unsigned lambda; + if (argc == 10) + 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_; + float t_; + + global_t_.start(); + + if (argc > 3 && atoi(argv[3]) != 0) + { + // Extract foreground + timer_.start(); + std::cout << "** Using split_bg_fg" << std::endl; + image2d<value::rgb8> + fg = preprocessing::split_bg_fg(input_rgb, + lambda, + 32).second(); + 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 + { + timer_.start(); + std::cout << "** Using data::transform(intensity)" << std::endl; + intensity_ima = data::transform(input_rgb, + mln::fun::v2v::rgb_to_int_u<8>()); + t_ = timer_; + std::cout << "Intensity image " << t_ << std::endl; + } + + + // Binarize foreground to use it in the processing chain. + timer_.restart(); + image2d<bool> input; + unsigned w = std::min(intensity_ima.nrows() / 3, intensity_ima.ncols() / 3); + if (! w % 2) + ++w; + w = std::min(w, 101u); + 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); + } + else + { + 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) +// io::pbm::save(input, "input.pbm"); + t_ = timer_; + std::cout << "Foreground binarized. " << t_ << std::endl; + + + + typedef image2d<value::label_16> L; + + /// Finding objects. + timer_.restart(); + + typedef object_image(L) Obj; + Obj filtered_objects; + + { + util::array<box2d> bboxes; + util::array<point2d> mass_centers; + + value::label_16 nobjects; + L components = extract_components(input, nobjects, bboxes, mass_centers); + + filtered_objects = Obj(components, nobjects, bboxes, mass_centers); + } + + t_ = timer_; + std::cout << "Object extracted " << t_ << " - " << filtered_objects.nlabels() << " objects" << std::endl; + +// if (debug) +// io::pgm::save(data::stretch(value::int_u8(), filtered_objects), "ref_objects.pgm"); + + + /// linking potential objects + timer_.restart(); + util::couple<object_links<L>, object_links<L> > + links = primitive::link::left_right(filtered_objects); + + 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); +// 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); + t_ = timer_; + std::cout << "Link done " << t_ << std::endl; + + + +#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 + + + + // Validating left and right links. + timer_.restart(); + object_links<L> + merged_links = primitive::link::merge_double_link(filtered_objects, + left_link, + right_link); + t_ = timer_; + std::cout << "Right/Left Validation. " << t_ << std::endl; + + + // Remove links if bboxes have too different sizes. + timer_.restart(); + object_links<L> + hratio_filtered_links = filter::object_links_bbox_h_ratio(filtered_objects, + merged_links, + 1.50f); + + + + +#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 + + + + + //Remove links if bboxes overlap too much. + object_links<L> overlap_filtered_links + = filter::object_links_bbox_overlap(filtered_objects, + hratio_filtered_links, + 0.80f); + + + + +#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 + + + t_ = timer_; + std::cout << "Objects links filtered. " << t_ << std::endl; + + timer_.restart(); + object_groups<L> + groups = primitive::group::from_single_link(filtered_objects, + 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, + groups); +#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); + + scribo::draw::bounding_boxes(decision_image, filtered_objects, 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); + io::ppm::save(decision_image, + scribo::make::debug_filename("group_image.ppm")); + } +#endif // !NOUT + + + std::cout << "Filtering groups..." << std::endl; + + util::timer g_timer; + + timer_.restart(); + // Remove objects part of groups with strictly less than 3 objects. + + g_timer.start(); + object_groups<L> filtered_small_groups; + if (argc > 6 && atoi(argv[6]) != 0) + { + std::cout << "** Using group too small" << std::endl; + filtered_small_groups = filter::object_groups_small(groups, 3); + } + else + filtered_small_groups = groups; + t_ = g_timer; + std::cout << "Small groups removed " << t_ << std::endl; + + + +#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; + if (argc > 7 && atoi(argv[7]) != 0) + { + std::cout << "** Using group too thin" << std::endl; + filtered_thin_groups + = filter::object_groups_v_thickness(filtered_small_groups, 8); + } + else + filtered_thin_groups = filtered_small_groups; + t_ = g_timer; + 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) + { + std::cout << "** Using objects_with_two_holes" << std::endl; + grouped_objects = scribo::filter::objects_with_two_holes(grouped_objects, 5); + t_ = g_timer; + std::cout << "Objects_with_holes " << t_ << std::endl; + } + + + t_ = timer_; + std::cout << "Objects groups filtered. " << t_ << std::endl; + + + 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(), + grouped_objects, + 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"); + io::ppm::save(compute_text_image(input_rgb, grouped_objects), + out_base_dir + "_out_text.ppm"); + + t_ = timer_; + std::cout << "Output saved " << t_ << std::endl; + + std::cout << "# objects = " << grouped_objects.nlabels() << std::endl; + + trace::exiting("main"); + return grouped_objects.nlabels() != 0; +} -- 1.5.6.5
participants (1)
-
Guillaume Lazzara