4484: Improve and add new examples in Scribo.

* src/Makefile.am, * src/extract/primitive/Makefile.am, * src/text/Makefile.am: Add new targets. * src/extract/primitive/find_thick_and_single_lines.cc, * src/text/cleantxt.cc, * src/text_in_photo_ppm.cc: New full examples. * src/extract/primitive/find_thick_lines.cc: Use the lines_*_thick routines. * src/text_in_doc.cc, * src/text_in_photo.cc: Improve outputs. --- scribo/ChangeLog | 18 ++ scribo/src/Makefile.am | 2 + scribo/src/extract/primitive/Makefile.am | 4 +- ...ick_lines.cc => find_thick_and_single_lines.cc} | 52 +--- scribo/src/extract/primitive/find_thick_lines.cc | 33 +-- scribo/src/text/Makefile.am | 28 ++ scribo/src/text/cleantxt.cc | 79 +++++ scribo/src/text_in_doc.cc | 104 ++++--- scribo/src/text_in_photo_ppm.cc | 318 ++++++++++++++++++++ 9 files changed, 536 insertions(+), 102 deletions(-) copy scribo/src/extract/primitive/{find_thick_lines.cc => find_thick_and_single_lines.cc} (70%) create mode 100644 scribo/src/text/cleantxt.cc create mode 100644 scribo/src/text_in_photo_ppm.cc diff --git a/scribo/ChangeLog b/scribo/ChangeLog index af2f788..8bdadd9 100644 --- a/scribo/ChangeLog +++ b/scribo/ChangeLog @@ -1,5 +1,23 @@ 2009-09-15 Guillaume Lazzara <lazzara@lrde.epita.fr> + Improve and add new examples in Scribo. + + * src/Makefile.am, + * src/extract/primitive/Makefile.am, + * src/text/Makefile.am: Add new targets. + + * src/extract/primitive/find_thick_and_single_lines.cc, + * src/text/cleantxt.cc, + * src/text_in_photo_ppm.cc: New full examples. + + * src/extract/primitive/find_thick_lines.cc: Use the lines_*_thick + routines. + + * src/text_in_doc.cc, + * src/text_in_photo.cc: Improve outputs. + +2009-09-15 Guillaume Lazzara <lazzara@lrde.epita.fr> + Make text cleaning work. * text/clean.hh: Do not use the distance map anymore. diff --git a/scribo/src/Makefile.am b/scribo/src/Makefile.am index 3b6a435..de051a4 100644 --- a/scribo/src/Makefile.am +++ b/scribo/src/Makefile.am @@ -37,6 +37,7 @@ bin_PROGRAMS = \ table_rebuild_opening \ table_rebuild_rank \ text_in_photo \ + text_in_photo_ppm \ text_in_photo_invert \ thin_bboxes @@ -50,6 +51,7 @@ superpose_SOURCES = superpose.cc table_rebuild_opening_SOURCES = table_rebuild_opening.cc table_rebuild_rank_SOURCES = table_rebuild_rank.cc text_in_photo_SOURCES = text_in_photo.cc +text_in_photo_ppm_SOURCES = text_in_photo_ppm.cc text_in_photo_invert_SOURCES = text_in_photo_invert.cc thin_bboxes_SOURCES = thin_bboxes.cc diff --git a/scribo/src/extract/primitive/Makefile.am b/scribo/src/extract/primitive/Makefile.am index 99be780..51850f6 100644 --- a/scribo/src/extract/primitive/Makefile.am +++ b/scribo/src/extract/primitive/Makefile.am @@ -28,7 +28,8 @@ bin_PROGRAMS = \ extract_thick_hlines \ find_discontinued_lines \ find_single_lines \ - find_thick_lines + find_thick_lines \ + find_thick_and_single_lines extract_discontinued_lines_SOURCES = extract_discontinued_lines.cc extract_discontinued_vlines_SOURCES = extract_discontinued_vlines.cc @@ -38,5 +39,6 @@ extract_thick_hlines_SOURCES = extract_thick_hlines.cc find_discontinued_lines_SOURCES = find_discontinued_lines.cc find_single_lines_SOURCES = find_single_lines.cc find_thick_lines_SOURCES = find_thick_lines.cc +find_thick_and_single_lines_SOURCES = find_thick_and_single_lines.cc diff --git a/scribo/src/extract/primitive/find_thick_lines.cc b/scribo/src/extract/primitive/find_thick_and_single_lines.cc similarity index 70% copy from scribo/src/extract/primitive/find_thick_lines.cc copy to scribo/src/extract/primitive/find_thick_and_single_lines.cc index 993bf42..fa66e29 100644 --- a/scribo/src/extract/primitive/find_thick_lines.cc +++ b/scribo/src/extract/primitive/find_thick_and_single_lines.cc @@ -35,13 +35,9 @@ #include <scribo/debug/usage.hh> #include <scribo/core/object_image.hh> -#include <scribo/primitive/extract/lines_h_thick.hh> -#include <scribo/primitive/extract/lines_v_thick.hh> -#include <scribo/primitive/extract/lines_h_single.hh> -#include <scribo/primitive/extract/lines_v_single.hh> - -#include <mln/util/timer.hh> +# include <scribo/primitive/extract/lines_v_thick_and_single.hh> +# include <scribo/primitive/extract/lines_h_thick_and_single.hh> const char *args_desc[][2] = { @@ -57,13 +53,14 @@ const char *args_desc[][2] = int main(int argc, char *argv[]) { using namespace mln; + using namespace scribo; if (argc != 7) return scribo::debug::usage(argv, "Extract thick horizontal and vertical lines.\ \n Common argument values: 150 10 150 10.", "<input.pbm> <vlength> <vratio> <hlength>\ - <hration> <output.ppm>", + <hratio> <output.ppm>", args_desc, "A color image. Horizontal lines are in red\ and vertical lines in green."); @@ -80,35 +77,20 @@ int main(int argc, char *argv[]) nhlines, nvlines; - util::timer t; - - t.start(); - object_image(L) - hlines = scribo::primitive::extract::lines_h_thick(input, c8(), - nhlines, atoi(argv[2])), - vlines = scribo::primitive::extract::lines_v_thick(input, c8(), - nvlines, atoi(argv[2])); - std::cout << "lines thick done" << std::endl; - std::cout << t << std::endl; - t.restart(); - - - hlines = scribo::primitive::extract::lines_h_single(hlines, - atoi(argv[2]), - 10); - - vlines = scribo::primitive::extract::lines_v_single(vlines, - atoi(argv[2]), - 10); - - std::cout << "lines single done" << std::endl; - std::cout << t << std::endl; - - image2d<value::rgb8> out = debug::superpose(input, hlines, literal::red); - out = debug::superpose(out, vlines, literal::green); - - io::ppm::save(out, argv[3]); + hlines = primitive::extract::lines_h_thick_and_single(input, c8(), + nhlines, + atoi(argv[2]), + atoi(argv[3])), + vlines = primitive::extract::lines_v_thick_and_single(input, c8(), + nvlines, + atoi(argv[4]), + atoi(argv[5])); + + image2d<value::rgb8> out = mln::debug::superpose(input, hlines, literal::red); + out = mln::debug::superpose(out, vlines, literal::green); + + io::ppm::save(out, argv[6]); trace::exiting("main"); } diff --git a/scribo/src/extract/primitive/find_thick_lines.cc b/scribo/src/extract/primitive/find_thick_lines.cc index 993bf42..045b34d 100644 --- a/scribo/src/extract/primitive/find_thick_lines.cc +++ b/scribo/src/extract/primitive/find_thick_lines.cc @@ -41,15 +41,12 @@ #include <scribo/primitive/extract/lines_h_single.hh> #include <scribo/primitive/extract/lines_v_single.hh> -#include <mln/util/timer.hh> const char *args_desc[][2] = { { "input.pbm", "A binary image. Objects are set to True." }, { "vlength ", "Minimum vertical line length." }, - { "vratio " "Minimum vertical ratio height/width." }, { "hlength ", "Minimum horizontal line length." }, - { "hratio " "Minimum horizontal ratio width/height." }, {0, 0} }; @@ -58,12 +55,11 @@ int main(int argc, char *argv[]) { using namespace mln; - if (argc != 7) + if (argc != 5) return scribo::debug::usage(argv, "Extract thick horizontal and vertical lines.\ -\n Common argument values: 150 10 150 10.", - "<input.pbm> <vlength> <vratio> <hlength>\ - <hration> <output.ppm>", +\n Common argument values: 150 150.", + "<input.pbm> <vlength> <hlength> <output.ppm>", args_desc, "A color image. Horizontal lines are in red\ and vertical lines in green."); @@ -80,35 +76,16 @@ int main(int argc, char *argv[]) nhlines, nvlines; - util::timer t; - - t.start(); - object_image(L) hlines = scribo::primitive::extract::lines_h_thick(input, c8(), nhlines, atoi(argv[2])), vlines = scribo::primitive::extract::lines_v_thick(input, c8(), - nvlines, atoi(argv[2])); - std::cout << "lines thick done" << std::endl; - std::cout << t << std::endl; - t.restart(); - - - hlines = scribo::primitive::extract::lines_h_single(hlines, - atoi(argv[2]), - 10); - - vlines = scribo::primitive::extract::lines_v_single(vlines, - atoi(argv[2]), - 10); - - std::cout << "lines single done" << std::endl; - std::cout << t << std::endl; + nvlines, atoi(argv[3])); image2d<value::rgb8> out = debug::superpose(input, hlines, literal::red); out = debug::superpose(out, vlines, literal::green); - io::ppm::save(out, argv[3]); + io::ppm::save(out, argv[4]); trace::exiting("main"); } diff --git a/scribo/src/text/Makefile.am b/scribo/src/text/Makefile.am index 5f5ed81..6b174ef 100644 --- a/scribo/src/text/Makefile.am +++ b/scribo/src/text/Makefile.am @@ -1 +1,29 @@ +# 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/>. +# + +## Process this file through Automake to create Makefile.in. + +include $(top_srcdir)/scribo/scribo.mk + SUBDIRS = grouping + + +bin_PROGRAMS = \ + cleantxt + + +cleantxt_SOURCES = cleantxt.cc \ No newline at end of file diff --git a/scribo/src/text/cleantxt.cc b/scribo/src/text/cleantxt.cc new file mode 100644 index 0000000..f303448 --- /dev/null +++ b/scribo/src/text/cleantxt.cc @@ -0,0 +1,79 @@ +// 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/io/pbm/all.hh> + +#include <mln/logical/not.hh> +#include <mln/core/alias/neighb2d.hh> +#include <mln/core/alias/w_window2d_int.hh> +#include <mln/make/w_window2d_int.hh> + + +#include <scribo/text/clean.hh> +#include <scribo/debug/usage.hh> + + +const char *args_desc[][2] = +{ + { "input.pbm", "A binary image. 'True' for objects, 'False'\ +for the background." }, + { "out.pbm", "A cleaned up binary image." }, + {0, 0} +}; + + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace mln; + + if (argc != 3) + return scribo::debug::usage(argv, + "Cleanup text areas.", + "input.pbm out.pbm", + args_desc, + ""); + + trace::entering("main"); + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + int vals[] = { 0, 9, 0, 9, 0, + 9, 6, 4, 6, 9, + 0, 4, 0, 4, 0, + 9, 6, 4, 6, 9, + 0, 9, 0, 9, 0 }; + w_window2d_int dmap_win = mln::make::w_window2d_int(vals); + + io::pbm::save(scribo::text::clean(logical::not_(input), dmap_win), argv[2]); + + trace::exiting("main"); +} diff --git a/scribo/src/text_in_doc.cc b/scribo/src/text_in_doc.cc index 81219c4..cfca7d1 100644 --- a/scribo/src/text_in_doc.cc +++ b/scribo/src/text_in_doc.cc @@ -45,6 +45,8 @@ #include <mln/draw/box.hh> +#include <mln/extension/adjust.hh> + #include <scribo/table/erase.hh> #include <scribo/draw/bounding_boxes.hh> @@ -83,12 +85,12 @@ #include <scribo/make/debug_filename.hh> - const char *args_desc[][2] = { { "input.pbm", "A binary image. 'False' for objects, 'True'\ for the background." }, { "out.txt", "A text file with all the recognized text" }, + { "output_dir", "Output directory for debug image" }, {0, 0} }; @@ -98,14 +100,15 @@ int main(int argc, char* argv[]) using namespace scribo; using namespace mln; - if (argc != 4) + if (argc != 3 && argc != 4) return scribo::debug::usage(argv, "Find text in a binarized photo.", - "input.pbm out.txt output_dir", + "input.pbm out.txt <output_dir>", args_desc, "Debug outputs. The recognized text is printed in the standard output."); - scribo::make::internal::debug_filename_prefix = argv[3]; + if (argc == 4) + scribo::make::internal::debug_filename_prefix = argv[3]; trace::entering("main"); @@ -115,9 +118,11 @@ int main(int argc, char* argv[]) logical::not_inplace(input); + typedef image2d<value::label_16> L; /// Extracting vertical and horizontal lines. + std::cout << "Extracting lines..." << std::endl; value::label_16 nhlines, nvlines; object_image(L) lbl_v = primitive::extract::lines_v_discontinued(input, c8(), @@ -125,12 +130,17 @@ int main(int argc, char* argv[]) object_image(L) lbl_h = primitive::extract::lines_h_discontinued(input, c8(), nhlines, 51, 6); + /// Reconstruct and erase tables. + std::cout << "Reconstructing and removing tables..." << std::endl; image2d<bool> input_notables = scribo::table::erase(input, lbl_h, lbl_v); + io::pbm::save(input_notables, "table_erased.ppm"); + /// Finding objects. + std::cout << "Finding objects..." << std::endl; value::label_16 nobjects; object_image(L) objects = scribo::primitive::extract::objects(input_notables, @@ -139,11 +149,12 @@ int main(int argc, char* argv[]) /// First filtering. + std::cout << "Filtering objects..." << std::endl; object_image(L) filtered_objects = scribo::filter::objects_small(objects, 6); filtered_objects - = scribo::filter::objects_thin(filtered_objects, 2); + = scribo::filter::objects_thin(filtered_objects, 1); // filtered_objects // = scribo::filter::objects_thick(filtered_objects, @@ -151,7 +162,8 @@ int main(int argc, char* argv[]) - /// Grouping potential objects + /// Linking potential objects + std::cout << "Linking objects..." << std::endl; object_links<L> left_link = primitive::link::with_single_left_link(filtered_objects, 30); object_links<L> right_link @@ -159,14 +171,17 @@ int main(int argc, char* argv[]) #ifndef NOUT - std::cout << "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")); + if (argc == 4) + { + 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 @@ -179,7 +194,8 @@ int main(int argc, char* argv[]) - // Remove links if bboxes have too different sizes. + // Remove links if bboxes are not aligned. + std::cout << "Filtering object links..." << std::endl; object_links<L> bottom_filtered_links = filter::object_links_bottom_aligned(filtered_objects, merged_links, @@ -188,13 +204,16 @@ int main(int argc, char* argv[]) #ifndef NOUT - image2d<value::rgb8> - bottom_decision_image = scribo::debug::decision_image(input, - merged_links, - bottom_filtered_links); - - io::ppm::save(bottom_decision_image, - scribo::make::debug_filename("bottom_links_decision_image.ppm")); + if (argc == 4) + { + image2d<value::rgb8> + bottom_decision_image = scribo::debug::decision_image(input, + merged_links, + bottom_filtered_links); + + io::ppm::save(bottom_decision_image, + scribo::make::debug_filename("bottom_links_decision_image.ppm")); + } #endif @@ -211,12 +230,15 @@ int main(int argc, char* argv[]) #ifndef NOUT - image2d<value::rgb8> - hratio_decision_image = scribo::debug::decision_image(input, - bottom_filtered_links, - hratio_filtered_links); - io::ppm::save(hratio_decision_image, - scribo::make::debug_filename("hratio_links_decision_image.ppm")); + if (argc == 4) + { + image2d<value::rgb8> + hratio_decision_image = scribo::debug::decision_image(input, + bottom_filtered_links, + hratio_filtered_links); + io::ppm::save(hratio_decision_image, + scribo::make::debug_filename("hratio_links_decision_image.ppm")); + } #endif @@ -232,12 +254,15 @@ int main(int argc, char* argv[]) #ifndef NOUT - 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")); + if (argc == 4) + { + image2d<value::rgb8> overlap_decision_image + = scribo::debug::decision_image(input, + hratio_filtered_links, + overlap_filtered_links); + io::ppm::save(overlap_decision_image, + scribo::make::debug_filename("overlap_links_decision_image.ppm")); + } #endif @@ -258,18 +283,21 @@ int main(int argc, char* argv[]) // groups, filtered_groups); // #endif + std::cout << "Grouping objects..." << std::endl; object_image(L) grouped_objects = primitive::group::apply(filtered_objects, groups); #ifndef NOUT - io::ppm::save(mln::labeling::colorize(value::rgb8(), - grouped_objects, - grouped_objects.nlabels()), - scribo::make::debug_filename("out.ppm")); + if (argc == 4) + io::ppm::save(mln::labeling::colorize(value::rgb8(), + grouped_objects, + grouped_objects.nlabels()), + scribo::make::debug_filename("out.ppm")); #endif + std::cout << "Text recognition..." << std::endl; text::recognition(grouped_objects, "fra", argv[2]); trace::exiting("main"); diff --git a/scribo/src/text_in_photo_ppm.cc b/scribo/src/text_in_photo_ppm.cc new file mode 100644 index 0000000..4cb5631 --- /dev/null +++ b/scribo/src/text_in_photo_ppm.cc @@ -0,0 +1,318 @@ +// 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/labeling/colorize.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/draw/box.hh> + +#include <scribo/binarization/sauvola.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.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/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_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> + +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} +}; + + +int main(int argc, char* argv[]) +{ + using namespace scribo; + using namespace mln; + + if (argc != 3 && argc != 4 && argc != 5) + return scribo::debug::usage(argv, + "Find text in a photo.", + "input.ppm output.ppm [debug_output_dir] [lambda]", + args_desc, + "A color image where the text is highlighted."); + + if (argc > 3) + scribo::make::internal::debug_filename_prefix = argv[3]; + + trace::entering("main"); + + image2d<value::rgb8> input_rgb; + io::ppm::load(input_rgb, argv[1]); + + + unsigned lambda; + if (argc == 5) + lambda = atoi(argv[4]); + else + lambda = 1.2 * (input_rgb.nrows() + input_rgb.ncols()); + + + // Extract foreground + std::cout << "Extracting foreground..." << std::endl; + image2d<value::rgb8> + fg = preprocessing::split_bg_fg(input_rgb, + lambda, + 32).second(); + + // Binarize foreground to use it in the processing chain. + std::cout << "Binarizing foreground..." << std::endl; + image2d<bool> input = binarization::sauvola(fg); + + + + typedef image2d<value::label_16> L; + + /// Finding objects. + std::cout << "Extracting 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 = filter::common::objects_photo(objects); + + + + /// linking potential objects + std::cout << "Linking objects..." << std::endl; + object_links<L> left_link + = primitive::link::with_single_left_link(filtered_objects, 30); + object_links<L> right_link + = primitive::link::with_single_right_link(filtered_objects, 30); + + + + + +#ifndef NOUT + if (argc > 3) + { + 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. + std::cout << "Filtering object links..." << std::endl; + object_links<L> + hratio_filtered_links = filter::object_links_bbox_h_ratio(filtered_objects, + merged_links, + 0.7f); + + + + +#ifndef NOUT + if (argc > 3) + { + 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 (argc > 3) + { + 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 + + + + std::cout << "Grouping objects..." << std::endl; + object_groups<L> + groups = primitive::group::from_single_link(filtered_objects, + overlap_filtered_links); + + + + /// Apply grouping in a temporary image (for debug purpose). + object_image(L) + raw_group_image = primitive::group::apply(filtered_objects, + filter::object_groups_small(groups, 2)); + + std::cout << "Filtering groups..." << std::endl; + + // Remove objects part of groups with strictly less than 3 objects. + object_groups<L> + filtered_small_groups = filter::object_groups_small(groups, 3); + + +#ifndef NOUT + image2d<value::rgb8> decision_image; + if (argc > 3) + { + decision_image = scribo::debug::decision_image(input, + groups, + filtered_small_groups); + io::ppm::save(decision_image, + scribo::make::debug_filename("small_groups_filter.ppm")); + } +#endif + + + + // Remove objects part of groups having a mean thickness lower than 8. + object_groups<L> filtered_thin_groups + = filter::object_groups_v_thickness(filtered_small_groups, 8); + + +#ifndef NOUT + if (argc > 3) + { + decision_image = scribo::debug::decision_image(input, + groups, + filtered_thin_groups); + + io::ppm::save(decision_image, + scribo::make::debug_filename("thin_groups_filter.ppm")); + } +#endif + + + + /// Apply grouping in the object image. + object_image(L) + grouped_objects = primitive::group::apply(filtered_objects, + filtered_thin_groups); + + + /// Objects have been grouped. We try to link groups together. + /// This time a single link is enough since non-wanted objects have + /// been removed. + left_link + = primitive::link::with_single_left_link(grouped_objects, 30); + + /// Grouping groups. + groups = primitive::group::from_single_link(grouped_objects, left_link); + + + grouped_objects = primitive::group::apply(grouped_objects, groups); + + + + +#ifndef NOUT + if (argc > 3) + { + scribo::draw::bounding_boxes(decision_image, raw_group_image, literal::yellow); + scribo::draw::bounding_boxes(decision_image, grouped_objects, literal::blue); + io::ppm::save(decision_image, scribo::make::debug_filename("decision_image.ppm")); + + std::cerr << "AFTER - nobjects = " << grouped_objects.nlabels() << std::endl; + } +#endif + + + std::cout << "Saving result..." << std::endl; + io::ppm::save(mln::labeling::colorize(value::rgb8(), + grouped_objects, + grouped_objects.nlabels()), + argv[2]); + + + trace::exiting("main"); +} -- 1.5.6.5
participants (1)
-
Guillaume Lazzara