3551: Update Scribo's code.

* scribo/Makefile: add new targets. * scribo/core/central_sites.hh, * scribo/core/component_bboxes.hh: add more assertions. * scribo/text/recognition.hh, * scribo/text/grouping/internal/find_root.hh, * scribo/text/grouping/internal/init_link_array.hh, * scribo/text/grouping/group_from_double_link.hh, * scribo/text/grouping/group_from_multiple_links.hh, * scribo/text/grouping/group_from_single_link.hh, * scribo/text/grouping/group_with_multiple_links.hh, * scribo/text/grouping/group_with_single_left_link.hh, * scribo/text/grouping/group_with_single_right_link.hh, * scribo/text/extract_bboxes.hh, * scribo/src/extract_text_double_link.cc, * scribo/src/extract_text_multiple_links.cc, * scribo/src/extract_text_single_link.cc, * scribo/debug/save_linked_textbboxes_image.hh, * scribo/debug/save_table_image.hh, * scribo/debug/save_textbboxes_image.hh, * scribo/draw/bounding_box_links.hh, * scribo/draw/bounding_boxes.hh: make use of util::text. * scribo/filter/large_components.hh, * scribo/filter/small_components.hh, * scribo/filter/thin_bboxes.hh: new filters. * scribo/make/debug_filename.hh: improve. * scribo/make/text.hh: Construct a text class. * scribo/src/dmap.cc, * scribo/src/morpho.cc, * scribo/src/table_extract.cc, * scribo/src/table_rebuild.cc, * scribo/src/thin_bboxes.cc: new sample code. * scribo/src/table.cc: fix include. * scribo/table/internal/align_lines.hh, * scribo/table/align_lines_horizontaly.hh, * scribo/table/align_lines_verticaly.hh, * scribo/table/connect_horizontal_lines.hh, * scribo/table/connect_vertical_lines.hh: add more parameters. * scribo/table/extract.hh: new routine to extract document tables. * scribo/table/extract_lines_with_opening.hh: new routine to extract document tables. * scribo/table/extract_lines_with_rank.hh: fix missing bbox.enlarge. * scribo/table/internal/connect_lines.hh: make it compile. * scribo/table/internal/repair_lines.hh: make it work. * scribo/table/rebuild.hh: new routine to rebuild document tables. * scribo/core/erase_bboxes.hh, * scribo/table/repair_horizontal_lines.hh: revamp. * scribo/tests/filter/small_and_large_bboxes.cc, * scribo/tests/table/extract_lines_with_rank.cc, * scribo/tests/table/repair_lines.cc: new tests. * scribo/text/extract_lines.hh: new routine to extract text automatically. * scribo/text/grouping/internal/update_link_array.hh, * scribo/text/grouping/internal/update_link_graph.hh: fix conditions. * scribo/util/text.hh: new object to represent text components. --- milena/sandbox/ChangeLog | 80 ++++++++- milena/sandbox/scribo/Makefile | 27 ++- milena/sandbox/scribo/core/central_sites.hh | 2 +- milena/sandbox/scribo/core/component_bboxes.hh | 19 ++- milena/sandbox/scribo/core/erase_bboxes.hh | 4 +- .../scribo/debug/save_linked_textbboxes_image.hh | 49 +++--- milena/sandbox/scribo/debug/save_table_image.hh | 65 +++++-- .../sandbox/scribo/debug/save_textbboxes_image.hh | 7 +- milena/sandbox/scribo/draw/bounding_box_links.hh | 26 ++-- milena/sandbox/scribo/draw/bounding_boxes.hh | 4 +- milena/sandbox/scribo/filter/large_components.hh | 196 ++++++++++++++++++ milena/sandbox/scribo/filter/small_components.hh | 207 ++++++++++++++++++++ milena/sandbox/scribo/filter/thin_bboxes.hh | 165 ++++++++++++++++ milena/sandbox/scribo/make/debug_filename.hh | 33 +++- .../{text/extract_bboxes.hh => make/text.hh} | 81 +++++--- milena/sandbox/scribo/src/dmap.cc | 26 +++ .../sandbox/scribo/src/extract_text_double_link.cc | 69 ++++---- .../scribo/src/extract_text_multiple_links.cc | 34 ++-- .../sandbox/scribo/src/extract_text_single_link.cc | 72 ++++--- milena/sandbox/scribo/src/morpho.cc | 64 ++++++ milena/sandbox/scribo/src/table.cc | 2 +- ...act_text_multiple_links.cc => table_extract.cc} | 37 ++--- ...act_text_multiple_links.cc => table_rebuild.cc} | 45 +++-- milena/sandbox/scribo/src/thin_bboxes.cc | 32 +++ .../scribo/table/align_lines_horizontaly.hh | 18 ++- .../sandbox/scribo/table/align_lines_verticaly.hh | 15 +- .../scribo/table/connect_horizontal_lines.hh | 14 +- .../sandbox/scribo/table/connect_vertical_lines.hh | 14 +- .../{text/extract_bboxes.hh => table/extract.hh} | 73 ++++---- ..._with_rank.hh => extract_lines_with_opening.hh} | 67 ++++--- .../scribo/table/extract_lines_with_rank.hh | 27 ++- .../sandbox/scribo/table/internal/align_lines.hh | 9 +- .../sandbox/scribo/table/internal/connect_lines.hh | 17 ++- .../sandbox/scribo/table/internal/repair_lines.hh | 67 +++++-- milena/sandbox/scribo/table/rebuild.hh | 147 ++++++++++++++ .../scribo/table/repair_horizontal_lines.hh | 6 +- .../filter/small_and_large_bboxes.cc} | 13 ++- .../scribo/tests/table/extract_lines_with_rank.cc | 36 ++++ milena/sandbox/scribo/tests/table/repair_lines.cc | 45 +++++ milena/sandbox/scribo/text/extract_bboxes.hh | 15 +- milena/sandbox/scribo/text/extract_lines.hh | 133 +++++++++++++ .../scribo/text/grouping/group_from_double_link.hh | 65 +++++-- .../text/grouping/group_from_multiple_links.hh | 63 ++++--- .../scribo/text/grouping/group_from_single_link.hh | 43 +++-- .../text/grouping/group_with_multiple_links.hh | 37 ++--- .../text/grouping/group_with_single_left_link.hh | 47 ++--- .../text/grouping/group_with_single_right_link.hh | 49 ++--- .../scribo/text/grouping/internal/find_root.hh | 4 +- .../text/grouping/internal/init_link_array.hh | 7 +- .../text/grouping/internal/update_link_array.hh | 7 +- .../text/grouping/internal/update_link_graph.hh | 6 +- milena/sandbox/scribo/text/recognition.hh | 19 +- milena/sandbox/scribo/util/text.hh | 189 ++++++++++++++++++ 53 files changed, 2087 insertions(+), 511 deletions(-) create mode 100644 milena/sandbox/scribo/filter/large_components.hh create mode 100644 milena/sandbox/scribo/filter/small_components.hh create mode 100644 milena/sandbox/scribo/filter/thin_bboxes.hh copy milena/sandbox/scribo/{text/extract_bboxes.hh => make/text.hh} (56%) create mode 100644 milena/sandbox/scribo/src/dmap.cc create mode 100644 milena/sandbox/scribo/src/morpho.cc copy milena/sandbox/scribo/src/{extract_text_multiple_links.cc => table_extract.cc} (61%) copy milena/sandbox/scribo/src/{extract_text_multiple_links.cc => table_rebuild.cc} (61%) create mode 100644 milena/sandbox/scribo/src/thin_bboxes.cc copy milena/sandbox/scribo/{text/extract_bboxes.hh => table/extract.hh} (55%) copy milena/sandbox/scribo/table/{extract_lines_with_rank.hh => extract_lines_with_opening.hh} (67%) create mode 100644 milena/sandbox/scribo/table/rebuild.hh copy milena/sandbox/scribo/{src/extract_text_multiple_links.cc => tests/filter/small_and_large_bboxes.cc} (87%) create mode 100644 milena/sandbox/scribo/tests/table/extract_lines_with_rank.cc create mode 100644 milena/sandbox/scribo/tests/table/repair_lines.cc create mode 100644 milena/sandbox/scribo/text/extract_lines.hh create mode 100644 milena/sandbox/scribo/util/text.hh diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog index 8c7681f..7137a4d 100644 --- a/milena/sandbox/ChangeLog +++ b/milena/sandbox/ChangeLog @@ -1,4 +1,82 @@ -2009-03-16 Guillaume Lazzara <z@lrde.epita.fr> +2009-03-19 Guillaume Lazzara <z@lrde.epita.fr> + + Update Scribo's code. + + * scribo/Makefile: add new targets. + + * scribo/core/central_sites.hh, + * scribo/core/component_bboxes.hh: add more assertions. + + * scribo/text/recognition.hh, + * scribo/text/grouping/internal/find_root.hh, + * scribo/text/grouping/internal/init_link_array.hh, + * scribo/text/grouping/group_from_double_link.hh, + * scribo/text/grouping/group_from_multiple_links.hh, + * scribo/text/grouping/group_from_single_link.hh, + * scribo/text/grouping/group_with_multiple_links.hh, + * scribo/text/grouping/group_with_single_left_link.hh, + * scribo/text/grouping/group_with_single_right_link.hh, + * scribo/text/extract_bboxes.hh, + * scribo/src/extract_text_double_link.cc, + * scribo/src/extract_text_multiple_links.cc, + * scribo/src/extract_text_single_link.cc, + * scribo/debug/save_linked_textbboxes_image.hh, + * scribo/debug/save_table_image.hh, + * scribo/debug/save_textbboxes_image.hh, + * scribo/draw/bounding_box_links.hh, + * scribo/draw/bounding_boxes.hh: make use of util::text. + + * scribo/filter/large_components.hh, + * scribo/filter/small_components.hh, + * scribo/filter/thin_bboxes.hh: new filters. + + * scribo/make/debug_filename.hh: improve. + + * scribo/make/text.hh: Construct a text class. + + * scribo/src/dmap.cc, + * scribo/src/morpho.cc, + * scribo/src/table_extract.cc, + * scribo/src/table_rebuild.cc, + * scribo/src/thin_bboxes.cc: new sample code. + + * scribo/src/table.cc: fix include. + + * scribo/table/internal/align_lines.hh, + * scribo/table/align_lines_horizontaly.hh, + * scribo/table/align_lines_verticaly.hh, + * scribo/table/connect_horizontal_lines.hh, + * scribo/table/connect_vertical_lines.hh: add more parameters. + + * scribo/table/extract.hh: new routine to extract document tables. + + * scribo/table/extract_lines_with_opening.hh: new routine to extract + document tables. + + * scribo/table/extract_lines_with_rank.hh: fix missing bbox.enlarge. + + * scribo/table/internal/connect_lines.hh: make it compile. + + * scribo/table/internal/repair_lines.hh: make it work. + + * scribo/table/rebuild.hh: new routine to rebuild document tables. + + * scribo/core/erase_bboxes.hh, + * scribo/table/repair_horizontal_lines.hh: revamp. + + * scribo/tests/filter/small_and_large_bboxes.cc, + * scribo/tests/table/extract_lines_with_rank.cc, + * scribo/tests/table/repair_lines.cc: new tests. + + * scribo/text/extract_lines.hh: new routine to extract text + automatically. + + * scribo/text/grouping/internal/update_link_array.hh, + * scribo/text/grouping/internal/update_link_graph.hh: fix conditions. + + * scribo/util/text.hh: new object to represent text components. + +2009-03-19 Guillaume Lazzara <z@lrde.epita.fr> Add a buggy sample case. diff --git a/milena/sandbox/scribo/Makefile b/milena/sandbox/scribo/Makefile index cbb462b..09a3a2d 100644 --- a/milena/sandbox/scribo/Makefile +++ b/milena/sandbox/scribo/Makefile @@ -1,28 +1,41 @@ +CXX_FLAGS = -Wextra -Wall -I../.. -I../ -I$(HOME)/local/include -O1 -DNDEBUG # -ggdb #-O1 -DNDEBUG + all: table photo tabledbg: demat.hh - g++ -Wextra -Wall -I../.. -I../ -I$(HOME)/local/include -O1 -g src/table.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o bin/table.out + g++ -Wextra -Wall -I../.. -I../ -I. -I$(HOME)/local/include -O1 -g src/table.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o bin/table.out table: demat.hh - g++ -Wextra -Wall -I../.. -I. -I.. -I$(HOME)/local/include -O1 -DNDEBUG src/table.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o bin/table.out + g++ $(CXX_FLAGS) src/table.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o bin/table.out oldtable: demat.old.hh - g++ -Wextra -Wall -I../.. -I../ -I$(HOME)/local/include -O1 -DNDEBUG src/table_old.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o bin/table_old.out + g++ $(CXX_FLAGS) src/table_old.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o bin/table_old.out photo: demat.hh - g++ -Wextra -Wall -I../.. -I. -I.. -I$(HOME)/local/include -O1 -DNDEBUG src/photo.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o bin/photo.out + g++ $(CXX_FLAGS) src/photo.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o bin/photo.out + +dmap: + g++ $(CXX_FLAGS) src/dmap.cc -o bin/dmap.out extract_text_single_link: - g++ -Wextra -Wall -I../.. -I../ -I$(HOME)/local/include -O1 -DNDEBUG src/extract_text_single_link.cc -o bin/extract_text_single_link.out + g++ $(CXX_FLAGS) src/extract_text_single_link.cc -o bin/extract_text_single_link.out extract_text_double_link: - g++ -Wextra -Wall -I../.. -I../ -I$(HOME)/local/include -O1 -DNDEBUG src/extract_text_double_link.cc -o bin/extract_text_double_link.out + g++ $(CXX_FLAGS) src/extract_text_double_link.cc -o bin/extract_text_double_link.out extract_text_multiple_links: - g++ -Wextra -Wall -I../.. -I../ -I$(HOME)/local/include -O1 -DNDEBUG src/extract_text_multiple_links.cc -o bin/extract_text_multiple_links.out + g++ $(CXX_FLAGS) src/extract_text_multiple_links.cc -o bin/extract_text_multiple_links.out + +table_rebuild: + g++ $(CXX_FLAGS) src/table_rebuild.cc -o bin/table_rebuild.out + +table_extract: + g++ $(CXX_FLAGS) src/table_extract.cc -o bin/table_extract.out +thin_bboxes: + g++ $(CXX_FLAGS) src/thin_bboxes.cc -o bin/thin_bboxes.out clean: rm *.ppm *.pgm *.pbm diff --git a/milena/sandbox/scribo/core/central_sites.hh b/milena/sandbox/scribo/core/central_sites.hh index fe47625..80686f8 100644 --- a/milena/sandbox/scribo/core/central_sites.hh +++ b/milena/sandbox/scribo/core/central_sites.hh @@ -86,7 +86,7 @@ namespace scribo p2[dim] += n / 2; trace::exiting("scribo::central_sites"); - return make::couple(p1, p2); + return mln::make::couple(p1, p2); } # endif // ! MLN_INCLUDE_ONLY diff --git a/milena/sandbox/scribo/core/component_bboxes.hh b/milena/sandbox/scribo/core/component_bboxes.hh index 5af99fc..16b6fa0 100644 --- a/milena/sandbox/scribo/core/component_bboxes.hh +++ b/milena/sandbox/scribo/core/component_bboxes.hh @@ -43,23 +43,28 @@ # include <mln/util/array.hh> +# include <mln/debug/println.hh> namespace scribo { + using namespace mln; + /// Extract the components bboxes. template <typename I, typename N, typename V> - util::array< box<mln_site(I)> > + util::couple<util::array< box<mln_site(I)> >, mln_ch_value(I,V)> component_bboxes(const Image<I>& input, - const Neighborhood<N>& nbh, const V& label_type); + const Neighborhood<N>& nbh, + V& nbboxes); # ifndef MLN_INCLUDE_ONLY template <typename I, typename N, typename V> inline - util::array< box<mln_site(I)> > + util::couple<util::array< box<mln_site(I)> >, mln_ch_value(I,V)> component_bboxes(const Image<I>& input, - const Neighborhood<N>& nbh, const V&) + const Neighborhood<N>& nbh, + V& nbboxes) { trace::entering("scribo::component_bboxes"); @@ -68,13 +73,15 @@ namespace scribo mln_precondition(exact(input).is_valid()); mln_precondition(exact(nbh).is_valid()); - V nbboxes; mln_ch_value(I,V) lbl = labeling::blobs(input, nbh, nbboxes); + mln_assertion(exact(lbl).is_valid()); + typedef util::array< box<mln_site(I)> > bboxes_t; bboxes_t bboxes = labeling::compute(accu::meta::bbox(), lbl, nbboxes); + mln_postcondition(bboxes.nelements() == nbboxes.next()); trace::exiting("scribo::component_bboxes"); - return bboxes; + return mln::make::couple(bboxes, lbl); } # endif // ! MLN_INCLUDE_ONLY diff --git a/milena/sandbox/scribo/core/erase_bboxes.hh b/milena/sandbox/scribo/core/erase_bboxes.hh index cea998b..f4b2392 100644 --- a/milena/sandbox/scribo/core/erase_bboxes.hh +++ b/milena/sandbox/scribo/core/erase_bboxes.hh @@ -44,6 +44,8 @@ namespace scribo { + using namespace mln; + /// Remove the content of bounding boxes from an image. template <typename I> void @@ -68,7 +70,7 @@ namespace scribo for_all_components(i, bboxes) data::paste((pw::cst(false) | bboxes[i] | - (pw::value(input) == true)), input); + (pw::value(input) == true)), input); trace::exiting("scribo::erase_bboxes"); } diff --git a/milena/sandbox/scribo/debug/save_linked_textbboxes_image.hh b/milena/sandbox/scribo/debug/save_linked_textbboxes_image.hh index a7f8927..4012c05 100644 --- a/milena/sandbox/scribo/debug/save_linked_textbboxes_image.hh +++ b/milena/sandbox/scribo/debug/save_linked_textbboxes_image.hh @@ -42,6 +42,7 @@ # include <scribo/draw/bounding_boxes.hh> # include <scribo/draw/bounding_box_links.hh> +# include <scribo/util/text.hh> namespace scribo @@ -54,32 +55,32 @@ namespace scribo /// Save the bounding box links image. - template <typename I> + template <typename I, typename L> void save_linked_textbboxes_image(const Image<I>& input, - const util::array< box<mln_site(I)> >& textbboxes, - const util::array<unsigned>& link_array, + const scribo::util::text<L>& text, + const mln::util::array<unsigned>& link_array, const value::rgb8& box_value, const value::rgb8& link_value, const std::string& filename); - template <typename I> + template <typename I, typename L> void save_linked_textbboxes_image(const Image<I>& input, - const util::array< box<mln_site(I)> >& textbboxes, - const util::array<unsigned>& left_link, - const util::array<unsigned>& right_array, + const scribo::util::text<L>& text, + const mln::util::array<unsigned>& left_link, + const mln::util::array<unsigned>& right_array, const value::rgb8& box_value, const value::rgb8& left_link_value, const value::rgb8& right_link_value, const std::string& filename); - template <typename I, typename G> + template <typename I, typename L, typename G> void save_linked_textbboxes_image(const Image<I>& input, - const util::array< box<mln_site(I)> >& textbboxes, + const scribo::util::text<L>& text, const Graph<G>& g, const value::rgb8& box_value, const value::rgb8& link_value, @@ -89,12 +90,12 @@ namespace scribo # ifndef MLN_INCLUDE_ONLY - template <typename I> + template <typename I, typename L> inline void save_linked_textbboxes_image(const Image<I>& input, - const util::array< box<mln_site(I)> >& textbboxes, - const util::array<unsigned>& link_array, + const scribo::util::text<L>& text, + const mln::util::array<unsigned>& link_array, const value::rgb8& box_value, const value::rgb8& link_value, const std::string& filename) @@ -103,21 +104,21 @@ namespace scribo mln_precondition(exact(input).is_valid()); mln_ch_value(I,value::rgb8) tmp = level::convert(value::rgb8(), input); - draw::bounding_boxes(tmp, textbboxes, box_value); - draw::bounding_box_links(tmp, textbboxes, link_array, link_value); + draw::bounding_boxes(tmp, text.bboxes(), box_value); + draw::bounding_box_links(tmp, text.bboxes(), link_array, link_value); io::ppm::save(tmp, filename); trace::exiting("scribo::debug::save_linked_textbboxes_image"); } - template <typename I> + template <typename I, typename L> inline void save_linked_textbboxes_image(const Image<I>& input, - const util::array< box<mln_site(I)> >& textbboxes, - const util::array<unsigned>& left_link, - const util::array<unsigned>& right_link, + const scribo::util::text<L>& text, + const mln::util::array<unsigned>& left_link, + const mln::util::array<unsigned>& right_link, const value::rgb8& box_value, const value::rgb8& left_value, const value::rgb8& right_value, @@ -127,8 +128,8 @@ namespace scribo mln_precondition(exact(input).is_valid()); mln_ch_value(I,value::rgb8) tmp = level::convert(value::rgb8(), input); - draw::bounding_boxes(tmp, textbboxes, box_value); - draw::bounding_box_links(tmp, textbboxes, + draw::bounding_boxes(tmp, text.bboxes(), box_value); + draw::bounding_box_links(tmp, text.bboxes(), left_link, right_link, left_value, right_value); io::ppm::save(tmp, filename); @@ -137,11 +138,11 @@ namespace scribo } - template <typename I, typename G> + template <typename I, typename L, typename G> inline void save_linked_textbboxes_image(const Image<I>& input, - const util::array< box<mln_site(I)> >& textbboxes, + const scribo::util::text<L>& text, const Graph<G>& g, const value::rgb8& box_value, const value::rgb8& link_value, @@ -152,8 +153,8 @@ namespace scribo mln_precondition(exact(input).is_valid()); mln_ch_value(I,value::rgb8) tmp = level::convert(value::rgb8(), input); - draw::bounding_boxes(tmp, textbboxes, box_value); - draw::bounding_box_links(tmp, textbboxes, g, link_value); + draw::bounding_boxes(tmp, text.bboxes(), box_value); + draw::bounding_box_links(tmp, text.bboxes(), g, link_value); io::ppm::save(tmp, filename); trace::exiting("scribo::debug::save_linked_textbboxes_image"); diff --git a/milena/sandbox/scribo/debug/save_table_image.hh b/milena/sandbox/scribo/debug/save_table_image.hh index b170420..4ed0a68 100644 --- a/milena/sandbox/scribo/debug/save_table_image.hh +++ b/milena/sandbox/scribo/debug/save_table_image.hh @@ -36,7 +36,9 @@ # include <string> # include <mln/core/concept/image.hh> +# include <mln/core/image/image2d.hh> # include <mln/data/fill.hh> +# include <mln/level/convert.hh> # include <mln/util/array.hh> # include <mln/util/couple.hh> # include <mln/value/rgb8.hh> @@ -50,16 +52,29 @@ namespace scribo namespace debug { - /// Save lines bounding boxes in an image filled with \p bg_color. + using namespace mln; + + /// Save lines bounding boxes in a copy of \p input_. /// Bounding boxes are displayed with \p bbox_color. template <typename I> void - save_table(const Image<I>& input_, - util::couple<util::array<box<mln_site(I)> >, - util::array<box<mln_site(I)> > > tableboxes, - const value::rgb8& bg_color, - const value::rgb8& bbox_color, - const std::string& filename); + save_table_image(const Image<I>& input_, + util::couple<util::array<box<mln_site(I)> >, + util::array<box<mln_site(I)> > > tableboxes, + const value::rgb8& bbox_color, + const std::string& filename); + + /// Save lines bounding boxes in an image defined on \p input_domain + /// filled with \p bg_color. + /// Bounding boxes are displayed with \p bbox_color. + template <typename S> + void + save_table_image(const Site_Set<S>& input_domain, + util::couple<util::array<box<mln_site(S)> >, + util::array<box<mln_site(S)> > > tableboxes, + const value::rgb8& bg_color, + const value::rgb8& bbox_color, + const std::string& filename); # ifndef MLN_INCLUDE_ONLY @@ -67,18 +82,40 @@ namespace scribo template <typename I> void - save_table(const Image<I>& input_, - util::couple<util::array<box<mln_site(I)> >, - util::array<box<mln_site(I)> > > tableboxes, - const value::rgb8& bg_color, - const value::rgb8& bbox_color, - const std::string& filename) + save_table_image(const Image<I>& input_, + util::couple<util::array<box<mln_site(I)> >, + util::array<box<mln_site(I)> > > tableboxes, + const value::rgb8& bbox_color, + const std::string& filename) { trace::entering("scribo::debug::save_table_image"); +// mlc_converts_to(mln_value(I), value::rgb8)::check(); const I& input = exact(input_); mln_precondition(input.is_valid()); - mln_ch_value(I,value::rgb8) out2(exact(input).domain()); + mln_ch_value(I,value::rgb8) out2 = level::convert(value::rgb8(), input); + draw::bounding_boxes(out2, tableboxes.first(), bbox_color); + draw::bounding_boxes(out2, tableboxes.second(), bbox_color); + io::ppm::save(out2, filename); + + trace::exiting("scribo::internal::save_table"); + } + + + template <typename S> + void + save_table_image(const Site_Set<S>& input_domain_, + util::couple<util::array<box<mln_site(S)> >, + util::array<box<mln_site(S)> > > tableboxes, + const value::rgb8& bg_color, + const value::rgb8& bbox_color, + const std::string& filename) + { + trace::entering("scribo::debug::save_table_image"); + const S& input_domain = exact(input_domain_); + mln_precondition(input_domain.is_valid()); + + image2d<value::rgb8> out2(input_domain); data::fill(out2, bg_color); draw::bounding_boxes(out2, tableboxes.first(), bbox_color); draw::bounding_boxes(out2, tableboxes.second(), bbox_color); diff --git a/milena/sandbox/scribo/debug/save_textbboxes_image.hh b/milena/sandbox/scribo/debug/save_textbboxes_image.hh index b210b39..86a8b3f 100644 --- a/milena/sandbox/scribo/debug/save_textbboxes_image.hh +++ b/milena/sandbox/scribo/debug/save_textbboxes_image.hh @@ -40,6 +40,7 @@ # include <mln/io/ppm/save.hh> # include <scribo/draw/bounding_boxes.hh> +# include <scribo/make/debug_filename.hh> namespace scribo @@ -55,7 +56,7 @@ namespace scribo template <typename I> void save_textbboxes_image(const Image<I>& input, - const util::array< box<mln_site(I)> >& textbboxes, + const mln::util::array< box<mln_site(I)> >& textbboxes, const value::rgb8& value, const std::string& filename); @@ -66,7 +67,7 @@ namespace scribo inline void save_textbboxes_image(const Image<I>& input, - const util::array< box<mln_site(I)> >& textbboxes, + const mln::util::array< box<mln_site(I)> >& textbboxes, const value::rgb8& value, const std::string& filename) { @@ -75,7 +76,7 @@ namespace scribo mln_ch_value(I,value::rgb8) tmp = level::convert(value::rgb8(), input); draw::bounding_boxes(tmp, textbboxes, value); - io::ppm::save(tmp, filename); + io::ppm::save(tmp, scribo::make::debug_filename(filename)); trace::exiting("scribo::debug::save_textbboxes_image"); } diff --git a/milena/sandbox/scribo/draw/bounding_box_links.hh b/milena/sandbox/scribo/draw/bounding_box_links.hh index 7cf57ac..e33da38 100644 --- a/milena/sandbox/scribo/draw/bounding_box_links.hh +++ b/milena/sandbox/scribo/draw/bounding_box_links.hh @@ -52,17 +52,17 @@ namespace scribo template <typename I> void bounding_box_links(Image<I>& input_, - const util::array< box<mln_site(I)> >& bboxes, - const util::array<unsigned>& link_array, + const mln::util::array< box<mln_site(I)> >& bboxes, + const mln::util::array<unsigned>& link_array, const mln_value(I)& value); template <typename I> void bounding_box_links(Image<I>& input, - const util::array< box<mln_site(I)> >& bboxes, - const util::array<unsigned>& left_link, - const util::array<unsigned>& right_link, + const mln::util::array< box<mln_site(I)> >& bboxes, + const mln::util::array<unsigned>& left_link, + const mln::util::array<unsigned>& right_link, const mln_value(I)& left_link_value, const mln_value(I)& right_link_value); @@ -78,7 +78,7 @@ namespace scribo { draw_graph_edges_functor(I& ima, - const util::array<box<mln_site(I)> >& textbboxes, + const mln::util::array<box<mln_site(I)> >& textbboxes, const mln_value(I)& value) : ima_(ima), textbboxes_(textbboxes), value_(value) {} @@ -114,7 +114,7 @@ namespace scribo { return to_be_treated(id); } I& ima_; - const util::array<box<mln_site(I)> >& textbboxes_; + const mln::util::array<box<mln_site(I)> >& textbboxes_; mln_value(I) value_; unsigned current_vertex; std::vector<bool> deja_vu; @@ -127,8 +127,8 @@ namespace scribo inline void bounding_box_links(Image<I>& input_, - const util::array< box<mln_site(I)> >& bboxes, - const util::array<unsigned>& link_array, + const mln::util::array< box<mln_site(I)> >& bboxes, + const mln::util::array<unsigned>& link_array, const mln_value(I)& value) { trace::entering("scribo::draw::bounding_box_links"); @@ -152,9 +152,9 @@ namespace scribo inline void bounding_box_links(Image<I>& input, - const util::array< box<mln_site(I)> >& bboxes, - const util::array<unsigned>& left_link, - const util::array<unsigned>& right_link, + const mln::util::array< box<mln_site(I)> >& bboxes, + const mln::util::array<unsigned>& left_link, + const mln::util::array<unsigned>& right_link, const mln_value(I)& left_link_value, const mln_value(I)& right_link_value) { @@ -172,7 +172,7 @@ namespace scribo inline void bounding_box_links(Image<I>& input, - const util::array< box<mln_site(I)> >& bboxes, + const mln::util::array< box<mln_site(I)> >& bboxes, const Graph<G>& g, const mln_value(I)& link_value) { diff --git a/milena/sandbox/scribo/draw/bounding_boxes.hh b/milena/sandbox/scribo/draw/bounding_boxes.hh index 0db60a4..bfebaf3 100644 --- a/milena/sandbox/scribo/draw/bounding_boxes.hh +++ b/milena/sandbox/scribo/draw/bounding_boxes.hh @@ -51,7 +51,7 @@ namespace scribo template <typename I> void bounding_boxes(Image<I>& input_, - const util::array< box<mln_site(I)> >& boxes, + const mln::util::array< box<mln_site(I)> >& boxes, const mln_value(I)& value); @@ -63,7 +63,7 @@ namespace scribo inline void bounding_boxes(Image<I>& input_, - const util::array< box<mln_site(I)> >& boxes, + const mln::util::array< box<mln_site(I)> >& boxes, const mln_value(I)& value) { trace::entering("scribo::draw::bounding_boxes"); diff --git a/milena/sandbox/scribo/filter/large_components.hh b/milena/sandbox/scribo/filter/large_components.hh new file mode 100644 index 0000000..9ea4e02 --- /dev/null +++ b/milena/sandbox/scribo/filter/large_components.hh @@ -0,0 +1,196 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library 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. + +#ifndef SCRIBO_FILTER_LARGE_COMPONENTS_HH +# define SCRIBO_FILTER_LARGE_COMPONENTS_HH + +/// \file scribo/filter/large_components.hh +/// +/// Remove large components in a binary image. + + +# include <mln/core/concept/image.hh> +# include <mln/core/concept/neighborhood.hh> +# include <mln/core/concept/function.hh> + +# include <mln/labeling/blobs.hh> +# include <mln/labeling/relabel.hh> + +# include <mln/util/array.hh> +# include <mln/value/label_16.hh> + +# include <mln/pw/all.hh> + +namespace scribo +{ + + namespace filter + { + + using namespace mln; + + + /// Remove large components in a binary image. + /// Set to 'false' all the removed components. + /// + /// \param[in] input_ A binary image. + /// \param[in] nbh_ A neighborhood used for labeling \p input_. + /// \param[in] label_type The label type used for labeling. + /// \param[in] max_size The minimum cardinality of a component. + /// + /// \return A binary image without large components. + template <typename I, typename N, typename V> + mln_concrete(I) + large_components(const Image<I>& input_, + const Neighborhood<N>& nbh_, + const V& label_type, + unsigned max_size); + + + /// Remove large bboxes in a binary image. + /// Set to 'false' all the removed bboxes. + /// + /// \param[in] input_ A binary image. + /// \param[in] bboxes Bounding boxes of components extracted from \p + /// input_. + /// \param[in] max_size The minimum cardinality of a component. + /// + /// \return A binary image without large bboxes. + template <typename P> + util::array< box<P> > + large_components(const util::array< box<P> >& bboxes, + unsigned max_size); + + +# ifndef MLN_INCLUDE_ONLY + + + namespace internal + { + + + /// Filter Functor. Return false for all components which are too + /// large. + template <typename R> + struct filter_large_components_functor + : Function_l2b< filter_large_and_large_functor<R> > + { + filter_large_components_functor(const util::array<R>& nsitecomp, + unsigned max_size) + : nsitecomp_(nsitecomp), max_size_(max_size) + { + } + + + /// Return false if the components area is strictly inferior to + /// \p max_size_. + bool operator()(const value::label_16& l) const + { + return nsitecomp_[l] <= max_size_; + } + + + const util::array<R>& nsitecomp_; + unsigned max_size_; + }; + + + } // end of namespace scribo::filter::internal + + + + template <typename I, typename N, typename V> + inline + mln_concrete(I) + large_components(const Image<I>& input_, + const Neighborhood<N>& nbh_, + const V& label_type, + unsigned max_size) + { + trace::entering("scribo::filter::large_components"); + + const I& input = exact(input_); + const N& nbh = exact(nbh_); + + mln_precondition(input.is_valid()); + mln_precondition(nbh.is_valid()); + + V nlabels; + mln_ch_value(I,V) lbl = labeling::blobs(input, nbh, nlabels); + + typedef accu::count<mln_psite(I)> accu_count_t; + typedef mln_result(accu_count_t) accu_count_res_t; + typedef util::array<accu_count_res_t> nsitecomp_t; + nsitecomp_t nsitecomp = labeling::compute(accu_count_t(), lbl, nlabels); + + typedef internal::filter_large_and_large_functor<accu_count_res_t> func_t; + func_t fl2b(nsitecomp, max_size); + labeling::relabel_inplace(lbl, nlabels, fl2b); + + mln_concrete(I) output = duplicate(input); + data::fill((output | pw::value(lbl) == literal::zero).rw(), false); + + trace::exiting("scribo::filter::large_components"); + return output; + } + + + template <typename P> + inline + util::array< box<P> > + large_components(const util::array< box<P> >& bboxes, + unsigned max_size) + { + trace::entering("scribo::filter::large_components"); + + mln_precondition(input.is_valid()); + + typedef accu::count<P> accu_count_t; + typedef mln_result(accu_count_t) accu_count_res_t; + typedef util::array<accu_count_res_t> nsitecomp_t; + + util::array<box<P> > result; + result.append(box<P>()); + for_all_components(i, bboxes) + { + accu_count_res_t count = set::compute(accu_count_t(), bboxes[i]); + if (count <= max_size) + result.append(bboxes[i]); + } + + trace::exiting("scribo::filter::large_components"); + return result; + } + + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace scribo::filter + +} // end of namespace scribo + +#endif // ! SCRIBO_FILTER_LARGE_COMPONENTS_HH diff --git a/milena/sandbox/scribo/filter/small_components.hh b/milena/sandbox/scribo/filter/small_components.hh new file mode 100644 index 0000000..8cb6858 --- /dev/null +++ b/milena/sandbox/scribo/filter/small_components.hh @@ -0,0 +1,207 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library 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. + +#ifndef SCRIBO_FILTER_SMALL_COMPONENTS_HH +# define SCRIBO_FILTER_SMALL_COMPONENTS_HH + +/// \file scribo/filter/small_components.hh +/// +/// Remove small components in a binary image. + + +# include <mln/core/concept/image.hh> +# include <mln/core/concept/neighborhood.hh> +# include <mln/core/concept/function.hh> + +# include <mln/labeling/blobs.hh> +# include <mln/labeling/relabel.hh> + +# include <mln/util/array.hh> +# include <mln/value/label_16.hh> + +# include <mln/pw/all.hh> + +# include <scribo/util/text.hh> +# include <scribo/make/text.hh> + + +namespace scribo +{ + + namespace filter + { + + using namespace mln; + + + /// Remove small components in a binary image. + /// Set to 'false' all the removed components. + /// + /// \param[in] input_ A binary image. + /// \param[in] nbh_ A neighborhood used for labeling \p input_. + /// \param[in] label_type The label type used for labeling. + /// \param[in] min_size The minimum cardinality of a component. + /// + /// \return A binary image without small components. + template <typename I, typename N, typename V> + mln_concrete(I) + small_components(const Image<I>& input_, + const Neighborhood<N>& nbh_, + const V& label_type, + unsigned min_size); + + + /// Remove too small text components. + /// + /// \param[in] text Text data. + /// \param[in] min_size The minimum cardinality of a component. + /// + /// \return updated text data. + template <typename I> + scribo::util::text<I> + small_components(const scribo::util::text<I>& text, + unsigned min_size); + + +# ifndef MLN_INCLUDE_ONLY + + + namespace internal + { + + + /// Filter Functor. Return false for all components which are too + /// small. + template <typename R> + struct filter_small_components_functor + : Function_l2b< filter_small_components_functor<R> > + { + filter_small_components_functor(const mln::util::array<R>& nsitecomp, + unsigned min_size) + : nsitecomp_(nsitecomp), min_size_(min_size) + { + } + + + /// Return false if the components area is strictly inferior to + /// \p min_size_. + bool operator()(const value::label_16& l) const + { + return nsitecomp_[l] >= min_size_; + } + + + const mln::util::array<R>& nsitecomp_; + unsigned min_size_; + }; + + + } // end of namespace scribo::filter::internal + + + + template <typename I, typename N, typename V> + inline + mln_concrete(I) + small_components(const Image<I>& input_, + const Neighborhood<N>& nbh_, + const V& label_type, + unsigned min_size) + { + trace::entering("scribo::filter::small_components"); + + const I& input = exact(input_); + const N& nbh = exact(nbh_); + + mln_precondition(input.is_valid()); + mln_precondition(nbh.is_valid()); + + V nlabels; + mln_ch_value(I,V) lbl = labeling::blobs(input, nbh, nlabels); + + typedef accu::count<mln_psite(I)> accu_count_t; + typedef mln_result(accu_count_t) accu_count_res_t; + typedef mln::util::array<accu_count_res_t> nsitecomp_t; + nsitecomp_t nsitecomp = labeling::compute(accu_count_t(), lbl, nlabels); + + typedef internal::filter_small_components_functor<accu_count_res_t> func_t; + func_t fl2b(nsitecomp, min_size); + labeling::relabel_inplace(lbl, nlabels, fl2b); + + mln_concrete(I) output = duplicate(input); + data::fill((output | pw::value(lbl) == literal::zero).rw(), false); + + trace::exiting("scribo::filter::small_components"); + return output; + } + + + template <typename I> + inline + scribo::util::text<I> + small_components(const scribo::util::text<I>& text, + unsigned min_size) + { + trace::entering("scribo::filter::small_components"); + + mln_precondition(text.is_valid()); + + typedef mln_site(I) P; + typedef accu::count<P> accu_count_t; + typedef mln_result(accu_count_t) accu_count_res_t; + typedef mln::util::array<accu_count_res_t> nsitecomp_t; + + fun::i2v::array<bool> f(text.nbboxes().next(), false); + f(0) = true; + mln::util::array<box<P> > bresult; + bresult.append(box<P>()); + for_all_components(i, text.bboxes()) + { + accu_count_res_t count = set::compute(accu_count_t(), text.bbox(i)); + if (count >= min_size) + { + bresult.append(text.bbox(i)); + f(i) = true; + } + } + + mln_value(I) new_nbboxes; + I new_lbl = labeling::relabel(text.label_image(), text.nbboxes(), + new_nbboxes, f); + + trace::exiting("scribo::filter::small_components"); + return scribo::make::text(bresult, new_lbl, new_nbboxes); + } + + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace scribo::filter + +} // end of namespace scribo + +#endif // ! SCRIBO_FILTER_SMALL_COMPONENTS_HH diff --git a/milena/sandbox/scribo/filter/thin_bboxes.hh b/milena/sandbox/scribo/filter/thin_bboxes.hh new file mode 100644 index 0000000..de99242 --- /dev/null +++ b/milena/sandbox/scribo/filter/thin_bboxes.hh @@ -0,0 +1,165 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library 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. + +#ifndef SCRIBO_FILTER_THIN_BBOXES_HH +# define SCRIBO_FILTER_THIN_BBOXES_HH + +/// \file scribo/filter/thin_bboxes.hh +/// +/// Remove too thin bboxes. + +# include <mln/labeling/blobs.hh> +# include <mln/labeling/compute.hh> +# include <mln/util/array.hh> + +# include <scribo/util/text.hh> + +namespace scribo +{ + + namespace filter + { + +# ifndef MLN_INCLUDE_ONLY + + namespace internal + { + + + /// Filter Functor. Return false for all components which are too + /// large. + template <typename R> + struct filter_too_thin_component_functor + : Function_l2b< filter_too_thin_component_functor<R> > + { + filter_too_thin_component_functor(const mln::util::array<R>& compbboxes, + unsigned min_thickness) + : compbboxes_(compbboxes), min_thickness_(min_thickness) + { + } + + + /// Return false if the components is thinner than + /// \p min_thickness_. + bool operator()(const value::label_16& l) const + { + return compbboxes_[l].nrows() > min_thickness_ + && compbboxes_[l].ncols() > min_thickness_; + } + + + const mln::util::array<R>& compbboxes_; + unsigned min_thickness_; + }; + + + } // end of namespace scribo::filter::internal + + + template <typename I, typename N, typename V> + inline + mln_concrete(I) + thin_bboxes(const Image<I>& input_, + const Neighborhood<N>& nbh_, + const V& label_type, + unsigned min_thickness) + { + trace::entering("scribo::filter::thin_bboxes"); + + const I& input = exact(input_); + const N& nbh = exact(nbh_); + + mln_precondition(input.is_valid()); + mln_precondition(nbh.is_valid()); + + V nlabels; + mln_ch_value(I,V) lbl = labeling::blobs(input, nbh, nlabels); + + typedef accu::bbox<mln_psite(I)> accu_bbox_t; + typedef mln_result(accu_bbox_t) accu_bbox_res_t; + typedef mln::util::array<accu_bbox_res_t> compbboxes_t; + compbboxes_t compbboxes = labeling::compute(accu_bbox_t(), lbl, nlabels); + + typedef internal::filter_too_thin_component_functor<accu_bbox_res_t> func_t; + func_t fl2b(compbboxes, min_thickness); + labeling::relabel_inplace(lbl, nlabels, fl2b); + + mln_concrete(I) output = duplicate(input); + data::fill((output | pw::value(lbl) == literal::zero).rw(), false); + + trace::exiting("scribo::filter::thin_bboxes"); + return output; + } + + + template <typename L> + inline + scribo::util::text<L> + thin_bboxes(const scribo::util::text<L>& text, + unsigned min_thickness) + { + trace::entering("scribo::filter::thin_bboxes"); + + mln_precondition(text.is_valid()); + + typedef mln_site(L) P; + typedef accu::bbox<P> accu_bbox_t; + typedef mln_result(accu_bbox_t) accu_bbox_res_t; + typedef mln::util::array<accu_bbox_res_t> nsitecomp_t; + + typedef internal::filter_too_thin_component_functor<accu_bbox_res_t> func_t; + func_t is_not_too_thin(text.bboxes(), min_thickness); + + fun::i2v::array<bool> f(text.nbboxes().next(), false); + f(0) = true; + mln::util::array<box<P> > bresult; + bresult.append(box<P>()); + for_all_components(i, text.bboxes()) + if (is_not_too_thin(i)) + { + bresult.append(text.bbox(i)); + f(i) = true; + } + + mln_value(L) new_nbboxes; + L new_lbl = labeling::relabel(text.label_image(), text.nbboxes(), + mln::make::relabelfun(f, text.nbboxes(), new_nbboxes)); + + mln_assertion(new_nbboxes.next() == bresult.nelements()); + + trace::exiting("scribo::filter::thin_bboxes"); + return scribo::make::text(bresult, new_lbl, new_nbboxes); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace scribo::filter + +} // end of namespace scribo + + +#endif // ! SCRIBO_FILTER_THIN_BBOXES_HH diff --git a/milena/sandbox/scribo/make/debug_filename.hh b/milena/sandbox/scribo/make/debug_filename.hh index b159328..5a9728c 100644 --- a/milena/sandbox/scribo/make/debug_filename.hh +++ b/milena/sandbox/scribo/make/debug_filename.hh @@ -35,6 +35,7 @@ /// Construct and returns a formated output file name. # include <sstream> +# include <mln/trace/all.hh> namespace scribo @@ -46,25 +47,43 @@ namespace scribo /// Construct and returns a formated output file name: /// /// `input_filename`_`id`_`name` + /// \sa scribo::make::internal::debug_filename_prefix std::string - debug_filename(const char *input_filename, - const char *name); + debug_filename(const std::string& name); + namespace internal + { + + /// Set the default debug filename prefix. + extern char *debug_filename_prefix; + + } // end of namespace scribo::make::internal + # ifndef MLN_INCLUDE_ONLY + + namespace internal + { + + char *debug_filename_prefix = 0; + + } // end of namespace scribo::make::internal + + inline std::string - debug_filename(const char *input_filename, - const char *name) + debug_filename(const std::string& name) { static int file_id = 1; std::ostringstream os; - os << "./" - << input_filename - << "_"; + + if (internal::debug_filename_prefix != 0) + os << internal::debug_filename_prefix << "_"; + else + mln::trace::warning("You may like to set a default filename prefix."); if (file_id < 10) os << "0"; diff --git a/milena/sandbox/scribo/text/extract_bboxes.hh b/milena/sandbox/scribo/make/text.hh similarity index 56% copy from milena/sandbox/scribo/text/extract_bboxes.hh copy to milena/sandbox/scribo/make/text.hh index 0c88880..3c32ad0 100644 --- a/milena/sandbox/scribo/text/extract_bboxes.hh +++ b/milena/sandbox/scribo/make/text.hh @@ -1,5 +1,4 @@ // Copyright (C) 2009 EPITA Research and Development Laboratory -// (LRDE) // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -26,13 +25,12 @@ // reasons why the executable file might be covered by the GNU General // Public License. +#ifndef SCRIBO_MAKE_TEXT_HH +# define SCRIBO_MAKE_TEXT_HH -#ifndef SCRIBO_TEXT_GROUPING_EXTRACT_BBOXES_HH -# define SCRIBO_TEXT_GROUPING_EXTRACT_BBOXES_HH - -/// \file scribo/text/grouping/group_with_single_link.hh +/// \file scribo/make/text.hh /// -/// Extract text bounding boxes from a binary image. +/// Construct a util::text. # include <mln/core/concept/image.hh> # include <mln/core/concept/neighborhood.hh> @@ -40,56 +38,77 @@ # include <mln/labeling/blobs.hh> # include <mln/labeling/compute.hh> # include <mln/util/array.hh> +# include <scribo/util/text.hh> -# include <scribo/core/component_bboxes.hh> namespace scribo { - namespace text + namespace make { - using namespace mln; - /// Extract text bounding boxes from a binary image. - /// - /// \param[in] input_ A binary image. - /// - /// \return an array of bounding boxes. The first bounding box is - /// the background's. + template <typename L> + scribo::util::text<L> + text(const mln::util::array<box<mln_site(L)> >& bboxes, + const Image<L>& lbl, + mln_value(L)& nbboxes); + + template <typename I, typename N, typename V> - inline - util::array< box<mln_site(I)> > - extract_bboxes(const Image<I>& input_, - const Neighborhood<N>& nbh, V& nbboxes); + scribo::util::text<mln_ch_value(I,V)> + text(const Image<I>& input_, const Neighborhood<N>& nbh_, + V& nbboxes); + # ifndef MLN_INCLUDE_ONLY + template <typename L> + scribo::util::text<L> + text(const mln::util::array<box<mln_site(L)> >& bboxes, + const Image<L>& lbl, + mln_value(L)& nbboxes) + { + trace::entering("scribo::make::text"); + + mln_precondition(exact(lbl).is_valid()); + + scribo::util::text<L> result = scribo::util::text<L>(bboxes, lbl, + nbboxes); + + trace::exiting("scribo::make::text"); + return result; + } + + template <typename I, typename N, typename V> - inline - util::array< box<mln_site(I)> > - extract_bboxes(const Image<I>& input_, - const Neighborhood<N>& nbh, V& nbboxes) + scribo::util::text<mln_ch_value(I,V)> + text(const Image<I>& input_, const Neighborhood<N>& nbh_, + V& nbboxes) { - trace::entering("scribo::text::extract_bboxes"); + trace::entering("scribo::make::text"); const I& input = exact(input_); + const N& nbh = exact(nbh_); - mlc_equal(mln_value(I), bool)::check(); mln_precondition(input.is_valid()); + mln_precondition(nbh.is_valid()); + + typedef mln::util::array< box<mln_site(I)> > boxes_t; + + mln_ch_value(I,V) lbl = labeling::blobs(input, nbh, nbboxes); - typedef util::array< box<mln_site(I)> > bboxes_t; - bboxes_t bboxes = component_bboxes(input, nbh, nbboxes); + boxes_t cboxes = labeling::compute(accu::meta::bbox(), lbl, nbboxes); - trace::exiting("scribo::text::extract_bboxes"); - return bboxes; + trace::exiting("scribo::make::text"); + return make::text(cboxes, lbl, nbboxes); } # endif // ! MLN_INCLUDE_ONLY - } // end of namespace scribo::text + } // end of namespace scribo::make } // end of namespace scribo -#endif // ! SCRIBO_TEXT_GROUPING_EXTRACT_BBOXES_HH +#endif // ! SCRIBO_MAKE_TEXT_HH diff --git a/milena/sandbox/scribo/src/dmap.cc b/milena/sandbox/scribo/src/dmap.cc new file mode 100644 index 0000000..dac40ba --- /dev/null +++ b/milena/sandbox/scribo/src/dmap.cc @@ -0,0 +1,26 @@ +#include <mln/essential/2d.hh> +#include <mln/core/var.hh> +#include <mln/fun/l2l/wrap.hh> +#include <mln/transform/distance_and_influence_zone_geodesic.hh> + +int main(int, char *argv[]) +{ + using namespace mln; + + using value::int_u16; + using value::label_16; + using value::label_8; + using value::rgb8; + + image2d<bool> ima; + io::pbm::load(ima, argv[1]); + + label_16 nlabels; + image2d<label_16> lbl = labeling::blobs(ima, c8(), nlabels); + + mln_VAR(res, transform::distance_and_influence_zone_geodesic(lbl, c8(), mln_max(unsigned))); + + io::pgm::save(level::transform(res.first(), fun::l2l::wrap<label_8>()), "dmap.pgm"); + io::ppm::save(debug::colorize(value::rgb8(), res.second(), nlabels), "iz.ppm"); + +} diff --git a/milena/sandbox/scribo/src/extract_text_double_link.cc b/milena/sandbox/scribo/src/extract_text_double_link.cc index 26fccff..ea4b2b8 100644 --- a/milena/sandbox/scribo/src/extract_text_double_link.cc +++ b/milena/sandbox/scribo/src/extract_text_double_link.cc @@ -28,6 +28,7 @@ #include <iostream> #include <mln/essential/2d.hh> +#include <mln/debug/colorize.hh> #include <scribo/text/extract_bboxes.hh> #include <scribo/text/grouping/group_with_single_left_link.hh> @@ -44,17 +45,6 @@ int usage(const char *name) } -namespace scribo { namespace text { namespace grouping -{ - using namespace mln; - - template <typename I> - util::array< box<mln_site(I)> > - group_from_double_link(const util::array< box<mln_site(I)> >& textbboxes, - util::array<unsigned>& left_link, - util::array<unsigned>& right_link); -}}} - int main(int argc, char* argv[]) { using namespace scribo; @@ -63,47 +53,56 @@ int main(int argc, char* argv[]) if (argc < 1) return usage(argv[0]); + scribo::make::internal::debug_filename_prefix = "extract_text_double_link"; + image2d<bool> input; io::pbm::load(input, argv[1]); value::label_16 nbboxes; - util::array<box2d> textbboxes = text::extract_bboxes(input, c8(), nbboxes); + scribo::util::text<image2d<value::label_16> > text + = text::extract_bboxes(input, c8(), nbboxes); - util::array<unsigned> left_link - = text::grouping::group_with_single_left_link(input, - c8(), nbboxes, - textbboxes, 30); - util::array<unsigned> right_link - = text::grouping::group_with_single_right_link(input, - c8(), nbboxes, - textbboxes, 30); + mln::util::array<unsigned> left_link + = text::grouping::group_with_single_left_link(text, 30); + mln::util::array<unsigned> right_link + = text::grouping::group_with_single_right_link(text, 30); std::cout << "BEFORE - nbboxes = " << nbboxes << std::endl; - scribo::debug::save_linked_textbboxes_image(input, - textbboxes, left_link, - literal::red, literal::cyan, - "test_double_link_left_linked.ppm"); - scribo::debug::save_linked_textbboxes_image(input, - textbboxes, right_link, - literal::red, literal::cyan, - "test_double_link_right_linked.ppm"); +// scribo::debug::save_linked_textbboxes_image(input, +// text, left_link, +// literal::red, literal::cyan, +// scribo::make::debug_filename("left_linked.ppm")); +// scribo::debug::save_linked_textbboxes_image(input, +// text, right_link, +// literal::red, literal::cyan, +// scribo::make::debug_filename("right_linked.ppm")); scribo::debug::save_linked_textbboxes_image(input, - textbboxes, left_link, right_link, + text, left_link, right_link, literal::red, literal::cyan, literal::yellow, - "test_double_link_double_linked.ppm"); + scribo::make::debug_filename("links.ppm")); + +// io::ppm::save(mln::debug::colorize(value::rgb8(), +// text.label_image(), +// text.nbboxes()), +// scribo::make::debug_filename("lbl_before.ppm")); // With validation. - util::array< box<point2d> > grouped_textbboxes - = text::grouping::group_from_double_link(textbboxes, left_link, right_link); + scribo::util::text<image2d<value::label_16> > grouped_text + = text::grouping::group_from_double_link(text, left_link, right_link); + + io::ppm::save(mln::debug::colorize(value::rgb8(), + grouped_text.label_image(), + grouped_text.nbboxes()), + scribo::make::debug_filename("label_color.ppm")); - std::cout << "AFTER double grouping - nbboxes = " << grouped_textbboxes.nelements() << std::endl; + std::cout << "AFTER double grouping - nbboxes = " << grouped_text.bboxes().nelements() << std::endl; - scribo::debug::save_textbboxes_image(input, grouped_textbboxes, + scribo::debug::save_textbboxes_image(input, grouped_text.bboxes(), literal::red, - "test_double_link_grouped_text.ppm"); + scribo::make::debug_filename("bboxes.ppm")); } diff --git a/milena/sandbox/scribo/src/extract_text_multiple_links.cc b/milena/sandbox/scribo/src/extract_text_multiple_links.cc index 9b181e6..0c8c624 100644 --- a/milena/sandbox/scribo/src/extract_text_multiple_links.cc +++ b/milena/sandbox/scribo/src/extract_text_multiple_links.cc @@ -50,29 +50,39 @@ int main(int argc, char* argv[]) if (argc < 1) return usage(argv[0]); + scribo::make::internal::debug_filename_prefix = "extract_text_multiple_links"; + image2d<bool> input; io::pbm::load(input, argv[1]); value::label_16 nbboxes; - util::array<box2d> textbboxes = text::extract_bboxes(input, c8(), nbboxes); + scribo::util::text<image2d<value::label_16> > text + = text::extract_bboxes(input, c8(), nbboxes); - util::graph g = text::grouping::group_with_multiple_links(input, - c8(), nbboxes, - textbboxes, 30); + mln::util::graph g = text::grouping::group_with_multiple_links(text, 30); - std::cout << "BEFORE - nbboxes = " << nbboxes << std::endl; + std::cout << "BEFORE - nbboxes = " << nbboxes.next() << std::endl; scribo::debug::save_linked_textbboxes_image(input, - textbboxes, g, + text, g, literal::red, literal::cyan, - "test_multiple_links_left_linked.ppm"); + scribo::make::debug_filename("left_linked.ppm")); +// io::ppm::save(mln::debug::colorize(value::rgb8(), +// text.label_image(), +// text.nbboxes()), +// scribo::make::debug_filename("lbl_before.ppm")); - util::array< box<point2d> > grouped_textbboxes - = text::grouping::group_from_multiple_links(textbboxes, g); + scribo::util::text<image2d<value::label_16> > grouped_text + = text::grouping::group_from_multiple_links(text, g); - std::cout << "AFTER - nbboxes = " << grouped_textbboxes.nelements() << std::endl; + std::cout << "AFTER - nbboxes = " << grouped_text.bboxes().nelements() << std::endl; - scribo::debug::save_textbboxes_image(input, grouped_textbboxes, + scribo::debug::save_textbboxes_image(input, grouped_text.bboxes(), literal::red, - "test_multiple_links_grouped_text.ppm"); + scribo::make::debug_filename("grouped_text.ppm")); + io::ppm::save(mln::debug::colorize(value::rgb8(), + grouped_text.label_image(), + grouped_text.nbboxes()), + scribo::make::debug_filename("label_color.ppm")); + } diff --git a/milena/sandbox/scribo/src/extract_text_single_link.cc b/milena/sandbox/scribo/src/extract_text_single_link.cc index 5b4e248..1dee956 100644 --- a/milena/sandbox/scribo/src/extract_text_single_link.cc +++ b/milena/sandbox/scribo/src/extract_text_single_link.cc @@ -51,56 +51,70 @@ int main(int argc, char* argv[]) if (argc < 1) return usage(argv[0]); + scribo::make::internal::debug_filename_prefix = "extract_text_single_link"; + image2d<bool> input; io::pbm::load(input, argv[1]); value::label_16 nbboxes; - util::array<box2d> textbboxes = text::extract_bboxes(input, c8(), nbboxes); + scribo::util::text<image2d<value::label_16> > text + = text::extract_bboxes(input, c8(), nbboxes); { std::cout << "* Left grouping" << std::endl; - util::array<unsigned> left_link - = text::grouping::group_with_single_left_link(input, - c8(), nbboxes, - textbboxes, 30); + mln::util::array<unsigned> left_link + = text::grouping::group_with_single_left_link(text, 30); std::cout << "BEFORE - nbboxes = " << nbboxes << std::endl; scribo::debug::save_linked_textbboxes_image(input, - textbboxes, left_link, + text, left_link, literal::red, literal::cyan, - "test_single_left_link_linked.ppm"); - - util::array< box<point2d> > grouped_textbboxes - = text::grouping::group_from_single_link(textbboxes, left_link); - - std::cout << "AFTER - nbboxes = " << grouped_textbboxes.nelements() << std::endl; - - scribo::debug::save_textbboxes_image(input, grouped_textbboxes, + scribo::make::debug_filename("left_links.ppm")); +// io::ppm::save(mln::debug::colorize(value::rgb8(), +// text.label_image(), +// text.nbboxes()), +// scribo::make::debug_filename("lbl_before.ppm")); + + scribo::util::text<image2d<value::label_16> > grouped_text + = text::grouping::group_from_single_link(text, left_link); + + std::cout << "AFTER - nbboxes = " << grouped_text.bboxes().nelements() << std::endl; + io::ppm::save(mln::debug::colorize(value::rgb8(), + grouped_text.label_image(), + grouped_text.nbboxes()), + scribo::make::debug_filename("left_label_color.ppm")); + scribo::debug::save_textbboxes_image(input, grouped_text.bboxes(), literal::red, - "test_single_left_link_grouped_text.ppm"); + scribo::make::debug_filename("left_bboxes.ppm")); } { std::cout << "* Left grouping" << std::endl; - util::array<unsigned> right_link - = text::grouping::group_with_single_right_link(input, - c8(), nbboxes, - textbboxes, 30); + mln::util::array<unsigned> right_link + = text::grouping::group_with_single_right_link(text, 30); std::cout << "BEFORE - nbboxes = " << nbboxes << std::endl; scribo::debug::save_linked_textbboxes_image(input, - textbboxes, right_link, + text, right_link, literal::red, literal::cyan, - "test_single_right_link_linked.ppm"); - - util::array< box<point2d> > grouped_textbboxes - = text::grouping::group_from_single_link(textbboxes, right_link); - - std::cout << "AFTER - nbboxes = " << grouped_textbboxes.nelements() << std::endl; - - scribo::debug::save_textbboxes_image(input, grouped_textbboxes, + scribo::make::debug_filename("right_links.ppm")); +// io::ppm::save(mln::debug::colorize(value::rgb8(), +// text.label_image(), +// text.nbboxes()), +// scribo::make::debug_filename("lbl_before.ppm")); + + scribo::util::text<image2d<value::label_16> > grouped_text + = text::grouping::group_from_single_link(text, right_link); + + io::ppm::save(mln::debug::colorize(value::rgb8(), + grouped_text.label_image(), + grouped_text.nbboxes()), + scribo::make::debug_filename("right_label_color.ppm")); + std::cout << "AFTER - nbboxes = " << grouped_text.bboxes().nelements() << std::endl; + + scribo::debug::save_textbboxes_image(input, grouped_text.bboxes(), literal::red, - "test_single_right_link_grouped_text.ppm"); + scribo::make::debug_filename("right_bboxes.ppm")); } diff --git a/milena/sandbox/scribo/src/morpho.cc b/milena/sandbox/scribo/src/morpho.cc new file mode 100644 index 0000000..a527a3d --- /dev/null +++ b/milena/sandbox/scribo/src/morpho.cc @@ -0,0 +1,64 @@ +#include <mln/essential/2d.hh> +#include <mln/transform/distance_and_influence_zone_geodesic.hh> +#include <mln/core/var.hh> +#include <mln/fun/l2l/wrap.hh> +#include <mln/win/hline2d.hh> +#include <mln/morpho/watershed/flooding.hh> +#include <mln/morpho/watershed/superpose.hh> + +#include <scribo/make/debug_filename.hh> + +int main(int argc, char *argv[]) +{ + using namespace mln; + + using value::int_u16; + using value::label_16; + using value::label_8; + using value::rgb8; + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + scribo::make::internal::debug_filename_prefix = "morpho"; + + label_16 nlabels; + image2d<label_16> lbl = labeling::blobs(input, c8(), nlabels); + + mln_VAR(res, transform::distance_and_influence_zone_geodesic(lbl, c8(), mln_max(unsigned))); + + io::pgm::save(level::transform(res.first(), fun::l2l::wrap<label_8>()), "dmap.pgm"); + io::ppm::save(debug::colorize(rgb8(), res.second(), nlabels), "iz.ppm"); + + image2d<unsigned>& dmap = res.first(); + { + image2d<unsigned> clo = morpho::closing::structural(dmap, win::hline2d(51)); + io::pgm::save(clo, scribo::make::debug_filename("clo_line_51.pgm")); + label_16 nlabels; + image2d<label_16> wsd = morpho::watershed::flooding(clo, c8(), nlabels); + + io::ppm::save(morpho::watershed::superpose(input, wsd), + scribo::make::debug_filename("wsd_line_51.ppm")); + } + + { + image2d<unsigned> clo = morpho::closing::structural(dmap, win::rectangle2d(11, 101)); + io::pgm::save(clo, scribo::make::debug_filename("clo_rectangle_11_101.pgm")); + label_16 nlabels; + image2d<label_16> wsd = morpho::watershed::flooding(clo, c8(), nlabels); + + io::ppm::save(morpho::watershed::superpose(input, wsd), + scribo::make::debug_filename("wsd_rectangle_11_101.ppm")); + } + + { + image2d<unsigned> clo = morpho::closing::structural(dmap, win::disk2d(51)); + io::pgm::save(clo, scribo::make::debug_filename("clo_disk_51.pgm")); + label_16 nlabels; + image2d<label_16> wsd = morpho::watershed::flooding(clo, c8(), nlabels); + + io::ppm::save(morpho::watershed::superpose(input, wsd), + scribo::make::debug_filename("wsd_disk_51.ppm")); + } + +??? diff --git a/milena/sandbox/scribo/src/table.cc b/milena/sandbox/scribo/src/table.cc index 3472599..3a12c57 100644 --- a/milena/sandbox/scribo/src/table.cc +++ b/milena/sandbox/scribo/src/table.cc @@ -26,7 +26,7 @@ // Public License. -#include "demat.hh" +#include <demat.hh> int main(int argc, char*argv[]) { diff --git a/milena/sandbox/scribo/src/extract_text_multiple_links.cc b/milena/sandbox/scribo/src/table_extract.cc similarity index 61% copy from milena/sandbox/scribo/src/extract_text_multiple_links.cc copy to milena/sandbox/scribo/src/table_extract.cc index 9b181e6..36142a2 100644 --- a/milena/sandbox/scribo/src/extract_text_multiple_links.cc +++ b/milena/sandbox/scribo/src/table_extract.cc @@ -28,13 +28,10 @@ #include <iostream> #include <mln/essential/2d.hh> +#include <mln/io/dump/save.hh> -#include <scribo/text/extract_bboxes.hh> -#include <scribo/text/grouping/group_with_multiple_links.hh> -#include <scribo/text/grouping/group_from_multiple_links.hh> +#include <scribo/table/extract.hh> -#include <scribo/debug/save_textbboxes_image.hh> -#include <scribo/debug/save_linked_textbboxes_image.hh> int usage(const char *name) { @@ -42,6 +39,7 @@ int usage(const char *name) return 1; } + int main(int argc, char* argv[]) { using namespace scribo; @@ -50,29 +48,20 @@ int main(int argc, char* argv[]) if (argc < 1) return usage(argv[0]); + scribo::make::internal::debug_filename_prefix = argv[0]; + image2d<bool> input; io::pbm::load(input, argv[1]); + logical::not_inplace(input); - value::label_16 nbboxes; - util::array<box2d> textbboxes = text::extract_bboxes(input, c8(), nbboxes); - - util::graph g = text::grouping::group_with_multiple_links(input, - c8(), nbboxes, - textbboxes, 30); + trace::quiet = false; - std::cout << "BEFORE - nbboxes = " << nbboxes << std::endl; - scribo::debug::save_linked_textbboxes_image(input, - textbboxes, g, - literal::red, literal::cyan, - "test_multiple_links_left_linked.ppm"); + value::label_16 ncells; + image2d<value::label_16> tables = scribo::table::extract(input, ncells); - util::array< box<point2d> > grouped_textbboxes - = text::grouping::group_from_multiple_links(textbboxes, g); + std::cout << "ncells (including background) = " << ncells << std::endl; + io::ppm::save(mln::debug::colorize(value::rgb8(), tables, ncells), + scribo::make::debug_filename("table_cells.ppm")); - std::cout << "AFTER - nbboxes = " << grouped_textbboxes.nelements() << std::endl; - - scribo::debug::save_textbboxes_image(input, grouped_textbboxes, - literal::red, - "test_multiple_links_grouped_text.ppm"); + io::dump::save(tables, scribo::make::debug_filename("table_cells.dump")); } - diff --git a/milena/sandbox/scribo/src/extract_text_multiple_links.cc b/milena/sandbox/scribo/src/table_rebuild.cc similarity index 61% copy from milena/sandbox/scribo/src/extract_text_multiple_links.cc copy to milena/sandbox/scribo/src/table_rebuild.cc index 9b181e6..d195b5b 100644 --- a/milena/sandbox/scribo/src/extract_text_multiple_links.cc +++ b/milena/sandbox/scribo/src/table_rebuild.cc @@ -29,12 +29,11 @@ #include <mln/essential/2d.hh> -#include <scribo/text/extract_bboxes.hh> -#include <scribo/text/grouping/group_with_multiple_links.hh> -#include <scribo/text/grouping/group_from_multiple_links.hh> +#include <scribo/table/rebuild.hh> +#include <scribo/table/erase.hh> +#include <scribo/table/extract_lines_with_rank.hh> +#include <scribo/make/debug_filename.hh> -#include <scribo/debug/save_textbboxes_image.hh> -#include <scribo/debug/save_linked_textbboxes_image.hh> int usage(const char *name) { @@ -42,6 +41,7 @@ int usage(const char *name) return 1; } + int main(int argc, char* argv[]) { using namespace scribo; @@ -50,29 +50,30 @@ int main(int argc, char* argv[]) if (argc < 1) return usage(argv[0]); + scribo::make::internal::debug_filename_prefix = argv[0]; + image2d<bool> input; io::pbm::load(input, argv[1]); + logical::not_inplace(input); - value::label_16 nbboxes; - util::array<box2d> textbboxes = text::extract_bboxes(input, c8(), nbboxes); + typedef util::couple<util::array<box2d>,util::array<box2d> > tblboxes_t; - util::graph g = text::grouping::group_with_multiple_links(input, - c8(), nbboxes, - textbboxes, 30); + win::vline2d vline(51); + win::hline2d hline(51); + tblboxes_t lineboxes + = table::extract_lines_with_rank(input, c8(), value::label_16(), + vline, hline, 6, 6); - std::cout << "BEFORE - nbboxes = " << nbboxes << std::endl; - scribo::debug::save_linked_textbboxes_image(input, - textbboxes, g, - literal::red, literal::cyan, - "test_multiple_links_left_linked.ppm"); + value::label_8 ncells; + image2d<value::label_8> tables = scribo::table::rebuild(input, lineboxes, 30, ncells); - util::array< box<point2d> > grouped_textbboxes - = text::grouping::group_from_multiple_links(textbboxes, g); - std::cout << "AFTER - nbboxes = " << grouped_textbboxes.nelements() << std::endl; + std::cout << "ncells (including background) = " << ncells << std::endl; + io::ppm::save(mln::debug::colorize(value::rgb8(), tables, ncells), + scribo::make::debug_filename("table_cells.ppm")); + io::pgm::save(tables, scribo::make::debug_filename("table_cells.pgm")); - scribo::debug::save_textbboxes_image(input, grouped_textbboxes, - literal::red, - "test_multiple_links_grouped_text.ppm"); + image2d<bool> in_wo_tables = table::erase(input, lineboxes); + io::pbm::save(in_wo_tables, + scribo::make::debug_filename("input_wo_tables.pbm")); } - diff --git a/milena/sandbox/scribo/src/thin_bboxes.cc b/milena/sandbox/scribo/src/thin_bboxes.cc new file mode 100644 index 0000000..77b158b --- /dev/null +++ b/milena/sandbox/scribo/src/thin_bboxes.cc @@ -0,0 +1,32 @@ +#include <mln/essential/2d.hh> +#include <scribo/text/extract_lines.hh> +#include <scribo/filter/thin_bboxes.hh> + +int usage(const char *name) +{ + std::cout << "Usage: " << name << " <input.pbm> " << std::endl; + return 1; +} + +int main(int argc, char *argv[]) +{ + using namespace mln; + + if (argc < 1) + return usage(argv[0]); + + scribo::make::internal::debug_filename_prefix = "thin_bboxes"; + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + value::label_16 nlines; + typedef scribo::util::text<image2d<value::label_16> > text_t; + text_t lines = scribo::text::extract_lines(input, c8(), nlines); + + text_t filtered_lines = scribo::filter::thin_bboxes(lines, 5); + + scribo::debug::save_textbboxes_image(input, filtered_lines.bboxes(), + literal::red, + scribo::make::debug_filename("thickness_filter")); +} diff --git a/milena/sandbox/scribo/table/align_lines_horizontaly.hh b/milena/sandbox/scribo/table/align_lines_horizontaly.hh index e75f2f2..4828cfe 100644 --- a/milena/sandbox/scribo/table/align_lines_horizontaly.hh +++ b/milena/sandbox/scribo/table/align_lines_horizontaly.hh @@ -38,8 +38,8 @@ # include <mln/core/concept/image.hh> # include <mln/core/site_set/box.hh> # include <mln/geom/nrows.hh> -# include <mln/geom/min_nrow.hh> -# include <mln/geom/max_nrow.hh> +# include <mln/geom/min_row.hh> +# include <mln/geom/max_row.hh> # include <mln/util/array.hh> @@ -52,18 +52,24 @@ namespace scribo namespace table { + using namespace mln; + /// Align line bounding boxes horizontaly. /// /// \param[in] input Image from which the line bboxes are /// extracted from. /// \param[in, out] lines_bboxes horizontal lines bounding boxes. + /// \param[in] max_alignment_diff max space between two lines to + /// consider they are potentialy on the + /// same line. /// /// \return A list of the resulting aligned rows. Each integer is actually /// a row number. template <typename I> util::array<int> align_lines_horizontaly(const Image<I>& input, - util::array<box<mln_site(I)> >& lines_bboxes); + util::array<box<mln_site(I)> >& lines_bboxes, + unsigned max_alignment_diff); # ifndef MLN_INCLUDE_ONLY @@ -72,7 +78,8 @@ namespace scribo template <typename I> util::array<int> align_lines_horizontaly(const Image<I>& input, - util::array<box<mln_site(I)> >& lines_bboxes) + util::array<box<mln_site(I)> >& lines_bboxes, + max_alignment_diff) { trace::entering("scribo::table::align_lines_horizontaly"); @@ -80,7 +87,8 @@ namespace scribo util::array<int> res = internal::align_lines(geom::nrows(input), geom::min_row(input), geom::max_row(input), - lines_bboxes, 0); + lines_bboxes, 0, + max_alignment_diff); trace::exiting("scribo::table::align_lines_horizontaly"); return res; diff --git a/milena/sandbox/scribo/table/align_lines_verticaly.hh b/milena/sandbox/scribo/table/align_lines_verticaly.hh index 7e860d0..e4d04ba 100644 --- a/milena/sandbox/scribo/table/align_lines_verticaly.hh +++ b/milena/sandbox/scribo/table/align_lines_verticaly.hh @@ -38,8 +38,8 @@ # include <mln/core/concept/image.hh> # include <mln/core/site_set/box.hh> # include <mln/geom/ncols.hh> -# include <mln/geom/min_ncol.hh> -# include <mln/geom/max_ncol.hh> +# include <mln/geom/min_col.hh> +# include <mln/geom/max_col.hh> # include <mln/util/array.hh> @@ -53,18 +53,24 @@ namespace scribo namespace table { + using namespace mln; + /// Align line bounding boxes verticaly. /// /// \param[in] input Image from which the line bboxes are /// extracted from. /// \param[in, out] lines_bboxes vertical lines bounding boxes. + /// \param[in] max_alignment_diff max space between two lines to + /// consider they are potentialy on the + /// same line. /// /// \return A list of the resulting aligned cols. Each integer is actually /// a col number. template <typename I> util::array<int> align_lines_verticaly(const Image<I>& input, - util::array<box<mln_site(I)> >& lines_bboxes); + util::array<box<mln_site(I)> >& lines_bboxes, + unsigned max_alignment_diff); # ifndef MLN_INCLUDE_ONLY @@ -81,7 +87,8 @@ namespace scribo util::array<int> res = internal::align_lines(geom::ncols(input), geom::min_col(input), geom::max_col(input), - lines_bboxes, 1); + lines_bboxes, 1, + max_alignment_diff); trace::exiting("scribo::table::align_lines_horizontaly"); return res; diff --git a/milena/sandbox/scribo/table/connect_horizontal_lines.hh b/milena/sandbox/scribo/table/connect_horizontal_lines.hh index 7dcf638..c1d3bd6 100644 --- a/milena/sandbox/scribo/table/connect_horizontal_lines.hh +++ b/milena/sandbox/scribo/table/connect_horizontal_lines.hh @@ -55,12 +55,15 @@ namespace scribo /// bounding boxes. /// \param[in] input The image from where the lines are /// extracted. + /// \param[in] max_distance max distance allowed between a vertical + /// and horizontal lines. template <typename I> void connect_vertical_lines(const util::array<int>& aligned_rows, util::couple<util::array<box<mln_site(I)> >, - util::array<box<mln_site(I)> > > tableboxes, - const Image<I>& input) + util::array<box<mln_site(I)> > >& tableboxes, + const Image<I>& input, + unsigned max_distance); # ifndef MLN_INCLUDE_ONLY @@ -70,14 +73,15 @@ namespace scribo void connect_horizontal_lines(const util::array<int>& aligned_cols, util::couple<util::array<box<mln_site(I)> >, - util::array<box<mln_site(I)> > > tableboxes, - const Image<I>& input) + util::array<box<mln_site(I)> > >& tableboxes, + const Image<I>& input, + unsigned max_distance) { trace::entering("scribo::table::connect_horizontal_lines"); mln_precondition(exact(input).is_valid()); internal::connect_lines(aligned_cols, tableboxes.second(), - 1, exact(input).ncols()); + 1, exact(input).ncols(), max_distance); trace::exiting("scribo::table::connect_horizontal_lines"); } diff --git a/milena/sandbox/scribo/table/connect_vertical_lines.hh b/milena/sandbox/scribo/table/connect_vertical_lines.hh index 98c39f7..2ab4990 100644 --- a/milena/sandbox/scribo/table/connect_vertical_lines.hh +++ b/milena/sandbox/scribo/table/connect_vertical_lines.hh @@ -55,12 +55,15 @@ namespace scribo /// bounding boxes. /// \param[in] input The image from where the lines are /// extracted. + /// \param[in] max_distance max distance allowed between a vertical + /// and horizontal lines. template <typename I> void connect_vertical_lines(const util::array<int>& aligned_rows, util::couple<util::array<box<mln_site(I)> >, - util::array<box<mln_site(I)> > > tableboxes, - const Image<I>& input) + util::array<box<mln_site(I)> > >& tableboxes, + const Image<I>& input, + unsigned max_distance); # ifndef MLN_INCLUDE_ONLY @@ -71,14 +74,15 @@ namespace scribo void connect_vertical_lines(const util::array<int>& aligned_rows, util::couple<util::array<box<mln_site(I)> >, - util::array<box<mln_site(I)> > > tableboxes, - const Image<I>& input) + util::array<box<mln_site(I)> > >& tableboxes, + const Image<I>& input, + unsigned max_distance) { trace::entering("scribo::table::connect_vertical_lines"); mln_precondition(exact(input).is_valid()); internal::connect_lines(aligned_rows, tableboxes.first(), - 0, exact(input).nrows()); + 0, exact(input).nrows(), max_distance); trace::exiting("scribo::table::connect_vertical_lines"); } diff --git a/milena/sandbox/scribo/text/extract_bboxes.hh b/milena/sandbox/scribo/table/extract.hh similarity index 55% copy from milena/sandbox/scribo/text/extract_bboxes.hh copy to milena/sandbox/scribo/table/extract.hh index 0c88880..06520c9 100644 --- a/milena/sandbox/scribo/text/extract_bboxes.hh +++ b/milena/sandbox/scribo/table/extract.hh @@ -26,70 +26,69 @@ // reasons why the executable file might be covered by the GNU General // Public License. +#ifndef SCRIBO_TABLE_EXTRACT_HH +# define SCRIBO_TABLE_EXTRACT_HH -#ifndef SCRIBO_TEXT_GROUPING_EXTRACT_BBOXES_HH -# define SCRIBO_TEXT_GROUPING_EXTRACT_BBOXES_HH - -/// \file scribo/text/grouping/group_with_single_link.hh +/// \file scribo/table/extract.hh /// -/// Extract text bounding boxes from a binary image. +/// Extract tables from a binary image. +/// Use arbitrary criterions. # include <mln/core/concept/image.hh> -# include <mln/core/concept/neighborhood.hh> -# include <mln/core/site_set/box.hh> -# include <mln/labeling/blobs.hh> -# include <mln/labeling/compute.hh> +# include <mln/util/couple.hh> # include <mln/util/array.hh> -# include <scribo/core/component_bboxes.hh> +# include <scribo/table/rebuild.hh> +# include <scribo/table/erase.hh> +# include <scribo/table/extract_lines_with_rank.hh> + +# include <scribo/make/debug_filename.hh> + namespace scribo { - namespace text + namespace table { - using namespace mln; + template <typename I, typename V> + mln_ch_value(I,V) + extract(const Image<I>& input_, V& ncells); - /// Extract text bounding boxes from a binary image. - /// - /// \param[in] input_ A binary image. - /// - /// \return an array of bounding boxes. The first bounding box is - /// the background's. - template <typename I, typename N, typename V> - inline - util::array< box<mln_site(I)> > - extract_bboxes(const Image<I>& input_, - const Neighborhood<N>& nbh, V& nbboxes); # ifndef MLN_INCLUDE_ONLY - - template <typename I, typename N, typename V> + template <typename I, typename V> inline - util::array< box<mln_site(I)> > - extract_bboxes(const Image<I>& input_, - const Neighborhood<N>& nbh, V& nbboxes) + mln_ch_value(I,V) + extract(const Image<I>& input_, V& ncells) { - trace::entering("scribo::text::extract_bboxes"); + trace::entering("scribo::table::extract"); const I& input = exact(input_); - - mlc_equal(mln_value(I), bool)::check(); mln_precondition(input.is_valid()); + mlc_equal(mln_value(I), bool)::check(); + + typedef util::array< box<mln_site(I)> > boxarray_t; + typedef util::couple<boxarray_t, boxarray_t> tblboxes_t; + + win::line<mln_grid(I::site), 0, mln_coord(I::site)> vline(51); + win::line<mln_grid(I::site), 1, mln_coord(I::site)> hline(51); + tblboxes_t lineboxes + = table::extract_lines_with_rank(input, c8(), V(), + vline, hline, 6, 6); - typedef util::array< box<mln_site(I)> > bboxes_t; - bboxes_t bboxes = component_bboxes(input, nbh, nbboxes); + image2d<V> tables + = scribo::table::rebuild(input, lineboxes, 30, ncells); - trace::exiting("scribo::text::extract_bboxes"); - return bboxes; + trace::exiting("scribo::table::extract"); + return tables; } # endif // ! MLN_INCLUDE_ONLY - } // end of namespace scribo::text + } // end of namespace scribo::table } // end of namespace scribo -#endif // ! SCRIBO_TEXT_GROUPING_EXTRACT_BBOXES_HH +#endif // ! SCRIBO_TABLE_EXTRACT_HH diff --git a/milena/sandbox/scribo/table/extract_lines_with_rank.hh b/milena/sandbox/scribo/table/extract_lines_with_opening.hh similarity index 67% copy from milena/sandbox/scribo/table/extract_lines_with_rank.hh copy to milena/sandbox/scribo/table/extract_lines_with_opening.hh index 242dc30..55fd77f 100644 --- a/milena/sandbox/scribo/table/extract_lines_with_rank.hh +++ b/milena/sandbox/scribo/table/extract_lines_with_opening.hh @@ -27,12 +27,12 @@ // Public License. -#ifndef SCRIBO_TABLE_EXTRACT_LINES_WITH_RANK_HH -# define SCRIBO_TABLE_EXTRACT_LINES_WITH_RANK_HH +#ifndef SCRIBO_TABLE_EXTRACT_LINES_WITH_OPENING_HH +# define SCRIBO_TABLE_EXTRACT_LINES_WITH_OPENING_HH -/// \file scribo/table/extract_lines_with_rank.hh +/// \file scribo/table/extract_lines_with_opening.hh /// -/// Extract table lines using a rank filter. +/// Extract table lines using a morphological opening filter. # include <mln/core/concept/image.hh> @@ -40,14 +40,14 @@ # include <mln/core/concept/neighborhood.hh> # include <mln/core/site_set/box.hh> -# include <mln/morpho/rank_filter.hh> +# include <mln/morpho/erosion.hh> # include <mln/accu/bbox.hh> # include <mln/util/array.hh> # include <mln/util/couple.hh> - +# include <scribo/core/macros.hh> # include <scribo/core/component_bboxes.hh> namespace scribo @@ -56,18 +56,18 @@ namespace scribo namespace table { - /// Find table bboxes thanks to a rank filter. + using namespace mln; + + /// Find table bboxes thanks to a opening filter. /*! * * \param[in] input_ A binary image. * \param[in] nbh_ The neighborhood used for labeling image components. * \param[in] label_type The type used to store the labels. - * \param[in] vwin Window used to extract the vertical lines in the rank - * filter. - * \param[in] hwin Window used to extract the horizontal lines in the rank - * filter. - * \param[in] vrank_k Rank used for vertical lines filtering. - * \param[in] hrank_k Rank used for horizontal lines filtering. + * \param[in] vwin Window used to extract the vertical lines in a morphological + * opening + * \param[in] hwin Window used to extract the horizontal lines in a morphological + * opening * * \return pair of array of bounding boxes. The first array holds the * vertical lines bounding boxes and the second one the @@ -76,45 +76,58 @@ namespace scribo template <typename I, typename N, typename V, typename HW, typename VW> util::couple<util::array<box<mln_site(I)> >, util::array<box<mln_site(I)> > > - extract_lines_with_rank(const Image<I>& input_, - const Neighborhood<N>& nbh_, const V& label_type, - const Window<HW>& vwin, const Window<VW>& hwin, - unsigned vrank_k, unsigned hrank_k); + extract_lines_with_opening(const Image<I>& input_, + const Neighborhood<N>& nbh_, const V& label_type, + const Window<HW>& vwin, const Window<VW>& hwin); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename N, typename V, typename HW, typename VW> + template <typename I, typename N, typename V, typename VW, typename HW> inline util::couple<util::array<box<mln_site(I)> >, util::array<box<mln_site(I)> > > - extract_lines_with_rank(const Image<I>& input_, + extract_lines_with_opening(const Image<I>& input_, const Neighborhood<N>& nbh_, const V& label_type, - const Window<HW>& vwin, const Window<VW>& hwin, - unsigned vrank_k, unsigned hrank_k) + const Window<VW>& vwin_, const Window<HW>& hwin_); { - trace::entering("scribo::table::extract_lines_with_rank"); + trace::entering("scribo::table::extract_lines_with_opening"); mlc_equal(mln_value(I),bool)::check(); mlc_is_a(V, mln::value::Symbolic)::check(); + const I& input = exact(input_); const N& nbh = exact(nbh_); + const VW& vwin = exact(vwin_); + const HW& hwin = exact(hwin_); + mln_precondition(input.is_valid()); mln_precondition(nbh.is_valid()); - mln_precondition(exact(vwin).is_valid()); - mln_precondition(exact(hwin).is_valid()); + mln_precondition(vwin.is_valid()); + mln_precondition(hwin.is_valid()); typedef accu::bbox<mln_psite(I)> A; typedef util::array<mln_result(A)> boxes_t; // Vertical lines - mln_ch_value(I,bool) vfilter = morpho::rank_filter(input, vwin, vrank_k); + mln_ch_value(I,bool) vfilter = morpho::erosion(input, vwin); boxes_t vboxes = component_bboxes(vfilter, nbh, label_type); + for_all_components(i, vboxes) + { + vboxes[i].enlarge(0, vwin.length() / 2); + vboxes[i].crop_wrt(input.domain()); + } // Horizontal lines. - mln_ch_value(I,bool) hfilter = morpho::rank_filter(input, hwin, hrank_k); + mln_ch_value(I,bool) hfilter = morpho::erosion(input, hwin); boxes_t hboxes = component_bboxes(hfilter, nbh, label_type); + for_all_components(i, hboxes) + { + hboxes[i].enlarge(1, hwin.length() / 2); + hboxes[i].crop_wrt(input.domain()); + } + trace::exiting("scribo::table::extract_lines_with_opening"); return mln::make::couple(vboxes, hboxes); } @@ -124,4 +137,4 @@ namespace scribo } // end of namespace scribo -#endif // ! SCRIBO_TABLE_EXTRACT_LINES_WITH_RANK_HH +#endif // ! SCRIBO_TABLE_EXTRACT_LINES_WITH_OPENING_HH diff --git a/milena/sandbox/scribo/table/extract_lines_with_rank.hh b/milena/sandbox/scribo/table/extract_lines_with_rank.hh index 242dc30..63c90b1 100644 --- a/milena/sandbox/scribo/table/extract_lines_with_rank.hh +++ b/milena/sandbox/scribo/table/extract_lines_with_rank.hh @@ -47,7 +47,7 @@ # include <mln/util/array.hh> # include <mln/util/couple.hh> - +# include <scribo/core/macros.hh> # include <scribo/core/component_bboxes.hh> namespace scribo @@ -56,6 +56,8 @@ namespace scribo namespace table { + using namespace mln; + /// Find table bboxes thanks to a rank filter. /*! * @@ -84,25 +86,29 @@ namespace scribo # ifndef MLN_INCLUDE_ONLY - template <typename I, typename N, typename V, typename HW, typename VW> + template <typename I, typename N, typename V, typename VW, typename HW> inline util::couple<util::array<box<mln_site(I)> >, util::array<box<mln_site(I)> > > extract_lines_with_rank(const Image<I>& input_, const Neighborhood<N>& nbh_, const V& label_type, - const Window<HW>& vwin, const Window<VW>& hwin, + const Window<VW>& vwin_, const Window<HW>& hwin_, unsigned vrank_k, unsigned hrank_k) { trace::entering("scribo::table::extract_lines_with_rank"); mlc_equal(mln_value(I),bool)::check(); mlc_is_a(V, mln::value::Symbolic)::check(); + const I& input = exact(input_); const N& nbh = exact(nbh_); + const VW& vwin = exact(vwin_); + const HW& hwin = exact(hwin_); + mln_precondition(input.is_valid()); mln_precondition(nbh.is_valid()); - mln_precondition(exact(vwin).is_valid()); - mln_precondition(exact(hwin).is_valid()); + mln_precondition(vwin.is_valid()); + mln_precondition(hwin.is_valid()); typedef accu::bbox<mln_psite(I)> A; typedef util::array<mln_result(A)> boxes_t; @@ -110,11 +116,22 @@ namespace scribo // Vertical lines mln_ch_value(I,bool) vfilter = morpho::rank_filter(input, vwin, vrank_k); boxes_t vboxes = component_bboxes(vfilter, nbh, label_type); + for_all_components(i, vboxes) + { + vboxes[i].enlarge(0, vwin.length() / 2); + vboxes[i].crop_wrt(input.domain()); + } // Horizontal lines. mln_ch_value(I,bool) hfilter = morpho::rank_filter(input, hwin, hrank_k); boxes_t hboxes = component_bboxes(hfilter, nbh, label_type); + for_all_components(i, hboxes) + { + hboxes[i].enlarge(1, hwin.length() / 2); + hboxes[i].crop_wrt(input.domain()); + } + trace::exiting("scribo::table::extract_lines_with_rank"); return mln::make::couple(vboxes, hboxes); } diff --git a/milena/sandbox/scribo/table/internal/align_lines.hh b/milena/sandbox/scribo/table/internal/align_lines.hh index aaad9fa..202b2dd 100644 --- a/milena/sandbox/scribo/table/internal/align_lines.hh +++ b/milena/sandbox/scribo/table/internal/align_lines.hh @@ -51,6 +51,8 @@ namespace scribo namespace internal { + using namespace mln; + /// Align table lines bboxes according to a given dimension. /// /// \return A list of the resulting aligned cols. Each integer is actually @@ -102,7 +104,8 @@ namespace scribo int min_coord, int max_coord, util::array<box<P> >& line_boxes, - unsigned dim) + unsigned dim, + unsigned max_alignment_diff) { trace::entering("scribo::internal::align_lines"); @@ -114,9 +117,9 @@ namespace scribo // Map components with actual lines. for_all_components(i, line_boxes) { - int minline = line_boxes[i].pmin()[dim] - 5; + int minline = line_boxes[i].pmin()[dim] - max_alignment_diff; minline = (minline < min_coord ? min_coord : minline); - int maxline = line_boxes[i].pmax()[dim] + 5; + int maxline = line_boxes[i].pmax()[dim] + max_alignment_diff; maxline = (maxline > max_coord ? max_coord : maxline); for (int line = minline; diff --git a/milena/sandbox/scribo/table/internal/connect_lines.hh b/milena/sandbox/scribo/table/internal/connect_lines.hh index d510fe2..08f395f 100644 --- a/milena/sandbox/scribo/table/internal/connect_lines.hh +++ b/milena/sandbox/scribo/table/internal/connect_lines.hh @@ -35,6 +35,7 @@ /// Connect vertical lines with aligned rows. # include <mln/core/image/image1d.hh> +# include <mln/core/alias/neighb1d.hh> # include <mln/data/fill.hh> @@ -45,7 +46,7 @@ # include <mln/opt/at.hh> # include <scribo/core/macros.hh> - +# include <scribo/core/central_sites.hh> namespace scribo { @@ -56,6 +57,8 @@ namespace scribo namespace internal { + using namespace mln; + /// Connect vertical and horizontal lines if they are close to each other. /// /// ------ ------ @@ -70,7 +73,8 @@ namespace scribo connect_lines(const util::array<int>& aligned_lines, util::array< box<P> >& boxes, unsigned dim, - unsigned dim_size); + unsigned dim_size, + unsigned max_distance); # ifndef MLN_INCLUDE_ONLY @@ -81,7 +85,8 @@ namespace scribo connect_lines(const util::array<int>& aligned_lines, util::array< box<P> >& boxes, unsigned dim, - unsigned dim_size) + unsigned dim_size, + unsigned max_distance) { trace::entering("scribo::table::internal::connect_lines"); @@ -91,12 +96,12 @@ namespace scribo for_all_elements(i, aligned_lines) opt::at(l, aligned_lines[i]) = i; - for (unsigned i = 0; i < settings.max_dist_lines; ++i) + for (unsigned i = 0; i < max_distance; ++i) l = morpho::elementary::dilation(l, c2()); for_all_components(i, boxes) { - util::couple<point2d, point2d> cp = central_sites(boxes[i], dim); + util::couple<P,P> cp = central_sites(boxes[i], dim); if (opt::at(l, cp.first()[dim]) != -1) boxes[i].pmin()[dim] = aligned_lines[opt::at(l, cp.first()[dim])]; if (opt::at(l, cp.second()[dim]) != -1) @@ -110,6 +115,8 @@ namespace scribo # endif // ! MLN_INCLUDE_ONLY + } // end of namespace scribo::table::internal + } // end of namespace scribo::table } // end of namespace scribo diff --git a/milena/sandbox/scribo/table/internal/repair_lines.hh b/milena/sandbox/scribo/table/internal/repair_lines.hh index 87f0933..cf21564 100644 --- a/milena/sandbox/scribo/table/internal/repair_lines.hh +++ b/milena/sandbox/scribo/table/internal/repair_lines.hh @@ -41,10 +41,17 @@ # include <mln/data/fill.hh> # include <mln/util/couple.hh> # include <mln/util/array.hh> +# include <mln/util/ord.hh> # include <mln/win/line.hh> # include <mln/pw/all.hh> +# include <mln/debug/colorize.hh> +# include <mln/value/rgb8.hh> +# include <mln/value/label_16.hh> +# include <scribo/make/debug_filename.hh> + # include <scribo/core/central_sites.hh> +# include <scribo/core/macros.hh> # include <scribo/table/internal/repair_lines.hh> @@ -57,15 +64,23 @@ namespace scribo namespace internal { + /// Repair lines which have small discontinuities. + /// FIXME: buggy. Sometimes few lines move or shrink! + template <unsigned axis, typename I> + void + repair_lines(const Image<I>& input_, + util::array<box<mln_site(I)> >& tableboxes, + unsigned max_discontinuity); + # ifndef MLN_INCLUDE_ONLY - /// Repair lines which have small discontinuities. - /// FIXME: buggy. Sometimes few lines move or shrink! + template <unsigned axis, typename I> void repair_lines(const Image<I>& input_, - util::array<box<mln_site(I)> >& tableboxes) + util::array<box<mln_site(I)> >& tableboxes, + unsigned max_discontinuity) { trace::entering("scribo::table::internal::repair_lines"); @@ -76,7 +91,7 @@ namespace scribo typedef win::line<mln_grid(P), axis, mln_coord(P)> line_t; // Initialization - mln_ch_value(I,unsigned) l(input.domain()); + mln_ch_value(I,value::label_16) l(input.domain()); data::fill(l, literal::zero); for_all_components(i, tableboxes) { @@ -86,28 +101,52 @@ namespace scribo } // Repair - extension_val<mln_ch_value(I,unsigned)> l_ext(l, literal::zero); + extension_val<mln_ch_value(I,value::label_16)> l_ext(l, literal::zero); util::array<box<P> > result; std::vector<bool> to_keep(tableboxes.nelements(), true); - mln_VAR(tbb_ima, extend(l | pw::value(l) != literal::zero, l)); + mln_VAR(tbb_ima, extend(l | pw::value(l) != pw::cst(literal::zero), l)); //FIXME: use a half window, just the bottom of the vertical line. - line_t vl(settings.repair_max_dist); + line_t vl(max_discontinuity); mln_piter(tbb_ima_t) p(tbb_ima.domain()); mln_qiter(line_t) q(vl, p); for_all(p) + { + util::couple<P,P> cp_p = central_sites(tableboxes[l_ext(p)], axis); for_all(q) if (l_ext(q) != literal::zero && l_ext(q) != l_ext(p)) { - to_keep[l_ext(q)] = false; - - tableboxes[l_ext(p)].pmax() = tableboxes[l_ext(q)].pmax(); - - util::couple<P,P> cp = central_sites(tableboxes[l_ext(q)], axis); - l_ext(cp.first()) = l_ext(p); - l_ext(cp.second()) = l_ext(p); + if (util::ord_strict(tableboxes[l_ext(p)].pmax(), + tableboxes[l_ext(q)].pmax())) + { + tableboxes[l_ext(p)].pmax() = tableboxes[l_ext(q)].pmax(); + to_keep[l_ext(q)] = false; + } + + if (util::ord_strict(tableboxes[l_ext(q)].pmin(), + tableboxes[l_ext(p)].pmin())) + { + tableboxes[l_ext(p)].pmin() = tableboxes[l_ext(q)].pmin(); + to_keep[l_ext(q)] = false; + } + + if (!to_keep[l_ext(q)]) + { + util::couple<P,P> cp_q = central_sites(tableboxes[l_ext(q)], axis); + l_ext(cp_q.first()) = literal::zero; + l_ext(cp_q.second()) = literal::zero; + + unsigned p_i = l_ext(p); + l_ext(cp_p.first()) = literal::zero; + l_ext(cp_p.second()) = literal::zero; + + util::couple<P,P> new_cp_p = central_sites(tableboxes[p_i], axis); + l_ext(new_cp_p.first()) = p_i; + l_ext(new_cp_p.second()) = p_i; + } } + } // Remove merged boxes. diff --git a/milena/sandbox/scribo/table/rebuild.hh b/milena/sandbox/scribo/table/rebuild.hh new file mode 100644 index 0000000..b78112d --- /dev/null +++ b/milena/sandbox/scribo/table/rebuild.hh @@ -0,0 +1,147 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory +// (LRDE) +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library 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. + +#ifndef SCRIBO_TABLE_REBUILD_HH +# define SCRIBO_TABLE_REBUILD_HH + +/// \file scribo/table/rebuild.hh +/// +/// Rebuild a table from its line bounding boxes. + +# include <mln/core/concept/image.hh> +# include <mln/labeling/background.hh> +# include <mln/util/array.hh> +# include <mln/util/couple.hh> +# include <mln/value/label_8.hh> + +# include <scribo/table/align_lines_verticaly.hh> +# include <scribo/table/align_lines_horizontaly.hh> +# include <scribo/table/connect_vertical_lines.hh> +# include <scribo/table/connect_horizontal_lines.hh> +# include <scribo/table/repair_horizontal_lines.hh> +# include <scribo/table/repair_vertical_lines.hh> + +# include <scribo/debug/save_table_image.hh> + + + +namespace scribo +{ + + namespace table + { + + template <typename I, typename V> + mln_ch_value(I,V) + rebuild(const Image<I>& in_, + const util::couple<util::array<box<mln_site(I)> >, + util::array<box<mln_site(I)> > >& lineboxes, + unsigned max_dist_lines, + V& ncells); + + +# ifndef MLN_INCLUDE_ONLY + + + template <typename I, typename V> + mln_ch_value(I,V) + rebuild(const Image<I>& in_, + const util::couple<util::array<box<mln_site(I)> >, + util::array<box<mln_site(I)> > >& lineboxes, + unsigned max_dist_lines, + V& ncells) + { + trace::entering("scribo::table::rebuild"); + const I& in = exact(in_); + + mlc_equal(mln_value(I), bool)::check(); + mln_precondition(in.is_valid()); + + util::couple<util::array<box<mln_site(I)> >, + util::array<box<mln_site(I)> > > tblboxes = lineboxes; + +//# ifndef SCRIBO_NDEBUG +// scribo::debug::save_table_image(in, tblboxes, +// literal::red, "table.ppm"); +//# endif + scribo::debug::save_table_image(in, tblboxes, + literal::red, "table-raw.ppm"); + + util::array<int> rows = align_lines_horizontaly(in, tblboxes.second(), 5); + util::array<int> cols = align_lines_verticaly(in, tblboxes.first(), 5); + +# ifndef SCRIBO_NDEBUG + scribo::debug::save_table_image(in, tblboxes, + literal::red, "table-aligned.ppm"); +# endif + + repair_vertical_lines(in, tblboxes, 30); + repair_horizontal_lines(in, tblboxes, 30); + +# ifndef SCRIBO_NDEBUG + scribo::debug::save_table_image(in, tblboxes, + literal::red, "table-repaired.ppm"); +# endif + + // Connect vertical lines with horizontal lines. + connect_vertical_lines(rows, tblboxes, in, max_dist_lines); + connect_horizontal_lines(cols, tblboxes, in, max_dist_lines); + +# ifndef SCRIBO_NDEBUG + scribo::debug::save_table_image(in, tblboxes, + literal::red, "table-connected.ppm"); +# endif + + + mln_ch_value(I,bool) res; + initialize(res, in); + data::fill(res, false); + for_all_components(i, tblboxes.first()) + mln::draw::box(res, tblboxes.first()[i], true); + for_all_components(i, tblboxes.second()) + mln::draw::box(res, tblboxes.second()[i], true); + + mln_ch_value(I,V) lbl = labeling::background(res, c8(), ncells); + +//# ifndef SCRIBO_NDEBUG +// scribo::debug::save_table_image(in, tblboxes, +// literal::red, "table-connected.ppm"); +//# endif + + trace::exiting("scribo::table::rebuild"); + return lbl; + } + + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace scribo::table + +} // end of namespace scribo + +#endif // ! SCRIBO_TABLE_REBUILD_HH diff --git a/milena/sandbox/scribo/table/repair_horizontal_lines.hh b/milena/sandbox/scribo/table/repair_horizontal_lines.hh index 7c1edbd..e871480 100644 --- a/milena/sandbox/scribo/table/repair_horizontal_lines.hh +++ b/milena/sandbox/scribo/table/repair_horizontal_lines.hh @@ -59,9 +59,9 @@ namespace scribo template <typename I> void repair_horizontal_lines(const Image<I>& input, - util::couple<util::array<box<mln_site(I)> >, - util::array<box<mln_site(I)> > >& tableboxes, - unsigned max_discontinuity); + util::couple<util::array<box<mln_site(I)> >, + util::array<box<mln_site(I)> > >& tableboxes, + unsigned max_discontinuity); # ifndef MLN_INCLUDE_ONLY diff --git a/milena/sandbox/scribo/src/extract_text_multiple_links.cc b/milena/sandbox/scribo/tests/filter/small_and_large_bboxes.cc similarity index 87% copy from milena/sandbox/scribo/src/extract_text_multiple_links.cc copy to milena/sandbox/scribo/tests/filter/small_and_large_bboxes.cc index 9b181e6..2cf7ebc 100644 --- a/milena/sandbox/scribo/src/extract_text_multiple_links.cc +++ b/milena/sandbox/scribo/tests/filter/small_and_large_bboxes.cc @@ -32,6 +32,7 @@ #include <scribo/text/extract_bboxes.hh> #include <scribo/text/grouping/group_with_multiple_links.hh> #include <scribo/text/grouping/group_from_multiple_links.hh> +#include <scribo/filter/small_components.hh> #include <scribo/debug/save_textbboxes_image.hh> #include <scribo/debug/save_linked_textbboxes_image.hh> @@ -50,6 +51,8 @@ int main(int argc, char* argv[]) if (argc < 1) return usage(argv[0]); + scribo::make::internal::debug_filename_prefix = argv[0]; + image2d<bool> input; io::pbm::load(input, argv[1]); @@ -66,7 +69,7 @@ int main(int argc, char* argv[]) literal::red, literal::cyan, "test_multiple_links_left_linked.ppm"); - util::array< box<point2d> > grouped_textbboxes + util::array<box2d> grouped_textbboxes = text::grouping::group_from_multiple_links(textbboxes, g); std::cout << "AFTER - nbboxes = " << grouped_textbboxes.nelements() << std::endl; @@ -74,5 +77,13 @@ int main(int argc, char* argv[]) scribo::debug::save_textbboxes_image(input, grouped_textbboxes, literal::red, "test_multiple_links_grouped_text.ppm"); + + util::array<box2d> filtered_textbboxes + = scribo::filter::small_components(grouped_textbboxes, 6); + + scribo::debug::save_textbboxes_image(input, filtered_textbboxes, + literal::red, + "test_multiple_links_filtered_text.ppm"); + } diff --git a/milena/sandbox/scribo/tests/table/extract_lines_with_rank.cc b/milena/sandbox/scribo/tests/table/extract_lines_with_rank.cc new file mode 100644 index 0000000..ed5ce3c --- /dev/null +++ b/milena/sandbox/scribo/tests/table/extract_lines_with_rank.cc @@ -0,0 +1,36 @@ +#include <mln/essential/2d.hh> +#include <scribo/table/extract_lines_with_rank.hh> +#include <scribo/debug/save_table_image.hh> +#include <mln/util/couple.hh> + +int main(int argc, char *argv[]) +{ + using namespace mln; + + if (argc < 2) + { + std::cout << "Usage: " << argv[0] << " <image.pbm>" << std::endl; + return 1; + } + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + typedef util::couple<util::array<box2d>, + util::array<box2d> > tblboxes_t; + + tblboxes_t lineboxes; + lineboxes.first().append(make::box2d(0,0, 59,59)); + lineboxes.first().append(make::box2d(0,28, 27, 32)); + lineboxes.first().append(make::box2d(31,28, 59,32)); + lineboxes.second().append(make::box2d(0,0, 59,59)); + lineboxes.second().append(make::box2d(27,0, 31, 26)); + lineboxes.second().append(make::box2d(27,34, 31,59)); + + + tblboxes_t lineboxes_test = scribo::table::extract_lines_with_rank(input, c8(), + value::label_16(), win::vline2d(11), + win::hline2d(11), 2, 2); + + mln_assertion(lineboxes == lineboxes_test); +} diff --git a/milena/sandbox/scribo/tests/table/repair_lines.cc b/milena/sandbox/scribo/tests/table/repair_lines.cc new file mode 100644 index 0000000..ff5551c --- /dev/null +++ b/milena/sandbox/scribo/tests/table/repair_lines.cc @@ -0,0 +1,45 @@ +#include <mln/essential/2d.hh> +#include <scribo/table/repair_vertical_lines.hh> +#include <scribo/table/repair_horizontal_lines.hh> +#include <scribo/table/extract_lines_with_rank.hh> +#include <scribo/debug/save_table_image.hh> +#include <mln/util/couple.hh> + +int main(int argc, char *argv[]) +{ + using namespace mln; + + if (argc < 2) + { + std::cout << "Usage: " << argv[0] << " <image.pbm>" << std::endl; + return 1; + } + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + typedef util::couple<util::array<box2d>, + util::array<box2d> > tblboxes_t; + + tblboxes_t lineboxes; + lineboxes.first().append(make::box2d(0,0, 1,1)); // Dummy value for component 0. + lineboxes.first().append(make::box2d(0,28, 27, 32)); + lineboxes.first().append(make::box2d(31,28, 59,32)); + lineboxes.second().append(make::box2d(0,0, 1,1)); // Dummy value for component 0. + lineboxes.second().append(make::box2d(27,0, 31, 26)); + lineboxes.second().append(make::box2d(27,34, 31,59)); + + +// tblboxes_t lineboxes = scribo::table::extract_lines_with_rank(input, c8(), value::label_16(), win::vline2d(11), win::hline2d(11), 2, 2); +// +// std::cout << lineboxes.first() << std::endl; +// std::cout << lineboxes.second() << std::endl; + + scribo::table::repair_vertical_lines(input, lineboxes, 31); + scribo::table::repair_horizontal_lines(input, lineboxes, 31); + + mln_assertion(lineboxes.first().nelements() == 2); + mln_assertion(lineboxes.second().nelements() == 2); + mln_assertion(lineboxes.first()[1] == make::box2d(0,28, 59,32)); + mln_assertion(lineboxes.second()[1] == make::box2d(27,0, 31,59)); +} diff --git a/milena/sandbox/scribo/text/extract_bboxes.hh b/milena/sandbox/scribo/text/extract_bboxes.hh index 0c88880..4a936b5 100644 --- a/milena/sandbox/scribo/text/extract_bboxes.hh +++ b/milena/sandbox/scribo/text/extract_bboxes.hh @@ -42,6 +42,8 @@ # include <mln/util/array.hh> # include <scribo/core/component_bboxes.hh> +# include <scribo/util/text.hh> +# include <scribo/make/text.hh> namespace scribo { @@ -58,8 +60,7 @@ namespace scribo /// \return an array of bounding boxes. The first bounding box is /// the background's. template <typename I, typename N, typename V> - inline - util::array< box<mln_site(I)> > + scribo::util::text<mln_ch_value(I,V)> extract_bboxes(const Image<I>& input_, const Neighborhood<N>& nbh, V& nbboxes); @@ -68,7 +69,7 @@ namespace scribo template <typename I, typename N, typename V> inline - util::array< box<mln_site(I)> > + scribo::util::text<mln_ch_value(I,V)> extract_bboxes(const Image<I>& input_, const Neighborhood<N>& nbh, V& nbboxes) { @@ -79,11 +80,13 @@ namespace scribo mlc_equal(mln_value(I), bool)::check(); mln_precondition(input.is_valid()); - typedef util::array< box<mln_site(I)> > bboxes_t; - bboxes_t bboxes = component_bboxes(input, nbh, nbboxes); + typedef mln::util::array< box<mln_site(I)> > bboxes_t; + typedef mln::util::couple<bboxes_t, mln_ch_value(I,V)> bboxes_and_lbl_t; + bboxes_and_lbl_t bboxes_and_lbl = component_bboxes(input, nbh, nbboxes); trace::exiting("scribo::text::extract_bboxes"); - return bboxes; + return scribo::make::text(bboxes_and_lbl.first(), + bboxes_and_lbl.second(), nbboxes); } # endif // ! MLN_INCLUDE_ONLY diff --git a/milena/sandbox/scribo/text/extract_lines.hh b/milena/sandbox/scribo/text/extract_lines.hh new file mode 100644 index 0000000..6be2e37 --- /dev/null +++ b/milena/sandbox/scribo/text/extract_lines.hh @@ -0,0 +1,133 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library 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. + +#ifndef SCRIBO_TEXT_EXTRACT_LINES_HH +# define SCRIBO_TEXT_EXTRACT_LINES_HH + +/// \file scribo/text/extract_lines.hh +/// +/// Extract line of text bounding boxes. + + +# include <mln/core/concept/image.hh> +# include <mln/core/site_set/box.hh> + +# include <mln/data/fill.hh> + +# include <mln/accu/bbox.hh> + +# include <mln/draw/box.hh> + +# include <mln/labeling/blobs.hh> +# include <mln/labeling/compute.hh> + +# include <mln/util/array.hh> +# include <mln/util/graph.hh> +# include <mln/value/label_16.hh> + +# include <scribo/text/grouping/group_with_multiple_links.hh> +# include <scribo/text/grouping/group_from_multiple_links.hh> +# include <scribo/filter/small_components.hh> +# include <scribo/util/text.hh> + +# include <scribo/debug/save_textbboxes_image.hh> +# include <scribo/debug/save_linked_textbboxes_image.hh> + +namespace scribo +{ + + namespace text + { + + using namespace mln; + + + template <typename I, typename N, typename V> + scribo::util::text<mln_ch_value(I,V)> + extract_lines(const Image<I>& input_, + const Neighborhood<N>& nbh_, + V& nbboxes); + + +# ifndef MLN_INCLUDE_ONLY + + + template <typename I, typename N, typename V> + scribo::util::text<mln_ch_value(I,V)> + extract_lines(const Image<I>& input_, + const Neighborhood<N>& nbh_, + V& nbboxes) + { + trace::entering("scribo::text::extract_lines"); + + const I& input = exact(input_); + const N& nbh = exact(nbh_); + + mln_precondition(input.is_valid()); + mln_precondition(nbh.is_valid()); + + scribo::util::text<mln_ch_value(I,V)> text + = scribo::make::text(input, nbh, nbboxes); + +# ifndef SCRIBO_NDEBUG + debug::save_textbboxes_image(input, text.bboxes(), literal::red, + scrib::make::debug_filename("character-bboxes.ppm")); +# endif // ! SCRIBO_NDEBUG + + //Link character bboxes to their left neighboor if possible. + mln::util::graph g + = text::grouping::group_with_multiple_links(text, 30); +# ifndef SCRIBO_NDEBUG + debug::save_linked_textbboxes_image(input, + text, g, + literal::red, literal::cyan, + scribo::make::debug_filename("multiple_links_left_linked.ppm")); +# endif // ! SCRIBO_NDEBUG + + //Merge character bboxes through a graph. + scribo::util::text<mln_ch_value(I,V)> grouped_text + = text::grouping::group_from_multiple_links(text, g); + +# ifndef SCRIBO_NDEBUG + debug::save_textbboxes_image(input, grouped_text.bboxes(), + literal::red, + scribo::make::debug_filename("multiple_links_grouped_text.ppm")); +# endif // ! SCRIBO_NDEBUG + + + trace::exiting("scribo::text::extract_lines"); + return grouped_text; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace scribo::text + +} // end of namespace scribo + +#endif // ! SCRIBO_TEXT_EXTRACT_LINES_HH + diff --git a/milena/sandbox/scribo/text/grouping/group_from_double_link.hh b/milena/sandbox/scribo/text/grouping/group_from_double_link.hh index d178a80..582abcd 100644 --- a/milena/sandbox/scribo/text/grouping/group_from_double_link.hh +++ b/milena/sandbox/scribo/text/grouping/group_from_double_link.hh @@ -41,10 +41,14 @@ # include <mln/util/array.hh> +# include <mln/fun/l2l/relabel.hh> + # include <scribo/text/grouping/internal/find_root.hh> # include <scribo/core/macros.hh> +# include <scribo/util/text.hh> + namespace scribo { @@ -56,42 +60,67 @@ namespace scribo { /// FIXME: Add much more doc! - template <typename P> - util::array< box<P> > - group_from_double_link(const util::array< box<P> >& textbboxes, - util::array<unsigned>& left_link, - util::array<unsigned>& right_link); + template <typename I> + scribo::util::text<I> + group_from_double_link(const scribo::util::text<I>& text, + const mln::util::array<unsigned>& left_link, + const mln::util::array<unsigned>& right_link); # ifndef MLN_INCLUDE_ONLY - template <typename P> + template <typename I> inline - util::array< box<P> > - group_from_double_link(const util::array< box<P> >& textbboxes, - util::array<unsigned>& left_link, - util::array<unsigned>& right_link) + scribo::util::text<I> + group_from_double_link(const scribo::util::text<I>& text, + const mln::util::array<unsigned>& left_link, + const mln::util::array<unsigned>& right_link) { trace::entering("scribo::text::grouping::group_from_double_link"); mln_precondition(left_link.nelements() == right_link.nelements()); - util::array< accu::bbox<P> > tboxes; - tboxes.resize(textbboxes.nelements()); - for_all_components(i, textbboxes) + mln::util::array< accu::bbox<mln_site(I)> > tboxes; + tboxes.resize(text.bboxes().nelements()); + + mln::util::array<unsigned> left_parent = left_link; + for_all_components(i, left_parent) + left_parent[i] = internal::find_root(left_parent, i); + + fun::i2v::array<mln_value(I)> f(text.bboxes().nelements(), + literal::zero); + for_all_components(i, text.bboxes()) { unsigned nbh = right_link[left_link[i]]; if (nbh == i) - tboxes[left_link[i]].take(textbboxes[i]); + { + tboxes[left_parent[i]].take(text.bbox(i)); + f(i) = left_parent[left_link[i]]; + } else - tboxes[i].take(textbboxes[i]); + { + f(i) = i; + tboxes[i].take(text.bbox(i)); + } } - util::array< box<P> > result; + // Update bounding boxes information. + mln::util::array< box<mln_site(I)> > bresult; // component 0, the background, has an invalid box. - result.append(box<P>()); + bresult.append(box<mln_site(I)>()); for_all_components(i, tboxes) if (tboxes[i].is_valid()) - result.append(tboxes[i]); + bresult.append(tboxes[i]); + + // Update label image. + mln_value(I) new_nbboxes; + I new_lbl = labeling::relabel(text.label_image(), + text.nbboxes(), + mln::make::relabelfun(f, text.nbboxes(), + new_nbboxes)); + + mln_assertion(bresult.nelements() == new_nbboxes.next()); + + scribo::util::text<I> result(bresult, new_lbl, new_nbboxes); trace::exiting("scribo::text::grouping::group_from_double_link"); return result; diff --git a/milena/sandbox/scribo/text/grouping/group_from_multiple_links.hh b/milena/sandbox/scribo/text/grouping/group_from_multiple_links.hh index 612fb87..059fa22 100644 --- a/milena/sandbox/scribo/text/grouping/group_from_multiple_links.hh +++ b/milena/sandbox/scribo/text/grouping/group_from_multiple_links.hh @@ -47,6 +47,9 @@ # include <mln/util/array.hh> # include <scribo/core/macros.hh> +# include <scribo/util/text.hh> +# include <scribo/make/text.hh> + namespace scribo { @@ -58,9 +61,9 @@ namespace scribo { /// FIXME: Add much more doc! - template <typename G, typename P> - util::array<box<P> > - group_from_multiple_links(util::array<box<P> >& textbboxes, + template <typename I, typename G> + scribo::util::text<I> + group_from_multiple_links(const scribo::util::text<I>& text, const Graph<G>& g_); # ifndef MLN_INCLUDE_ONLY @@ -71,14 +74,15 @@ namespace scribo /// Functor to be passed to depth_first_search. /// Map each component vertex with its representative vertex id. + template <typename V> struct map_vertex_to_component_id_functor { - template <typename G> - void init(const Graph<G>& g) - { - vertextocomp.resize(exact(g).v_nmax(), mln_max(unsigned)); - ncomp = 0; - } + template <typename G> + void init(const Graph<G>& g) + { + vertextocomp.resize(exact(g).v_nmax(), mln_max(V)); + ncomp = 0; + } void final() {} @@ -96,23 +100,23 @@ namespace scribo {} bool to_be_treated(unsigned id) - { return vertextocomp(id) == mln_max(unsigned); } + { return vertextocomp(id) == mln_max(V); } bool to_be_queued(unsigned id) { return to_be_treated(id); } unsigned ncomp; - fun::i2v::array<unsigned> vertextocomp; + fun::l2l::relabel<V> vertextocomp; }; } // end of namespace scribo::text::grouping::internal - template <typename G, typename P> + template <typename I, typename G> inline - util::array<box<P> > - group_from_multiple_links(util::array<box<P> >& textbboxes, + scribo::util::text<I> + group_from_multiple_links(const scribo::util::text<I>& text, const Graph<G>& g_) { trace::entering("scribo::text::grouping::group_from_multiple_links"); @@ -121,25 +125,34 @@ namespace scribo mln_assertion(g.is_valid()); - internal::map_vertex_to_component_id_functor f; + internal::map_vertex_to_component_id_functor<mln_value(I)> f; canvas::browsing::depth_first_search(g, f); - util::array< accu::bbox<P> > tboxes; - tboxes.resize(textbboxes.nelements()); - for_all_components(i, textbboxes) - tboxes[f.vertextocomp(i)].take(textbboxes[i]); + mln::util::array< accu::bbox<mln_site(I)> > tboxes; + tboxes.resize(text.nbboxes().next()); + for_all_components(i, text.bboxes()) + tboxes[f.vertextocomp(i)].take(text.bbox(i)); - util::array< box<P> > result; + // Update bounding boxes. + mln::util::array<box<mln_site(I)> > bresult; // Component 0 - the background has not valid bboxes. - result.append(box<P>()); - for_all_components(i, textbboxes) + bresult.append(box<mln_site(I)>()); + for_all_components(i, text.bboxes()) if (tboxes[i].is_valid()) - result.append(tboxes[i].to_result()); + bresult.append(tboxes[i].to_result()); + + mln_assertion(bresult.nelements() == f.ncomp); + + // Update label image. + mln_value(I) new_nbboxes; + I new_lbl = labeling::relabel(text.label_image(), + text.nbboxes(), + f.vertextocomp); - mln_assertion(result.nelements() == f.ncomp); + mln_assertion(new_nbboxes.next() == bresult.nelements()); trace::exiting("scribo::text::grouping::group_from_multiple_links"); - return result; + return scribo::make::text(bresult, new_lbl, new_nbboxes); } diff --git a/milena/sandbox/scribo/text/grouping/group_from_single_link.hh b/milena/sandbox/scribo/text/grouping/group_from_single_link.hh index eccde96..43bb7b1 100644 --- a/milena/sandbox/scribo/text/grouping/group_from_single_link.hh +++ b/milena/sandbox/scribo/text/grouping/group_from_single_link.hh @@ -44,6 +44,7 @@ # include <scribo/text/grouping/internal/find_root.hh> # include <scribo/core/macros.hh> +# include <scribo/util/text.hh> namespace scribo @@ -56,38 +57,46 @@ namespace scribo { /// FIXME: Add much more doc! - template <typename P> - util::array< box<P> > - group_from_single_link(const util::array< box<P> >& textbboxes, - util::array<unsigned>& link_array); + template <typename I> + scribo::util::text<I> + group_from_single_link(const scribo::util::text<I>& text, + const mln::util::array<unsigned>& link_array); # ifndef MLN_INCLUDE_ONLY - template <typename P> + template <typename I> inline - util::array< box<P> > - group_from_single_link(const util::array< box<P> >& textbboxes, - util::array<unsigned>& link_array) + scribo::util::text<I> + group_from_single_link(const scribo::util::text<I>& text, + const mln::util::array<unsigned>& link_array) { trace::entering("scribo::text::grouping::group_from_single_link"); - for (unsigned i = 0; i < link_array.nelements(); ++i) - link_array[i] = internal::find_root(link_array, i); + mln_precondition(text.is_valid()); + mln_precondition(link_array.nelements() == text.nbboxes().next()); + mln_precondition(link_array.nelements() == text.bboxes().nelements()); - util::array< accu::bbox<P> > tboxes; - tboxes.resize(textbboxes.nelements()); - for_all_components(i, textbboxes) - tboxes[link_array[i]].take(textbboxes[i]); + mln::util::array<unsigned> parent_array = link_array; + for_all_components(i, parent_array) + internal::find_root(parent_array, i); - util::array< box<P> > result; + mln::util::array< accu::bbox<mln_site(I)> > tboxes; + tboxes.resize(text.nbboxes().next()); + for_all_components(i, text.bboxes()) + tboxes[parent_array[i]].take(text.bbox(i)); + + mln::util::array< box<mln_site(I)> > result; // component 0, the background, has an invalid box. - result.append(box<P>()); + result.append(box<mln_site(I)>()); for_all_components(i, tboxes) if (tboxes[i].is_valid()) result.append(tboxes[i]); + I lbl = labeling::relabel(text.label_image(), text.nbboxes(), + convert::to<fun::l2l::relabel<mln_value(I)> >(parent_array)); + mln_value(I) new_nbboxes = result.nelements() - 1; trace::exiting("scribo::text::grouping::group_from_single_link"); - return result; + return scribo::make::text(result, lbl, new_nbboxes); } # endif // ! MLN_INCLUDE_ONLY diff --git a/milena/sandbox/scribo/text/grouping/group_with_multiple_links.hh b/milena/sandbox/scribo/text/grouping/group_with_multiple_links.hh index 2f769fc..236cf16 100644 --- a/milena/sandbox/scribo/text/grouping/group_with_multiple_links.hh +++ b/milena/sandbox/scribo/text/grouping/group_with_multiple_links.hh @@ -43,6 +43,7 @@ # include <scribo/core/macros.hh> # include <scribo/text/grouping/internal/init_link_array.hh> # include <scribo/text/grouping/internal/update_link_graph.hh> +# include <scribo/util/text.hh> namespace scribo { @@ -55,44 +56,34 @@ namespace scribo /// Group character bounding boxes with multiple links. /// Look up for neighbors on the left of each box. - template <typename I, typename N, typename V> - util::graph - group_with_multiple_links(const Image<I>& input_, - const Neighborhood<N>& nbh, V& nbboxes, - const util::array<box<mln_site(I)> >& textbboxes, + template <typename I> + mln::util::graph + group_with_multiple_links(const scribo::util::text<I>& text, unsigned neighb_max_distance); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename N, typename V> - util::graph - group_with_multiple_links(const Image<I>& input_, - const Neighborhood<N>& nbh, V& nbboxes, - const util::array<box<mln_site(I)> >& textbboxes, + template <typename I> + inline + mln::util::graph + group_with_multiple_links(const scribo::util::text<I>& text, unsigned neighb_max_distance) { trace::entering("scribo::text::grouping::group_with_multiple_links"); - const I& input = exact(input_); + mln::util::graph g(text.nbboxes().next()); - mlc_equal(mln_value(I), bool)::check(); - mln_assertion(input.is_valid()); - - typedef mln_ch_value(I,V) lbl_t; - lbl_t lbl = labeling::blobs(input, nbh, nbboxes); - - util::graph g(nbboxes.next()); - - for_all_ncomponents(i, nbboxes) + for_all_ncomponents(i, text.nbboxes()) { - unsigned midcol = (textbboxes[i].pmax().col() - - textbboxes[i].pmin().col()) / 2; + unsigned midcol = (text.bbox(i).pmax().col() + - text.bbox(i).pmin().col()) / 2; int dmax = midcol + neighb_max_distance; - mln_site(I) c = textbboxes[i].center(); + mln_site(I) c = text.bbox(i).center(); /// First site on the right of the central site mln_site(I) p = c + right; + const I& lbl = text.label_image(); while (lbl.domain().has(p) && (lbl(p) == literal::zero || lbl(p) == i) && math::abs(p.col() - c.col()) < dmax) ++p.col(); diff --git a/milena/sandbox/scribo/text/grouping/group_with_single_left_link.hh b/milena/sandbox/scribo/text/grouping/group_with_single_left_link.hh index f1a3013..ca1a8da 100644 --- a/milena/sandbox/scribo/text/grouping/group_with_single_left_link.hh +++ b/milena/sandbox/scribo/text/grouping/group_with_single_left_link.hh @@ -46,6 +46,8 @@ # include <scribo/core/macros.hh> # include <scribo/text/grouping/internal/init_link_array.hh> # include <scribo/text/grouping/internal/update_link_array.hh> +# include <scribo/text/grouping/internal/find_root.hh> +# include <scribo/util/text.hh> //FIXME: not generic. # include <mln/core/alias/dpoint2d.hh> @@ -63,46 +65,34 @@ namespace scribo /// if possible. /// Iterate to the right but link boxes to the left. /// - /// \return an util::array. Map a bounding box to its left neighbor. - template <typename I, typename N, typename V> + /// \return an mln::util::array. Map a bounding box to its left neighbor. + template <typename L> inline - util::array<unsigned> - group_with_single_left_link(const Image<I>& input_, - const Neighborhood<N>& nbh, V& nbboxes, - const util::array< box<mln_site(I)> >& textbboxes, + mln::util::array<unsigned> + group_with_single_left_link(const scribo::util::text<L>& text, unsigned neighb_max_distance); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename N, typename V> + template <typename L> inline - util::array<unsigned> - group_with_single_left_link(const Image<I>& input_, - const Neighborhood<N>& nbh_, V& nbboxes, - const util::array< box<mln_site(I)> >& textbboxes, + mln::util::array<unsigned> + group_with_single_left_link(const scribo::util::text<L>& text, unsigned neighb_max_distance) { trace::entering("scribo::text::grouping::group_with_single_left_link"); - const I& input = exact(input_); - const N& nbh = exact(nbh_); + mln_precondition(text.is_valid()); - mlc_equal(mln_value(I), bool)::check(); - mln_assertion(input.is_valid()); - mln_precondition(nbh.is_valid()); - - typedef mln_ch_value(I,V) lbl_t; - lbl_t lbl = labeling::blobs(input, nbh, nbboxes); - - util::array<unsigned> left_link(nbboxes.next()); + mln::util::array<unsigned> left_link(text.nbboxes().next()); internal::init_link_array(left_link); - for_all_ncomponents(i, nbboxes) + for_all_ncomponents(i, text.nbboxes()) { - unsigned midcol = (textbboxes[i].pmax().col() - - textbboxes[i].pmin().col()) / 2; + unsigned midcol = (text.bbox(i).pmax().col() + - text.bbox(i).pmin().col()) / 2; int dmax = midcol + neighb_max_distance; - mln_site(I) c = textbboxes[i].center(); + mln_site(L) c = text.bbox(i).center(); /// /// Find a neighbor on the right @@ -110,14 +100,15 @@ namespace scribo ///FIXME: the following code is not generic... /// First site on the right of the central site - mln_site(I) p = c + right; + mln_site(L) p = c + right; - while (lbl.domain().has(p) && (lbl(p) == literal::zero || lbl(p) == i) + const L& lbl = text.label_image(); + while (lbl.domain().has(p) && (lbl(p) == literal::zero || lbl(p) == i || + left_link[i] == lbl(p)) && math::abs(p.col() - c.col()) < dmax) ++p.col(); internal::update_link_array(lbl, left_link, p, c, i, dmax); - } trace::exiting("scribo::text::grouping::group_with_single_left_link"); diff --git a/milena/sandbox/scribo/text/grouping/group_with_single_right_link.hh b/milena/sandbox/scribo/text/grouping/group_with_single_right_link.hh index 7f1eeac..5740b09 100644 --- a/milena/sandbox/scribo/text/grouping/group_with_single_right_link.hh +++ b/milena/sandbox/scribo/text/grouping/group_with_single_right_link.hh @@ -46,6 +46,8 @@ # include <scribo/core/macros.hh> # include <scribo/text/grouping/internal/init_link_array.hh> # include <scribo/text/grouping/internal/update_link_array.hh> +# include <scribo/text/grouping/internal/find_root.hh> +# include <scribo/util/text.hh> //FIXME: not generic. # include <mln/core/alias/dpoint2d.hh> @@ -63,46 +65,34 @@ namespace scribo /// if possible. /// Iterate to the right but link boxes to the right. /// - /// \return an util::array. Map a bounding box to its right neighbor. - template <typename I, typename N, typename V> + /// \return an mln::util::array. Map a bounding box to its right neighbor. + template <typename L> inline - util::array<unsigned> - group_with_single_right_link(const Image<I>& input_, - const Neighborhood<N>& nbh, V& nbboxes, - const util::array< box<mln_site(I)> >& textbboxes, + mln::util::array<unsigned> + group_with_single_right_link(const scribo::util::text<L>& text, unsigned neighb_max_distance); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename N, typename V> + template <typename L> inline - util::array<unsigned> - group_with_single_right_link(const Image<I>& input_, - const Neighborhood<N>& nbh_, V& nbboxes, - const util::array< box<mln_site(I)> >& textbboxes, + mln::util::array<unsigned> + group_with_single_right_link(const scribo::util::text<L>& text, unsigned neighb_max_distance) { trace::entering("scribo::text::grouping::group_with_single_right_link"); - const I& input = exact(input_); - const N& nbh = exact(nbh_); + mln_precondition(text.is_valid()); - mlc_equal(mln_value(I), bool)::check(); - mln_assertion(input.is_valid()); - mln_precondition(nbh.is_valid()); - - typedef mln_ch_value(I,V) lbl_t; - lbl_t lbl = labeling::blobs(input, nbh, nbboxes); - - util::array<unsigned> right_link(nbboxes.next()); + mln::util::array<unsigned> right_link(text.nbboxes().next()); internal::init_link_array(right_link); - for_all_ncomponents(i, nbboxes) + for_all_ncomponents(i, text.nbboxes()) { - unsigned midcol = (textbboxes[i].pmax().col() - - textbboxes[i].pmin().col()) / 2; + unsigned midcol = (text.bbox(i).pmax().col() + - text.bbox(i).pmin().col()) / 2; int dmax = midcol + neighb_max_distance; - mln_site(I) c = textbboxes[i].center(); + mln_site(L) c = text.bbox(i).center(); /// /// Find a neighbor on the left @@ -110,14 +100,15 @@ namespace scribo ///FIXME: the following code is not generic... /// First site on the left of the central site - mln_site(I) p = c + left; + mln_site(L) p = c + left; - while (lbl.domain().has(p) && (lbl(p) == literal::zero || lbl(p) == i) - && math::abs(p.col() - c.col()) < dmax) + const L& lbl = text.label_image(); + while (lbl.domain().has(p) && (lbl(p) == literal::zero + || lbl(p) == i || right_link[i] == lbl(p)) + && math::abs(p.col() - c.col()) < dmax) --p.col(); internal::update_link_array(lbl, right_link, p, c, i, dmax); - } trace::exiting("scribo::text::grouping::group_with_single_right_link"); diff --git a/milena/sandbox/scribo/text/grouping/internal/find_root.hh b/milena/sandbox/scribo/text/grouping/internal/find_root.hh index 0b1e307..9e3eedf 100644 --- a/milena/sandbox/scribo/text/grouping/internal/find_root.hh +++ b/milena/sandbox/scribo/text/grouping/internal/find_root.hh @@ -52,13 +52,13 @@ namespace scribo /// Find root in a parent array arrays. unsigned - find_root(util::array<unsigned>& parent, unsigned x); + find_root(mln::util::array<unsigned>& parent, unsigned x); # ifndef MLN_INCLUDE_ONLY inline unsigned - find_root(util::array<unsigned>& parent, unsigned x) + find_root(mln::util::array<unsigned>& parent, unsigned x) { if (parent[x] == x) return x; diff --git a/milena/sandbox/scribo/text/grouping/internal/init_link_array.hh b/milena/sandbox/scribo/text/grouping/internal/init_link_array.hh index ba197f9..7e4f751 100644 --- a/milena/sandbox/scribo/text/grouping/internal/init_link_array.hh +++ b/milena/sandbox/scribo/text/grouping/internal/init_link_array.hh @@ -41,6 +41,8 @@ namespace scribo { + using namespace mln; + namespace text { @@ -51,13 +53,14 @@ namespace scribo { /// Initialize a link array. - void init_link_array(util::array<unsigned>& link_array); + void + init_link_array(mln::util::array<unsigned>& link_array); # ifndef MLN_INCLUDE_ONLY inline void - init_link_array(util::array<unsigned>& link_array) + init_link_array(mln::util::array<unsigned>& link_array) { for (unsigned i = 0; i < link_array.nelements(); ++i) link_array[i] = i; diff --git a/milena/sandbox/scribo/text/grouping/internal/update_link_array.hh b/milena/sandbox/scribo/text/grouping/internal/update_link_array.hh index 242d18f..501d6f2 100644 --- a/milena/sandbox/scribo/text/grouping/internal/update_link_array.hh +++ b/milena/sandbox/scribo/text/grouping/internal/update_link_array.hh @@ -56,7 +56,7 @@ namespace scribo /// on the right of the current bbox. template <typename I> void - update_link_array(const Image<I>& lbl, util::array<unsigned>& link_array, + update_link_array(const Image<I>& lbl, mln::util::array<unsigned>& link_array, const mln_site(I)& p, const mln_site(I)& c, unsigned i, int dmax); @@ -65,7 +65,7 @@ namespace scribo template <typename I> inline void - update_link_array(const Image<I>& lbl_, util::array<unsigned>& link_array, + update_link_array(const Image<I>& lbl_, mln::util::array<unsigned>& link_array, const mln_site(I)& p, const mln_site(I)& c, unsigned i, int dmax) { @@ -75,7 +75,8 @@ namespace scribo mln_assertion(lbl.is_valid()); if (lbl.domain().has(p) && lbl(p) != literal::zero && lbl(p) != i - && (math::abs(p.col() - c.col())) < dmax && link_array[lbl(p)] == lbl(p)) + && (math::abs(p.col() - c.col())) < dmax && link_array[lbl(p)] == lbl(p) + && link_array[i] != lbl(p)) link_array[lbl(p)] = i; } diff --git a/milena/sandbox/scribo/text/grouping/internal/update_link_graph.hh b/milena/sandbox/scribo/text/grouping/internal/update_link_graph.hh index e31c5e8..f572a47 100644 --- a/milena/sandbox/scribo/text/grouping/internal/update_link_graph.hh +++ b/milena/sandbox/scribo/text/grouping/internal/update_link_graph.hh @@ -52,7 +52,7 @@ namespace scribo /// Update graph edges if a valid neighbor is found. template <typename I> void - update_link_graph(Image<I>& lbl_, util::graph& g, + update_link_graph(const Image<I>& lbl_, mln::util::graph& g, const mln_site(I)& p, const mln_site(I)& c, unsigned i, int dmax); @@ -63,7 +63,7 @@ namespace scribo template <typename I> inline void - update_link_graph(Image<I>& lbl_, util::graph& g, + update_link_graph(const Image<I>& lbl_, mln::util::graph& g, const mln_site(I)& p, const mln_site(I)& c, unsigned i, int dmax) { @@ -72,7 +72,7 @@ namespace scribo mlc_is_a(mln_value(I), mln::value::Symbolic)::check(); mln_precondition(exact(lbl).is_valid()); - if (lbl.domain().has(p) && lbl(p) != 0u && lbl(p) != i + if (lbl.domain().has(p) && lbl(p) != literal::zero && lbl(p) != i && (math::abs(p.col() - c.col())) < dmax) g.add_edge(lbl(p), i); } diff --git a/milena/sandbox/scribo/text/recognition.hh b/milena/sandbox/scribo/text/recognition.hh index 98c3b67..c11ed54 100644 --- a/milena/sandbox/scribo/text/recognition.hh +++ b/milena/sandbox/scribo/text/recognition.hh @@ -54,6 +54,8 @@ namespace scribo namespace text { + using namespace mln; + /// Passes the text bboxes to Tesseract (OCR) and store the result in /// an image of characters. /// @@ -71,8 +73,8 @@ namespace scribo template <typename I, typename N, typename V> mln_ch_value(I,char) text_recognition(const Image<I>& input_, - const Neighborhood<N>& nbh_, V& nbboxes, - const util::array< box<mln_site(I)> >& textbboxes, + const Neighborhood<N>& nbh_, const V& label_type, + const scribo::util::text_bboxes<mln_ch_value(I,V)>& textbboxes, const char *language); @@ -81,8 +83,8 @@ namespace scribo template <typename I, typename N, typename V> mln_ch_value(I,char) text_recognition(const Image<I>& input_, - const Neighborhood<N>& nbh_, V& nbboxes, - const util::array< box<mln_site(I)> >& textbboxes, + const Neighborhood<N>& nbh_, const V& label_type, + const scribo::util::text_bboxes<mln_ch_value(I,V)>& textbboxes, const char *language) { trace::entering("scribo::text::recognition"); @@ -93,6 +95,7 @@ namespace scribo mln_precondition(input.is_valid()); mln_precondition(nbh.is_valid()); + V nbboxes; mln_ch_value(I,V) lbl = labeling::blobs(input, nbh, nbboxes); /// Use text bboxes with Tesseract @@ -104,7 +107,7 @@ namespace scribo { if (textbboxes[i].is_valid()) { - mln_ch_value(I,bool) b(textbboxes[i], 0); + mln_ch_value(I,bool) b(textbboxes.bboxes()[i], 0); data::fill(b, false); data::fill((b | (pw::value(lbl) == pw::cst(i))).rw(), true); @@ -119,9 +122,9 @@ namespace scribo - mln_site(I) p = textbboxes[i].center(); - p.col() -= (textbboxes[i].pmax().col() - - textbboxes[i].pmin().col()) / 2; + mln_site(I) p = textbboxes.bboxes[i].center(); + p.col() -= (textbboxes.bboxes()[i].pmax().col() + - textbboxes.bboxes()[i].pmin().col()) / 2; if (s != 0) debug::put_word(txt, p, s); free(s); diff --git a/milena/sandbox/scribo/util/text.hh b/milena/sandbox/scribo/util/text.hh new file mode 100644 index 0000000..2619a79 --- /dev/null +++ b/milena/sandbox/scribo/util/text.hh @@ -0,0 +1,189 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library 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. + +#ifndef SCRIBO_UTIL_TEXT_HH +# define SCRIBO_UTIL_TEXT_HH + +/// \file scribo/util/text.hh +/// +/// A class representing text bounding boxes and their associated +/// labeled image. + +# include <mln/core/image/image2d.hh> +# include <mln/core/concept/proxy.hh> +# include <mln/core/site_set/box.hh> +# include <mln/value/label_16.hh> +# include <mln/util/couple.hh> +# include <mln/util/array.hh> + +namespace scribo +{ + + using namespace mln; + + namespace util + { + + /// Store text bounding boxes and their associated labeled image. + template <typename L> + class text + { + public: + typedef mln_site(L) site; + typedef mln::util::array<box<site> > boxes_t; + + text(); + text(const mln::util::array<box<mln_site(L)> >& bboxes, + const Image<L>& lbl, + const mln_value(L)& nbboxes); + + const L& label_image() const; + L& label_image(); + + const mln_value(L)& nbboxes() const; + mln_value(L)& nbboxes(); + + const boxes_t& bboxes() const; + boxes_t& bboxes(); + + const box<mln_site(L)>& bbox(unsigned i) const; + box<mln_site(L)>& bbox(unsigned i); + + bool is_valid() const; + + private: + boxes_t bboxes_; + L lbl_; + mln_value(L) nbboxes_; + }; + + +# ifndef MLN_INCLUDE_ONLY + + + template <typename L> + inline + text<L>::text() + { + } + + template <typename L> + inline + text<L>::text(const mln::util::array<box<mln_site(L)> >& bboxes, + const Image<L>& lbl, + const mln_value(L)& nbboxes) + : bboxes_(bboxes), lbl_(exact(lbl)), nbboxes_(nbboxes) + { + mln_assertion(bboxes.nelements() == nbboxes.next()); + } + + template <typename L> + inline + const L& + text<L>::label_image() const + { + mln_precondition(lbl_.is_valid()); + return lbl_; + } + + template <typename L> + inline + L& + text<L>::label_image() + { + return lbl_; + } + + template <typename L> + inline + const mln_value(L)& + text<L>::nbboxes() const + { + return nbboxes_; + } + + template <typename L> + inline + mln_value(L)& + text<L>::nbboxes() + { + return nbboxes_; + } + + template <typename L> + inline + const typename text<L>::boxes_t& + text<L>::bboxes() const + { + mln_precondition(bboxes_.nelements() == nbboxes_.next()); + return bboxes_; + } + + template <typename L> + inline + typename text<L>::boxes_t& + text<L>::bboxes() + { + return bboxes_; + } + + template <typename L> + inline + const box<mln_site(L)>& + text<L>::bbox(unsigned i) const + { + mln_precondition(bboxes_.nelements() == nbboxes_.next()); + mln_precondition(i < bboxes_.nelements()); + return bboxes_[i]; + } + + template <typename L> + inline + box<mln_site(L)>& + text<L>::bbox(unsigned i) + { + mln_precondition(bboxes_.nelements() == nbboxes_.next()); + mln_precondition(i < bboxes_.nelements()); + return bboxes_[i]; + } + + template <typename L> + inline + bool + text<L>::is_valid() const + { + return lbl_.is_valid() && bboxes_.nelements() == nbboxes_.next(); + } + + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace scribo::util + +} // end of namespace scribo + +#endif // ! SCRIBO_UTIL_TEXT_HH -- 1.5.6.5
participants (1)
-
Guillaume Lazzara