Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
March 2009
- 9 participants
- 202 discussions
10 Mar '09
---
ChangeLog | 4 ++++
configure.ac | 1 +
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 721d35a..e27b4aa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-03-10 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ * configure.ac: configure tests/morpho/opening/approx.
+
2009-03-09 Frederic Bour <bour(a)lrde.epita.fr>
Add missing trait for thru_morpher.
diff --git a/configure.ac b/configure.ac
index 40969bb..d8a30b5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -248,6 +248,7 @@ AC_CONFIG_FILES([
milena/tests/morpho/watershed/Makefile
milena/tests/morpho/closing/Makefile
milena/tests/morpho/opening/Makefile
+ milena/tests/morpho/opening/approx/Makefile
milena/tests/norm/Makefile
milena/tests/opt/Makefile
milena/tests/pw/Makefile
--
1.5.6.5
1
0
* scribo/Makefile: update include path.
* scribo/core/central_sites.hh,
* scribo/core/component_bboxes.hh,
* scribo/core/erase_bboxes.hh,
* scribo/core/macros.hh,
* scribo/debug/save_label_image.hh,
* 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,
* scribo/make/debug_filename.hh,
* scribo/make/influence_zone_graph.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,
* scribo/table/erase.hh,
* scribo/table/extract_lines_with_rank.hh,
* scribo/table/internal/align_lines.hh,
* scribo/table/internal/connect_lines.hh,
* scribo/table/internal/repair_lines.hh,
* scribo/table/repair_horizontal_lines.hh,
* scribo/table/repair_vertical_lines.hh,
* scribo/text/extract_bboxes.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/grouping/internal/find_root.hh,
* scribo/text/grouping/internal/init_link_array.hh,
* scribo/text/grouping/internal/update_link_array.hh,
* scribo/text/grouping/internal/update_link_graph.hh,
* scribo/text/recognition.hh: new routines.
* scribo/photo.cc,
* scribo/table.cc: move...
* scribo/src/photo.cc,
* scribo/src/table.cc: ... here.
* scribo/src/extract_text_double_link.cc,
* scribo/src/extract_text_multiple_links.cc,
* scribo/src/extract_text_single_link.cc: new small test related to
text extraction.
---
milena/sandbox/ChangeLog | 52 +++++
milena/sandbox/scribo/Makefile | 23 ++-
milena/sandbox/scribo/core/central_sites.hh | 97 ++++++++++
milena/sandbox/scribo/core/component_bboxes.hh | 85 +++++++++
.../scribo/{photo.cc => core/erase_bboxes.hh} | 77 +++++---
milena/sandbox/scribo/{photo.cc => core/macros.hh} | 45 +----
.../scribo/{photo.cc => debug/save_label_image.hh} | 77 +++++----
.../scribo/debug/save_linked_textbboxes_image.hh | 170 +++++++++++++++++
milena/sandbox/scribo/debug/save_table_image.hh | 97 ++++++++++
.../sandbox/scribo/debug/save_textbboxes_image.hh | 90 +++++++++
milena/sandbox/scribo/draw/bounding_box_links.hh | 197 ++++++++++++++++++++
milena/sandbox/scribo/draw/bounding_boxes.hh | 93 +++++++++
.../scribo/{photo.cc => make/debug_filename.hh} | 89 ++++++----
milena/sandbox/scribo/make/influence_zone_graph.hh | 121 ++++++++++++
.../sandbox/scribo/src/extract_text_double_link.cc | 109 +++++++++++
.../scribo/src/extract_text_multiple_links.cc | 78 ++++++++
.../sandbox/scribo/src/extract_text_single_link.cc | 108 +++++++++++
milena/sandbox/scribo/{ => src}/photo.cc | 0
milena/sandbox/scribo/{ => src}/table.cc | 0
.../scribo/table/align_lines_horizontaly.hh | 97 ++++++++++
.../sandbox/scribo/table/align_lines_verticaly.hh | 98 ++++++++++
.../scribo/table/connect_horizontal_lines.hh | 94 ++++++++++
.../sandbox/scribo/table/connect_vertical_lines.hh | 95 ++++++++++
milena/sandbox/scribo/table/erase.hh | 97 ++++++++++
.../scribo/table/extract_lines_with_rank.hh | 127 +++++++++++++
.../sandbox/scribo/table/internal/align_lines.hh | 183 ++++++++++++++++++
.../sandbox/scribo/table/internal/connect_lines.hh | 118 ++++++++++++
.../sandbox/scribo/table/internal/repair_lines.hh | 132 +++++++++++++
.../scribo/table/repair_horizontal_lines.hh | 92 +++++++++
.../sandbox/scribo/table/repair_vertical_lines.hh | 98 ++++++++++
milena/sandbox/scribo/text/extract_bboxes.hh | 95 ++++++++++
.../scribo/text/grouping/group_from_double_link.hh | 108 +++++++++++
.../text/grouping/group_from_multiple_links.hh | 154 +++++++++++++++
.../scribo/text/grouping/group_from_single_link.hh | 101 ++++++++++
.../text/grouping/group_with_multiple_links.hh | 115 ++++++++++++
.../text/grouping/group_with_single_left_link.hh | 135 +++++++++++++
.../text/grouping/group_with_single_right_link.hh | 135 +++++++++++++
.../grouping/internal/find_root.hh} | 82 +++++----
.../grouping/internal/init_link_array.hh} | 79 +++++----
.../text/grouping/internal/update_link_array.hh | 93 +++++++++
.../text/grouping/internal/update_link_graph.hh | 92 +++++++++
milena/sandbox/scribo/text/recognition.hh | 142 ++++++++++++++
42 files changed, 3970 insertions(+), 200 deletions(-)
create mode 100644 milena/sandbox/scribo/core/central_sites.hh
create mode 100644 milena/sandbox/scribo/core/component_bboxes.hh
copy milena/sandbox/scribo/{photo.cc => core/erase_bboxes.hh} (51%)
copy milena/sandbox/scribo/{photo.cc => core/macros.hh} (52%)
copy milena/sandbox/scribo/{photo.cc => debug/save_label_image.hh} (52%)
create mode 100644 milena/sandbox/scribo/debug/save_linked_textbboxes_image.hh
create mode 100644 milena/sandbox/scribo/debug/save_table_image.hh
create mode 100644 milena/sandbox/scribo/debug/save_textbboxes_image.hh
create mode 100644 milena/sandbox/scribo/draw/bounding_box_links.hh
create mode 100644 milena/sandbox/scribo/draw/bounding_boxes.hh
copy milena/sandbox/scribo/{photo.cc => make/debug_filename.hh} (52%)
create mode 100644 milena/sandbox/scribo/make/influence_zone_graph.hh
create mode 100644 milena/sandbox/scribo/src/extract_text_double_link.cc
create mode 100644 milena/sandbox/scribo/src/extract_text_multiple_links.cc
create mode 100644 milena/sandbox/scribo/src/extract_text_single_link.cc
copy milena/sandbox/scribo/{ => src}/photo.cc (100%)
rename milena/sandbox/scribo/{ => src}/table.cc (100%)
create mode 100644 milena/sandbox/scribo/table/align_lines_horizontaly.hh
create mode 100644 milena/sandbox/scribo/table/align_lines_verticaly.hh
create mode 100644 milena/sandbox/scribo/table/connect_horizontal_lines.hh
create mode 100644 milena/sandbox/scribo/table/connect_vertical_lines.hh
create mode 100644 milena/sandbox/scribo/table/erase.hh
create mode 100644 milena/sandbox/scribo/table/extract_lines_with_rank.hh
create mode 100644 milena/sandbox/scribo/table/internal/align_lines.hh
create mode 100644 milena/sandbox/scribo/table/internal/connect_lines.hh
create mode 100644 milena/sandbox/scribo/table/internal/repair_lines.hh
create mode 100644 milena/sandbox/scribo/table/repair_horizontal_lines.hh
create mode 100644 milena/sandbox/scribo/table/repair_vertical_lines.hh
create mode 100644 milena/sandbox/scribo/text/extract_bboxes.hh
create mode 100644 milena/sandbox/scribo/text/grouping/group_from_double_link.hh
create mode 100644 milena/sandbox/scribo/text/grouping/group_from_multiple_links.hh
create mode 100644 milena/sandbox/scribo/text/grouping/group_from_single_link.hh
create mode 100644 milena/sandbox/scribo/text/grouping/group_with_multiple_links.hh
create mode 100644 milena/sandbox/scribo/text/grouping/group_with_single_left_link.hh
create mode 100644 milena/sandbox/scribo/text/grouping/group_with_single_right_link.hh
copy milena/sandbox/scribo/{photo.cc => text/grouping/internal/find_root.hh} (52%)
rename milena/sandbox/scribo/{photo.cc => text/grouping/internal/init_link_array.hh} (52%)
create mode 100644 milena/sandbox/scribo/text/grouping/internal/update_link_array.hh
create mode 100644 milena/sandbox/scribo/text/grouping/internal/update_link_graph.hh
create mode 100644 milena/sandbox/scribo/text/recognition.hh
diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog
index 4b4d75e..beea9cf 100644
--- a/milena/sandbox/ChangeLog
+++ b/milena/sandbox/ChangeLog
@@ -1,3 +1,55 @@
+2009-03-10 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Split Scribo's code into several routines.
+
+ * scribo/Makefile: update include path.
+
+ * scribo/core/central_sites.hh,
+ * scribo/core/component_bboxes.hh,
+ * scribo/core/erase_bboxes.hh,
+ * scribo/core/macros.hh,
+ * scribo/debug/save_label_image.hh,
+ * 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,
+ * scribo/make/debug_filename.hh,
+ * scribo/make/influence_zone_graph.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,
+ * scribo/table/erase.hh,
+ * scribo/table/extract_lines_with_rank.hh,
+ * scribo/table/internal/align_lines.hh,
+ * scribo/table/internal/connect_lines.hh,
+ * scribo/table/internal/repair_lines.hh,
+ * scribo/table/repair_horizontal_lines.hh,
+ * scribo/table/repair_vertical_lines.hh,
+ * scribo/text/extract_bboxes.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/grouping/internal/find_root.hh,
+ * scribo/text/grouping/internal/init_link_array.hh,
+ * scribo/text/grouping/internal/update_link_array.hh,
+ * scribo/text/grouping/internal/update_link_graph.hh,
+ * scribo/text/recognition.hh: new routines.
+
+ * scribo/photo.cc,
+ * scribo/table.cc: move...
+ * scribo/src/photo.cc,
+ * scribo/src/table.cc: ... here.
+
+ * scribo/src/extract_text_double_link.cc,
+ * scribo/src/extract_text_multiple_links.cc,
+ * scribo/src/extract_text_single_link.cc: new small test related to
+ text extraction.
+
2009-03-10 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Implement 3D watershed and various tools.
diff --git a/milena/sandbox/scribo/Makefile b/milena/sandbox/scribo/Makefile
index 5d09e02..cbb462b 100644
--- a/milena/sandbox/scribo/Makefile
+++ b/milena/sandbox/scribo/Makefile
@@ -1,16 +1,31 @@
all: table photo
tabledbg: demat.hh
- g++ -Wextra -Wall -I../.. -I$(HOME)/local/include -O1 -g table.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o table
+ 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
table: demat.hh
- g++ -Wextra -Wall -I../.. -I$(HOME)/local/include -O1 -DNDEBUG table.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o table
+ 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
+
+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
photo: demat.hh
- g++ -Wextra -Wall -I../.. -I$(HOME)/local/include -O1 -DNDEBUG photo.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o photo
+ 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
+
+
+
+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
+
+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
+
+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
+
clean:
rm *.ppm *.pgm *.pbm
dist-clean: clean
- rm -f table photo
+ rm -f bin/table.out bin/photo.out
diff --git a/milena/sandbox/scribo/core/central_sites.hh b/milena/sandbox/scribo/core/central_sites.hh
new file mode 100644
index 0000000..fe47625
--- /dev/null
+++ b/milena/sandbox/scribo/core/central_sites.hh
@@ -0,0 +1,97 @@
+// 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_CORE_CENTRAL_SITES_HH
+# define SCRIBO_CORE_CENTRAL_SITES_HH
+
+/// \file scribo/core/central_sites.hh
+///
+/// Returns the edge central sites of a box.
+
+# include <mln/util/couple.hh>
+# include <mln/core/site_set/box.hh>
+
+namespace scribo
+{
+ using namespace mln;
+
+ /// Returns the edge central sites of a box
+ ///
+ /// \param[in] b the bbbox
+ /// \param[in] dim the dimension used to compute the site.
+ /*!
+ **
+ ** If dim == 0, returns the left and right central sites.
+ **
+ ** |-------| \n
+ ** X X \n
+ ** |-------| \n
+ **
+ ** If dim == 1, returns the top and bottom central sites.
+ **
+ ** |---X---| \n
+ ** | | \n
+ ** |---X---| \n
+ **
+ **
+ ** ... And so on.
+ **
+ */
+ template <typename P>
+ util::couple<P,P>
+ central_sites(const box<P>& b, unsigned dim);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename P>
+ inline
+ util::couple<P,P>
+ central_sites(const box<P>& b, unsigned dim)
+ {
+ trace::entering("scribo::central_sites");
+ mln_precondition(b.is_valid());
+
+ unsigned n = b.pmax()[dim] - b.pmin()[dim];
+
+ P p1 = b.center();
+ p1[dim] -= n / 2;
+ P p2 = b.center();
+ p2[dim] += n / 2;
+
+ trace::exiting("scribo::central_sites");
+ return make::couple(p1, p2);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_CORE_CENTRAL_SITES_HH
diff --git a/milena/sandbox/scribo/core/component_bboxes.hh b/milena/sandbox/scribo/core/component_bboxes.hh
new file mode 100644
index 0000000..5af99fc
--- /dev/null
+++ b/milena/sandbox/scribo/core/component_bboxes.hh
@@ -0,0 +1,85 @@
+// 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_CORE_COMPONENT_BBOXES_HH
+# define SCRIBO_CORE_COMPONENT_BBOXES_HH
+
+/// \file scribo/core/component_bboxes.hh
+///
+/// Extract the bounding boxes of image components.
+
+# 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/array.hh>
+
+
+namespace scribo
+{
+
+ /// Extract the components bboxes.
+ template <typename I, typename N, typename V>
+ util::array< box<mln_site(I)> >
+ component_bboxes(const Image<I>& input,
+ const Neighborhood<N>& nbh, const V& label_type);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I, typename N, typename V>
+ inline
+ util::array< box<mln_site(I)> >
+ component_bboxes(const Image<I>& input,
+ const Neighborhood<N>& nbh, const V&)
+ {
+ trace::entering("scribo::component_bboxes");
+
+ mlc_equal(mln_value(I),bool)::check();
+ mlc_is_a(V, mln::value::Symbolic)::check();
+ 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);
+ typedef util::array< box<mln_site(I)> > bboxes_t;
+ bboxes_t bboxes = labeling::compute(accu::meta::bbox(), lbl, nbboxes);
+
+ trace::exiting("scribo::component_bboxes");
+ return bboxes;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_CORE_COMPONENT_BBOXES_HH
diff --git a/milena/sandbox/scribo/photo.cc b/milena/sandbox/scribo/core/erase_bboxes.hh
similarity index 51%
copy from milena/sandbox/scribo/photo.cc
copy to milena/sandbox/scribo/core/erase_bboxes.hh
index a173750..cea998b 100644
--- a/milena/sandbox/scribo/photo.cc
+++ b/milena/sandbox/scribo/core/erase_bboxes.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// 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
@@ -25,40 +26,56 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
+#ifndef SCRIBO_CORE_ERASE_BBOXES_HH
+# define SCRIBO_CORE_ERASE_BBOXES_HH
-#include "demat.hh"
+/// \file scribo/core/erase_bboxes.hh
+///
+/// Remove the content of bounding boxes from an image.
-int main(int argc, char*argv[])
+# include <mln/core/concept/image.hh>
+# include <mln/core/site_set/box.hh>
+# include <mln/data/paste.hh>
+# include <mln/pw/all.hh>
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+
+namespace scribo
{
- using namespace mln;
- using value::int_u8;
- if (argc < 2)
+ /// Remove the content of bounding boxes from an image.
+ template <typename I>
+ void
+ erase_bboxes(Image<I>& input_,
+ const util::array< box<mln_site(I)> >& bboxes);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename I>
+ void
+ erase_bboxes(Image<I>& input_,
+ const util::array< box<mln_site(I)> >& bboxes)
{
- std::cout << argv[0] << " <in.pbm> <out.pgm> <l> <bbox_larger> <bbox_distance> <min_comp_nsites>" << std::endl
- << std::endl << std::endl
- << std::endl
- << "=========="
- << std::endl << std::endl
- << "<in.pbm> B/W inverted input image."
- << std::endl << std::endl
-/* << "<out.ppm> RGB8 output image."
- << std::endl << std::endl
- << "<bbox_distance> Maximum distance between character bounding boxes. Used for bbox grouping."
- << std::endl << std::endl
- << "<min_comp_nsites> Minimum site count of a character/text component."
- << std::endl
- << " If a component have a site count lesser than this value, it is erased."
- << std::endl << std::endl
- << std::endl*/
- << "=========="
- << std::endl << std::endl
- << "HINT: compile with -DNOUT to avoid debug images."
- << std::endl << std::endl;
- return 1;
+ trace::entering("scribo::erase_bboxes");
+
+ mlc_equal(mln_value(I),bool)::check();
+
+ I& input = exact(input_);
+ mln_precondition(input.is_valid());
+
+ for_all_components(i, bboxes)
+ data::paste((pw::cst(false) | bboxes[i] |
+ (pw::value(input) == true)), input);
+
+ trace::exiting("scribo::erase_bboxes");
}
- scribo::demat_photo(argv);
- return 0;
-}
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_CORE_ERASE_BBOXES_HH
diff --git a/milena/sandbox/scribo/photo.cc b/milena/sandbox/scribo/core/macros.hh
similarity index 52%
copy from milena/sandbox/scribo/photo.cc
copy to milena/sandbox/scribo/core/macros.hh
index a173750..91a335c 100644
--- a/milena/sandbox/scribo/photo.cc
+++ b/milena/sandbox/scribo/core/macros.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// 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
@@ -25,40 +26,16 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
+#ifndef SCRIBO_CORE_MACROS_HH
+# define SCRIBO_CORE_MACROS_HH
-#include "demat.hh"
+# define for_all_ncomponents(C, NCOMP) \
+ for (unsigned C = 1; C <= NCOMP; ++C)
-int main(int argc, char*argv[])
-{
- using namespace mln;
- using value::int_u8;
+# define for_all_components(C, S) \
+ for (unsigned C = 1; C < S.nelements(); ++C)
- if (argc < 2)
- {
- std::cout << argv[0] << " <in.pbm> <out.pgm> <l> <bbox_larger> <bbox_distance> <min_comp_nsites>" << std::endl
- << std::endl << std::endl
- << std::endl
- << "=========="
- << std::endl << std::endl
- << "<in.pbm> B/W inverted input image."
- << std::endl << std::endl
-/* << "<out.ppm> RGB8 output image."
- << std::endl << std::endl
- << "<bbox_distance> Maximum distance between character bounding boxes. Used for bbox grouping."
- << std::endl << std::endl
- << "<min_comp_nsites> Minimum site count of a character/text component."
- << std::endl
- << " If a component have a site count lesser than this value, it is erased."
- << std::endl << std::endl
- << std::endl*/
- << "=========="
- << std::endl << std::endl
- << "HINT: compile with -DNOUT to avoid debug images."
- << std::endl << std::endl;
- return 1;
- }
+# define for_all_elements(E, S) \
+ for (unsigned E = 0; E < S.nelements(); ++E)
- scribo::demat_photo(argv);
-
- return 0;
-}
+#endif // ! SCRIBO_CORE_MACROS_HH
diff --git a/milena/sandbox/scribo/photo.cc b/milena/sandbox/scribo/debug/save_label_image.hh
similarity index 52%
copy from milena/sandbox/scribo/photo.cc
copy to milena/sandbox/scribo/debug/save_label_image.hh
index a173750..e9b01f1 100644
--- a/milena/sandbox/scribo/photo.cc
+++ b/milena/sandbox/scribo/debug/save_label_image.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// 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,39 +27,49 @@
// Public License.
-#include "demat.hh"
+#ifndef SCRIBO_MAKE_DEBUG_SAVE_LABEL_IMAGE_HH
+# define SCRIBO_MAKE_DEBUG_SAVE_LABEL_IMAGE_HH
-int main(int argc, char*argv[])
+/// \file scribo/debug/save_label_image.hh
+///
+/// Save a labeled image in a color image.
+
+namespace scribo
{
- using namespace mln;
- using value::int_u8;
- if (argc < 2)
+ namespace debug
{
- std::cout << argv[0] << " <in.pbm> <out.pgm> <l> <bbox_larger> <bbox_distance> <min_comp_nsites>" << std::endl
- << std::endl << std::endl
- << std::endl
- << "=========="
- << std::endl << std::endl
- << "<in.pbm> B/W inverted input image."
- << std::endl << std::endl
-/* << "<out.ppm> RGB8 output image."
- << std::endl << std::endl
- << "<bbox_distance> Maximum distance between character bounding boxes. Used for bbox grouping."
- << std::endl << std::endl
- << "<min_comp_nsites> Minimum site count of a character/text component."
- << std::endl
- << " If a component have a site count lesser than this value, it is erased."
- << std::endl << std::endl
- << std::endl*/
- << "=========="
- << std::endl << std::endl
- << "HINT: compile with -DNOUT to avoid debug images."
- << std::endl << std::endl;
- return 1;
- }
-
- scribo::demat_photo(argv);
-
- return 0;
-}
+
+ /// Save a labeled image in a color image.
+ template <typename I>
+ void
+ save_label_image(const Image<I>& lbl, const mln_value(I)& nlabels,
+ const char *filename);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ inline
+ void
+ save_label_image(const Image<I>& lbl, const mln_value(I)& nlabels,
+ const char *filename)
+ {
+ trace::entering("scribo::debug::save_label_image");
+ mlc_is_a(mln_value(I), mln::value::Symbolic)::check();
+ mln_precondition(exact(lbl).is_valid());
+
+ io::ppm::save(debug::colorize(rgb8(), lbl, nlabels), filename);
+
+ trace::exiting("scribo::debug::save_label_image");
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::debug
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_MAKE_DEBUG_SAVE_LABEL_IMAGE_HH
diff --git a/milena/sandbox/scribo/debug/save_linked_textbboxes_image.hh b/milena/sandbox/scribo/debug/save_linked_textbboxes_image.hh
new file mode 100644
index 0000000..a7f8927
--- /dev/null
+++ b/milena/sandbox/scribo/debug/save_linked_textbboxes_image.hh
@@ -0,0 +1,170 @@
+// 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_DEBUG_SAVE_LINKED_TEXTBBOXES_IMAGE_HH
+# define SCRIBO_DEBUG_SAVE_LINKED_TEXTBBOXES_IMAGE_HH
+
+/// \file scribo/draw/bounding_boxes.hh
+///
+/// Save the bounding box links image.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/graph.hh>
+# include <mln/level/convert.hh>
+# include <mln/value/rgb8.hh>
+# include <mln/util/array.hh>
+# include <mln/io/ppm/save.hh>
+
+# include <scribo/draw/bounding_boxes.hh>
+# include <scribo/draw/bounding_box_links.hh>
+
+
+namespace scribo
+{
+
+ namespace debug
+ {
+
+ using namespace mln;
+
+
+ /// Save the bounding box links image.
+ template <typename I>
+ void
+ save_linked_textbboxes_image(const Image<I>& input,
+ const util::array< box<mln_site(I)> >& textbboxes,
+ const util::array<unsigned>& link_array,
+ const value::rgb8& box_value,
+ const value::rgb8& link_value,
+ const std::string& filename);
+
+
+ template <typename I>
+ 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 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>
+ void
+ save_linked_textbboxes_image(const Image<I>& input,
+ const util::array< box<mln_site(I)> >& textbboxes,
+ const Graph<G>& g,
+ const value::rgb8& box_value,
+ const value::rgb8& link_value,
+ const std::string& filename);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename I>
+ 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 value::rgb8& box_value,
+ const value::rgb8& link_value,
+ const std::string& filename)
+ {
+ trace::entering("scribo::debug::save_linked_textbboxes_image");
+ 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);
+ io::ppm::save(tmp, filename);
+
+ trace::exiting("scribo::debug::save_linked_textbboxes_image");
+ }
+
+
+ template <typename I>
+ 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 value::rgb8& box_value,
+ const value::rgb8& left_value,
+ const value::rgb8& right_value,
+ const std::string& filename)
+ {
+ trace::entering("scribo::debug::save_linked_textbboxes_image");
+ 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,
+ left_link, right_link,
+ left_value, right_value);
+ io::ppm::save(tmp, filename);
+
+ trace::exiting("scribo::debug::save_linked_textbboxes_image");
+ }
+
+
+ template <typename I, typename G>
+ inline
+ void
+ save_linked_textbboxes_image(const Image<I>& input,
+ const util::array< box<mln_site(I)> >& textbboxes,
+ const Graph<G>& g,
+ const value::rgb8& box_value,
+ const value::rgb8& link_value,
+ const std::string& filename)
+ {
+ trace::entering("scribo::debug::save_linked_textbboxes_image");
+ mln_precondition(exact(g).is_valid());
+ 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);
+ io::ppm::save(tmp, filename);
+
+ trace::exiting("scribo::debug::save_linked_textbboxes_image");
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::debug
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_DEBUG_SAVE_LINKED_TEXTBBOXES_IMAGE_HH
diff --git a/milena/sandbox/scribo/debug/save_table_image.hh b/milena/sandbox/scribo/debug/save_table_image.hh
new file mode 100644
index 0000000..b170420
--- /dev/null
+++ b/milena/sandbox/scribo/debug/save_table_image.hh
@@ -0,0 +1,97 @@
+// 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_DEBUG_SAVE_TABLE_IMAGE_HH
+# define SCRIBO_DEBUG_SAVE_TABLE_IMAGE_HH
+
+/// \file scribo/debug/save_table_image.hh
+///
+/// Save table line bounding boxes in an image.
+
+# include <string>
+
+# include <mln/core/concept/image.hh>
+# include <mln/data/fill.hh>
+# include <mln/util/array.hh>
+# include <mln/util/couple.hh>
+# include <mln/value/rgb8.hh>
+# include <mln/io/ppm/save.hh>
+
+# include <scribo/draw/bounding_boxes.hh>
+
+namespace scribo
+{
+
+ namespace debug
+ {
+
+ /// Save lines bounding boxes in an image filled with \p bg_color.
+ /// 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);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ 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)
+ {
+ trace::entering("scribo::debug::save_table_image");
+ const I& input = exact(input_);
+ mln_precondition(input.is_valid());
+
+ mln_ch_value(I,value::rgb8) out2(exact(input).domain());
+ data::fill(out2, bg_color);
+ 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");
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::debug
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_DEBUG_SAVE_TABLE_IMAGE_HH
diff --git a/milena/sandbox/scribo/debug/save_textbboxes_image.hh b/milena/sandbox/scribo/debug/save_textbboxes_image.hh
new file mode 100644
index 0000000..b210b39
--- /dev/null
+++ b/milena/sandbox/scribo/debug/save_textbboxes_image.hh
@@ -0,0 +1,90 @@
+// 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_DEBUG_SAVE_TEXTBBOXES_IMAGE_HH
+# define SCRIBO_DEBUG_SAVE_TEXTBBOXES_IMAGE_HH
+
+/// \file scribo/draw/bounding_boxes.hh
+///
+/// Draw a list of bounding boxes and their associated mass center.
+
+# include <mln/core/concept/image.hh>
+# include <mln/level/convert.hh>
+# include <mln/value/rgb8.hh>
+# include <mln/util/array.hh>
+# include <mln/io/ppm/save.hh>
+
+# include <scribo/draw/bounding_boxes.hh>
+
+
+namespace scribo
+{
+
+ namespace debug
+ {
+
+ using namespace mln;
+
+
+ /// Draw a list of bounding boxes and their associated mass center.
+ template <typename I>
+ void
+ save_textbboxes_image(const Image<I>& input,
+ const util::array< box<mln_site(I)> >& textbboxes,
+ const value::rgb8& value,
+ const std::string& filename);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ inline
+ void
+ save_textbboxes_image(const Image<I>& input,
+ const util::array< box<mln_site(I)> >& textbboxes,
+ const value::rgb8& value,
+ const std::string& filename)
+ {
+ trace::entering("scribo::debug::save_textbboxes_image");
+ mln_precondition(exact(input).is_valid());
+
+ mln_ch_value(I,value::rgb8) tmp = level::convert(value::rgb8(), input);
+ draw::bounding_boxes(tmp, textbboxes, value);
+ io::ppm::save(tmp, filename);
+
+ trace::exiting("scribo::debug::save_textbboxes_image");
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::debug
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_DEBUG_SAVE_TEXTBBOXES_IMAGE_HH
diff --git a/milena/sandbox/scribo/draw/bounding_box_links.hh b/milena/sandbox/scribo/draw/bounding_box_links.hh
new file mode 100644
index 0000000..7cf57ac
--- /dev/null
+++ b/milena/sandbox/scribo/draw/bounding_box_links.hh
@@ -0,0 +1,197 @@
+// 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_DRAW_BOUNDING_BOX_LINKS_HH
+# define SCRIBO_DRAW_BOUNDING_BOX_LINKS_HH
+
+/// \file scribo/draw/bounding_boxes.hh
+///
+/// Draw a list of bounding box links.
+
+# include <mln/core/concept/image.hh>
+# include <mln/draw/line.hh>
+# include <mln/util/array.hh>
+# include <mln/canvas/browsing/depth_first_search.hh>
+
+# include <scribo/core/macros.hh>
+
+namespace scribo
+{
+
+ namespace draw
+ {
+
+ using namespace mln;
+
+ /// Draw a list of bounding box links.
+ 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_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_value(I)& left_link_value,
+ const mln_value(I)& right_link_value);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace internal
+ {
+ /// Functor to be passed to depth_first_search.
+ template <typename I>
+ struct draw_graph_edges_functor
+ {
+
+ draw_graph_edges_functor(I& ima,
+ const util::array<box<mln_site(I)> >& textbboxes,
+ const mln_value(I)& value)
+ : ima_(ima), textbboxes_(textbboxes), value_(value)
+ {}
+
+ template <typename G>
+ void
+ init(const Graph<G>& g)
+ { deja_vu.resize(exact(g).v_nmax(), false); }
+
+ void final()
+ {}
+
+ void next_component()
+ {}
+
+ void new_component_from_vertex(unsigned)
+ {}
+
+ void added_to_queue(unsigned id)
+ {
+ deja_vu[id] = true;
+ mln::draw::line(ima_, textbboxes_[current_vertex].center(),
+ textbboxes_[id].center(), value_);
+ }
+
+ void process_vertex(unsigned id)
+ { current_vertex = id; }
+
+ bool to_be_treated(unsigned id)
+ { return ! deja_vu[id]; }
+
+ bool to_be_queued(unsigned id)
+ { return to_be_treated(id); }
+
+ I& ima_;
+ const util::array<box<mln_site(I)> >& textbboxes_;
+ mln_value(I) value_;
+ unsigned current_vertex;
+ std::vector<bool> deja_vu;
+ };
+
+ } // end of namespace scribo::text::grouping::internal
+
+
+ template <typename I>
+ inline
+ void
+ bounding_box_links(Image<I>& input_,
+ const util::array< box<mln_site(I)> >& bboxes,
+ const util::array<unsigned>& link_array,
+ const mln_value(I)& value)
+ {
+ trace::entering("scribo::draw::bounding_box_links");
+
+ I& input = exact(input_);
+
+ mln_precondition(input.is_valid());
+
+ for_all_components(i, link_array)
+ if (link_array[i] != i)
+ mln::draw::line(input,
+ bboxes[i].center(),
+ bboxes[link_array[i]].center(),
+ value);
+
+ trace::exiting("scribo::draw::bounding_box_links");
+ }
+
+
+ template <typename I>
+ 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_value(I)& left_link_value,
+ const mln_value(I)& right_link_value)
+ {
+ trace::entering("scribo::draw::bounding_box_links");
+ mln_precondition(exact(input).is_valid());
+
+ bounding_box_links(input, bboxes, left_link, left_link_value);
+ bounding_box_links(input, bboxes, right_link, right_link_value);
+
+ trace::exiting("scribo::draw::bounding_box_links");
+ }
+
+
+ template <typename I, typename G>
+ inline
+ void
+ bounding_box_links(Image<I>& input,
+ const util::array< box<mln_site(I)> >& bboxes,
+ const Graph<G>& g,
+ const mln_value(I)& link_value)
+ {
+ trace::entering("scribo::draw::bounding_box_links");
+ mln_precondition(exact(input).is_valid());
+ mln_precondition(exact(g).v_nmax() == bboxes.nelements());
+
+ internal::draw_graph_edges_functor<I> f(exact(input), bboxes, link_value);
+ canvas::browsing::depth_first_search(g, f);
+
+ trace::exiting("scribo::draw::bounding_box_links");
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::draw
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_DRAW_BOUNDING_BOX_LINKS_HH
diff --git a/milena/sandbox/scribo/draw/bounding_boxes.hh b/milena/sandbox/scribo/draw/bounding_boxes.hh
new file mode 100644
index 0000000..0db60a4
--- /dev/null
+++ b/milena/sandbox/scribo/draw/bounding_boxes.hh
@@ -0,0 +1,93 @@
+// 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_DRAW_BOUNDING_BOXES_HH
+# define SCRIBO_DRAW_BOUNDING_BOXES_HH
+
+/// \file scribo/draw/bounding_boxes.hh
+///
+/// Draw a list of bounding boxes and their associated mass center.
+
+# include <mln/core/concept/image.hh>
+# include <mln/draw/box.hh>
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+
+namespace scribo
+{
+
+ namespace draw
+ {
+
+ using namespace mln;
+
+ /// Draw a list of bounding boxes and their associated mass center.
+ template <typename I>
+ void
+ bounding_boxes(Image<I>& input_,
+ const util::array< box<mln_site(I)> >& boxes,
+ const mln_value(I)& value);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename I>
+ inline
+ void
+ bounding_boxes(Image<I>& input_,
+ const util::array< box<mln_site(I)> >& boxes,
+ const mln_value(I)& value)
+ {
+ trace::entering("scribo::draw::bounding_boxes");
+
+ I& input = exact(input_);
+
+ mln_precondition(input.is_valid());
+
+ for_all_components(i, boxes)
+ if (boxes[i].is_valid())
+ {
+ input(boxes[i].center()) = value;
+ mln::draw::box(input, boxes[i], value);
+ }
+
+ trace::exiting("scribo::draw::bounding_boxes");
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::draw
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_DRAW_BOUNDING_BOXES_HH
diff --git a/milena/sandbox/scribo/photo.cc b/milena/sandbox/scribo/make/debug_filename.hh
similarity index 52%
copy from milena/sandbox/scribo/photo.cc
copy to milena/sandbox/scribo/make/debug_filename.hh
index a173750..b159328 100644
--- a/milena/sandbox/scribo/photo.cc
+++ b/milena/sandbox/scribo/make/debug_filename.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// 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,39 +27,61 @@
// Public License.
-#include "demat.hh"
+#ifndef SCRIBO_MAKE_DEBUG_FILENAME_HH
+# define SCRIBO_MAKE_DEBUG_FILENAME_HH
-int main(int argc, char*argv[])
+/// \file scribo/make/debug_filename.hh
+///
+/// Construct and returns a formated output file name.
+
+# include <sstream>
+
+
+namespace scribo
{
- using namespace mln;
- using value::int_u8;
- if (argc < 2)
+ namespace make
{
- std::cout << argv[0] << " <in.pbm> <out.pgm> <l> <bbox_larger> <bbox_distance> <min_comp_nsites>" << std::endl
- << std::endl << std::endl
- << std::endl
- << "=========="
- << std::endl << std::endl
- << "<in.pbm> B/W inverted input image."
- << std::endl << std::endl
-/* << "<out.ppm> RGB8 output image."
- << std::endl << std::endl
- << "<bbox_distance> Maximum distance between character bounding boxes. Used for bbox grouping."
- << std::endl << std::endl
- << "<min_comp_nsites> Minimum site count of a character/text component."
- << std::endl
- << " If a component have a site count lesser than this value, it is erased."
- << std::endl << std::endl
- << std::endl*/
- << "=========="
- << std::endl << std::endl
- << "HINT: compile with -DNOUT to avoid debug images."
- << std::endl << std::endl;
- return 1;
- }
-
- scribo::demat_photo(argv);
-
- return 0;
-}
+
+ /// Construct and returns a formated output file name:
+ ///
+ /// `input_filename`_`id`_`name`
+ std::string
+ debug_filename(const char *input_filename,
+ const char *name);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ inline
+ std::string
+ debug_filename(const char *input_filename,
+ const char *name)
+ {
+ static int file_id = 1;
+
+ std::ostringstream os;
+ os << "./"
+ << input_filename
+ << "_";
+
+ if (file_id < 10)
+ os << "0";
+
+ os << file_id++
+ << "_"
+ << name;
+ return os.str();
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::make
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_MAKE_DEBUG_FILENAME_HH
diff --git a/milena/sandbox/scribo/make/influence_zone_graph.hh b/milena/sandbox/scribo/make/influence_zone_graph.hh
new file mode 100644
index 0000000..c3ad15e
--- /dev/null
+++ b/milena/sandbox/scribo/make/influence_zone_graph.hh
@@ -0,0 +1,121 @@
+// 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_MAKE_INFLUENCE_ZONE_GRAPH_HH
+# define SCRIBO_MAKE_INFLUENCE_ZONE_GRAPH_HH
+
+/// \file scribo/make/influence_zone_graph.hh
+///
+/// Create a region adjacency graph from the influence zone image
+/// of binary image.
+
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+# include <mln/labeling/blobs.hh>
+
+# include <mln/transform/influence_zone_geodesic.hh>
+
+# include <mln/util/graph.hh>
+
+
+namespace scribo
+{
+
+ namespace text
+ {
+
+ namespace grouping
+ {
+
+ using namespace mln;
+
+
+ /// Compute a labeled image of input, then compute an influence
+ /// zone image and make a graph from it.
+ ///
+ /// \param[in] input_ a binary image.
+ /// \param[in] nbh_ a neighbordhood.
+ /// \param[in] label_type The type of this argument is used
+ /// as label type while labeling the image.
+ /// \param[in] iz_dmax Max distance of the influence zone.
+ ///
+ /// \return a region adjacency graph.
+ template <typename I, typename V>
+ util::graph
+ influence_zone_graph(const Image<I>& input_,
+ const Neighborhood<N>& nbh_,
+ const V& label_type,
+ unsigned iz_dmax);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I, typename V>
+ util::graph
+ influence_zone_graph(const Image<I>& input_,
+ const Neighborhood<N>& nbh_,
+ const V& label_type,
+ unsigned iz_dmax)
+ {
+ trace::entering("scribo::make::influence_zone_graph");
+
+ (void) label_type;
+ I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mlc_is_equal(mln_value(I), bool)::check();
+ mln_assertion(input.is_valid());
+ mln_assertion(nbh.is_valid());
+
+ V nlabels;
+ typedef mln_ch_value(I,V) lbl_t;
+ lbl_t lbl = labeling::blobs(input, nbh, nlabels);
+
+ lbl_t iz = transform::influence_zone_geodesic(lbl, nbh, iz_dmax);
+
+ util::graph g = make::graph(iz | (pw::value(iz) != pw::cst(literal::zero)),
+ nbh, nlabels);
+
+ trace::exiting("scribo::make::influence_zone_graph");
+ return g;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::text::grouping
+
+ } // end of namespace scribo::text
+
+} // end of namespace scribo
+
+
+
+#endif // ! SCRIBO_MAKE_INFLUENCE_ZONE_GRAPH_HH
+
diff --git a/milena/sandbox/scribo/src/extract_text_double_link.cc b/milena/sandbox/scribo/src/extract_text_double_link.cc
new file mode 100644
index 0000000..26fccff
--- /dev/null
+++ b/milena/sandbox/scribo/src/extract_text_double_link.cc
@@ -0,0 +1,109 @@
+// 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.
+
+#include <iostream>
+
+#include <mln/essential/2d.hh>
+
+#include <scribo/text/extract_bboxes.hh>
+#include <scribo/text/grouping/group_with_single_left_link.hh>
+#include <scribo/text/grouping/group_with_single_right_link.hh>
+#include <scribo/debug/save_linked_textbboxes_image.hh>
+#include <scribo/text/grouping/group_from_double_link.hh>
+
+#include <scribo/debug/save_textbboxes_image.hh>
+
+int usage(const char *name)
+{
+ std::cout << "Usage: " << name << " <input.pbm> " << std::endl;
+ return 1;
+}
+
+
+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;
+ using namespace mln;
+
+ if (argc < 1)
+ return usage(argv[0]);
+
+ image2d<bool> input;
+ io::pbm::load(input, argv[1]);
+
+ value::label_16 nbboxes;
+ util::array<box2d> textbboxes = 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);
+
+ 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,
+ textbboxes, left_link, right_link,
+ literal::red, literal::cyan,
+ literal::yellow,
+ "test_double_link_double_linked.ppm");
+
+ // With validation.
+ util::array< box<point2d> > grouped_textbboxes
+ = text::grouping::group_from_double_link(textbboxes, left_link, right_link);
+
+ std::cout << "AFTER double grouping - nbboxes = " << grouped_textbboxes.nelements() << std::endl;
+
+ scribo::debug::save_textbboxes_image(input, grouped_textbboxes,
+ literal::red,
+ "test_double_link_grouped_text.ppm");
+
+}
+
diff --git a/milena/sandbox/scribo/src/extract_text_multiple_links.cc b/milena/sandbox/scribo/src/extract_text_multiple_links.cc
new file mode 100644
index 0000000..9b181e6
--- /dev/null
+++ b/milena/sandbox/scribo/src/extract_text_multiple_links.cc
@@ -0,0 +1,78 @@
+// 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.
+
+#include <iostream>
+
+#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/debug/save_textbboxes_image.hh>
+#include <scribo/debug/save_linked_textbboxes_image.hh>
+
+int usage(const char *name)
+{
+ std::cout << "Usage: " << name << " <input.pbm> " << std::endl;
+ return 1;
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace scribo;
+ using namespace mln;
+
+ if (argc < 1)
+ return usage(argv[0]);
+
+ image2d<bool> input;
+ io::pbm::load(input, argv[1]);
+
+ 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);
+
+ 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");
+
+ util::array< box<point2d> > grouped_textbboxes
+ = text::grouping::group_from_multiple_links(textbboxes, g);
+
+ 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");
+}
+
diff --git a/milena/sandbox/scribo/src/extract_text_single_link.cc b/milena/sandbox/scribo/src/extract_text_single_link.cc
new file mode 100644
index 0000000..5b4e248
--- /dev/null
+++ b/milena/sandbox/scribo/src/extract_text_single_link.cc
@@ -0,0 +1,108 @@
+// 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.
+
+#include <iostream>
+
+#include <mln/essential/2d.hh>
+
+#include <scribo/text/extract_bboxes.hh>
+#include <scribo/text/grouping/group_with_single_left_link.hh>
+#include <scribo/text/grouping/group_with_single_right_link.hh>
+#include <scribo/text/grouping/group_from_single_link.hh>
+
+#include <scribo/debug/save_textbboxes_image.hh>
+#include <scribo/debug/save_linked_textbboxes_image.hh>
+
+int usage(const char *name)
+{
+ std::cout << "Usage: " << name << " <input.pbm> " << std::endl;
+ return 1;
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace scribo;
+ using namespace mln;
+
+ if (argc < 1)
+ return usage(argv[0]);
+
+ image2d<bool> input;
+ io::pbm::load(input, argv[1]);
+
+ value::label_16 nbboxes;
+ util::array<box2d> textbboxes = 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);
+
+ std::cout << "BEFORE - nbboxes = " << nbboxes << std::endl;
+ scribo::debug::save_linked_textbboxes_image(input,
+ textbboxes, 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,
+ literal::red,
+ "test_single_left_link_grouped_text.ppm");
+ }
+
+ {
+ std::cout << "* Left grouping" << std::endl;
+ util::array<unsigned> right_link
+ = text::grouping::group_with_single_right_link(input,
+ c8(), nbboxes,
+ textbboxes, 30);
+
+ std::cout << "BEFORE - nbboxes = " << nbboxes << std::endl;
+ scribo::debug::save_linked_textbboxes_image(input,
+ textbboxes, 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,
+ literal::red,
+ "test_single_right_link_grouped_text.ppm");
+ }
+
+
+}
+
diff --git a/milena/sandbox/scribo/photo.cc b/milena/sandbox/scribo/src/photo.cc
similarity index 100%
copy from milena/sandbox/scribo/photo.cc
copy to milena/sandbox/scribo/src/photo.cc
diff --git a/milena/sandbox/scribo/table.cc b/milena/sandbox/scribo/src/table.cc
similarity index 100%
rename from milena/sandbox/scribo/table.cc
rename to milena/sandbox/scribo/src/table.cc
diff --git a/milena/sandbox/scribo/table/align_lines_horizontaly.hh b/milena/sandbox/scribo/table/align_lines_horizontaly.hh
new file mode 100644
index 0000000..e75f2f2
--- /dev/null
+++ b/milena/sandbox/scribo/table/align_lines_horizontaly.hh
@@ -0,0 +1,97 @@
+// 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_ALIGN_LINES_HORIZONTALY_HH
+# define SCRIBO_TABLE_ALIGN_LINES_HORIZONTALY_HH
+
+/// \file scribo/table/align_lines_horizontaly.hh
+///
+/// Align line bounding boxes horizontaly.
+
+
+# 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/util/array.hh>
+
+# include <scribo/table/internal/align_lines.hh>
+
+
+namespace scribo
+{
+
+ namespace table
+ {
+
+ /// 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.
+ ///
+ /// \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);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename I>
+ util::array<int>
+ align_lines_horizontaly(const Image<I>& input,
+ util::array<box<mln_site(I)> >& lines_bboxes)
+ {
+ trace::entering("scribo::table::align_lines_horizontaly");
+
+ mln_precondition(exact(input).is_valid());
+ util::array<int> res = internal::align_lines(geom::nrows(input),
+ geom::min_row(input),
+ geom::max_row(input),
+ lines_bboxes, 0);
+
+ trace::exiting("scribo::table::align_lines_horizontaly");
+ return res;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::table
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_TABLE_ALIGN_LINES_HORIZONTALY_HH
diff --git a/milena/sandbox/scribo/table/align_lines_verticaly.hh b/milena/sandbox/scribo/table/align_lines_verticaly.hh
new file mode 100644
index 0000000..7e860d0
--- /dev/null
+++ b/milena/sandbox/scribo/table/align_lines_verticaly.hh
@@ -0,0 +1,98 @@
+// 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_ALIGN_LINES_VERTICALY_HH
+# define SCRIBO_TABLE_ALIGN_LINES_VERTICALY_HH
+
+/// \file scribo/table/align_lines_verticaly.hh
+///
+/// Align line bounding boxes verticaly.
+
+
+# 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/util/array.hh>
+
+# include <scribo/table/internal/align_lines.hh>
+
+
+
+namespace scribo
+{
+
+ namespace table
+ {
+
+ /// 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.
+ ///
+ /// \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);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename I>
+ util::array<int>
+ align_lines_verticaly(const Image<I>& input,
+ util::array<box<mln_site(I)> >& lines_bboxes)
+ {
+ trace::entering("scribo::table::align_lines_horizontaly");
+
+ mln_precondition(exact(input).is_valid());
+ util::array<int> res = internal::align_lines(geom::ncols(input),
+ geom::min_col(input),
+ geom::max_col(input),
+ lines_bboxes, 1);
+
+ trace::exiting("scribo::table::align_lines_horizontaly");
+ return res;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::table
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_TABLE_ALIGN_LINES_VERTICALY_HH
diff --git a/milena/sandbox/scribo/table/connect_horizontal_lines.hh b/milena/sandbox/scribo/table/connect_horizontal_lines.hh
new file mode 100644
index 0000000..7dcf638
--- /dev/null
+++ b/milena/sandbox/scribo/table/connect_horizontal_lines.hh
@@ -0,0 +1,94 @@
+// 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_CONNECT_HORIZONTAL_LINES_HH
+# define SCRIBO_TABLE_CONNECT_HORIZONTAL_LINES_HH
+
+/// \file scribo/table/connect_horizontal_lines.hh
+///
+/// Connect horizontal lines with the new aligned columns.
+
+# include <mln/core/concept/image.hh>
+# include <mln/util/array.hh>
+# include <mln/util/couple.hh>
+
+# include <scribo/table/internal/connect_lines.hh>
+
+
+namespace scribo
+{
+
+ namespace table
+ {
+
+
+ /// Connect horizontal lines with the new aligned columns.
+ ///
+ /// \param[in] aligned_cols a list of new aligned cols.
+ /// \param[in,out] tableboxes the vertical and horizontal lines
+ /// bounding boxes.
+ /// \param[in] input The image from where the lines are
+ /// extracted.
+ 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)
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename I>
+ 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)
+ {
+ trace::entering("scribo::table::connect_horizontal_lines");
+ mln_precondition(exact(input).is_valid());
+
+ internal::connect_lines(aligned_cols, tableboxes.second(),
+ 1, exact(input).ncols());
+
+ trace::exiting("scribo::table::connect_horizontal_lines");
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::table
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_TABLE_CONNECT_HORIZONTAL_LINES_HH
diff --git a/milena/sandbox/scribo/table/connect_vertical_lines.hh b/milena/sandbox/scribo/table/connect_vertical_lines.hh
new file mode 100644
index 0000000..98c39f7
--- /dev/null
+++ b/milena/sandbox/scribo/table/connect_vertical_lines.hh
@@ -0,0 +1,95 @@
+// 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_CONNECT_VERTICAL_LINES_HH
+# define SCRIBO_TABLE_CONNECT_VERTICAL_LINES_HH
+
+/// \file scribo/table/connect_vertical_lines.hh
+///
+/// Connect vertical lines with aligned rows.
+
+# include <mln/core/concept/image.hh>
+# include <mln/util/array.hh>
+# include <mln/util/couple.hh>
+
+# include <scribo/table/internal/connect_lines.hh>
+
+
+namespace scribo
+{
+
+ namespace table
+ {
+
+
+ /// Connect vertical lines with the new aligned rows.
+ ///
+ /// \param[in] aligned_rows a list of new aligned rows.
+ /// \param[in,out] tableboxes the vertical and horizontal lines
+ /// bounding boxes.
+ /// \param[in] input The image from where the lines are
+ /// extracted.
+ 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)
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ /// Connect vertical lines with the new aligned rows.
+ 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)
+ {
+ trace::entering("scribo::table::connect_vertical_lines");
+ mln_precondition(exact(input).is_valid());
+
+ internal::connect_lines(aligned_rows, tableboxes.first(),
+ 0, exact(input).nrows());
+
+ trace::exiting("scribo::table::connect_vertical_lines");
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::table
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_TABLE_CONNECT_VERTICAL_LINES_HH
diff --git a/milena/sandbox/scribo/table/erase.hh b/milena/sandbox/scribo/table/erase.hh
new file mode 100644
index 0000000..9d94edb
--- /dev/null
+++ b/milena/sandbox/scribo/table/erase.hh
@@ -0,0 +1,97 @@
+// 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_ERASE_HH
+# define SCRIBO_TABLE_ERASE_HH
+
+/// \file scribo/table/erase.hh
+///
+/// Erase the table lines in an image.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/site_set/box.hh>
+# include <mln/core/routine/duplicate.hh>
+
+# include <mln/util/array.hh>
+# include <mln/util/couple.hh>
+
+# include <scribo/core/erase_bboxes.hh>
+
+namespace scribo
+{
+
+ namespace table
+ {
+
+ /// Erase table line bboxes from an image.
+ ///
+ /// \param[in] line_bboxes vertical and horizontal line bounding
+ /// boxes.
+ /// \param[in] in A binary image from which the table line
+ /// bboxes are extracted.
+ ///
+ ///
+ /// \return A copy of \p in where the table lines are removed.
+ template <typename I>
+ mln_concrete(I)
+ erase(const Image<I>& in,
+ const util::couple<util::array< box<mln_site(I)> >,
+ util::array< box<mln_site(I)> > >& line_bboxes);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename I>
+ mln_concrete(I)
+ erase(const Image<I>& in,
+ const util::couple<util::array< box<mln_site(I)> >,
+ util::array< box<mln_site(I)> > >& line_bboxes)
+ {
+ trace::entering("scribo::internal::erase_table");
+ mlc_equal(mln_value(I),bool)::check();
+ mln_precondition(exact(in).is_valid());
+
+ I output = duplicate(in);
+
+ erase_bboxes(output, line_bboxes.first());
+ erase_bboxes(output, line_bboxes.second());
+
+ trace::exiting("scribo::internal::erase_table");
+ return output;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::table
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_TABLE_ERASE_HH
diff --git a/milena/sandbox/scribo/table/extract_lines_with_rank.hh b/milena/sandbox/scribo/table/extract_lines_with_rank.hh
new file mode 100644
index 0000000..242dc30
--- /dev/null
+++ b/milena/sandbox/scribo/table/extract_lines_with_rank.hh
@@ -0,0 +1,127 @@
+// 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_EXTRACT_LINES_WITH_RANK_HH
+# define SCRIBO_TABLE_EXTRACT_LINES_WITH_RANK_HH
+
+/// \file scribo/table/extract_lines_with_rank.hh
+///
+/// Extract table lines using a rank filter.
+
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/window.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/core/site_set/box.hh>
+
+# include <mln/morpho/rank_filter.hh>
+
+# include <mln/accu/bbox.hh>
+
+# include <mln/util/array.hh>
+# include <mln/util/couple.hh>
+
+
+# include <scribo/core/component_bboxes.hh>
+
+namespace scribo
+{
+
+ namespace table
+ {
+
+ /// Find table bboxes thanks to a rank 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.
+ *
+ * \return pair of array of bounding boxes. The first array holds the
+ * vertical lines bounding boxes and the second one the
+ * horizontal lines bounding boxes.
+ */
+ 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);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I, typename N, typename V, typename HW, typename VW>
+ 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,
+ 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_);
+ mln_precondition(input.is_valid());
+ mln_precondition(nbh.is_valid());
+ mln_precondition(exact(vwin).is_valid());
+ mln_precondition(exact(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);
+ boxes_t vboxes = component_bboxes(vfilter, nbh, label_type);
+
+ // Horizontal lines.
+ mln_ch_value(I,bool) hfilter = morpho::rank_filter(input, hwin, hrank_k);
+ boxes_t hboxes = component_bboxes(hfilter, nbh, label_type);
+
+ return mln::make::couple(vboxes, hboxes);
+ }
+
+# endif // !MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::table
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_TABLE_EXTRACT_LINES_WITH_RANK_HH
diff --git a/milena/sandbox/scribo/table/internal/align_lines.hh b/milena/sandbox/scribo/table/internal/align_lines.hh
new file mode 100644
index 0000000..aaad9fa
--- /dev/null
+++ b/milena/sandbox/scribo/table/internal/align_lines.hh
@@ -0,0 +1,183 @@
+// 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_INTERNAL_ALIGN_LINES_HH
+# define SCRIBO_TABLE_INTERNAL_ALIGN_LINES_HH
+
+/// \file scribo/table/internal/align_lines.hh
+///
+/// Align table lines verticaly or horizontaly.
+
+
+# include <mln/core/site_set/box.hh>
+# include <mln/util/array.hh>
+# include <mln/util/set.hh>
+
+# include <scribo/core/macros.hh>
+
+
+namespace scribo
+{
+
+ namespace table
+ {
+
+ namespace internal
+ {
+
+ /// Align table lines bboxes according to a given dimension.
+ ///
+ /// \return A list of the resulting aligned cols. Each integer is actually
+ /// a col number.
+ /*
+ **
+ ** 0 1 3 4 5 6
+ ** ------------ -------
+ ** 0 |- - - - - | | {0,1} |
+ ** 1 | - - | | {0,1} |
+ ** 2 | | | {1} |
+ ** 3 | | | |
+ ** 4 | | | {2} |
+ ** 5 |- - | | {2} |
+ ** 6 | | | {2} |
+ **
+ ** \p hboxes contains all the table lines bboxes. Each bbox is
+ ** associated with an id, its location in the array.
+ **
+ ** For each bbox, its id is marked in a vector. The location is defined,
+ ** according to the given parameter \p dim, either by the row or the col
+ ** value of the pmin site.
+ **
+ ** Ids are then propagated in the vector according a small delta value.
+ ** if bbox ids are at the same location in the vector, their related bboxes
+ ** are likely to be on the same line.
+ **
+ ** Finally, iterate over the vector until all bboxes have been treated.
+ ** For each iteration, the set with a specific number of elements is found
+ ** and all bboxes referenced in this set are aligned on the same row or col.
+ **
+ */
+ template <typename P>
+ util::array<int>
+ align_lines(unsigned nsites,
+ int min_coord,
+ int max_coord,
+ util::array<box<P> >& line_boxes,
+ unsigned dim);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename P>
+ util::array<int>
+ align_lines(unsigned nsites,
+ int min_coord,
+ int max_coord,
+ util::array<box<P> >& line_boxes,
+ unsigned dim)
+ {
+ trace::entering("scribo::internal::align_lines");
+
+ mln_precondition(nsites > 0);
+
+ util::array< util::set<unsigned> > lines;
+ lines.resize(nsites);
+
+ // Map components with actual lines.
+ for_all_components(i, line_boxes)
+ {
+ int minline = line_boxes[i].pmin()[dim] - 5;
+ minline = (minline < min_coord ? min_coord : minline);
+ int maxline = line_boxes[i].pmax()[dim] + 5;
+ maxline = (maxline > max_coord ? max_coord : maxline);
+
+ for (int line = minline;
+ line <= maxline; ++line)
+ lines[line].insert(i);
+ }
+
+ // Init box2line
+ util::array<int> box2line;
+ box2line.resize(line_boxes.nelements());
+ for_all_elements(i, box2line)
+ box2line[i] = -1;
+
+ // Find the line with the highest element count.
+ unsigned max_nelts = 0;
+ for_all_elements(i, lines)
+ if (max_nelts < lines[i].nelements())
+ max_nelts = lines[i].nelements();
+
+ // Aligning lines
+ // FIXME: not optimal... Make it faster!
+ // We may do too much iterations (while loop) and some of them may
+ // be done for nothing...
+ util::array<int> newlines;
+ while (max_nelts > 0)
+ {
+ for_all_elements(i, lines)
+ if (lines[i].nelements() == max_nelts)
+ {
+ accu::mean<unsigned> mean;
+ for_all_elements(j, lines[i])
+ if (box2line[lines[i][j]] == -1)
+ mean.take(line_boxes[lines[i][j]].center()[dim]);
+
+ if (mean.is_valid())
+ {
+ for_all_elements(j, lines[i])
+ if (box2line[lines[i][j]] == -1)
+ {
+ line_boxes[lines[i][j]].pmin()[dim] = mean.to_result();
+ line_boxes[lines[i][j]].pmax()[dim] = mean.to_result();
+ box2line[lines[i][j]] = mean.to_result();
+ }
+ newlines.append(mean.to_result());
+ }
+ }
+ --max_nelts;
+ }
+
+ trace::exiting("scribo::internal::align_lines");
+ return newlines;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::table::internal
+
+ } // end of namespace scribo::table
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_TABLE_INTERNAL_ALIGN_LINES_HH
diff --git a/milena/sandbox/scribo/table/internal/connect_lines.hh b/milena/sandbox/scribo/table/internal/connect_lines.hh
new file mode 100644
index 0000000..d510fe2
--- /dev/null
+++ b/milena/sandbox/scribo/table/internal/connect_lines.hh
@@ -0,0 +1,118 @@
+// 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_INTERNAL_CONNECT_LINES_HH
+# define SCRIBO_TABLE_INTERNAL_CONNECT_LINES_HH
+
+/// \file scribo/table/connect_vertical_lines.hh
+///
+/// Connect vertical lines with aligned rows.
+
+# include <mln/core/image/image1d.hh>
+
+# include <mln/data/fill.hh>
+
+# include <mln/morpho/elementary/dilation.hh>
+# include <mln/util/array.hh>
+# include <mln/util/couple.hh>
+
+# include <mln/opt/at.hh>
+
+# include <scribo/core/macros.hh>
+
+
+namespace scribo
+{
+
+ namespace table
+ {
+
+ namespace internal
+ {
+
+ /// Connect vertical and horizontal lines if they are close to each other.
+ ///
+ /// ------ ------
+ /// ---> |
+ /// | |
+ /// | |
+ ///
+ ///
+ /// FIXME: doc arguments.
+ template <typename P>
+ void
+ connect_lines(const util::array<int>& aligned_lines,
+ util::array< box<P> >& boxes,
+ unsigned dim,
+ unsigned dim_size);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename P>
+ void
+ connect_lines(const util::array<int>& aligned_lines,
+ util::array< box<P> >& boxes,
+ unsigned dim,
+ unsigned dim_size)
+ {
+ trace::entering("scribo::table::internal::connect_lines");
+
+ image1d<int> l(dim_size);
+ data::fill(l, -1);
+
+ for_all_elements(i, aligned_lines)
+ opt::at(l, aligned_lines[i]) = i;
+
+ for (unsigned i = 0; i < settings.max_dist_lines; ++i)
+ l = morpho::elementary::dilation(l, c2());
+
+ for_all_components(i, boxes)
+ {
+ util::couple<point2d, point2d> 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)
+ boxes[i].pmax()[dim] = aligned_lines[opt::at(l, cp.second()[dim])];
+ }
+
+ trace::exiting("scribo::table::internal::connect_lines");
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::table
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_TABLE_INTERNAL_CONNECT_LINES_HH
diff --git a/milena/sandbox/scribo/table/internal/repair_lines.hh b/milena/sandbox/scribo/table/internal/repair_lines.hh
new file mode 100644
index 0000000..87f0933
--- /dev/null
+++ b/milena/sandbox/scribo/table/internal/repair_lines.hh
@@ -0,0 +1,132 @@
+// 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_INTERNAL_REPAIR_LINES_HH
+# define SCRIBO_TABLE_INTERNAL_REPAIR_LINES_HH
+
+/// \file scribo/table/internal/repair_lines.hh
+///
+/// Repair lines which have small discontinuities.
+
+# include <vector>
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/image/extension_val.hh>
+# include <mln/core/site_set/box.hh>
+# include <mln/data/fill.hh>
+# include <mln/util/couple.hh>
+# include <mln/util/array.hh>
+# include <mln/win/line.hh>
+# include <mln/pw/all.hh>
+
+# include <scribo/core/central_sites.hh>
+# include <scribo/table/internal/repair_lines.hh>
+
+
+namespace scribo
+{
+
+ namespace table
+ {
+
+ namespace internal
+ {
+
+
+# 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)
+ {
+ trace::entering("scribo::table::internal::repair_lines");
+
+ const I& input = exact(input_);
+ mln_precondition(input.is_valid());
+
+ typedef mln_site(I) P;
+ typedef win::line<mln_grid(P), axis, mln_coord(P)> line_t;
+
+ // Initialization
+ mln_ch_value(I,unsigned) l(input.domain());
+ data::fill(l, literal::zero);
+ for_all_components(i, tableboxes)
+ {
+ util::couple<P,P> cp = central_sites(tableboxes[i], axis);
+ l(cp.first()) = i;
+ l(cp.second()) = i;
+ }
+
+ // Repair
+ extension_val<mln_ch_value(I,unsigned)> 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));
+ //FIXME: use a half window, just the bottom of the vertical line.
+ line_t vl(settings.repair_max_dist);
+ mln_piter(tbb_ima_t) p(tbb_ima.domain());
+ mln_qiter(line_t) q(vl, p);
+ for_all(p)
+ 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);
+ }
+
+
+ // Remove merged boxes.
+ for_all_elements(i, tableboxes)
+ if (to_keep[i])
+ result.append(tableboxes[i]);
+
+ tableboxes = result;
+ trace::exiting("scribo::table::internal::repair_lines");
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::table::internal
+
+ } // end of namespace scribo::table
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_TABLE_INTERNAL_REPAIR_LINES_HH
diff --git a/milena/sandbox/scribo/table/repair_horizontal_lines.hh b/milena/sandbox/scribo/table/repair_horizontal_lines.hh
new file mode 100644
index 0000000..7c1edbd
--- /dev/null
+++ b/milena/sandbox/scribo/table/repair_horizontal_lines.hh
@@ -0,0 +1,92 @@
+// 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_REPAIR_HORIZONTAL_LINES_HH
+# define SCRIBO_TABLE_REPAIR_HORIZONTAL_LINES_HH
+
+/// \file scribo/table/repair_horizontal_lines.hh
+///
+/// Repair horizontal lines which have small discontinuities.
+
+# include <mln/core/concept/image.hh>
+# include <mln/util/couple.hh>
+# include <mln/util/array.hh>
+
+# include <scribo/table/internal/repair_lines.hh>
+
+namespace scribo
+{
+
+ namespace table
+ {
+
+
+ /// Repair horizontal lines which have small discontinuities.
+ /*!
+ * ---- ---- ==> ----------
+ *
+ * \param[in] input Image from which the table bounding
+ * boxes are extracted.
+ * \param[in,out] tablesboxes Table line bounding boxes.
+ * \param[in] max_discontinuity Repair discontinuity which are smaller
+ * than this value.
+ */
+ 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);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ inline
+ 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)
+ {
+ trace::entering("scribo::table::repair_horizontal_lines");
+ mln_precondition(exact(input).is_valid());
+
+ internal::repair_lines<1>(input, tableboxes.second(), max_discontinuity);
+
+ trace::exiting("scribo::table::repair_horizontal_lines");
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::table
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_TABLE_REPAIR_HORIZONTAL_LINES_HH
diff --git a/milena/sandbox/scribo/table/repair_vertical_lines.hh b/milena/sandbox/scribo/table/repair_vertical_lines.hh
new file mode 100644
index 0000000..94ae3f1
--- /dev/null
+++ b/milena/sandbox/scribo/table/repair_vertical_lines.hh
@@ -0,0 +1,98 @@
+// 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_REPAIR_VERTICAL_LINES_HH
+# define SCRIBO_TABLE_REPAIR_VERTICAL_LINES_HH
+
+/// \file scribo/table/repair_vertical_lines.hh
+///
+/// Repair vertical lines which have small discontinuities.
+
+# include <mln/core/concept/image.hh>
+# include <mln/util/couple.hh>
+# include <mln/util/array.hh>
+
+# include <scribo/table/internal/repair_lines.hh>
+
+namespace scribo
+{
+
+ namespace table
+ {
+
+
+ /// Repair vertical lines which have small discontinuities.
+ /*!
+ *
+ * | | \n
+ * | | \n
+ * ==> | \n
+ * | | \n
+ * | | \n
+ *
+ *
+ * \param[in] input Image from which the table bounding
+ * boxes are extracted.
+ * \param[in,out] tablesboxes Table line bounding boxes.
+ * \param[in] max_discontinuity Repair discontinuity which are smaller
+ * than this value.
+ */
+ template <typename I>
+ void
+ repair_vertical_lines(const Image<I>& input,
+ util::couple<util::array<box<mln_site(I)> >,
+ util::array<box<mln_site(I)> > >& tblboxes,
+ unsigned max_discontinuity);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ inline
+ void
+ repair_vertical_lines(const Image<I>& input,
+ util::couple<util::array<box<mln_site(I)> >,
+ util::array<box<mln_site(I)> > >& tblboxes,
+ unsigned max_discontinuity)
+ {
+ trace::entering("scribo::table::repair_vertical_lines");
+ mln_precondition(exact(input).is_valid());
+
+ internal::repair_lines<0>(input, tblboxes.first(), max_discontinuity);
+
+ trace::exiting("scribo::table::repair_vertical_lines");
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::table
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_TABLE_REPAIR_VERTICAL_LINES_HH
diff --git a/milena/sandbox/scribo/text/extract_bboxes.hh b/milena/sandbox/scribo/text/extract_bboxes.hh
new file mode 100644
index 0000000..0c88880
--- /dev/null
+++ b/milena/sandbox/scribo/text/extract_bboxes.hh
@@ -0,0 +1,95 @@
+// 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_TEXT_GROUPING_EXTRACT_BBOXES_HH
+# define SCRIBO_TEXT_GROUPING_EXTRACT_BBOXES_HH
+
+/// \file scribo/text/grouping/group_with_single_link.hh
+///
+/// Extract text bounding boxes from a binary image.
+
+# 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/array.hh>
+
+# include <scribo/core/component_bboxes.hh>
+
+namespace scribo
+{
+
+ namespace text
+ {
+
+ 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 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>
+ inline
+ util::array< box<mln_site(I)> >
+ extract_bboxes(const Image<I>& input_,
+ const Neighborhood<N>& nbh, V& nbboxes)
+ {
+ trace::entering("scribo::text::extract_bboxes");
+
+ const I& input = exact(input_);
+
+ 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);
+
+ trace::exiting("scribo::text::extract_bboxes");
+ return bboxes;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::text
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_TEXT_GROUPING_EXTRACT_BBOXES_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
new file mode 100644
index 0000000..d178a80
--- /dev/null
+++ b/milena/sandbox/scribo/text/grouping/group_from_double_link.hh
@@ -0,0 +1,108 @@
+// 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_TEXT_GROUPING_GROUP_FROM_DOUBLE_LINK_HH
+# define SCRIBO_TEXT_GROUPING_GROUP_FROM_DOUBLE_LINK_HH
+
+/// \file scribo/text/grouping/group_from_double_link.hh
+///
+/// Link text bounding boxes with their left neighbor.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/site_set/box.hh>
+
+# include <mln/accu/bbox.hh>
+
+# include <mln/util/array.hh>
+
+# include <scribo/text/grouping/internal/find_root.hh>
+
+# include <scribo/core/macros.hh>
+
+
+namespace scribo
+{
+
+ namespace text
+ {
+
+ namespace grouping
+ {
+
+ /// 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);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename P>
+ 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)
+ {
+ 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)
+ {
+ unsigned nbh = right_link[left_link[i]];
+ if (nbh == i)
+ tboxes[left_link[i]].take(textbboxes[i]);
+ else
+ tboxes[i].take(textbboxes[i]);
+ }
+
+ util::array< box<P> > result;
+ // component 0, the background, has an invalid box.
+ result.append(box<P>());
+ for_all_components(i, tboxes)
+ if (tboxes[i].is_valid())
+ result.append(tboxes[i]);
+
+ trace::exiting("scribo::text::grouping::group_from_double_link");
+ return result;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::text::grouping
+
+ } // end of namespace scribo::text
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_TEXT_GROUPING_GROUP_FROM_DOUBLE_LINK_HH
diff --git a/milena/sandbox/scribo/text/grouping/group_from_multiple_links.hh b/milena/sandbox/scribo/text/grouping/group_from_multiple_links.hh
new file mode 100644
index 0000000..612fb87
--- /dev/null
+++ b/milena/sandbox/scribo/text/grouping/group_from_multiple_links.hh
@@ -0,0 +1,154 @@
+// 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_GROUPING_GROUP_FROM_MULTIPLE_LINKS_HH
+# define SCRIBO_TEXT_GROUPING_GROUP_FROM_MULTIPLE_LINKS_HH
+
+/// \file scribo/text/grouping/group_from_multiple_links.hh
+///
+/// Link text bounding boxes with their neighbors.
+
+# include <mln/core/concept/graph.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/core/site_set/box.hh>
+
+# include <mln/canvas/browsing/depth_first_search.hh>
+
+# include <mln/accu/bbox.hh>
+
+# include <mln/pw/all.hh>
+
+# include <mln/fun/i2v/array.hh>
+
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+
+namespace scribo
+{
+
+ namespace text
+ {
+
+ namespace grouping
+ {
+
+ /// FIXME: Add much more doc!
+ template <typename G, typename P>
+ util::array<box<P> >
+ group_from_multiple_links(util::array<box<P> >& textbboxes,
+ const Graph<G>& g_);
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace internal
+ {
+
+ /// Functor to be passed to depth_first_search.
+ /// Map each component vertex with its representative vertex id.
+ 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;
+ }
+
+ void final()
+ {}
+
+ void next_component()
+ { ++ncomp; }
+
+ void new_component_from_vertex(unsigned id)
+ { vertextocomp(id) = ncomp; }
+
+ void added_to_queue(unsigned id)
+ { new_component_from_vertex(id); }
+
+ void process_vertex(unsigned)
+ {}
+
+ bool to_be_treated(unsigned id)
+ { return vertextocomp(id) == mln_max(unsigned); }
+
+ bool to_be_queued(unsigned id)
+ { return to_be_treated(id); }
+
+ unsigned ncomp;
+ fun::i2v::array<unsigned> vertextocomp;
+ };
+
+ } // end of namespace scribo::text::grouping::internal
+
+
+
+ template <typename G, typename P>
+ inline
+ util::array<box<P> >
+ group_from_multiple_links(util::array<box<P> >& textbboxes,
+ const Graph<G>& g_)
+ {
+ trace::entering("scribo::text::grouping::group_from_multiple_links");
+
+ const G& g = exact(g_);
+
+ mln_assertion(g.is_valid());
+
+ internal::map_vertex_to_component_id_functor 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]);
+
+ util::array< box<P> > result;
+ // Component 0 - the background has not valid bboxes.
+ result.append(box<P>());
+ for_all_components(i, textbboxes)
+ if (tboxes[i].is_valid())
+ result.append(tboxes[i].to_result());
+
+ mln_assertion(result.nelements() == f.ncomp);
+
+ trace::exiting("scribo::text::grouping::group_from_multiple_links");
+ return result;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::text::grouping
+
+ } // end of namespace scribo::text
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_TEXT_GROUPING_GROUP_FROM_MULTIPLE_LINKS_HH
diff --git a/milena/sandbox/scribo/text/grouping/group_from_single_link.hh b/milena/sandbox/scribo/text/grouping/group_from_single_link.hh
new file mode 100644
index 0000000..eccde96
--- /dev/null
+++ b/milena/sandbox/scribo/text/grouping/group_from_single_link.hh
@@ -0,0 +1,101 @@
+// 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_TEXT_GROUPING_GROUP_FROM_SINGLE_LINK_HH
+# define SCRIBO_TEXT_GROUPING_GROUP_FROM_SINGLE_LINK_HH
+
+/// \file scribo/text/grouping/group_from_single_link.hh
+///
+/// Link text bounding boxes with their left neighbor.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/site_set/box.hh>
+
+# include <mln/accu/bbox.hh>
+
+# include <mln/util/array.hh>
+
+# include <scribo/text/grouping/internal/find_root.hh>
+
+# include <scribo/core/macros.hh>
+
+
+namespace scribo
+{
+
+ namespace text
+ {
+
+ namespace grouping
+ {
+
+ /// 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);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename P>
+ inline
+ util::array< box<P> >
+ group_from_single_link(const util::array< box<P> >& textbboxes,
+ 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);
+
+ util::array< accu::bbox<P> > tboxes;
+ tboxes.resize(textbboxes.nelements());
+ for_all_components(i, textbboxes)
+ tboxes[link_array[i]].take(textbboxes[i]);
+
+ util::array< box<P> > result;
+ // component 0, the background, has an invalid box.
+ result.append(box<P>());
+ for_all_components(i, tboxes)
+ if (tboxes[i].is_valid())
+ result.append(tboxes[i]);
+
+ trace::exiting("scribo::text::grouping::group_from_single_link");
+ return result;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::text::grouping
+
+ } // end of namespace scribo::text
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_TEXT_GROUPING_GROUP_FROM_SINGLE_LINK_HH
diff --git a/milena/sandbox/scribo/text/grouping/group_with_multiple_links.hh b/milena/sandbox/scribo/text/grouping/group_with_multiple_links.hh
new file mode 100644
index 0000000..2f769fc
--- /dev/null
+++ b/milena/sandbox/scribo/text/grouping/group_with_multiple_links.hh
@@ -0,0 +1,115 @@
+// 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_TEXT_GROUPING_GROUP_WITH_MULTIPLE_LINKS_HH
+# define SCRIBO_TEXT_GROUPING_GROUP_WITH_MULTIPLE_LINKS_HH
+
+/// \file scribo/text/grouping/group_with_multiple_links.hh
+///
+/// Group character bounding boxes with multiple links.
+
+# include <mln/core/concept/image.hh>
+
+# include <mln/math/abs.hh>
+
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/text/grouping/internal/init_link_array.hh>
+# include <scribo/text/grouping/internal/update_link_graph.hh>
+
+namespace scribo
+{
+
+ namespace text
+ {
+
+ namespace grouping
+ {
+
+ /// 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,
+ 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,
+ unsigned neighb_max_distance)
+ {
+ trace::entering("scribo::text::grouping::group_with_multiple_links");
+
+ const I& input = exact(input_);
+
+ 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)
+ {
+ unsigned midcol = (textbboxes[i].pmax().col()
+ - textbboxes[i].pmin().col()) / 2;
+ int dmax = midcol + neighb_max_distance;
+ mln_site(I) c = textbboxes[i].center();
+
+ /// First site on the right of the central site
+ mln_site(I) p = c + right;
+
+ while (lbl.domain().has(p) && (lbl(p) == literal::zero || lbl(p) == i)
+ && math::abs(p.col() - c.col()) < dmax)
+ ++p.col();
+
+ internal::update_link_graph(lbl, g, p, c, i, dmax);
+ }
+
+ trace::exiting("scribo::text::grouping::group_with_multiple_links");
+ return g;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::text::grouping
+
+ } // end of namespace scribo::text
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_TEXT_GROUPING_GROUP_WITH_MULTIPLE_LINKS_HH
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
new file mode 100644
index 0000000..f1a3013
--- /dev/null
+++ b/milena/sandbox/scribo/text/grouping/group_with_single_left_link.hh
@@ -0,0 +1,135 @@
+// 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_TEXT_GROUPING_GROUP_WITH_SINGLE_LEFT_LINK_HH
+# define SCRIBO_TEXT_GROUPING_GROUP_WITH_SINGLE_LEFT_LINK_HH
+
+/// \file scribo/text/grouping/group_with_single_left_link.hh
+///
+/// Link text bounding boxes with their left neighbor.
+///
+/// Merge code with text::grouping::group_with_single_right_link.hh
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+# include <mln/math/abs.hh>
+
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/text/grouping/internal/init_link_array.hh>
+# include <scribo/text/grouping/internal/update_link_array.hh>
+
+//FIXME: not generic.
+# include <mln/core/alias/dpoint2d.hh>
+
+namespace scribo
+{
+
+ namespace text
+ {
+
+ namespace grouping
+ {
+
+ /// Map each character bounding box to its left bounding box neighbor
+ /// 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>
+ 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,
+ unsigned neighb_max_distance);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I, typename N, typename V>
+ 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,
+ unsigned neighb_max_distance)
+ {
+ trace::entering("scribo::text::grouping::group_with_single_left_link");
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ 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());
+ internal::init_link_array(left_link);
+
+ for_all_ncomponents(i, nbboxes)
+ {
+ unsigned midcol = (textbboxes[i].pmax().col()
+ - textbboxes[i].pmin().col()) / 2;
+ int dmax = midcol + neighb_max_distance;
+ mln_site(I) c = textbboxes[i].center();
+
+ ///
+ /// Find a neighbor on the right
+ ///
+
+ ///FIXME: the following code is not generic...
+ /// First site on the right of the central site
+ mln_site(I) p = c + right;
+
+ while (lbl.domain().has(p) && (lbl(p) == literal::zero || lbl(p) == i)
+ && 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");
+ return left_link;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::text::grouping
+
+ } // end of namespace scribo::text
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_TEXT_GROUPING_GROUP_WITH_SINGLE_LEFT_LINK_HH
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
new file mode 100644
index 0000000..7f1eeac
--- /dev/null
+++ b/milena/sandbox/scribo/text/grouping/group_with_single_right_link.hh
@@ -0,0 +1,135 @@
+// 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_TEXT_GROUPING_GROUP_WITH_SINGLE_RIGHT_LINK_HH
+# define SCRIBO_TEXT_GROUPING_GROUP_WITH_SINGLE_RIGHT_LINK_HH
+
+/// \file scribo/text/grouping/group_with_single_right_link.hh
+///
+/// Link text bounding boxes with their right neighbor.
+///
+/// Merge code with text::grouping::group_with_single_right_link.hh
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+# include <mln/math/abs.hh>
+
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/text/grouping/internal/init_link_array.hh>
+# include <scribo/text/grouping/internal/update_link_array.hh>
+
+//FIXME: not generic.
+# include <mln/core/alias/dpoint2d.hh>
+
+namespace scribo
+{
+
+ namespace text
+ {
+
+ namespace grouping
+ {
+
+ /// Map each character bounding box to its right bounding box neighbor
+ /// 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>
+ 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,
+ unsigned neighb_max_distance);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I, typename N, typename V>
+ 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,
+ unsigned neighb_max_distance)
+ {
+ trace::entering("scribo::text::grouping::group_with_single_right_link");
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ 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());
+ internal::init_link_array(right_link);
+
+ for_all_ncomponents(i, nbboxes)
+ {
+ unsigned midcol = (textbboxes[i].pmax().col()
+ - textbboxes[i].pmin().col()) / 2;
+ int dmax = midcol + neighb_max_distance;
+ mln_site(I) c = textbboxes[i].center();
+
+ ///
+ /// Find a neighbor on the left
+ ///
+
+ ///FIXME: the following code is not generic...
+ /// First site on the left of the central site
+ mln_site(I) p = c + left;
+
+ while (lbl.domain().has(p) && (lbl(p) == literal::zero || lbl(p) == i)
+ && 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");
+ return right_link;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::text::grouping
+
+ } // end of namespace scribo::text
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_TEXT_GROUPING_GROUP_WITH_SINGLE_RIGHT_LINK_HH
diff --git a/milena/sandbox/scribo/photo.cc b/milena/sandbox/scribo/text/grouping/internal/find_root.hh
similarity index 52%
copy from milena/sandbox/scribo/photo.cc
copy to milena/sandbox/scribo/text/grouping/internal/find_root.hh
index a173750..0b1e307 100644
--- a/milena/sandbox/scribo/photo.cc
+++ b/milena/sandbox/scribo/text/grouping/internal/find_root.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// 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,39 +27,54 @@
// Public License.
-#include "demat.hh"
+#ifndef SCRIBO_TEXT_GROUPING_INTERNAL_FIND_ROOT_LINK_ARRAY_HH
+# define SCRIBO_TEXT_GROUPING_INTERNAL_FIND_ROOT_LINK_ARRAY_HH
-int main(int argc, char*argv[])
+/// \file scribo/text/grouping/internal/find_root.hh
+///
+/// Find root in a parent array arrays.
+
+
+# include <mln/util/array.hh>
+
+
+namespace scribo
{
- using namespace mln;
- using value::int_u8;
- if (argc < 2)
+ namespace text
{
- std::cout << argv[0] << " <in.pbm> <out.pgm> <l> <bbox_larger> <bbox_distance> <min_comp_nsites>" << std::endl
- << std::endl << std::endl
- << std::endl
- << "=========="
- << std::endl << std::endl
- << "<in.pbm> B/W inverted input image."
- << std::endl << std::endl
-/* << "<out.ppm> RGB8 output image."
- << std::endl << std::endl
- << "<bbox_distance> Maximum distance between character bounding boxes. Used for bbox grouping."
- << std::endl << std::endl
- << "<min_comp_nsites> Minimum site count of a character/text component."
- << std::endl
- << " If a component have a site count lesser than this value, it is erased."
- << std::endl << std::endl
- << std::endl*/
- << "=========="
- << std::endl << std::endl
- << "HINT: compile with -DNOUT to avoid debug images."
- << std::endl << std::endl;
- return 1;
- }
-
- scribo::demat_photo(argv);
-
- return 0;
-}
+
+ namespace grouping
+ {
+
+ namespace internal
+ {
+
+ /// Find root in a parent array arrays.
+ unsigned
+ find_root(util::array<unsigned>& parent, unsigned x);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ inline
+ unsigned
+ find_root(util::array<unsigned>& parent, unsigned x)
+ {
+ if (parent[x] == x)
+ return x;
+ else
+ return parent[x] = find_root(parent, parent[x]);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::text::grouping::internal
+
+ } // end of namespace scribo::text::grouping
+
+ } // end of namespace scribo::text
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_TEXT_GROUPING_INTERNAL_FIND_ROOT_LINK_ARRAY_HH
diff --git a/milena/sandbox/scribo/photo.cc b/milena/sandbox/scribo/text/grouping/internal/init_link_array.hh
similarity index 52%
rename from milena/sandbox/scribo/photo.cc
rename to milena/sandbox/scribo/text/grouping/internal/init_link_array.hh
index a173750..ba197f9 100644
--- a/milena/sandbox/scribo/photo.cc
+++ b/milena/sandbox/scribo/text/grouping/internal/init_link_array.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// 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,39 +27,51 @@
// Public License.
-#include "demat.hh"
+#ifndef SCRIBO_TEXT_GROUPING_INTERNAL_INIT_LINK_ARRAY_HH
+# define SCRIBO_TEXT_GROUPING_INTERNAL_INIT_LINK_ARRAY_HH
-int main(int argc, char*argv[])
+/// \file scribo/text/grouping/internal/init_link_array.hh
+///
+/// Initialize a link array.
+
+
+# include <mln/util/array.hh>
+
+
+namespace scribo
{
- using namespace mln;
- using value::int_u8;
- if (argc < 2)
+ namespace text
{
- std::cout << argv[0] << " <in.pbm> <out.pgm> <l> <bbox_larger> <bbox_distance> <min_comp_nsites>" << std::endl
- << std::endl << std::endl
- << std::endl
- << "=========="
- << std::endl << std::endl
- << "<in.pbm> B/W inverted input image."
- << std::endl << std::endl
-/* << "<out.ppm> RGB8 output image."
- << std::endl << std::endl
- << "<bbox_distance> Maximum distance between character bounding boxes. Used for bbox grouping."
- << std::endl << std::endl
- << "<min_comp_nsites> Minimum site count of a character/text component."
- << std::endl
- << " If a component have a site count lesser than this value, it is erased."
- << std::endl << std::endl
- << std::endl*/
- << "=========="
- << std::endl << std::endl
- << "HINT: compile with -DNOUT to avoid debug images."
- << std::endl << std::endl;
- return 1;
- }
-
- scribo::demat_photo(argv);
-
- return 0;
-}
+
+ namespace grouping
+ {
+
+ namespace internal
+ {
+
+ /// Initialize a link array.
+ void init_link_array(util::array<unsigned>& link_array);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ inline
+ void
+ init_link_array(util::array<unsigned>& link_array)
+ {
+ for (unsigned i = 0; i < link_array.nelements(); ++i)
+ link_array[i] = i;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::text::grouping::internal
+
+ } // end of namespace scribo::text::grouping
+
+ } // end of namespace scribo::text
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_TEXT_GROUPING_INTERNAL_INIT_LINK_ARRAY_HH
diff --git a/milena/sandbox/scribo/text/grouping/internal/update_link_array.hh b/milena/sandbox/scribo/text/grouping/internal/update_link_array.hh
new file mode 100644
index 0000000..242d18f
--- /dev/null
+++ b/milena/sandbox/scribo/text/grouping/internal/update_link_array.hh
@@ -0,0 +1,93 @@
+// 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_TEXT_GROUPING_INTERNAL_UPDATE_LINK_ARRAY_HH
+# define SCRIBO_TEXT_GROUPING_INTERNAL_UPDATE_LINK_ARRAY_HH
+
+/// \file scribo/text/grouping/internal/update_link_array.hh
+///
+/// Update a lookup table if a neighbor is found on the right of
+/// the current bbox.
+
+
+# include <mln/core/concept/image.hh>
+# include <mln/util/array.hh>
+
+
+namespace scribo
+{
+
+ namespace text
+ {
+
+ namespace grouping
+ {
+
+ namespace internal
+ {
+
+ /// Update the lookup table \p link_array if a neighbor is found
+ /// on the right of the current bbox.
+ template <typename I>
+ void
+ update_link_array(const Image<I>& lbl, util::array<unsigned>& link_array,
+ const mln_site(I)& p, const mln_site(I)& c,
+ unsigned i, int dmax);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ inline
+ void
+ update_link_array(const Image<I>& lbl_, util::array<unsigned>& link_array,
+ const mln_site(I)& p, const mln_site(I)& c,
+ unsigned i, int dmax)
+ {
+ const I& lbl = exact(lbl_);
+
+ mlc_is_a(mln_value(I), mln::value::Symbolic)::check();
+ 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))
+ link_array[lbl(p)] = i;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::text::grouping::internal
+
+ } // end of namespace scribo::text::grouping
+
+ } // end of namespace scribo::text
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_TEXT_GROUPING_INTERNAL_UPDATE_LINK_ARRAY_HH
diff --git a/milena/sandbox/scribo/text/grouping/internal/update_link_graph.hh b/milena/sandbox/scribo/text/grouping/internal/update_link_graph.hh
new file mode 100644
index 0000000..e31c5e8
--- /dev/null
+++ b/milena/sandbox/scribo/text/grouping/internal/update_link_graph.hh
@@ -0,0 +1,92 @@
+// 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_TEXT_GROUPING_INTERNAL_UPDATE_LINK_GRAPH_HH
+# define SCRIBO_TEXT_GROUPING_INTERNAL_UPDATE_LINK_GRAPH_HH
+
+/// \file scribo/text/grouping/internal/update_link_array.hh
+///
+/// Update graph edges if a valid neighbor is found.
+
+# include <mln/core/concept/image.hh>
+# include <mln/util/graph.hh>
+
+namespace scribo
+{
+
+ namespace text
+ {
+
+ namespace grouping
+ {
+
+ namespace internal
+ {
+
+ /// Update graph edges if a valid neighbor is found.
+ template <typename I>
+ void
+ update_link_graph(Image<I>& lbl_, util::graph& g,
+ const mln_site(I)& p, const mln_site(I)& c,
+ unsigned i, int dmax);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename I>
+ inline
+ void
+ update_link_graph(Image<I>& lbl_, util::graph& g,
+ const mln_site(I)& p, const mln_site(I)& c,
+ unsigned i, int dmax)
+ {
+ const I& lbl = exact(lbl_);
+
+ 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
+ && (math::abs(p.col() - c.col())) < dmax)
+ g.add_edge(lbl(p), i);
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::text::grouping::internal
+
+ } // end of namespace scribo::text::grouping
+
+ } // end of namespace scribo::text
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_TEXT_GROUPING_INTERNAL_UPDATE_LINK_GRAPH_HH
diff --git a/milena/sandbox/scribo/text/recognition.hh b/milena/sandbox/scribo/text/recognition.hh
new file mode 100644
index 0000000..98c3b67
--- /dev/null
+++ b/milena/sandbox/scribo/text/recognition.hh
@@ -0,0 +1,142 @@
+// 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_TEXT_RECOGNITION_HH
+# define SCRIBO_TEXT_RECOGNITION_HH
+
+/// \file scribo/text/recognition.hh
+///
+/// Passes the text bounding boxes to an OCR (Tesseract).
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/core/site_set/box.hh>
+# include <mln/util/array.hh>
+# include <mln/labeling/blobs.hh>
+# include <mln/data/fill.hh>
+# include <mln/pw/all.hh>
+# include <mln/debug/put_words.hh>
+
+# include <scribo/core/macros.hh>
+
+# include <tesseract/baseapi.h>
+
+
+
+namespace scribo
+{
+
+ namespace text
+ {
+
+ /// Passes the text bboxes to Tesseract (OCR) and store the result in
+ /// an image of characters.
+ ///
+ /// \param[in] input_ image from where the text bboxes are extracted.
+ /// \param[in] nbh_ The neighborhood used to label \p input_.
+ /// \param[in] nbboxes The value type used in the labeled image.
+ /// \param[in] textbboxes array of text bounding boxes.
+ /// \param[in] language the language which should be recognized by Tesseract.
+ /// (fra, en, ...)
+ ///
+ /// \return An image of characters.
+ ///
+ /// FIXME: For each text bbox, we create a new image. We may like to avoid that.
+ /// FIXME: Do not store the result in an image?
+ 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 char *language);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ 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 char *language)
+ {
+ trace::entering("scribo::text::recognition");
+
+ mlc_equal(mln_value(I), bool)::check();
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+ mln_precondition(input.is_valid());
+ mln_precondition(nbh.is_valid());
+
+ mln_ch_value(I,V) lbl = labeling::blobs(input, nbh, nbboxes);
+
+ /// Use text bboxes with Tesseract
+ TessBaseAPI::InitWithLanguage(NULL, NULL, language, NULL, false, 0, NULL);
+ mln_ch_value(I,char) txt(input.domain());
+ data::fill(txt, ' ');
+
+ for_all_components(i, textbboxes)
+ {
+ if (textbboxes[i].is_valid())
+ {
+ mln_ch_value(I,bool) b(textbboxes[i], 0);
+ data::fill(b, false);
+ data::fill((b | (pw::value(lbl) == pw::cst(i))).rw(), true);
+
+ char* s = TessBaseAPI::TesseractRect(
+ (unsigned char*) b.buffer(),
+ sizeof (bool), // Pixel size.
+ b.ncols() * sizeof (bool), // Row_offset
+ 0, // Left
+ 0, // Top
+ b.ncols(), // n cols
+ b.nrows()); // n rows
+
+
+
+ mln_site(I) p = textbboxes[i].center();
+ p.col() -= (textbboxes[i].pmax().col()
+ - textbboxes[i].pmin().col()) / 2;
+ if (s != 0)
+ debug::put_word(txt, p, s);
+ free(s);
+ }
+ }
+
+ trace::exiting("scribo::text::recognition");
+ return text;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::text
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_TEXT_RECOGNITION_HH
--
1.5.6.5
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-03-10 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Implement 3D watershed and various tools.
* fabien/bin/dicom2pgm.cc: New tool.
* fabien/bin/dump2pgm.cc: New tool.
* fabien/bin/dump2pgm8b.cc: New tool.
* fabien/bin/dump_mask.cc: New tool.
* fabien/bin/filetype.hh: New.
* fabien/bin/pnms2dump.cc: New tool.
* fabien/igr/Makefile: Update.
* fabien/igr/check2d_wsd.sh: Shell script for testing.
* fabien/igr/check3d_wsd.sh: Shell script for testing.
* fabien/igr/watershed.cc: Rename this...
* fabien/igr/watershed.hh: ...into this.
* fabien/igr/watershed2d.cc: Implement 2D watershed.
* fabien/igr/watershed3d.cc: Implement 3D watershed.
---
TODO | 7 -
bin/dicom2pgm.cc | 34 +++++
bin/dump2pgm.cc | 37 +++++
bin/dump2pgm8b.cc | 38 ++++++
bin/dump_mask.cc | 86 +++++++++++++
bin/filetype.hh | 54 ++++++++
bin/pnms2dump.cc | 97 +++++++++++++++
igr/Makefile | 9 -
igr/check2d_wsd.sh | 32 +++++
igr/check3d_wsd.sh | 34 +++++
igr/watershed.hh | 331 ++++++++++++++++++++++++++++++++++++++++++++++++++++
igr/watershed2d.cc | 331 ++++++++++++++++++++++++++++++++++++++++++++++++++++
igr/watershed3d.cc | 334 +++++++++++++++++++++++++++++++++++++++++++++++++++++
13 files changed, 1419 insertions(+), 5 deletions(-)
Index: trunk/milena/sandbox/fabien/igr/watershed.cc (deleted)
===================================================================
Index: trunk/milena/sandbox/fabien/igr/watershed2d.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/watershed2d.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/watershed2d.cc (revision 3503)
@@ -0,0 +1,331 @@
+#include <iostream>
+#include <mln/core/image/image2d.hh>
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/core/image/image_if.hh>
+
+#include <mln/io/ppm/save.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/dicom/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/dump/save.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/label_16.hh>
+
+#include <mln/level/transform.hh>
+#include <mln/level/stretch.hh>
+
+#include <mln/labeling/mean_values.hh>
+
+#include <mln/convert/to_fun.hh>
+
+#include <mln/make/graph.hh>
+
+#include <mln/morpho/gradient.hh>
+#include <mln/morpho/closing/area.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/fun/l2l/wrap.hh>
+
+#include <mln/core/var.hh>
+#include <mln/morpho/elementary/dilation.hh>
+
+#include <mln/core/routine/extend.hh>
+
+#include <mln/util/graph.hh>
+
+#include <mln/essential/2d.hh>
+#include <mln/core/alias/vec3d.hh>
+#include <mln/debug/draw_graph.hh>
+#include <mln/util/graph.hh>
+#include <mln/accu/center.hh>
+#include <mln/io/dump/all.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb16.hh>
+#include <mln/accu/compute.hh>
+#include <mln/core/alias/dpoint2d.hh>
+#include <mln/draw/box.hh>
+#include <mln/level/stretch.hh>
+#include <mln/fun/v2v/id.hh>
+#include <mln/fun/l2l/wrap.hh>
+#include <mln/core/image/line_graph_elt_neighborhood.hh>
+#include <mln/morpho/elementary/dilation.hh>
+#include <mln/labeling/mean_values.hh>
+#include <mln/extension/adjust_fill.hh>
+#include <mln/extract/all.hh>
+#include <mln/make/region_adjacency_graph.hh>
+
+
+
+// Given a color image and a wshed image, computes the component graph.
+// Vertex values are computed thanks to a RGB image.
+
+namespace mln
+{
+
+ template <typename V>
+ value::int_u8 dist(const V& c1, const V& c2)
+ {
+ unsigned d = math::diff_abs(c1.red(), c2.red());
+ unsigned d_;
+ d_ = math::diff_abs(c1.green(), c2.green());
+
+ if (d_ > d)
+ d = d_;
+
+ d_ = math::diff_abs(c1.blue(), c2.blue());
+
+ if (d_ > d)
+ d = d_;
+ return d;
+ }
+
+
+ // ima_v, image on graph vertices; value = mean color per vertex (watershed basin)
+ template <typename I>
+ inline
+ pw::image<fun::i2v::array<value::int_u8>,
+ p_edges<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_edge_graph_image(const I& ima_v, const util::graph& g)
+ {
+ // edge sites.
+ typedef fun::i2v::array<mln_site(I)> edge_site_t;
+ edge_site_t edge_site(g.e_nmax(), literal::origin);
+ typedef p_edges<util::graph, edge_site_t > pe_t;
+ pe_t pe(g, edge_site);
+
+ // edge values
+ typedef fun::i2v::array<value::int_u8> edge_values_t;
+ edge_values_t edge_values(g.e_nmax());
+
+ // image on graph edges
+ typedef pw::image<edge_values_t, pe_t> ima_e_t;
+ ima_e_t ima_e = (edge_values | pe);
+
+ mln_piter(ima_e_t) e(ima_e.domain());
+ for_all(e) // in ima_e
+ ima_e(e) = math::diff_abs(ima_v.function()(e.element().v1()), ima_v.function()(e.element().v2()));
+
+ return ima_e;
+ }
+
+
+ template <typename I, typename J>
+ inline
+ util::array<mln_value(I)>
+ mean_color_values(const I& input, const J& w, mln_value(J) nbasins)
+ {
+ // Cf. sandbox/theo/color/segment_rgb_pixels.cc
+
+ util::array<float> m_3f = labeling::compute(accu::mean<mln_value(I)>(),
+ input, // input color image
+ w, // watershed labeling
+ nbasins);
+ m_3f[0] = literal::zero;
+
+ util::array<mln_value(I)> m;
+ convert::from_to(m_3f, m);
+ m[0] = 150u;
+
+ /*io::ppm::save(level::transform(w,
+ convert::to< fun::i2v::array<mln_value(I)> >(m)),
+ "wst_rag_wshd_color.ppm");*/
+
+ return m;
+ }
+
+
+ template <typename I, typename J>
+ pw::image<fun::i2v::array<mln_value(I)>, p_vertices<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_vertex_graph_image(const util::graph& g, const I&input, const J& w, const mln_value(J)& nbasins)
+ {
+ typedef util::array<mln_site(I)> vertex_sites_t;
+ vertex_sites_t site_values;
+ convert::from_to(labeling::compute(accu::center<mln_site(I)>(), w, nbasins),
+ site_values);
+
+ typedef fun::i2v::array<mln_site(J)> f_sites_t;
+ f_sites_t sites;
+ convert::from_to(site_values, sites);
+
+ // p_vertices
+ typedef p_vertices<util::graph, f_sites_t> S;
+ S pv(g, sites);
+
+
+ typedef fun::i2v::array<mln_value(I)> vertex_values_t;
+ vertex_values_t vertex_values;
+ convert::from_to(mean_color_values(input, w, nbasins), vertex_values);
+
+ mln_VAR(ima_v, (vertex_values | pv));
+
+ return ima_v;
+ }
+
+
+ template <typename I, typename V>
+ struct edge_to_color : Function_p2v< edge_to_color<I,V> >
+ {
+ typedef V result;
+
+ edge_to_color(const I& ima)
+ : ima_(ima)
+ {
+ }
+
+ V
+ operator()(const unsigned& e) const
+ {
+ return convert::to<V>(ima_.function()(e));
+ }
+
+ const I& ima_;
+ };
+
+ template <typename V>
+ inline
+ unsigned
+ find_root(util::array<V>& parent, const unsigned& x)
+ {
+ if (parent[x] == x)
+ return x;
+ else
+ return parent[x] = find_root(parent, parent[x]);
+ }
+
+
+ template <typename I, typename V, typename E>
+ inline
+ image2d<mln_value(I)>
+ make_debug_graph_image(const I& input,
+ const V& ima_v, const E& ima_e,
+ unsigned box_size, const value::int_u12& bg)
+ {
+ image2d<mln_value(I)> ima;
+ initialize(ima, input);
+
+ data::fill(ima, bg);
+ debug::draw_graph(ima, ima_v.domain(),
+ pw::cst(150u),
+ edge_to_color<E, mln_value(I)>(ima_e));
+
+ dpoint2d tl(-box_size,-box_size);
+ dpoint2d br(box_size,box_size);
+ mln_piter(V) p(ima_v.domain());
+ for_all(p)
+ {
+ box2d b(p + tl, p + br);
+ b.crop_wrt(ima.domain());
+ data::fill((ima | b).rw(), convert::to<mln_value(I)>(ima_v(p)));
+ }
+
+ return ima;
+ }
+
+}
+
+
+///////////////////
+// //
+// Main Function //
+// //
+///////////////////
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::int_u12;
+ using value::rgb8;
+ using value::label_16;
+
+ if (argc < 4)
+ {
+ std::cout << "Usage: " << argv[0] << " <ima.dcm> <closure_lambda> <box_size> <dist_max>"
+ << std::endl;
+ return 1;
+ }
+
+ unsigned closure_lambda = atoi(argv[2]);
+ unsigned box_size = atoi(argv[3]);
+ unsigned dist_max = atoi(argv[4]);
+
+ image2d<int_u12> dcm;
+ io::dicom::load(dcm, argv[1]);
+
+ io::pgm::save(level::stretch(int_u8(), dcm), "wsd_01_src.pgm");
+
+ image2d<int_u12> grad = morpho::gradient(dcm, win_c4p());
+ image2d<int_u12> clo = morpho::closing::area(grad, c4(), closure_lambda);
+
+ label_16 nbasins;
+ image2d<label_16> wshed = morpho::meyer_wst(clo, c4(), nbasins);
+
+ io::pgm::save(level::stretch(int_u8(), clo), "wsd_02.pgm");
+ io::pgm::save(level::transform(wshed, fun::l2l::wrap<int_u8>()), "wsd_03.pgm");
+
+ mln_VAR(vol2_, morpho::elementary::dilation(extend(wshed | (pw::value(wshed) == 0u), wshed), c8()));
+
+ data::fill((wshed | (pw::value(wshed) == 0u)).rw(), vol2_);
+
+ io::pgm::save(level::transform(wshed, fun::l2l::wrap<int_u8>()), "wsd_04.pgm");
+
+ /// Build graph
+ util::graph g = make::graph(wshed, c4(), nbasins);
+ // Build graph images and compute distance values with a RGB image.
+ mln_VAR(ima_v, make_vertex_graph_image(g, dcm, wshed, nbasins));
+ mln_VAR(ima_e, make_edge_graph_image(ima_v, g));
+
+ /// Try to merge vertices.
+ mln_piter_(ima_e_t) e(ima_e.domain());
+ util::array<label_16> parent(g.v_nmax());
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ parent[i] = i;
+
+ for_all(e)
+ {
+ unsigned v1 = e.element().v1();
+ unsigned v2 = e.element().v2();
+ if (ima_e(e) <= dist_max && find_root(parent, v1) != find_root(parent, v2))
+ parent[find_root(parent, v1)] = find_root(parent, v2);
+ }
+
+ fun::i2v::array<label_16> f(parent.nelements());
+ std::vector<unsigned> new_label(parent.nelements(), 0);
+ unsigned nbasins2 = 0;
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ {
+ unsigned p = find_root(parent, i);
+ mln_assertion(parent[p] == find_root(parent, i));
+ if (new_label[p] == 0)
+ new_label[p] = nbasins2++;
+ f(i) = new_label[p];
+ }
+ mln_invariant(f(0) == 0u);
+ --nbasins2; // nbasins2 does not count the basin with label 0.
+ image2d<label_16> wsd2 = level::transform(wshed, f);
+
+ io::pgm::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()), "wsd_05.pgm");
+
+ /// Reconstruct a graph from the simplified image.
+ util::graph g2 = make::graph(wsd2, c4(), nbasins2);
+
+ // Compute distance values with a RGB image.
+ mln_VAR(ima_v2, make_vertex_graph_image(g2, dcm, wsd2, nbasins2));
+ mln_VAR(ima_e2, make_edge_graph_image(ima_v2, g2));
+
+ mln_VAR(wsd2_, morpho::elementary::dilation(extend(wsd2 | (pw::value(wsd2) == 0u), wsd2), c8()));
+
+ data::fill((wsd2 | (pw::value(wsd2) == 0u)).rw(), wsd2_);
+
+ io::pgm::save(level::transform(labeling::mean_values(dcm, wsd2, nbasins2), fun::l2l::wrap<int_u8>()), "wsd_06_mean_colors.pgm");
+ io::pgm::save(level::stretch(int_u8(), make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, 4095)), "wsd_07_graph_image2_white.pgm");
+ io::pgm::save(level::stretch(int_u8(), make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, 0)), "wsd_08_graph_image2_black.pgm");
+ io::pgm::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()), "wsd_99_result.pgm");
+}
Index: trunk/milena/sandbox/fabien/igr/watershed3d.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/watershed3d.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/watershed3d.cc (revision 3503)
@@ -0,0 +1,334 @@
+#include <iostream>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/core/alias/neighb3d.hh>
+#include <mln/core/alias/window3d.hh>
+#include <mln/core/image/image_if.hh>
+
+#include <mln/io/ppm/save.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/dicom/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/dump/save.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/label_16.hh>
+
+#include <mln/level/transform.hh>
+#include <mln/level/stretch.hh>
+
+#include <mln/labeling/mean_values.hh>
+
+#include <mln/convert/to_fun.hh>
+
+#include <mln/make/graph.hh>
+
+#include <mln/morpho/gradient.hh>
+#include <mln/morpho/closing/area.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/fun/l2l/wrap.hh>
+
+#include <mln/core/var.hh>
+#include <mln/morpho/elementary/dilation.hh>
+
+#include <mln/core/routine/extend.hh>
+
+#include <mln/util/graph.hh>
+
+#include <mln/essential/2d.hh>
+#include <mln/core/alias/vec3d.hh>
+#include <mln/debug/draw_graph.hh>
+#include <mln/util/graph.hh>
+#include <mln/accu/center.hh>
+#include <mln/io/dump/all.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb16.hh>
+#include <mln/accu/compute.hh>
+#include <mln/core/alias/dpoint2d.hh>
+#include <mln/draw/box.hh>
+#include <mln/level/stretch.hh>
+#include <mln/fun/v2v/id.hh>
+#include <mln/fun/l2l/wrap.hh>
+#include <mln/core/image/line_graph_elt_neighborhood.hh>
+#include <mln/morpho/elementary/dilation.hh>
+#include <mln/labeling/mean_values.hh>
+#include <mln/extension/adjust_fill.hh>
+#include <mln/extract/all.hh>
+#include <mln/make/region_adjacency_graph.hh>
+
+
+
+// Given a color image and a wshed image, computes the component graph.
+// Vertex values are computed thanks to a RGB image.
+
+namespace mln
+{
+
+ template <typename V>
+ value::int_u8 dist(const V& c1, const V& c2)
+ {
+ unsigned d = math::diff_abs(c1.red(), c2.red());
+ unsigned d_;
+ d_ = math::diff_abs(c1.green(), c2.green());
+
+ if (d_ > d)
+ d = d_;
+
+ d_ = math::diff_abs(c1.blue(), c2.blue());
+
+ if (d_ > d)
+ d = d_;
+ return d;
+ }
+
+
+ // ima_v, image on graph vertices; value = mean color per vertex (watershed basin)
+ template <typename I>
+ inline
+ pw::image<fun::i2v::array<value::int_u8>,
+ p_edges<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_edge_graph_image(const I& ima_v, const util::graph& g)
+ {
+ // edge sites.
+ typedef fun::i2v::array<mln_site(I)> edge_site_t;
+ edge_site_t edge_site(g.e_nmax(), literal::origin);
+ typedef p_edges<util::graph, edge_site_t > pe_t;
+ pe_t pe(g, edge_site);
+
+ // edge values
+ typedef fun::i2v::array<value::int_u8> edge_values_t;
+ edge_values_t edge_values(g.e_nmax());
+
+ // image on graph edges
+ typedef pw::image<edge_values_t, pe_t> ima_e_t;
+ ima_e_t ima_e = (edge_values | pe);
+
+ mln_piter(ima_e_t) e(ima_e.domain());
+ for_all(e) // in ima_e
+ ima_e(e) = math::diff_abs(ima_v.function()(e.element().v1()), ima_v.function()(e.element().v2()));
+
+ return ima_e;
+ }
+
+
+ template <typename I, typename J>
+ inline
+ util::array<mln_value(I)>
+ mean_color_values(const I& input, const J& w, mln_value(J) nbasins)
+ {
+ // Cf. sandbox/theo/color/segment_rgb_pixels.cc
+
+ util::array<float> m_3f = labeling::compute(accu::mean<mln_value(I)>(),
+ input, // input color image
+ w, // watershed labeling
+ nbasins);
+ m_3f[0] = literal::zero;
+
+ util::array<mln_value(I)> m;
+ convert::from_to(m_3f, m);
+ m[0] = 150u;
+
+ /*io::ppm::save(level::transform(w,
+ convert::to< fun::i2v::array<mln_value(I)> >(m)),
+ "wst_rag_wshd_color.ppm");*/
+
+ return m;
+ }
+
+
+ template <typename I, typename J>
+ pw::image<fun::i2v::array<mln_value(I)>, p_vertices<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_vertex_graph_image(const util::graph& g, const I&input, const J& w, const mln_value(J)& nbasins)
+ {
+ typedef util::array<mln_site(I)> vertex_sites_t;
+ vertex_sites_t site_values;
+ convert::from_to(labeling::compute(accu::center<mln_site(I)>(), w, nbasins),
+ site_values);
+
+ typedef fun::i2v::array<mln_site(J)> f_sites_t;
+ f_sites_t sites;
+ convert::from_to(site_values, sites);
+
+ // p_vertices
+ typedef p_vertices<util::graph, f_sites_t> S;
+ S pv(g, sites);
+
+
+ typedef fun::i2v::array<mln_value(I)> vertex_values_t;
+ vertex_values_t vertex_values;
+ convert::from_to(mean_color_values(input, w, nbasins), vertex_values);
+
+ mln_VAR(ima_v, (vertex_values | pv));
+
+ return ima_v;
+ }
+
+
+ template <typename I, typename V>
+ struct edge_to_color : Function_p2v< edge_to_color<I,V> >
+ {
+ typedef V result;
+
+ edge_to_color(const I& ima)
+ : ima_(ima)
+ {
+ }
+
+ V
+ operator()(const unsigned& e) const
+ {
+ return convert::to<V>(ima_.function()(e));
+ }
+
+ const I& ima_;
+ };
+
+ template <typename V>
+ inline
+ unsigned
+ find_root(util::array<V>& parent, const unsigned& x)
+ {
+ if (parent[x] == x)
+ return x;
+ else
+ return parent[x] = find_root(parent, parent[x]);
+ }
+
+
+ template <typename I, typename V, typename E>
+ inline
+ image3d<mln_value(I)>
+ make_debug_graph_image(const I& input,
+ const V& ima_v, const E& ima_e,
+ unsigned box_size, const value::int_u12& bg)
+ {
+ image3d<mln_value(I)> ima;
+ initialize(ima, input);
+
+ data::fill(ima, bg);
+ debug::draw_graph(ima, ima_v.domain(),
+ pw::cst(150u),
+ edge_to_color<E, mln_value(I)>(ima_e));
+
+ dpoint3d tl(-box_size,-box_size, -box_size);
+ dpoint3d br(box_size,box_size, -box_size);
+ mln_piter(V) p(ima_v.domain());
+ for_all(p)
+ {
+ box3d b(p + tl, p + br);
+ b.crop_wrt(ima.domain());
+ data::fill((ima | b).rw(), convert::to<mln_value(I)>(ima_v(p)));
+ }
+
+ return ima;
+ }
+
+}
+
+
+///////////////////
+// //
+// Main Function //
+// //
+///////////////////
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::int_u12;
+ using value::rgb8;
+ using value::label_16;
+
+ if (argc < 4)
+ {
+ std::cout << "Usage: " << argv[0] << " <ima.dcm> <closure_lambda> <box_size> <dist_max>"
+ << std::endl;
+ return 1;
+ }
+
+ unsigned closure_lambda = atoi(argv[2]);
+ unsigned box_size = atoi(argv[3]);
+ unsigned dist_max = atoi(argv[4]);
+
+ image3d<int_u12> dcm;
+ io::dicom::load(dcm, argv[1]);
+
+ io::dump::save(level::stretch(int_u8(), dcm), "wsd_01_src.dump");
+
+ image3d<int_u12> grad = morpho::gradient(dcm, win_c4p_3d());
+ image3d<int_u12> clo = morpho::closing::area(grad, c6(), closure_lambda);
+
+ label_16 nbasins;
+ image3d<label_16> wshed = morpho::meyer_wst(clo, c6(), nbasins);
+
+ io::dump::save(level::stretch(int_u8(), clo), "wsd_02.dump");
+ io::dump::save(level::transform(wshed, fun::l2l::wrap<int_u8>()), "wsd_03.dump");
+
+ mln_VAR(vol2_, morpho::elementary::dilation(extend(wshed | (pw::value(wshed) == 0u), wshed), c26()));
+
+ data::fill((wshed | (pw::value(wshed) == 0u)).rw(), vol2_);
+
+ io::dump::save(level::transform(wshed, fun::l2l::wrap<int_u8>()), "wsd_04.dump");
+
+ /// Build graph
+ util::graph g = make::graph(wshed, c6(), nbasins);
+ // Build graph images and compute distance values with a RGB image.
+ mln_VAR(ima_v, make_vertex_graph_image(g, dcm, wshed, nbasins));
+ mln_VAR(ima_e, make_edge_graph_image(ima_v, g));
+
+ /// Try to merge vertices.
+ mln_piter_(ima_e_t) e(ima_e.domain());
+ util::array<label_16> parent(g.v_nmax());
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ parent[i] = i;
+
+ for_all(e)
+ {
+ unsigned v1 = e.element().v1();
+ unsigned v2 = e.element().v2();
+ if (ima_e(e) <= dist_max && find_root(parent, v1) != find_root(parent, v2))
+ parent[find_root(parent, v1)] = find_root(parent, v2);
+ }
+
+ fun::i2v::array<label_16> f(parent.nelements());
+ std::vector<unsigned> new_label(parent.nelements(), 0);
+ unsigned nbasins2 = 0;
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ {
+ unsigned p = find_root(parent, i);
+ mln_assertion(parent[p] == find_root(parent, i));
+ if (new_label[p] == 0)
+ new_label[p] = nbasins2++;
+ f(i) = new_label[p];
+ }
+ mln_invariant(f(0) == 0u);
+ --nbasins2; // nbasins2 does not count the basin with label 0.
+ image3d<label_16> wsd2 = level::transform(wshed, f);
+
+ io::dump::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()), "wsd_05.dump");
+
+ /// Reconstruct a graph from the simplified image.
+ util::graph g2 = make::graph(wsd2, c6(), nbasins2);
+
+ // Compute distance values with a RGB image.
+ mln_VAR(ima_v2, make_vertex_graph_image(g2, dcm, wsd2, nbasins2));
+ mln_VAR(ima_e2, make_edge_graph_image(ima_v2, g2));
+
+ mln_VAR(wsd2_, morpho::elementary::dilation(extend(wsd2 | (pw::value(wsd2) == 0u), wsd2), c26()));
+
+ data::fill((wsd2 | (pw::value(wsd2) == 0u)).rw(), wsd2_);
+
+ io::dump::save(level::transform(labeling::mean_values(dcm, wsd2, nbasins2), fun::l2l::wrap<int_u8>()), "wsd_06_mean_colors.dump");
+ //io::dump::save(level::stretch(int_u8(), make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, 4095)), "wsd_07_graph_image2_white.dump");
+ //io::dump::save(level::stretch(int_u8(), make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, 0)), "wsd_08_graph_image2_black.dump");
+ io::dump::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()), "wsd_99_result.dump");
+}
Index: trunk/milena/sandbox/fabien/igr/watershed.hh
===================================================================
--- trunk/milena/sandbox/fabien/igr/watershed.hh (revision 0)
+++ trunk/milena/sandbox/fabien/igr/watershed.hh (revision 3503)
@@ -0,0 +1,331 @@
+#include <iostream>
+#include <mln/core/image/image2d.hh>
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/core/image/image_if.hh>
+
+#include <mln/io/ppm/save.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/dicom/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/dump/save.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/label_16.hh>
+
+#include <mln/level/transform.hh>
+#include <mln/level/stretch.hh>
+
+#include <mln/labeling/mean_values.hh>
+
+#include <mln/convert/to_fun.hh>
+
+#include <mln/make/graph.hh>
+
+#include <mln/morpho/gradient.hh>
+#include <mln/morpho/closing/area.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/fun/l2l/wrap.hh>
+
+#include <mln/core/var.hh>
+#include <mln/morpho/elementary/dilation.hh>
+
+#include <mln/core/routine/extend.hh>
+
+#include <mln/util/graph.hh>
+
+#include <mln/essential/2d.hh>
+#include <mln/core/alias/vec3d.hh>
+#include <mln/debug/draw_graph.hh>
+#include <mln/util/graph.hh>
+#include <mln/accu/center.hh>
+#include <mln/io/dump/all.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb16.hh>
+#include <mln/accu/compute.hh>
+#include <mln/core/alias/dpoint2d.hh>
+#include <mln/draw/box.hh>
+#include <mln/level/stretch.hh>
+#include <mln/fun/v2v/id.hh>
+#include <mln/fun/l2l/wrap.hh>
+#include <mln/core/image/line_graph_elt_neighborhood.hh>
+#include <mln/morpho/elementary/dilation.hh>
+#include <mln/labeling/mean_values.hh>
+#include <mln/extension/adjust_fill.hh>
+#include <mln/extract/all.hh>
+#include <mln/make/region_adjacency_graph.hh>
+
+
+
+// Given a color image and a wshed image, computes the component graph.
+// Vertex values are computed thanks to a RGB image.
+
+namespace mln
+{
+
+ template <typename V>
+ value::int_u8 dist(const V& c1, const V& c2)
+ {
+ unsigned d = math::diff_abs(c1.red(), c2.red());
+ unsigned d_;
+ d_ = math::diff_abs(c1.green(), c2.green());
+
+ if (d_ > d)
+ d = d_;
+
+ d_ = math::diff_abs(c1.blue(), c2.blue());
+
+ if (d_ > d)
+ d = d_;
+ return d;
+ }
+
+
+ // ima_v, image on graph vertices; value = mean color per vertex (watershed basin)
+ template <typename I>
+ inline
+ pw::image<fun::i2v::array<value::int_u8>,
+ p_edges<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_edge_graph_image(const I& ima_v, const util::graph& g)
+ {
+ // edge sites.
+ typedef fun::i2v::array<mln_site(I)> edge_site_t;
+ edge_site_t edge_site(g.e_nmax(), literal::origin);
+ typedef p_edges<util::graph, edge_site_t > pe_t;
+ pe_t pe(g, edge_site);
+
+ // edge values
+ typedef fun::i2v::array<value::int_u8> edge_values_t;
+ edge_values_t edge_values(g.e_nmax());
+
+ // image on graph edges
+ typedef pw::image<edge_values_t, pe_t> ima_e_t;
+ ima_e_t ima_e = (edge_values | pe);
+
+ mln_piter(ima_e_t) e(ima_e.domain());
+ for_all(e) // in ima_e
+ ima_e(e) = math::diff_abs(ima_v.function()(e.element().v1()), ima_v.function()(e.element().v2()));
+
+ return ima_e;
+ }
+
+
+ template <typename I, typename J>
+ inline
+ util::array<mln_value(I)>
+ mean_color_values(const I& input, const J& w, mln_value(J) nbasins)
+ {
+ // Cf. sandbox/theo/color/segment_rgb_pixels.cc
+
+ util::array<float> m_3f = labeling::compute(accu::mean<mln_value(I)>(),
+ input, // input color image
+ w, // watershed labeling
+ nbasins);
+ m_3f[0] = literal::zero;
+
+ util::array<mln_value(I)> m;
+ convert::from_to(m_3f, m);
+ m[0] = 150u;
+
+ /*io::ppm::save(level::transform(w,
+ convert::to< fun::i2v::array<mln_value(I)> >(m)),
+ "wst_rag_wshd_color.ppm");*/
+
+ return m;
+ }
+
+
+ template <typename I, typename J>
+ pw::image<fun::i2v::array<mln_value(I)>, p_vertices<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_vertex_graph_image(const util::graph& g, const I&input, const J& w, const mln_value(J)& nbasins)
+ {
+ typedef util::array<mln_site(I)> vertex_sites_t;
+ vertex_sites_t site_values;
+ convert::from_to(labeling::compute(accu::center<mln_site(I)>(), w, nbasins),
+ site_values);
+
+ typedef fun::i2v::array<mln_site(J)> f_sites_t;
+ f_sites_t sites;
+ convert::from_to(site_values, sites);
+
+ // p_vertices
+ typedef p_vertices<util::graph, f_sites_t> S;
+ S pv(g, sites);
+
+
+ typedef fun::i2v::array<mln_value(I)> vertex_values_t;
+ vertex_values_t vertex_values;
+ convert::from_to(mean_color_values(input, w, nbasins), vertex_values);
+
+ mln_VAR(ima_v, (vertex_values | pv));
+
+ return ima_v;
+ }
+
+
+ template <typename I, typename V>
+ struct edge_to_color : Function_p2v< edge_to_color<I,V> >
+ {
+ typedef V result;
+
+ edge_to_color(const I& ima)
+ : ima_(ima)
+ {
+ }
+
+ V
+ operator()(const unsigned& e) const
+ {
+ return convert::to<V>(ima_.function()(e));
+ }
+
+ const I& ima_;
+ };
+
+ template <typename V>
+ inline
+ unsigned
+ find_root(util::array<V>& parent, const unsigned& x)
+ {
+ if (parent[x] == x)
+ return x;
+ else
+ return parent[x] = find_root(parent, parent[x]);
+ }
+
+
+ template <typename I, typename V, typename E>
+ inline
+ image2d<mln_value(I)>
+ make_debug_graph_image(const I& input,
+ const V& ima_v, const E& ima_e,
+ unsigned box_size, const value::int_u12& bg)
+ {
+ image2d<mln_value(I)> ima;
+ initialize(ima, input);
+
+ data::fill(ima, bg);
+ debug::draw_graph(ima, ima_v.domain(),
+ pw::cst(150u),
+ edge_to_color<E, mln_value(I)>(ima_e));
+
+ dpoint2d tl(-box_size,-box_size);
+ dpoint2d br(box_size,box_size);
+ mln_piter(V) p(ima_v.domain());
+ for_all(p)
+ {
+ box2d b(p + tl, p + br);
+ b.crop_wrt(ima.domain());
+ data::fill((ima | b).rw(), convert::to<mln_value(I)>(ima_v(p)));
+ }
+
+ return ima;
+ }
+
+}
+
+
+///////////////////
+// //
+// Main Function //
+// //
+///////////////////
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::int_u12;
+ using value::rgb8;
+ using value::label_16;
+
+ if (argc < 4)
+ {
+ std::cout << "Usage: " << argv[0] << " <ima.dcm> <closure_lambda> <box_size> <dist_max>"
+ << std::endl;
+ return 1;
+ }
+
+ unsigned closure_lambda = atoi(argv[2]);
+ unsigned box_size = atoi(argv[3]);
+ unsigned dist_max = atoi(argv[4]);
+
+ image2d<int_u12> dcm;
+ io::dicom::load(dcm, argv[1]);
+
+ io::pgm::save(level::stretch(int_u8(), dcm), "wsd_01_src.pgm");
+
+ image2d<int_u12> grad = morpho::gradient(dcm, win_c4p());
+ image2d<int_u12> clo = morpho::closing::area(grad, c4(), closure_lambda);
+
+ label_16 nbasins;
+ image2d<label_16> wshed = morpho::meyer_wst(clo, c4(), nbasins);
+
+ io::pgm::save(level::stretch(int_u8(), clo), "wsd_02.pgm");
+ io::pgm::save(level::transform(wshed, fun::l2l::wrap<int_u8>()), "wsd_03.pgm");
+
+ mln_VAR(vol2_, morpho::elementary::dilation(extend(wshed | (pw::value(wshed) == 0u), wshed), c8()));
+
+ data::fill((wshed | (pw::value(wshed) == 0u)).rw(), vol2_);
+
+ io::pgm::save(level::transform(wshed, fun::l2l::wrap<int_u8>()), "wsd_04.pgm");
+
+ /// Build graph
+ util::graph g = make::graph(wshed, c4(), nbasins);
+ // Build graph images and compute distance values with a RGB image.
+ mln_VAR(ima_v, make_vertex_graph_image(g, dcm, wshed, nbasins));
+ mln_VAR(ima_e, make_edge_graph_image(ima_v, g));
+
+ /// Try to merge vertices.
+ mln_piter_(ima_e_t) e(ima_e.domain());
+ util::array<label_16> parent(g.v_nmax());
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ parent[i] = i;
+
+ for_all(e)
+ {
+ unsigned v1 = e.element().v1();
+ unsigned v2 = e.element().v2();
+ if (ima_e(e) <= dist_max && find_root(parent, v1) != find_root(parent, v2))
+ parent[find_root(parent, v1)] = find_root(parent, v2);
+ }
+
+ fun::i2v::array<label_16> f(parent.nelements());
+ std::vector<unsigned> new_label(parent.nelements(), 0);
+ unsigned nbasins2 = 0;
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ {
+ unsigned p = find_root(parent, i);
+ mln_assertion(parent[p] == find_root(parent, i));
+ if (new_label[p] == 0)
+ new_label[p] = nbasins2++;
+ f(i) = new_label[p];
+ }
+ mln_invariant(f(0) == 0u);
+ --nbasins2; // nbasins2 does not count the basin with label 0.
+ image2d<label_16> wsd2 = level::transform(wshed, f);
+
+ io::pgm::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()), "wsd_05.pgm");
+
+ /// Reconstruct a graph from the simplified image.
+ util::graph g2 = make::graph(wsd2, c4(), nbasins2);
+
+ // Compute distance values with a RGB image.
+ mln_VAR(ima_v2, make_vertex_graph_image(g2, dcm, wsd2, nbasins2));
+ mln_VAR(ima_e2, make_edge_graph_image(ima_v2, g2));
+
+ mln_VAR(wsd2_, morpho::elementary::dilation(extend(wsd2 | (pw::value(wsd2) == 0u), wsd2), c8()));
+
+ data::fill((wsd2 | (pw::value(wsd2) == 0u)).rw(), wsd2_);
+
+ io::pgm::save(level::transform(labeling::mean_values(dcm, wsd2, nbasins2), fun::l2l::wrap<int_u8>()), "wsd_06_mean_colors.pgm");
+ io::pgm::save(level::stretch(int_u8(), make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, 4095)), "wsd_07_graph_image2_white.pgm");
+ io::pgm::save(level::stretch(int_u8(), make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, 0)), "wsd_08_graph_image2_black.pgm");
+ io::pgm::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()), "wsd_99_result.pgm");
+}
Index: trunk/milena/sandbox/fabien/igr/check2d_wsd.sh
===================================================================
--- trunk/milena/sandbox/fabien/igr/check2d_wsd.sh (revision 0)
+++ trunk/milena/sandbox/fabien/igr/check2d_wsd.sh (revision 3503)
@@ -0,0 +1,32 @@
+#!/bin/zsh
+
+process_file ()
+{
+ echo "Processing $2..."
+ box_size=2
+
+ for lambda_closure in 10 50 100 500 1000; do
+ echo " for lambda_closure = ${lambda_closure}";
+
+ for dist_max in 5 10 50 100 500; do
+ echo " for lambda_dist = ${dist_max}";
+
+ ./wsd2d $1 $lambda_closure $box_size $dist_max
+
+ mv wsd_01_src.pgm results/${2}_${lambda_closure}_${dist_max}_01.pgm
+ mv wsd_02.pgm results/${2}_${lambda_closure}_${dist_max}_02.pgm
+ mv wsd_03.pgm results/${2}_${lambda_closure}_${dist_max}_03.pgm
+ mv wsd_04.pgm results/${2}_${lambda_closure}_${dist_max}_04.pgm
+ mv wsd_05.pgm results/${2}_${lambda_closure}_${dist_max}_05.pgm
+ mv wsd_06_mean_colors.pgm results/${2}_${lambda_closure}_${dist_max}_06.pgm
+ mv wsd_07_graph_image2_white.pgm results/${2}_${lambda_closure}_${dist_max}_07.pgm
+ mv wsd_08_graph_image2_black.pgm results/${2}_${lambda_closure}_${dist_max}_08.pgm
+ mv wsd_99_result.pgm results/${2}_${lambda_closure}_${dist_max}_99.pgm
+
+ done;
+ done
+}
+
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0049.dcm" "49"
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0055.dcm" "55"
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0058.dcm" "58"
Property changes on: trunk/milena/sandbox/fabien/igr/check2d_wsd.sh
___________________________________________________________________
Name: svn:executable
+ *
Index: trunk/milena/sandbox/fabien/igr/check3d_wsd.sh
===================================================================
--- trunk/milena/sandbox/fabien/igr/check3d_wsd.sh (revision 0)
+++ trunk/milena/sandbox/fabien/igr/check3d_wsd.sh (revision 3503)
@@ -0,0 +1,34 @@
+#!/bin/zsh
+
+process_file ()
+{
+ echo "Processing $2..."
+ box_size=2
+
+ for lambda_closure in 10 50 100 500 1000; do
+ echo " for lambda_closure = ${lambda_closure}";
+
+ for dist_max in 5 10 50 100 500; do
+ echo " for lambda_dist = ${dist_max}";
+
+ ./wsd3d $1 $lambda_closure $box_size $dist_max
+
+ ../bin/dump2pgm8b wsd_01_src.dump results/${2}_${lambda_closure}_${dist_max}_01.pgm
+ ../bin/dump2pgm8b wsd_02.dump results/${2}_${lambda_closure}_${dist_max}_02.pgm
+ ../bin/dump2pgm8b wsd_03.dump results/${2}_${lambda_closure}_${dist_max}_03.pgm
+ ../bin/dump2pgm8b wsd_04.dump results/${2}_${lambda_closure}_${dist_max}_04.pgm
+ ../bin/dump2pgm8b wsd_05.dump results/${2}_${lambda_closure}_${dist_max}_05.pgm
+ ../bin/dump2pgm8b wsd_06_mean_colors.dump results/${2}_${lambda_closure}_${dist_max}_06.pgm
+#../bin/dump2pgm8b wsd_07_graph_image2_white.dump results/${2}_${lambda_closure}_${dist_max}_07.pgm
+#../bin/dump2pgm8b wsd_08_graph_image2_black.dump results/${2}_${lambda_closure}_${dist_max}_08.pgm
+ ../bin/dump2pgm8b wsd_99_result.dump results/${2}_${lambda_closure}_${dist_max}_99.pgm
+
+ rm *.dump
+
+ done;
+ done
+}
+
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0052.dcm" "52"
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0061.dcm" "61"
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0064.dcm" "64"
Property changes on: trunk/milena/sandbox/fabien/igr/check3d_wsd.sh
___________________________________________________________________
Name: svn:executable
+ *
Index: trunk/milena/sandbox/fabien/igr/Makefile
===================================================================
--- trunk/milena/sandbox/fabien/igr/Makefile (revision 3502)
+++ trunk/milena/sandbox/fabien/igr/Makefile (revision 3503)
@@ -8,7 +8,7 @@
-framework CoreFoundation
CXXFLAGS = -DNDEBUG -O1
-all: 2d 3d wsd
+all: 2d 3d wsd2d wsd3d
2d: seg_vol_irm.hh seg2d.cc
g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} seg2d.cc -o seg2d
@@ -16,8 +16,11 @@
3d: seg_vol_irm.hh seg3d.cc
g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} seg3d.cc -o seg3d
-wsd: watershed.cc
- g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o wsd
+wsd2d: watershed.hh watershed2d.cc
+ g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o wsd2d
+
+wsd3d: watershed.hh watershed3d.cc
+ g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o wsd3d
clean:
rm -rf *.dump *.p?m *.plot *.log *.csv
Index: trunk/milena/sandbox/fabien/TODO
===================================================================
--- trunk/milena/sandbox/fabien/TODO (revision 3502)
+++ trunk/milena/sandbox/fabien/TODO (revision 3503)
@@ -13,7 +13,7 @@
[X] Generate histograms (normal, bg, obj, p_bg, p_obj)
[ ] Test processing chain on US
[X] Create README file for special images
-[ ] Implement watershed
+[X] Implement watershed
[X] Create tool for dicom mask
[X] Check conversion for mask (everything except int_u12(0))
[ ] Extract ROI (projection or fill holes)
@@ -22,4 +22,7 @@
[ ] After threshold, take biggest object and then erode, dilate
[ ] Fix n_max
[ ] Create routine for binary images (keep n big bg & m big objects)
-[ ] US: projection of internal gradient
+[X] US: projection of internal gradient
+[X] Create 3D US morpho with 2D stack
+[ ] Create macro for_all_slice
+[ ] Batch process watershed with 2D, 3D and any combination of parameters
Index: trunk/milena/sandbox/fabien/bin/dump2pgm.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dump2pgm.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/dump2pgm.cc (revision 3503)
@@ -0,0 +1,37 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/make/image3d.hh>
+#include <mln/debug/slices_2d.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/io/dump/load.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <mln/literal/colors.hh>
+
+
+int usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.dump output.pgm" << std::endl;
+ return 1;
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::rgb8;
+
+ if (argc != 3)
+ return usage(argv);
+
+ image3d<int_u12> vol;
+ io::dump::load(vol, argv[1]);
+
+ rgb8 bg = literal::black;
+ image2d<int_u8> ima = debug::slices_2d(vol, 1.f, bg);
+ io::pgm::save(ima, argv[2]);
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/bin/filetype.hh
===================================================================
--- trunk/milena/sandbox/fabien/bin/filetype.hh (revision 0)
+++ trunk/milena/sandbox/fabien/bin/filetype.hh (revision 3503)
@@ -0,0 +1,54 @@
+#include <string>
+
+// 2d
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+
+// 3d
+#include <mln/core/image/image3d.hh>
+#include <mln/core/alias/neighb3d.hh>
+
+
+// pbm
+#include <mln/io/pbm/load.hh>
+#include <mln/io/pbm/save.hh>
+
+// pgm
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+
+// ppm
+#include <mln/io/ppm/load.hh>
+#include <mln/io/ppm/save.hh>
+
+
+//dump
+#include <mln/io/dump/load.hh>
+#include <mln/io/dump/save.hh>
+
+
+namespace mln
+{
+
+ namespace filetype
+ {
+ enum id { pbm, pgm, ppm, dump, unknown };
+ }
+
+ filetype::id
+ get_filetype(const std::string& filename)
+ {
+ if (filename.find(".pbm") == filename.length() - 4)
+ return filetype::pbm;
+ if (filename.find(".pgm") == filename.length() - 4)
+ return filetype::pgm;
+ if (filename.find(".ppm") == filename.length() - 4)
+ return filetype::ppm;
+ if (filename.find(".dump") == filename.length() - 5)
+ return filetype::dump;
+ return filetype::unknown;
+ }
+
+} // mln
+
+
Index: trunk/milena/sandbox/fabien/bin/dump_mask.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dump_mask.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/dump_mask.cc (revision 3503)
@@ -0,0 +1,86 @@
+#include <mln/core/concept/image.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/core/image/slice_image.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/neighb3d.hh>
+#include <mln/core/var.hh>
+
+#include <mln/geom/ncols.hh>
+#include <mln/geom/nrows.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/io/dump/load.hh>
+#include <mln/io/pbm/save.hh>
+
+#include <mln/literal/colors.hh>
+#include <mln/morpho/elementary/gradient_internal.hh>
+
+#include <mln/level/transform.hh>
+#include <mln/fun/v2b/threshold.hh>
+
+#include <mln/data/fill.hh>
+#include <mln/pw/all.hh>
+
+
+int usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.dump" << std::endl;
+ return 1;
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc != 2)
+ return usage(argv);
+
+ image3d<int_u8> input;
+ io::dump::load(input, argv[1]);
+
+ image3d<bool> ima = level::transform(input, fun::v2b::threshold<int_u8>(1));
+ mln_VAR(grad_int, morpho::elementary::gradient_internal(ima, c6()));
+
+ util::array<unsigned> xproj(ima.nrows(), 0);
+ util::array<unsigned> yproj(ima.ncols(), 0);
+ util::array<unsigned> xgradproj(grad_int.nrows(), 0);
+ util::array<unsigned> ygradproj(grad_int.ncols(), 0);
+
+ mln_piter_(image3d<bool>) p(ima.domain());
+ for_all(p)
+ {
+ if (ima(p))
+ {
+ ++xproj[p.row()];
+ ++yproj[p.col()];
+ }
+ if (grad_int(p))
+ {
+ ++xgradproj[p.row()];
+ ++ygradproj[p.col()];
+ }
+ }
+
+ // Plot files
+ std::ofstream fout_x("x.plot");
+ std::ofstream fout_xgrad("xgrad.plot");
+ for (unsigned int i = 0; i < xproj.nelements(); ++i)
+ {
+ fout_x << i << " " << xproj[i] << std::endl;
+ fout_xgrad << i << " " << xgradproj[i] << std::endl;
+ }
+
+ std::ofstream fout_y("y.plot");
+ std::ofstream fout_ygrad("ygrad.plot");
+ for (unsigned int i = 0; i < yproj.nelements(); ++i)
+ {
+ fout_y << i << " " << yproj[i] << std::endl;
+ fout_ygrad << i << " " << ygradproj[i] << std::endl;
+ }
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/bin/dicom2pgm.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dicom2pgm.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/dicom2pgm.cc (revision 3503)
@@ -0,0 +1,34 @@
+#include <mln/core/concept/image.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/io/dicom/load.hh>
+#include <mln/io/pgm/save.hh>
+
+
+
+int usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.dcm output.dump" << std::endl;
+ std::cerr << "\t work for 2D images encoded in int_u8" << std::endl;
+ return 1;
+}
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::int_u12;
+
+ if (argc != 3)
+ return usage(argv);
+
+ image2d<int_u8> ima;
+ io::dicom::load(ima, argv[1]);
+ io::pgm::save(ima, argv[2]);
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/bin/dump2pgm8b.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dump2pgm8b.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/dump2pgm8b.cc (revision 3503)
@@ -0,0 +1,38 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/make/image3d.hh>
+#include <mln/debug/slices_2d.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/io/dump/load.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <mln/literal/colors.hh>
+
+
+int usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.dump output.pgm" << std::endl;
+ return 1;
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::rgb8;
+ using value::int_u8;
+
+ if (argc != 3)
+ return usage(argv);
+
+ image3d<int_u8> vol;
+ io::dump::load(vol, argv[1]);
+
+ rgb8 bg = literal::black;
+ image2d<int_u8> ima = debug::slices_2d(vol, 1.f, 0);
+ io::pgm::save(ima, argv[2]);
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/bin/pnms2dump.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/pnms2dump.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/pnms2dump.cc (revision 3503)
@@ -0,0 +1,97 @@
+#include "filetype.hh"
+
+#include <mln/make/image3d.hh>
+
+
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " output.dump input1.xxx .. inputn.xxx" << std::endl;
+ std::cerr << " It works with binary (pbm), gray-level (int_u8), and color (rgb8) images." << std::endl;
+ abort();
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc < 3)
+ usage(argv);
+
+ trace::entering("main");
+
+ std::string filename = argv[2];
+
+ switch (get_filetype(argv[2]))
+ {
+ case filetype::pbm:
+ {
+ typedef image2d<bool> I;
+ util::array<I> arr;
+ for (int i = 2; i < argc; ++i)
+ {
+ I ima;
+ io::pbm::load(ima, argv[i]);
+ arr.append(ima);
+ }
+ image3d<bool> vol = make::image3d(arr);
+ io::dump::save(vol, argv[1]);
+ }
+ break;
+
+ case filetype::pgm:
+ {
+ using value::int_u8;
+ typedef image2d<int_u8> I;
+ util::array<I> arr;
+ for (int i = 2; i < argc; ++i)
+ {
+ I ima;
+ io::pgm::load(ima, argv[i]);
+ arr.append(ima);
+ }
+ image3d<int_u8> vol = make::image3d(arr);
+ io::dump::save(vol, argv[1]);
+ }
+ break;
+
+ case filetype::ppm:
+ {
+ using value::rgb8;
+ typedef image2d<rgb8> I;
+ util::array<I> arr;
+ for (int i = 2; i < argc; ++i)
+ {
+ I ima;
+ io::ppm::load(ima, argv[i]);
+ arr.append(ima);
+ }
+ image3d<rgb8> vol = make::image3d(arr);
+ io::dump::save(vol, argv[1]);
+ }
+ break;
+
+ case filetype::dump:
+ {
+ std::cerr << "Output shall not be a dump file!" << std::endl;
+ usage(argv);
+ }
+ break;
+
+ case filetype::unknown:
+ std::cerr << "unknown filename extension!" << std::endl;
+ usage(argv);
+ break;
+
+ default:
+ std::cerr << "file type not handled!" << std::endl;
+ usage(argv);
+ }
+
+ trace::exiting("main");
+
+}
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk
ChangeLog:
2009-03-09 Frederic Bour <bour(a)lrde.epita.fr>
Add missing trait for thru_morpher.
* milena/sandbox/fred/fun/unary.hh: Add is_assignable trait, just
a workaround.
---
unary.hh | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
Index: trunk/milena/sandbox/fred/fun/unary.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/unary.hh (revision 3501)
+++ trunk/milena/sandbox/fred/fun/unary.hh (revision 3502)
@@ -77,6 +77,23 @@
};
}
+ namespace trait
+ {
+
+ namespace fun
+ {
+
+ /// Find correct implementation
+ template <typename F>
+ struct is_assignable
+ {
+ typedef metal::true_ ret;
+ };
+
+ }
+
+ }
+
namespace meta
{
template <template <class> class F>
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk
ChangeLog:
2009-03-09 Frederic Bour <bour(a)lrde.epita.fr>
Verify constness of "thru" image morpher.
* milena/mln/trait/image/props.hh: Correct small typos errors.
* milena/sandbox/fred/fun/abs.hh,
* milena/sandbox/fred/fun/cos.hh,
* milena/sandbox/fred/fun/inc.hh,
* milena/sandbox/fred/fun/norm.hh,
* milena/sandbox/fred/fun/red.hh:
Namespace name desambiguation.
* milena/sandbox/fred/fun/thru.cc,
* milena/sandbox/fred/fun/thru_morpher.hh:
Verify constness (WIP).
---
mln/trait/image/props.hh | 8 +--
sandbox/fred/fun/abs.hh | 4 -
sandbox/fred/fun/cos.hh | 4 -
sandbox/fred/fun/inc.hh | 4 -
sandbox/fred/fun/norm.hh | 12 ++--
sandbox/fred/fun/red.hh | 4 -
sandbox/fred/fun/thru.cc | 1
sandbox/fred/fun/thru_morpher.hh | 94 ++++++++++++++++++++++++++++++---------
8 files changed, 92 insertions(+), 39 deletions(-)
Index: trunk/milena/mln/trait/image/props.hh
===================================================================
--- trunk/milena/mln/trait/image/props.hh (revision 3500)
+++ trunk/milena/mln/trait/image/props.hh (revision 3501)
@@ -393,7 +393,7 @@
{
struct any { protected: any() {} };
struct slow : any { std::string name() const { return "speed::slow"; } };
- struct fast : any { std::string name() const { return "speedw::fast"; } };
+ struct fast : any { std::string name() const { return "speed::fast"; } };
struct fastest
: fast { std::string name() const { return "speed::fastest"; } };
};
@@ -502,11 +502,11 @@
struct any { protected: any() {} };
struct some : any { protected: some() {} };
struct read
- : some { std::string name() const { return "pw_io::read"; } };
+ : some { std::string name() const { return "vw_io::read"; } };
struct read_write
- : some { std::string name() const { return "pw_io::read_write"; } };
+ : some { std::string name() const { return "vw_io::read_write"; } };
struct none
- : any { std::string name() const { return "pw_io::none"; } };
+ : any { std::string name() const { return "vw_io::none"; } };
};
// vw_set: /any/
Index: trunk/milena/sandbox/fred/fun/cos.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/cos.hh (revision 3500)
+++ trunk/milena/sandbox/fred/fun/cos.hh (revision 3501)
@@ -18,7 +18,7 @@
namespace trait
{
template <typename T>
- struct set_unary_<fun::cos, mln::value::Floating, T>
+ struct set_unary_<mln::fun::cos, mln::value::Floating, T>
{
typedef set_unary_ ret;
typedef T result;
@@ -39,7 +39,7 @@
namespace meta
{
- typedef unary<fun::cos> cos;
+ typedef unary<mln::fun::cos> cos;
}
}
Index: trunk/milena/sandbox/fred/fun/abs.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/abs.hh (revision 3500)
+++ trunk/milena/sandbox/fred/fun/abs.hh (revision 3501)
@@ -17,7 +17,7 @@
namespace trait
{
template <typename T>
- struct set_unary_<fun::abs, mln::value::Scalar, T>
+ struct set_unary_<mln::fun::abs, mln::value::Scalar, T>
{
typedef set_unary_ ret;
typedef T result;
@@ -33,7 +33,7 @@
namespace meta
{
- typedef unary<fun::abs> abs;
+ typedef unary<mln::fun::abs> abs;
}
}
Index: trunk/milena/sandbox/fred/fun/thru.cc
===================================================================
--- trunk/milena/sandbox/fred/fun/thru.cc (revision 3500)
+++ trunk/milena/sandbox/fred/fun/thru.cc (revision 3501)
@@ -8,6 +8,7 @@
#include <iostream>
#define dbg_print(val) std::cout << #val << "\n\t -> \t" << (val) << std::endl
+
int main()
{
using namespace mln;
Index: trunk/milena/sandbox/fred/fun/inc.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/inc.hh (revision 3500)
+++ trunk/milena/sandbox/fred/fun/inc.hh (revision 3501)
@@ -15,7 +15,7 @@
namespace trait
{
template <typename T>
- struct set_unary_<fun::inc, mln::value::Scalar, T>
+ struct set_unary_<mln::fun::inc, mln::value::Scalar, T>
{
typedef set_unary_ ret;
typedef T result;
@@ -36,7 +36,7 @@
namespace meta
{
- typedef unary<fun::inc> inc;
+ typedef unary<mln::fun::inc> inc;
}
}
Index: trunk/milena/sandbox/fred/fun/red.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/red.hh (revision 3500)
+++ trunk/milena/sandbox/fred/fun/red.hh (revision 3501)
@@ -16,7 +16,7 @@
namespace trait
{
template <unsigned n>
- struct set_precise_unary_<fun::red, mln::value::rgb<n> >
+ struct set_precise_unary_<mln::fun::red, mln::value::rgb<n> >
{
typedef set_precise_unary_ ret;
typedef mln::value::rgb<n> argument;
@@ -37,7 +37,7 @@
namespace meta
{
- typedef unary<fun::red> red;
+ typedef unary<mln::fun::red> red;
}
}
Index: trunk/milena/sandbox/fred/fun/norm.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/norm.hh (revision 3500)
+++ trunk/milena/sandbox/fred/fun/norm.hh (revision 3501)
@@ -25,7 +25,7 @@
namespace trait
{
template <unsigned n, typename T>
- struct set_precise_unary_<fun::norm::l1, mln::algebra::vec<n, T> >
+ struct set_precise_unary_<mln::fun::norm::l1, mln::algebra::vec<n, T> >
{
typedef set_precise_unary_ ret;
typedef mln::algebra::vec<n, T> argument;
@@ -44,7 +44,7 @@
};
template <unsigned n, typename T>
- struct set_precise_unary_<fun::norm::l2, mln::algebra::vec<n, T> >
+ struct set_precise_unary_<mln::fun::norm::l2, mln::algebra::vec<n, T> >
{
typedef set_precise_unary_ ret;
typedef mln::algebra::vec<n, T> argument;
@@ -63,7 +63,7 @@
};
template <unsigned n, typename T>
- struct set_precise_unary_<fun::norm::linfty, mln::algebra::vec<n, T> >
+ struct set_precise_unary_<mln::fun::norm::linfty, mln::algebra::vec<n, T> >
{
typedef set_precise_unary_ ret;
typedef mln::algebra::vec<n, T> argument;
@@ -86,9 +86,9 @@
{
namespace norm
{
- typedef unary<fun::norm::l1> l1;
- typedef unary<fun::norm::l2> l2;
- typedef unary<fun::norm::linfty> linfty;
+ typedef unary<mln::fun::norm::l1> l1;
+ typedef unary<mln::fun::norm::l2> l2;
+ typedef unary<mln::fun::norm::linfty> linfty;
}
}
}
Index: trunk/milena/sandbox/fred/fun/thru_morpher.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/thru_morpher.hh (revision 3500)
+++ trunk/milena/sandbox/fred/fun/thru_morpher.hh (revision 3501)
@@ -30,7 +30,9 @@
# define THRU_HH
# include <mln/core/internal/image_value_morpher.hh>
+# include <mln/metal/bexpr.hh>
# include "meta_function.hh"
+# include "unary.hh" // For is_assignable trait
// FIXME: constness of thru_image
@@ -40,9 +42,23 @@
// Forward declaration.
template <typename I, typename F> struct thru_image;
-
namespace internal
{
+ template <typename I, typename F> struct thru_image_write;
+ template <typename I, typename F> struct thru_image_read;
+
+ /// Find correct implementation
+ template <typename I, typename F>
+ struct thru_find_impl
+ {
+ typedef thru_image_write<I, F> write;
+ typedef thru_image_read<I, F> read;
+ typedef mlc_if(mlc_and(typename trait::fun::is_assignable<F>::ret,
+ mlc_and(mlc_not(mlc_is_const(I)),
+ mlc_equal(mln_trait_image_pw_io(I),
+ trait::image::pw_io::read_write))),
+ write, read) ret;
+ };
/// Data structure for \c mln::thru_image<I>.
template <typename I, typename F>
@@ -62,7 +78,7 @@
{
template <typename I, typename F>
- struct image_< thru_image<I, F> > : image_< I > // Same as I except...
+ struct image_< thru_image<I, F> > : image_< typename mln::internal::thru_find_impl<I, F>::ret > // Same as I except...
{
// ...these changes.
typedef trait::image::category::value_morpher category;
@@ -70,14 +86,29 @@
typedef trait::image::value_access::computed value_access;
};
+ template <typename I, typename F>
+ struct image_< mln::internal::thru_image_write<I, F> > : image_< I > // Same as I except...
+ {
+ typedef trait::image::vw_io::read_write vw_io;
+ };
+
+ template <typename I, typename F>
+ struct image_< mln::internal::thru_image_read<I, F> > : image_< I > // Same as I except...
+ {
+ typedef trait::image::vw_io::read vw_io;
+ };
+
} // end of namespace mln::trait
// FIXME: Doc!
+ namespace internal
+ {
+
template <typename I, typename F>
- class thru_image : public internal::image_value_morpher< I, typename F::result, thru_image<I,F> >
+ class thru_image_read : public internal::image_value_morpher< I, typename F::result, thru_image<I,F> >
{
public:
@@ -90,23 +121,39 @@
/// Value associated type.
typedef typename F::result value;
+ /// Return type of read-only access.
+ typedef typename F::result rvalue;
+
+ rvalue operator()(const mln_psite(I)& p) const;
+
+ };
+
+ // Inheritance from read ?!
+ template <typename I, typename F>
+ class thru_image_write : public thru_image_read<I,F>
+ {
+ public:
+
/// Type returned by the read-write pixel value operator.
typedef typename F::lresult lvalue;
- /// Return type of read-only access.
- typedef typename F::result rvalue;
+ using thru_image_read<I,F>::operator();
+ lvalue operator()(const mln_psite(I)& p);
+
+ };
+ }
+
+ template <typename I, typename F>
+ class thru_image : public internal::thru_find_impl<I, F>::ret
+ {
+ public:
thru_image();
thru_image(I& ima);
thru_image(I& ima, const F& f);
- // Initialize an empty image.
void init_(I& ima, const F& f);
- rvalue operator()(const mln_psite(I)& p) const;
-
- lvalue operator()(const mln_psite(I)& p);
-
/// Const promotion via conversion.
operator thru_image<const I, F>() const;
};
@@ -116,7 +163,7 @@
Image<I>& ima);
template <typename I, typename F>
- thru_image<const I, F> thru(const mln::Function<F>& f,
+ const thru_image<const I, F> thru(const mln::Function<F>& f,
const Image<I>& ima);
template <typename I, typename M>
@@ -124,7 +171,7 @@
thru(const mln::Meta_Function<M>& f, Image<I>& ima);
template <typename I, typename M>
- thru_image<const I, mln_fun_with(M, mln_value(I))>
+ const thru_image<const I, mln_fun_with(M, mln_value(I))>
thru(const mln::Meta_Function<M>& f, const Image<I>& ima);
# ifndef MLN_INCLUDE_ONLY
@@ -180,17 +227,19 @@
template <typename I, typename F>
inline
- typename thru_image<I, F>::rvalue
- thru_image<I, F>::operator()(const mln_psite(I)& p) const
+ thru_image<I, F>::operator thru_image<const I, F>() const
{
- mln_precondition(this->is_valid());
- return this->data_->f_(this->data_->ima_(p));
+ thru_image<const I, F> tmp(this->data_->ima_, this->data_->f_);
+ return tmp;
}
+ namespace internal
+ {
+
template <typename I, typename F>
inline
- typename thru_image<I, F>::lvalue
- thru_image<I, F>::operator()(const mln_psite(I)& p)
+ typename thru_image_read<I, F>::rvalue
+ thru_image_read<I, F>::operator()(const mln_psite(I)& p) const
{
mln_precondition(this->is_valid());
return this->data_->f_(this->data_->ima_(p));
@@ -198,10 +247,13 @@
template <typename I, typename F>
inline
- thru_image<I, F>::operator thru_image<const I, F>() const
+ typename thru_image_write<I, F>::lvalue
+ thru_image_write<I, F>::operator()(const mln_psite(I)& p)
{
- thru_image<const I, F> tmp(this->data_->ima_, this->data_->default_value_);
- return tmp;
+ mln_precondition(this->is_valid());
+ return this->data_->f_(this->data_->ima_(p));
+ }
+
}
// thru
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-03-09 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Fix dicom_mask binary.
* fabien/bin/dicom_mask.cc: Fix bugs.
* fabien/igr/watershed.cc: Update with watershed implementation.
---
TODO | 2 ++
bin/dicom_mask.cc | 54 +++++++++++++++++++++++++++++++++++++++++++++++-------
igr/watershed.cc | 37 ++++++++++++++++++++++++-------------
3 files changed, 73 insertions(+), 20 deletions(-)
Index: trunk/milena/sandbox/fabien/igr/watershed.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/watershed.cc (revision 3499)
+++ trunk/milena/sandbox/fabien/igr/watershed.cc (revision 3500)
@@ -52,6 +52,7 @@
#include <mln/draw/box.hh>
#include <mln/level/stretch.hh>
#include <mln/fun/v2v/id.hh>
+#include <mln/fun/l2l/wrap.hh>
#include <mln/core/image/line_graph_elt_neighborhood.hh>
#include <mln/morpho/elementary/dilation.hh>
#include <mln/labeling/mean_values.hh>
@@ -121,7 +122,7 @@
{
// Cf. sandbox/theo/color/segment_rgb_pixels.cc
- util::array<vec3d_f> m_3f = labeling::compute(accu::mean<mln_value(I)>(),
+ util::array<float> m_3f = labeling::compute(accu::mean<mln_value(I)>(),
input, // input color image
w, // watershed labeling
nbasins);
@@ -129,11 +130,11 @@
util::array<mln_value(I)> m;
convert::from_to(m_3f, m);
- m[0] = literal::yellow;
+ m[0] = 150u;
- io::ppm::save(level::transform(w,
+ /*io::ppm::save(level::transform(w,
convert::to< fun::i2v::array<mln_value(I)> >(m)),
- "wst_rag_wshd_color.ppm");
+ "wst_rag_wshd_color.ppm");*/
return m;
}
@@ -159,7 +160,7 @@
typedef fun::i2v::array<mln_value(I)> vertex_values_t;
vertex_values_t vertex_values;
- // convert::from_to(mean_color_values(input, w, nbasins), vertex_values);
+ convert::from_to(mean_color_values(input, w, nbasins), vertex_values);
mln_VAR(ima_v, (vertex_values | pv));
@@ -203,14 +204,14 @@
image2d<mln_value(I)>
make_debug_graph_image(const I& input,
const V& ima_v, const E& ima_e,
- unsigned box_size, const value::rgb8& bg)
+ unsigned box_size, const value::int_u12& bg)
{
image2d<mln_value(I)> ima;
initialize(ima, input);
data::fill(ima, bg);
debug::draw_graph(ima, ima_v.domain(),
- pw::cst(mln_value(I)(literal::green)),
+ pw::cst(150u),
edge_to_color<E, mln_value(I)>(ima_e));
dpoint2d tl(-box_size,-box_size);
@@ -246,26 +247,35 @@
if (argc < 4)
{
- std::cout << "Usage: " << argv[0] << " <ima.dcm> <closure_lambda> <box_size>"
+ std::cout << "Usage: " << argv[0] << " <ima.dcm> <closure_lambda> <box_size> <dist_max>"
<< std::endl;
return 1;
}
+ unsigned closure_lambda = atoi(argv[2]);
unsigned box_size = atoi(argv[3]);
+ unsigned dist_max = atoi(argv[4]);
image2d<int_u12> dcm;
io::dicom::load(dcm, argv[1]);
+ io::pgm::save(level::stretch(int_u8(), dcm), "wsd_01_src.pgm");
+
image2d<int_u12> grad = morpho::gradient(dcm, win_c4p());
- image2d<int_u12> clo = morpho::closing::area(grad, c4(), atoi(argv[2]));
+ image2d<int_u12> clo = morpho::closing::area(grad, c4(), closure_lambda);
label_16 nbasins;
image2d<label_16> wshed = morpho::meyer_wst(clo, c4(), nbasins);
+ io::pgm::save(level::stretch(int_u8(), clo), "wsd_02.pgm");
+ io::pgm::save(level::transform(wshed, fun::l2l::wrap<int_u8>()), "wsd_03.pgm");
+
mln_VAR(vol2_, morpho::elementary::dilation(extend(wshed | (pw::value(wshed) == 0u), wshed), c8()));
data::fill((wshed | (pw::value(wshed) == 0u)).rw(), vol2_);
+ io::pgm::save(level::transform(wshed, fun::l2l::wrap<int_u8>()), "wsd_04.pgm");
+
/// Build graph
util::graph g = make::graph(wshed, c4(), nbasins);
// Build graph images and compute distance values with a RGB image.
@@ -282,8 +292,7 @@
{
unsigned v1 = e.element().v1();
unsigned v2 = e.element().v2();
- if (ima_e(e) <= (unsigned)(atoi(argv[5]))
- && find_root(parent, v1) != find_root(parent, v2))
+ if (ima_e(e) <= dist_max && find_root(parent, v1) != find_root(parent, v2))
parent[find_root(parent, v1)] = find_root(parent, v2);
}
@@ -302,6 +311,7 @@
--nbasins2; // nbasins2 does not count the basin with label 0.
image2d<label_16> wsd2 = level::transform(wshed, f);
+ io::pgm::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()), "wsd_05.pgm");
/// Reconstruct a graph from the simplified image.
util::graph g2 = make::graph(wsd2, c4(), nbasins2);
@@ -314,7 +324,8 @@
data::fill((wsd2 | (pw::value(wsd2) == 0u)).rw(), wsd2_);
+ io::pgm::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()), "wsd_99_result.pgm");
//io::ppm::save(labeling::mean_values(dcm, wsd2, nbasins2), "wst_rag_mean_colors.ppm");
- //io::ppm::save(make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, literal::white), "wst_rag_graph_image2_white.ppm");
- //io::ppm::save(make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, literal::black), "wst_rag_graph_image2_black.ppm");
+ io::pgm::save(make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, 4095), "wsd_graph_image2_white.pgm");
+ io::pgm::save(make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, 0), "wsd_graph_image2_black.pgm");
}
Index: trunk/milena/sandbox/fabien/TODO
===================================================================
--- trunk/milena/sandbox/fabien/TODO (revision 3499)
+++ trunk/milena/sandbox/fabien/TODO (revision 3500)
@@ -21,3 +21,5 @@
[X] Create dicom2dump (2d, 3d, int_u8, int_u12)
[ ] After threshold, take biggest object and then erode, dilate
[ ] Fix n_max
+[ ] Create routine for binary images (keep n big bg & m big objects)
+[ ] US: projection of internal gradient
Index: trunk/milena/sandbox/fabien/bin/dicom_mask.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dicom_mask.cc (revision 3499)
+++ trunk/milena/sandbox/fabien/bin/dicom_mask.cc (revision 3500)
@@ -1,5 +1,7 @@
#include <mln/core/concept/image.hh>
#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/var.hh>
#include <mln/geom/ncols.hh>
#include <mln/geom/nrows.hh>
@@ -9,6 +11,7 @@
#include <mln/io/pbm/save.hh>
#include <mln/literal/colors.hh>
+#include <mln/morpho/elementary/gradient_internal.hh>
#include <mln/level/transform.hh>
#include <mln/fun/v2b/threshold.hh>
@@ -36,29 +39,66 @@
image2d<int_u8> input;
io::dicom::load(input, argv[1]);
- util::array<unsigned> xproj(geom::nrows(input), 0);
- util::array<unsigned> yproj(geom::ncols(input), 0);
+ util::array<unsigned> xsrcproj(geom::nrows(input), 0);
+ util::array<unsigned> ysrcproj(geom::ncols(input), 0);
- mln_piter_(image2d<int_u8>) p(input.domain());
+ mln_piter_(image2d<int_u8>) psrc(input.domain());
+ for_all(psrc)
+ {
+ xsrcproj[psrc.row()] += input(psrc);
+ ysrcproj[psrc.col()] += input(psrc);
+ }
+ std::ofstream fout_xsrc("xsrc.plot");
+ for (unsigned int i = 0; i < xsrcproj.nelements(); ++i)
+ {
+ fout_xsrc << i << " " << xsrcproj[i] << std::endl;
+ }
+ std::ofstream fout_ysrc("ysrc.plot");
+ for (unsigned int i = 0; i < ysrcproj.nelements(); ++i)
+ {
+ fout_ysrc << i << " " << ysrcproj[i] << std::endl;
+ }
+
+ image2d<bool> ima = level::transform(input, fun::v2b::threshold<int_u8>(1));
+ io::pbm::save(ima, argv[2]);
+ mln_VAR(grad_int, morpho::elementary::gradient_internal(ima, c4()));
+
+ util::array<unsigned> xproj(geom::nrows(ima), 0);
+ util::array<unsigned> yproj(geom::ncols(ima), 0);
+ util::array<unsigned> xgradproj(geom::nrows(grad_int), 0);
+ util::array<unsigned> ygradproj(geom::ncols(grad_int), 0);
+
+ mln_piter_(image2d<bool>) p(ima.domain());
for_all(p)
{
- xproj[p.row()] += input(p);
- yproj[p.col()] += input(p);
+ if (ima(p))
+ {
+ ++xproj[p.row()];
+ ++yproj[p.col()];
+ }
+ }
+ mln_piter_(image2d<int_u8>) pgrad(grad_int.domain());
+ for_all(pgrad)
+ {
+ xgradproj[pgrad.row()] += grad_int(pgrad);
+ ygradproj[pgrad.col()] += grad_int(pgrad);
}
// Plot files
std::ofstream fout_x("x.plot");
+ std::ofstream fout_xgrad("xgrad.plot");
for (unsigned int i = 0; i < xproj.nelements(); ++i)
{
fout_x << i << " " << xproj[i] << std::endl;
+ fout_xgrad << i << " " << xgradproj[i] << std::endl;
}
std::ofstream fout_y("y.plot");
+ std::ofstream fout_ygrad("ygrad.plot");
for (unsigned int i = 0; i < yproj.nelements(); ++i)
{
fout_y << i << " " << yproj[i] << std::endl;
+ fout_ygrad << i << " " << ygradproj[i] << std::endl;
}
- image2d<bool> ima = level::transform(input, fun::v2b::threshold<int_u8>(1));
- io::pbm::save(ima, argv[2]);
}
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2009-03-08 Frederic Bour <bour(a)lrde.epita.fr>
Add work on meta functions and thru morpher.
* sandbox/fred/fun/abs.hh: New.
* sandbox/fred/fun/cos.hh: New.
* sandbox/fred/fun/fun.cc: New.
Some tests don't pass, see FIXMEs (operator==(rgb::red_t,int) ?)
* sandbox/fred/fun/inc.hh: New.
* sandbox/fred/fun/meta_function.hh: New.
* sandbox/fred/fun/norm.hh: New.
* sandbox/fred/fun/red.hh: New.
* sandbox/fred/fun/thru.cc: New.
* sandbox/fred/fun/thru_morpher.hh: New.
Constness of thru_image has to be corrected.
* sandbox/fred/fun/unary.hh: New.
* sandbox/fred/fun: New.
---
abs.hh | 40 ++++++++
cos.hh | 46 ++++++++++
fun.cc | 103 ++++++++++++++++++++++
inc.hh | 43 +++++++++
meta_function.hh | 132 +++++++++++++++++++++++++++++
norm.hh | 96 +++++++++++++++++++++
red.hh | 44 +++++++++
thru.cc | 30 ++++++
thru_morpher.hh | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
unary.hh | 115 +++++++++++++++++++++++++
10 files changed, 898 insertions(+)
Index: trunk/milena/sandbox/fred/fun/cos.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/cos.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/cos.hh (revision 3498)
@@ -0,0 +1,46 @@
+#ifndef COS_HH
+# define COS_HH
+
+# include "unary.hh"
+# include <mln/value/concept/floating.hh>
+# include <mln/math/acos.hh>
+# include <mln/math/cos.hh>
+
+namespace mln
+{
+ // COS, bijective
+ namespace fun
+ {
+ template <typename T>
+ struct cos : unary<cos, T> {};
+ }
+
+ namespace trait
+ {
+ template <typename T>
+ struct set_unary_<fun::cos, mln::value::Floating, T>
+ {
+ typedef set_unary_ ret;
+ typedef T result;
+ typedef T argument;
+ typedef T& lvalue;
+
+ static result read(const argument& x)
+ {
+ return math::cos(x);
+ }
+
+ static void write(lvalue l, const result& x)
+ {
+ l = math::acos(x);
+ }
+ };
+ }
+
+ namespace meta
+ {
+ typedef unary<fun::cos> cos;
+ }
+}
+
+#endif /* ! COS_HH */
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/abs.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/abs.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/abs.hh (revision 3498)
@@ -0,0 +1,40 @@
+#ifndef ABS_HH
+# define ABS_HH
+
+# include "unary.hh"
+# include <mln/value/concept/scalar.hh>
+# include <mln/math/abs.hh>
+
+namespace mln
+{
+ // ABS, pure
+ namespace fun
+ {
+ template <typename T>
+ struct abs : unary<abs, T> {};
+ }
+
+ namespace trait
+ {
+ template <typename T>
+ struct set_unary_<fun::abs, mln::value::Scalar, T>
+ {
+ typedef set_unary_ ret;
+ typedef T result;
+ typedef T argument;
+ typedef T& lvalue;
+
+ static result read(const argument& x)
+ {
+ return math::abs(x);
+ }
+ };
+ }
+
+ namespace meta
+ {
+ typedef unary<fun::abs> abs;
+ }
+}
+
+#endif /* ! ABS_HH */
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/thru.cc
===================================================================
--- trunk/milena/sandbox/fred/fun/thru.cc (revision 0)
+++ trunk/milena/sandbox/fred/fun/thru.cc (revision 3498)
@@ -0,0 +1,30 @@
+// Meta functions test
+#include "cos.hh"
+#include "thru_morpher.hh"
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/debug/all.hh>
+#include <iostream>
+
+#define dbg_print(val) std::cout << #val << "\n\t -> \t" << (val) << std::endl
+int main()
+{
+ using namespace mln;
+
+ meta::cos cos;
+ typedef image2d<float> I;
+ I ima(5, 5);
+
+ image2d<value::int_u8> tmp(5, 5);
+ debug::iota(tmp);
+ data::fill_with_image(ima, tmp);
+
+ debug::println(ima);
+ debug::println(thru(meta::cos(), ima));
+
+ thru_image<I, mln::fun::cos<float> > ima2 = thru(meta::cos(), ima);
+ data::fill_with_image(ima2, (pw::value(tmp) - pw::cst(13.0f)) / pw::cst(12.0f) | tmp.domain());
+
+ debug::println(ima);
+}
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/inc.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/inc.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/inc.hh (revision 3498)
@@ -0,0 +1,43 @@
+#ifndef INC_HH
+# define INC_HH
+
+# include "unary.hh"
+
+namespace mln
+{
+ // INC, bijective
+ namespace fun
+ {
+ template <typename T>
+ struct inc : unary<inc, T> {};
+ }
+
+ namespace trait
+ {
+ template <typename T>
+ struct set_unary_<fun::inc, mln::value::Scalar, T>
+ {
+ typedef set_unary_ ret;
+ typedef T result;
+ typedef T argument;
+ typedef T& lvalue;
+
+ static result read(const argument& x)
+ {
+ return x + 1;
+ }
+
+ static void write(lvalue l, const result& r)
+ {
+ l = r - 1;
+ }
+ };
+ }
+
+ namespace meta
+ {
+ typedef unary<fun::inc> inc;
+ }
+}
+
+#endif /* ! INC_HH */
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/red.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/red.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/red.hh (revision 3498)
@@ -0,0 +1,44 @@
+#ifndef RED_HH
+# define RED_HH
+
+# include "unary.hh"
+# include <mln/value/rgb.hh>
+
+namespace mln
+{
+ // RED, assignable
+ namespace fun
+ {
+ template <typename T>
+ struct red : unary<red, T> {};
+ }
+
+ namespace trait
+ {
+ template <unsigned n>
+ struct set_precise_unary_<fun::red, mln::value::rgb<n> >
+ {
+ typedef set_precise_unary_ ret;
+ typedef mln::value::rgb<n> argument;
+ typedef typename argument::red_t result;
+ typedef argument& lvalue;
+
+ static result read(const argument& x)
+ {
+ return x.red();
+ }
+
+ static void write(lvalue l, const result& r)
+ {
+ l.red() = r;
+ }
+ };
+ }
+
+ namespace meta
+ {
+ typedef unary<fun::red> red;
+ }
+}
+
+#endif /* ! RED_HH */
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/meta_function.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/meta_function.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/meta_function.hh (revision 3498)
@@ -0,0 +1,132 @@
+// Copyright (C) 2007, 2008 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 F 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 MLN_CORE_CONCEPT_META_FUNCTION_HH
+# define MLN_CORE_CONCEPT_META_FUNCTION_HH
+
+/// \file mln/core/concept/meta_function.hh
+///
+/// Definition of the concept of mln::Meta_Function.
+
+# include <mln/core/concept/object.hh>
+# include <mln/core/concept/function.hh>
+
+
+# define mln_fun_with(F, T) \
+typename F::template with< T >::ret
+
+# define mln_fun_with_(F, T) \
+F::with< T >::ret
+
+
+# define mln_fun_result(F, T) \
+typename F::template with< T >::ret::result
+
+
+# define mln_fun_result_(F, T) \
+F::with< T >::ret::result
+
+
+
+namespace mln
+{
+
+ // Fwd decl.
+ template <typename E> struct Meta_Function;
+
+ // Meta_Function category flag type.
+ template <>
+ struct Meta_Function<void>
+ {
+ typedef Object<void> super;
+ };
+
+
+ /*! \brief Base class for implementation of meta functions.
+ *
+ * The parameter \a E is the exact type.
+ *
+ * \see mln::doc::Meta_Function for a complete documentation of
+ * this class contents.
+ */
+ template <typename E>
+ struct Meta_Function : public Object<E>
+ {
+ typedef Meta_Function<void> category;
+ protected:
+ Meta_Function();
+ };
+
+
+ namespace fun
+ {
+
+ // To be specialized when some state (attributes) have to be transfered
+ // from the meta-function to the function.
+ // Warning: the first argument has to be an object with the exact type.
+ template <typename M, typename T>
+ mln_fun_with(M, T)
+ unmeta(const M&, T);
+
+ template <typename M, typename T>
+ void
+ unmeta(const Meta_Function<M>&, T); // Safety.
+
+ } // end of namespace mln::fun
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename E>
+ inline
+ Meta_Function<E>::Meta_Function()
+ {
+ // FIXME: Check "with" on E.
+ }
+
+ namespace fun
+ {
+
+ template <typename M, typename T>
+ inline
+ mln_fun_with(M, T)
+ unmeta(const M&, T)
+ {
+ mlc_is_a(M, Meta_Function)::check();
+ mln_fun_with(M, T) a;
+ return a;
+ }
+
+ } // end of namespace mln::fun
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_CONCEPT_META_FUNCTION_HH
Index: trunk/milena/sandbox/fred/fun/norm.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/norm.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/norm.hh (revision 3498)
@@ -0,0 +1,96 @@
+#ifndef NORM_HH
+# define NORM_HH
+
+# include "unary.hh"
+# include <mln/norm/all.hh>
+
+namespace mln
+{
+ // NORMS, reversible
+ namespace fun
+ {
+ namespace norm
+ {
+ template <typename T>
+ struct l1 : unary<l1, T> {};
+
+ template <typename T>
+ struct l2 : unary<l2, T> {};
+
+ template <typename T>
+ struct linfty : unary<linfty, T> {};
+ }
+ }
+
+ namespace trait
+ {
+ template <unsigned n, typename T>
+ struct set_precise_unary_<fun::norm::l1, mln::algebra::vec<n, T> >
+ {
+ typedef set_precise_unary_ ret;
+ typedef mln::algebra::vec<n, T> argument;
+ typedef argument& lvalue;
+ typedef mln_sum_product(argument,argument) result;
+
+ static result read(const argument& x)
+ {
+ return mln::norm::l1(x);
+ }
+
+ static void write(lvalue l, const result& x)
+ {
+ l = l / read(l) * x;
+ }
+ };
+
+ template <unsigned n, typename T>
+ struct set_precise_unary_<fun::norm::l2, mln::algebra::vec<n, T> >
+ {
+ typedef set_precise_unary_ ret;
+ typedef mln::algebra::vec<n, T> argument;
+ typedef argument& lvalue;
+ typedef mln_sum_product(argument,argument) result;
+
+ static result read(const argument& x)
+ {
+ return mln::norm::l2(x);
+ }
+
+ static void write(lvalue l, const result& x)
+ {
+ l = l / read(l) * x;
+ }
+ };
+
+ template <unsigned n, typename T>
+ struct set_precise_unary_<fun::norm::linfty, mln::algebra::vec<n, T> >
+ {
+ typedef set_precise_unary_ ret;
+ typedef mln::algebra::vec<n, T> argument;
+ typedef argument& lvalue;
+ typedef mln_sum_product(argument,argument) result;
+
+ static result read(const argument& x)
+ {
+ return mln::norm::linfty(x);
+ }
+
+ static void write(lvalue l, const result& x)
+ {
+ l = l / read(l) * x;
+ }
+ };
+ }
+
+ namespace meta
+ {
+ namespace norm
+ {
+ typedef unary<fun::norm::l1> l1;
+ typedef unary<fun::norm::l2> l2;
+ typedef unary<fun::norm::linfty> linfty;
+ }
+ }
+}
+
+#endif /* ! NORM_HH */
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/fun.cc
===================================================================
--- trunk/milena/sandbox/fred/fun/fun.cc (revision 0)
+++ trunk/milena/sandbox/fred/fun/fun.cc (revision 3498)
@@ -0,0 +1,103 @@
+// Meta functions test
+#include "abs.hh"
+#include "cos.hh"
+#include "inc.hh"
+#include "norm.hh"
+#include "red.hh"
+
+#include <iostream>
+
+#define dbg_print(val) std::cout << #val << "\n\t -> \t" << (val) << std::endl
+int main()
+{
+ mln::meta::abs abs;
+ mln::meta::cos cos;
+ mln::meta::inc inc;
+ mln::meta::red red;
+
+ mln::meta::norm::l1 l1;
+ mln::meta::norm::l2 l2;
+ mln::meta::norm::linfty linfty;
+
+ std::cout << "Read only tests." << std::endl;
+ std::cout << "----------------" << std::endl;
+
+ // ABS
+ mln_invariant(abs(-1) == 1);
+ dbg_print(abs(-1));
+ dbg_print(abs(-3.1415926535));
+
+ // INC
+ mln_invariant(inc(-1) == 0);
+ dbg_print(inc(-1));
+ dbg_print(inc(-3.1415926535));
+
+ // COS
+ mln_invariant(cos(0.) == 1.);
+ dbg_print(cos(0.));
+ dbg_print(cos(mln::math::acos(0.5)));
+
+ // RED
+ mln_invariant(red(mln::value::rgb8(8,13,21)) == 8);
+ dbg_print(red(mln::value::rgb8(8,13,21)));
+
+ // NORM
+ mln::algebra::vec<3, double> v;
+ v[0] = 1;
+ v[1] = -1;
+ v[2] = 0;
+ dbg_print(v);
+ dbg_print(l1(v));
+ dbg_print(l2(v));
+ dbg_print(linfty(v));
+
+ std::cout << "Read/Write tests." << std::endl;
+ std::cout << "-----------------" << std::endl;
+
+ // INC
+ {
+ int x;
+ dbg_print(inc(x) = 1);
+ mln_invariant(inc(x) == 1);
+ dbg_print(inc(x));
+ dbg_print(x);
+ }
+
+ // COS
+ {
+ double x;
+ dbg_print(cos(x) = 1.);
+ mln_invariant(cos(x) == 1.);
+ dbg_print(x);
+ }
+
+ // RED
+ {
+ mln::value::rgb8 rgb(8,13,21);
+ dbg_print(rgb);
+ dbg_print(red(rgb) = 0);
+// FIXME: Doesn't compile! mln_invariant(red(rgb) == 0);
+ dbg_print(rgb);
+ }
+
+ // NORM
+ {
+ dbg_print(v);
+ dbg_print(l1(v) = 1.0);
+ dbg_print(l1(v));
+ dbg_print(v);
+// mln_invariant(l1(v) == 1.0); FIXME: check with epsilon
+
+ dbg_print(l2(v) = 1.0);
+ dbg_print(l2(v));
+ dbg_print(v);
+// mln_invariant(l2(v) == 1.0);
+
+ dbg_print(linfty(v) = 1.0);
+ dbg_print(linfty(v));
+ dbg_print(v);
+// mln_invariant(linfty(v) == 1.0);
+ }
+
+ std::cout << "All invariants passed." << std::endl;
+}
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/thru_morpher.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/thru_morpher.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/thru_morpher.hh (revision 3498)
@@ -0,0 +1,249 @@
+// Copyright (C) 2007, 2008 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 THRU_HH
+# define THRU_HH
+
+# include <mln/core/internal/image_value_morpher.hh>
+# include "meta_function.hh"
+
+// FIXME: constness of thru_image
+
+namespace mln
+{
+
+ // Forward declaration.
+ template <typename I, typename F> struct thru_image;
+
+
+ namespace internal
+ {
+
+ /// Data structure for \c mln::thru_image<I>.
+ template <typename I, typename F>
+ struct data< thru_image<I, F> >
+ {
+ data(I& ima, const F& f);
+
+ I ima_;
+ // FIXME: value or pointer or whatever ?
+ F f_;
+ };
+
+ } // end of namespace mln::internal
+
+
+ namespace trait
+ {
+
+ template <typename I, typename F>
+ struct image_< thru_image<I, F> > : image_< I > // Same as I except...
+ {
+ // ...these changes.
+ typedef trait::image::category::value_morpher category;
+ typedef mln_internal_trait_image_speed_from(I) speed; // Un-fastest.
+ typedef trait::image::value_access::computed value_access;
+ };
+
+ } // end of namespace mln::trait
+
+
+
+ // FIXME: Doc!
+
+ template <typename I, typename F>
+ class thru_image : public internal::image_value_morpher< I, typename F::result, thru_image<I,F> >
+ {
+ public:
+
+ /// Skeleton.
+ typedef thru_image<tag::image_<I>, F> skeleton;
+
+ /// Point_Site associated type.
+ typedef mln_psite(I) psite;
+
+ /// Value associated type.
+ typedef typename F::result value;
+
+ /// Type returned by the read-write pixel value operator.
+ typedef typename F::lresult lvalue;
+
+ /// Return type of read-only access.
+ typedef typename F::result rvalue;
+
+ thru_image();
+ thru_image(I& ima);
+ thru_image(I& ima, const F& f);
+
+ // Initialize an empty image.
+ void init_(I& ima, const F& f);
+
+ rvalue operator()(const mln_psite(I)& p) const;
+
+ lvalue operator()(const mln_psite(I)& p);
+
+ /// Const promotion via conversion.
+ operator thru_image<const I, F>() const;
+ };
+
+ template <typename I, typename F>
+ thru_image<I, F> thru(const mln::Function<F>& f,
+ Image<I>& ima);
+
+ template <typename I, typename F>
+ thru_image<const I, F> thru(const mln::Function<F>& f,
+ const Image<I>& ima);
+
+ template <typename I, typename M>
+ thru_image<I, mln_fun_with(M, mln_value(I))>
+ thru(const mln::Meta_Function<M>& f, Image<I>& ima);
+
+ template <typename I, typename M>
+ thru_image<const I, mln_fun_with(M, mln_value(I))>
+ thru(const mln::Meta_Function<M>& f, const Image<I>& ima);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // internal::data< thru_image<I,S> >
+
+ namespace internal
+ {
+
+ template <typename I, typename F>
+ inline
+ data< thru_image<I, F> >::data(I& ima, const F& f)
+ : ima_(ima),
+ f_(f)
+ {
+ }
+
+ } // end of namespace mln::internal
+
+ // thru_image<I>
+
+ template <typename I, typename F>
+ inline
+ thru_image<I, F>::thru_image()
+ {
+ }
+
+ template <typename I, typename F>
+ inline
+ thru_image<I, F>::thru_image(I& ima, const F& f)
+ {
+ mln_precondition(ima.is_valid());
+ init_(ima, f);
+ }
+
+ template <typename I, typename F>
+ inline
+ thru_image<I, F>::thru_image(I& ima)
+ {
+ mln_precondition(ima.is_valid());
+ init_(ima, mln_value(I)());
+ }
+
+ template <typename I, typename F>
+ inline
+ void
+ thru_image<I, F>::init_(I& ima, const F& f)
+ {
+ mln_precondition(! this->is_valid());
+ mln_precondition(ima.is_valid());
+ this->data_ = new internal::data< thru_image<I, F> >(ima, f);
+ }
+
+ template <typename I, typename F>
+ inline
+ typename thru_image<I, F>::rvalue
+ thru_image<I, F>::operator()(const mln_psite(I)& p) const
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->f_(this->data_->ima_(p));
+ }
+
+ template <typename I, typename F>
+ inline
+ typename thru_image<I, F>::lvalue
+ thru_image<I, F>::operator()(const mln_psite(I)& p)
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->f_(this->data_->ima_(p));
+ }
+
+ template <typename I, typename F>
+ inline
+ thru_image<I, F>::operator thru_image<const I, F>() const
+ {
+ thru_image<const I, F> tmp(this->data_->ima_, this->data_->default_value_);
+ return tmp;
+ }
+
+ // thru
+ template <typename I, typename F>
+ thru_image<I, F> thru(const mln::Function<F>& f,
+ Image<I>& ima)
+ {
+ thru_image<I, F> tmp(exact(ima), exact(f));
+ return tmp;
+ }
+
+ template <typename I, typename F>
+ thru_image<const I, F> thru(const mln::Function<F>& f,
+ const Image<I>& ima)
+ {
+ thru_image<const I, F> tmp(exact(ima), exact(f));
+ return tmp;
+ }
+
+ template <typename I, typename M>
+ thru_image<I, mln_fun_with(M, mln_value(I))>
+ thru(const mln::Meta_Function<M>& f, Image<I>& ima)
+ {
+ typedef mln_fun_with(M, mln_value(I)) F;
+ thru_image<I, F> tmp(exact(ima), F());
+
+ return tmp;
+ }
+
+ template <typename I, typename M>
+ thru_image<const I, mln_fun_with(M, mln_value(I))>
+ thru(const mln::Meta_Function<M>& f, const Image<I>& ima)
+ {
+ typedef mln_fun_with(M, mln_value(I)) F;
+ thru_image<const I, F> tmp(exact(ima), F());
+
+ return tmp;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! THRU_HH
Index: trunk/milena/sandbox/fred/fun/unary.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/unary.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/unary.hh (revision 3498)
@@ -0,0 +1,115 @@
+#ifndef UNARY_HH
+# define UNARY_HH
+
+# include <mln/trait/solve.hh>
+# include <mln/fun/essential.hh>
+# include <mln/fun/internal/resolve.hh>
+# include "meta_function.hh"
+
+namespace mln
+{
+ // UNARY
+ namespace fun
+ {
+ namespace internal
+ {
+ template <typename Impl>
+ struct unary_modifier
+ {
+ typedef typename Impl::result result;
+ typedef typename Impl::argument argument;
+ typedef typename Impl::lvalue lvalue;
+ typedef unary_modifier lresult;
+
+ // FIXME: argument or lvalue? ~~~
+ unary_modifier(argument& x)
+ : x_(&x)
+ {
+ }
+
+ result to_result() const
+ {
+ return Impl::read(*x_);
+ };
+
+ operator result() const
+ {
+ return to_result();
+ };
+
+ const result& operator = (const result& r) const
+ {
+ Impl::write(*x_, r);
+ return r;
+ }
+
+ private:
+ argument *x_;
+ };
+ }
+
+ template <template <class> class Fun, typename T>
+ struct unary : mln::Function_v2v< Fun<T> >
+ {
+ // FIXME: mln_fun_internal_resolve? Fun<T> is not defined at this point...
+ // so mln_is_a(Fun<T>, Function) won't work.
+ typedef typename mln::trait::solve_unary< Fun, T >::ret impl;
+
+ typedef typename impl::result result;
+ typedef typename impl::argument argument;
+ typedef typename impl::lvalue lvalue;
+ typedef internal::unary_modifier<impl> lresult;
+
+ result operator () (const argument& value) const
+ {
+ return impl::read(value);
+ }
+
+ lresult operator () (argument& value) const
+ {
+ return lresult(value);
+ }
+
+ void set(lvalue l, const result& r) const
+ {
+ impl::write(l, r);
+ }
+ };
+ }
+
+ namespace meta
+ {
+ template <template <class> class F>
+ struct unary : mln::Meta_Function< unary<F> >
+ {
+ template <typename T>
+ typename F<T>::result operator()(const T& v) const
+ {
+ F<T> tmp;
+ return tmp(v);
+ }
+
+ template <typename T>
+ typename F<T>::lresult operator()(T& v) const
+ {
+ F<T> tmp;
+ return tmp(v);
+ }
+
+ template <typename T>
+ struct with
+ {
+ typedef F<T> ret;
+ };
+ };
+ }
+
+}
+
+template <typename Impl>
+std::ostream& operator << (std::ostream& o, const mln::fun::internal::unary_modifier<Impl>& m)
+{
+ return o << m.to_result();
+}
+
+#endif /* ! UNARY_HH */
\ No newline at end of file
1
0
r3497: Add routine to calculate the number of components retaled to a createria
by Edwin Carlinet 06 Mar '09
by Edwin Carlinet 06 Mar '09
06 Mar '09
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-03-06 Edwin Carlinet <carlinet(a)lrde.epita.fr>
Add routine to calculate the number of components retaled to a createria.
* edwin/tree/propagate.hh: Back propagation iterates on nodes now.
* edwin/tree/routines.hh: Add routine to get hightest nodes
satifying a criteria .
* edwin/tree/tree.cc: Add function to calcul number of
components retaled to a createria (in expectation of finding a
treshold).
---
propagate.hh | 13 +++--
routines.hh | 46 +------------------
tree.cc | 136 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
3 files changed, 122 insertions(+), 73 deletions(-)
Index: trunk/milena/sandbox/edwin/tree/propagate.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/propagate.hh (revision 3496)
+++ trunk/milena/sandbox/edwin/tree/propagate.hh (revision 3497)
@@ -60,12 +60,15 @@
void
back_propagate_subbranch(const T& t, A& a, mln_value(A) v)
{
- mln_bkd_piter(T) p(t.domain());
- for_all(p)
- if (t.is_a_node(p) && a(t.parent(p)) == v)
+ mln_fwd_piter(T::nodes_t) n(t.nodes());
+ for_all(n)
{
- mln_assertion(t.is_a_node(t.parent(p)));
- a(p) = a(t.parent(p));
+ mln_assertion(t.is_a_node(n));
+ if (a(t.parent(n)) == v)
+ {
+ mln_assertion(t.is_a_node(t.parent(n)));
+ a(n) = a(t.parent(n));
+ }
}
}
} // end of namespace mln::morpho::tree
Index: trunk/milena/sandbox/edwin/tree/tree.cc
===================================================================
--- trunk/milena/sandbox/edwin/tree/tree.cc (revision 3496)
+++ trunk/milena/sandbox/edwin/tree/tree.cc (revision 3497)
@@ -2,6 +2,7 @@
#include <mln/core/image/image2d.hh>
#include <mln/core/alias/neighb2d.hh>
#include <mln/core/routine/duplicate.hh>
+#include <mln/core/site_set/p_set.hh>
#include <mln/pw/all.hh>
#include <mln/value/int_u8.hh>
@@ -76,6 +77,9 @@
{
mln_VAR(a, morpho::tree::compute_attribute_image(a_, tree_));
+ display_tree_attributes(tree_, a);
+ find_treshold(a, tree_);
+
img_ = duplicate((pw::cst(lambda1) < pw::value(a) &&
pw::value(a) < pw::cst(lambda2))
| a.domain());
@@ -83,39 +87,125 @@
debug::println("attribut", a);
}
-// template <typename T>
-// inline
-// float
-// find_treshold(const T& t)
-// {
-// mln_bkd_piter(T) = p(t.domain());
+ template <typename I, typename T>
+ inline
+ float
+ find_treshold(const Image<I>& img_, const T& tree)
+ {
+ typedef p_set< mln_psite(I) > PS;
+ typedef p_array<mln_psite(I)> N;
+
+ I img = exact(img_);
+ PS pset, ps_rm; // component container.
+ mln_value(I) val, old;
+ std::vector< mln_value(I)> f_domain;
+ std::vector< unsigned> f;
+
+ //debug::println(img | tree.nodes());
+
+
+ N nodes = level::sort_psites_increasing(img);
+ mln_fwd_piter(N) n(nodes);
+ mln_fwd_piter(PS) p(pset), p_rm(ps_rm);
+ old = 0;
+
+ // FIXME: hack because we want iterate on nodes and we would
+ // have wanted to write:
+ // N nodes = level::sort_psites_increasing(img | tree.nodes)
+ //
+ // but it doesn't work, so we iterate on domain regarding if n is
+ // a node.
+
+ n.start();
+ while (n.is_valid() && !tree.is_a_node(n))
+ n.next();
+
+ while (n.is_valid() && tree.is_a_node(n))
+ {
+ val = img(n);
+ do {
+ // Remove p's children from set.
+ // FIXME: improve deletion pass.
+ ps_rm.clear();
+ for_all(p)
+ if (tree.parent(p) == n)
+ ps_rm.insert(p);
+
+ for_all(p_rm)
+ pset.remove(p_rm);
+
+ // Add the new representant to component set.
+ pset.insert(n);
+ do {
+ n.next();
+ } while (n.is_valid() && !tree.is_a_node(n));
+ } while (img(n) == val && n.is_valid());
+
+ if (pset.nsites() != old)
+ {
+ old = pset.nsites();
+ f_domain.push_back(val);
+ f.push_back(pset.nsites());
+ }
+
+
+ // Debug.
+ {
+ std::cout << " - " << val << ":" << pset.nsites() << " {";
+ for_all(p)
+ std::cout << p << ",";
+ std::cout << "}" << std::endl;
+ }
+ }
+
+ for (unsigned i = 0; i < f_domain.size() - 1; i++)
+ {
+ std::cout << "[" << f_domain[i] << ","
+ << f_domain[i + 1] << "[ -> "
+ << f[i] << std::endl;
+ }
+ std::cout << ">=" << f_domain[f_domain.size() - 1] << " -> "
+ << f[f_domain.size() - 1] << std::endl;
+
+ return 0;
+ }
-// for_all(p)
-// if (t.is_a_node(p))
-// {
-// if
-// }
-// }
template <typename I, typename A>
- void filtercheck(const Image<I>& img, const Meta_Accumulator<A>& a)
+ void filtercheck(treefilter<I>& f, const Meta_Accumulator<A>& a)
{
using value::label_8;
label_8 n;
util::array<unsigned int> counts;
+ util::array< mln_psite(I) > fnodes;
- debug::println("binaire:", img);
- mln_VAR(lbl, labeling::blobs(img, c4(), n));
- debug::println("blob:", lbl);
+ mln_VAR(lbl, labeling::blobs(f.img(), c4(), n));
counts = labeling::compute(a, lbl, n);
- for (unsigned i = 0; i < counts.nelements(); i++)
+
+ mln_VAR(acc, morpho::tree::compute_attribute_image(morpho::attribute::card<I>(), f.tree()));
+ fnodes = morpho::tree::get_first_nodes(f.img(), f.tree());
+
+ mln_assertion(counts.nelements() == fnodes.nelements() + 1);
+
+ std::vector<unsigned> counts2;
+ counts2.resize(fnodes.nelements());
+ std::transform(fnodes.hook_std_vector_().begin(), fnodes.hook_std_vector_().end(),
+ counts2.begin(), acc);
+
+ std::sort(counts.hook_std_vector_().begin(), counts.hook_std_vector_().end());
+ std::sort(counts2.begin(), counts2.end());
+
+ for (unsigned i = 0; i < counts2.size(); i++)
{
- std::cout << "counts[" << i << "]: " << counts[i]
+ mln_assertion(acc.domain().has(fnodes(p)));
+ std::cout << "counts[" << i << "]: (ref " << counts[i] << ") " << counts2[i]
<< std::endl;
}
+
+
}
} // end of namespace mln
@@ -157,20 +247,16 @@
else
usage(argv);
+
+
back_propagate_subbranch(f->tree(), f->img() ,true);
back_propagate_level(f->tree(), f->img());
- filtercheck(f->img(), accu::meta::count());
+ filtercheck(*f, accu::meta::count());
- util::array< mln_psite_(I) > counts;
- counts = morpho::tree::get_first_nodes(f->img(), f->tree());
- for (unsigned i = 0; i < counts.nelements(); i++)
- std::cout << "counts[" << i << "]: " << counts[i] << std::endl;
- mln_VAR(a, morpho::tree::compute_attribute_image(morpho::attribute::card<I>(), f->tree()));
- display_tree_attributes(f->tree(), a);
io::pbm::save(f->img(), "out.pbm");
delete f;
Index: trunk/milena/sandbox/edwin/tree/routines.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/routines.hh (revision 3496)
+++ trunk/milena/sandbox/edwin/tree/routines.hh (revision 3497)
@@ -49,60 +49,20 @@
data::fill(deja_vu, false);
bool can_break = false;
- mln_bkd_piter(T) p(tree.domain());
+ mln_bkd_piter(T) p(tree.nodes());
for_all(p)
{
- if (tree.is_a_node(p) && bin(p) && bin(t.parent(p))
+ mln_assertion(tree.is_a_node(p));
+ if (bin(p) && !bin(tree.parent(p)))
{
fnodes.append(p);
}
}
-
- // else if (can_break)
-// {
-// std::cout << p << std::endl;
-// break;
-// }
-
return fnodes;
}
}
}
-
-// namespace debug {
-
-// template <typename T, typename I>
-// void
-// println(const T& t, const Image<I> f_)
-// {
-// //theo's code
-// typedef mln_site(I) P;
-// I f = exact(f_);
-
-// mln_ch_value(I, bool) deja_vu;
-// initialize(deja_vu, f);
-// data::fill(deja_vu, false);
-
-// typedef typename T::nodes_t nodes_t;
-// mln_fwd_piter(T) p(t.nodes());
-// for_all(p)
-// {
-// if (deja_vu(p))
-// continue;
-// P e = p;
-// do
-// {
-// std::cout << f(e) << ':' << e << " -> ";
-// deja_vu(e) = true;
-// e = t.parent(e);
-// }
-// while (! deja_vu(e));
-// std::cout << f(e) << ':' << e << std::endl;
-// }
-// std::cout << std::endl;
-// }
-// }
}
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-03-06 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Add watershed implementation for IRM images.
* fabien/bin/Makefile: Update.
* fabien/bin/dicom2dump.cc: Update.
* fabien/bin/dicom_mask.cc: Update.
* fabien/igr/Makefile: Update.
* fabien/igr/dumps: Remove.
* fabien/igr/watershed.cc: Watershed implementation.
---
bin/Makefile | 3
bin/dicom2dump.cc | 19 ---
bin/dicom_mask.cc | 26 ++++
igr/Makefile | 9 -
igr/watershed.cc | 320 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 353 insertions(+), 24 deletions(-)
Index: trunk/milena/sandbox/fabien/igr/watershed.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/watershed.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/watershed.cc (revision 3496)
@@ -0,0 +1,320 @@
+#include <iostream>
+#include <mln/core/image/image2d.hh>
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/core/image/image_if.hh>
+
+#include <mln/io/ppm/save.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/dicom/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/dump/save.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/label_16.hh>
+
+#include <mln/level/transform.hh>
+#include <mln/level/stretch.hh>
+
+#include <mln/labeling/mean_values.hh>
+
+#include <mln/convert/to_fun.hh>
+
+#include <mln/make/graph.hh>
+
+#include <mln/morpho/gradient.hh>
+#include <mln/morpho/closing/area.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/fun/l2l/wrap.hh>
+
+#include <mln/core/var.hh>
+#include <mln/morpho/elementary/dilation.hh>
+
+#include <mln/core/routine/extend.hh>
+
+#include <mln/util/graph.hh>
+
+#include <mln/essential/2d.hh>
+#include <mln/core/alias/vec3d.hh>
+#include <mln/debug/draw_graph.hh>
+#include <mln/util/graph.hh>
+#include <mln/accu/center.hh>
+#include <mln/io/dump/all.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb16.hh>
+#include <mln/accu/compute.hh>
+#include <mln/core/alias/dpoint2d.hh>
+#include <mln/draw/box.hh>
+#include <mln/level/stretch.hh>
+#include <mln/fun/v2v/id.hh>
+#include <mln/core/image/line_graph_elt_neighborhood.hh>
+#include <mln/morpho/elementary/dilation.hh>
+#include <mln/labeling/mean_values.hh>
+#include <mln/extension/adjust_fill.hh>
+#include <mln/extract/all.hh>
+#include <mln/make/region_adjacency_graph.hh>
+
+
+
+// Given a color image and a wshed image, computes the component graph.
+// Vertex values are computed thanks to a RGB image.
+
+namespace mln
+{
+
+ template <typename V>
+ value::int_u8 dist(const V& c1, const V& c2)
+ {
+ unsigned d = math::diff_abs(c1.red(), c2.red());
+ unsigned d_;
+ d_ = math::diff_abs(c1.green(), c2.green());
+
+ if (d_ > d)
+ d = d_;
+
+ d_ = math::diff_abs(c1.blue(), c2.blue());
+
+ if (d_ > d)
+ d = d_;
+ return d;
+ }
+
+
+ // ima_v, image on graph vertices; value = mean color per vertex (watershed basin)
+ template <typename I>
+ inline
+ pw::image<fun::i2v::array<value::int_u8>,
+ p_edges<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_edge_graph_image(const I& ima_v, const util::graph& g)
+ {
+ // edge sites.
+ typedef fun::i2v::array<mln_site(I)> edge_site_t;
+ edge_site_t edge_site(g.e_nmax(), literal::origin);
+ typedef p_edges<util::graph, edge_site_t > pe_t;
+ pe_t pe(g, edge_site);
+
+ // edge values
+ typedef fun::i2v::array<value::int_u8> edge_values_t;
+ edge_values_t edge_values(g.e_nmax());
+
+ // image on graph edges
+ typedef pw::image<edge_values_t, pe_t> ima_e_t;
+ ima_e_t ima_e = (edge_values | pe);
+
+ mln_piter(ima_e_t) e(ima_e.domain());
+ for_all(e) // in ima_e
+ ima_e(e) = math::diff_abs(ima_v.function()(e.element().v1()), ima_v.function()(e.element().v2()));
+
+ return ima_e;
+ }
+
+
+ template <typename I, typename J>
+ inline
+ util::array<mln_value(I)>
+ mean_color_values(const I& input, const J& w, mln_value(J) nbasins)
+ {
+ // Cf. sandbox/theo/color/segment_rgb_pixels.cc
+
+ util::array<vec3d_f> m_3f = labeling::compute(accu::mean<mln_value(I)>(),
+ input, // input color image
+ w, // watershed labeling
+ nbasins);
+ m_3f[0] = literal::zero;
+
+ util::array<mln_value(I)> m;
+ convert::from_to(m_3f, m);
+ m[0] = literal::yellow;
+
+ io::ppm::save(level::transform(w,
+ convert::to< fun::i2v::array<mln_value(I)> >(m)),
+ "wst_rag_wshd_color.ppm");
+
+ return m;
+ }
+
+
+ template <typename I, typename J>
+ pw::image<fun::i2v::array<mln_value(I)>, p_vertices<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_vertex_graph_image(const util::graph& g, const I&input, const J& w, const mln_value(J)& nbasins)
+ {
+ typedef util::array<mln_site(I)> vertex_sites_t;
+ vertex_sites_t site_values;
+ convert::from_to(labeling::compute(accu::center<mln_site(I)>(), w, nbasins),
+ site_values);
+
+ typedef fun::i2v::array<mln_site(J)> f_sites_t;
+ f_sites_t sites;
+ convert::from_to(site_values, sites);
+
+ // p_vertices
+ typedef p_vertices<util::graph, f_sites_t> S;
+ S pv(g, sites);
+
+
+ typedef fun::i2v::array<mln_value(I)> vertex_values_t;
+ vertex_values_t vertex_values;
+ // convert::from_to(mean_color_values(input, w, nbasins), vertex_values);
+
+ mln_VAR(ima_v, (vertex_values | pv));
+
+ return ima_v;
+ }
+
+
+ template <typename I, typename V>
+ struct edge_to_color : Function_p2v< edge_to_color<I,V> >
+ {
+ typedef V result;
+
+ edge_to_color(const I& ima)
+ : ima_(ima)
+ {
+ }
+
+ V
+ operator()(const unsigned& e) const
+ {
+ return convert::to<V>(ima_.function()(e));
+ }
+
+ const I& ima_;
+ };
+
+ template <typename V>
+ inline
+ unsigned
+ find_root(util::array<V>& parent, const unsigned& x)
+ {
+ if (parent[x] == x)
+ return x;
+ else
+ return parent[x] = find_root(parent, parent[x]);
+ }
+
+
+ template <typename I, typename V, typename E>
+ inline
+ image2d<mln_value(I)>
+ make_debug_graph_image(const I& input,
+ const V& ima_v, const E& ima_e,
+ unsigned box_size, const value::rgb8& bg)
+ {
+ image2d<mln_value(I)> ima;
+ initialize(ima, input);
+
+ data::fill(ima, bg);
+ debug::draw_graph(ima, ima_v.domain(),
+ pw::cst(mln_value(I)(literal::green)),
+ edge_to_color<E, mln_value(I)>(ima_e));
+
+ dpoint2d tl(-box_size,-box_size);
+ dpoint2d br(box_size,box_size);
+ mln_piter(V) p(ima_v.domain());
+ for_all(p)
+ {
+ box2d b(p + tl, p + br);
+ b.crop_wrt(ima.domain());
+ data::fill((ima | b).rw(), convert::to<mln_value(I)>(ima_v(p)));
+ }
+
+ return ima;
+ }
+
+}
+
+
+///////////////////
+// //
+// Main Function //
+// //
+///////////////////
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::int_u12;
+ using value::rgb8;
+ using value::label_16;
+
+ if (argc < 4)
+ {
+ std::cout << "Usage: " << argv[0] << " <ima.dcm> <closure_lambda> <box_size>"
+ << std::endl;
+ return 1;
+ }
+
+ unsigned box_size = atoi(argv[3]);
+
+ image2d<int_u12> dcm;
+ io::dicom::load(dcm, argv[1]);
+
+ image2d<int_u12> grad = morpho::gradient(dcm, win_c4p());
+ image2d<int_u12> clo = morpho::closing::area(grad, c4(), atoi(argv[2]));
+
+ label_16 nbasins;
+ image2d<label_16> wshed = morpho::meyer_wst(clo, c4(), nbasins);
+
+ mln_VAR(vol2_, morpho::elementary::dilation(extend(wshed | (pw::value(wshed) == 0u), wshed), c8()));
+
+ data::fill((wshed | (pw::value(wshed) == 0u)).rw(), vol2_);
+
+ /// Build graph
+ util::graph g = make::graph(wshed, c4(), nbasins);
+ // Build graph images and compute distance values with a RGB image.
+ mln_VAR(ima_v, make_vertex_graph_image(g, dcm, wshed, nbasins));
+ mln_VAR(ima_e, make_edge_graph_image(ima_v, g));
+
+ /// Try to merge vertices.
+ mln_piter_(ima_e_t) e(ima_e.domain());
+ util::array<label_16> parent(g.v_nmax());
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ parent[i] = i;
+
+ for_all(e)
+ {
+ unsigned v1 = e.element().v1();
+ unsigned v2 = e.element().v2();
+ if (ima_e(e) <= (unsigned)(atoi(argv[5]))
+ && find_root(parent, v1) != find_root(parent, v2))
+ parent[find_root(parent, v1)] = find_root(parent, v2);
+ }
+
+ fun::i2v::array<label_16> f(parent.nelements());
+ std::vector<unsigned> new_label(parent.nelements(), 0);
+ unsigned nbasins2 = 0;
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ {
+ unsigned p = find_root(parent, i);
+ mln_assertion(parent[p] == find_root(parent, i));
+ if (new_label[p] == 0)
+ new_label[p] = nbasins2++;
+ f(i) = new_label[p];
+ }
+ mln_invariant(f(0) == 0u);
+ --nbasins2; // nbasins2 does not count the basin with label 0.
+ image2d<label_16> wsd2 = level::transform(wshed, f);
+
+
+ /// Reconstruct a graph from the simplified image.
+ util::graph g2 = make::graph(wsd2, c4(), nbasins2);
+
+ // Compute distance values with a RGB image.
+ mln_VAR(ima_v2, make_vertex_graph_image(g2, dcm, wsd2, nbasins2));
+ mln_VAR(ima_e2, make_edge_graph_image(ima_v2, g2));
+
+ mln_VAR(wsd2_, morpho::elementary::dilation(extend(wsd2 | (pw::value(wsd2) == 0u), wsd2), c8()));
+
+ data::fill((wsd2 | (pw::value(wsd2) == 0u)).rw(), wsd2_);
+
+ //io::ppm::save(labeling::mean_values(dcm, wsd2, nbasins2), "wst_rag_mean_colors.ppm");
+ //io::ppm::save(make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, literal::white), "wst_rag_graph_image2_white.ppm");
+ //io::ppm::save(make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, literal::black), "wst_rag_graph_image2_black.ppm");
+}
Index: trunk/milena/sandbox/fabien/igr/Makefile
===================================================================
--- trunk/milena/sandbox/fabien/igr/Makefile (revision 3495)
+++ trunk/milena/sandbox/fabien/igr/Makefile (revision 3496)
@@ -8,7 +8,7 @@
-framework CoreFoundation
CXXFLAGS = -DNDEBUG -O1
-all: 2d 3d
+all: 2d 3d wsd
2d: seg_vol_irm.hh seg2d.cc
g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} seg2d.cc -o seg2d
@@ -16,11 +16,8 @@
3d: seg_vol_irm.hh seg3d.cc
g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} seg3d.cc -o seg3d
-grad: grad_clo_and_wshd.cc
- g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o grad_clo
-
-wst: wst_rag.cc
- g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o wst_rag
+wsd: watershed.cc
+ g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o wsd
clean:
rm -rf *.dump *.p?m *.plot *.log *.csv
Index: trunk/milena/sandbox/fabien/bin/dicom2dump.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dicom2dump.cc (revision 3495)
+++ trunk/milena/sandbox/fabien/bin/dicom2dump.cc (revision 3496)
@@ -2,7 +2,6 @@
#include <mln/core/image/image2d.hh>
#include <mln/core/image/image3d.hh>
-#include <mln/value/int_u8.hh>
#include <mln/value/int_u12.hh>
#include <mln/io/dicom/load.hh>
#include <mln/io/dump/save.hh>
@@ -17,31 +16,15 @@
}
-/*int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u12;
-
- if (argc != 3)
- return usage(argv);
-
- image3d<int_u12> ima;
- io::dicom::load(ima, argv[1]);
- io::dump::save(ima, argv[2]);
-
- return 0;
-}*/
-
int main(int argc, char* argv[])
{
using namespace mln;
- using value::int_u8;
using value::int_u12;
if (argc != 3)
return usage(argv);
- image2d<int_u8> ima;
+ image3d<int_u12> ima;
io::dicom::load(ima, argv[1]);
io::dump::save(ima, argv[2]);
Index: trunk/milena/sandbox/fabien/bin/dicom_mask.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dicom_mask.cc (revision 3495)
+++ trunk/milena/sandbox/fabien/bin/dicom_mask.cc (revision 3496)
@@ -1,6 +1,9 @@
#include <mln/core/concept/image.hh>
#include <mln/core/image/image2d.hh>
+#include <mln/geom/ncols.hh>
+#include <mln/geom/nrows.hh>
+
#include <mln/value/int_u8.hh>
#include <mln/io/dicom/load.hh>
#include <mln/io/pbm/save.hh>
@@ -33,6 +36,29 @@
image2d<int_u8> input;
io::dicom::load(input, argv[1]);
+ util::array<unsigned> xproj(geom::nrows(input), 0);
+ util::array<unsigned> yproj(geom::ncols(input), 0);
+
+ mln_piter_(image2d<int_u8>) p(input.domain());
+ for_all(p)
+ {
+ xproj[p.row()] += input(p);
+ yproj[p.col()] += input(p);
+ }
+
+ // Plot files
+ std::ofstream fout_x("x.plot");
+ for (unsigned int i = 0; i < xproj.nelements(); ++i)
+ {
+ fout_x << i << " " << xproj[i] << std::endl;
+ }
+
+ std::ofstream fout_y("y.plot");
+ for (unsigned int i = 0; i < yproj.nelements(); ++i)
+ {
+ fout_y << i << " " << yproj[i] << std::endl;
+ }
+
image2d<bool> ima = level::transform(input, fun::v2b::threshold<int_u8>(1));
io::pbm::save(ima, argv[2]);
}
Index: trunk/milena/sandbox/fabien/bin/Makefile
===================================================================
--- trunk/milena/sandbox/fabien/bin/Makefile (revision 3495)
+++ trunk/milena/sandbox/fabien/bin/Makefile (revision 3496)
@@ -21,3 +21,6 @@
dump: dicom2dump.cc
g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o dicom2dump
+
+pgm: dicom2pgm.cc
+ g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o dicom2pgm
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Have all labeling routines be consistent.
* mln/core/concept/window.hh,
* mln/core/concept/neighborhood.hh
(positive_offsets_wrt): New.
* mln/morpho/tree/compute_parent.hh (todo): New.
(doc): Augment.
* mln/morpho/tree/data.hh (todo): New.
* mln/canvas/labeling.hh: Swap fwd and bkd between both passes.
(todo): New.
Now it is consistent with labeling::blobs.
* tests/level/sort_psites.cc: Test reversibility.
* tests/morpho/tree/data.cc: Precise fwd when needed.
* tests/labeling/foreground.cc: Upgrade doc style.
Augment test.
mln/canvas/labeling.hh | 26 +++++-------
mln/core/concept/neighborhood.hh | 18 ++++++++
mln/core/concept/window.hh | 30 ++++++++++++++
mln/morpho/tree/compute_parent.hh | 78 ++++++++++++++++++++++++++++++++++----
mln/morpho/tree/data.hh | 7 ++-
tests/labeling/foreground.cc | 38 +++++++++++++++---
tests/level/sort_psites.cc | 19 ++++++---
tests/morpho/tree/data.cc | 15 +++++--
8 files changed, 193 insertions(+), 38 deletions(-)
Index: mln/core/concept/window.hh
--- mln/core/concept/window.hh (revision 3494)
+++ mln/core/concept/window.hh (working copy)
@@ -121,6 +121,10 @@
template <typename I, typename W>
util::array<int>
+ positive_offsets_wrt(const Image<I>& ima, const Window<W>& win);
+
+ template <typename I, typename W>
+ util::array<int>
negative_offsets_wrt(const Image<I>& ima, const Window<W>& win);
@@ -346,6 +350,32 @@
template <typename I, typename W>
inline
util::array<int>
+ positive_offsets_wrt(const Image<I>& ima_, const Window<W>& win_)
+ {
+ mln_is_simple_window(W)::check();
+
+ const I& ima = exact(ima_);
+ const W& win = exact(win_);
+ mln_precondition(ima.is_valid());
+ mln_precondition(win.is_valid());
+
+ util::array<int> arr;
+ unsigned n = win.size();
+
+ for (unsigned i = 0; i < n; ++i)
+ {
+ int offset = ima.delta_index(win.dp(i));
+ if (offset > 0)
+ arr.append(offset);
+ }
+
+ return arr;
+ }
+
+
+ template <typename I, typename W>
+ inline
+ util::array<int>
negative_offsets_wrt(const Image<I>& ima_, const Window<W>& win_)
{
mln_is_simple_window(W)::check();
Index: mln/core/concept/neighborhood.hh
--- mln/core/concept/neighborhood.hh (revision 3494)
+++ mln/core/concept/neighborhood.hh (working copy)
@@ -104,6 +104,10 @@
template <typename I, typename N>
util::array<int>
+ positive_offsets_wrt(const Image<I>& ima, const Neighborhood<N>& nbh);
+
+ template <typename I, typename N>
+ util::array<int>
negative_offsets_wrt(const Image<I>& ima, const Neighborhood<N>& nbh);
@@ -166,6 +170,20 @@
template <typename I, typename N>
util::array<int>
+ positive_offsets_wrt(const Image<I>& ima_, const Neighborhood<N>& nbh_)
+ {
+ mln_is_simple_neighborhood(N)::check();
+
+ const I& ima = exact(ima_);
+ const N& nbh = exact(nbh_);
+ mln_precondition(ima.is_valid());
+ mln_precondition(nbh.is_valid());
+
+ return positive_offsets_wrt(ima, nbh.win());
+ }
+
+ template <typename I, typename N>
+ util::array<int>
negative_offsets_wrt(const Image<I>& ima_, const Neighborhood<N>& nbh_)
{
mln_is_simple_neighborhood(N)::check();
Index: mln/morpho/tree/compute_parent.hh
--- mln/morpho/tree/compute_parent.hh (revision 3494)
+++ mln/morpho/tree/compute_parent.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 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
@@ -33,6 +34,11 @@
/// Compute a canonized tree from an image.
///
/// \todo Specialize for low quant (and try fastest).
+///
+/// \todo Augment and improve documentation.
+///
+/// \todo Change level::sort so that the explanations below are valid
+/// whatever the choice 'increasing or decreasing'.
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
@@ -55,16 +61,72 @@
/// "natural" childhood relationship. The parenthood is thus
/// inverted w.r.t. to \p s.
///
- /// It is very convenient since all processing upon the parent
- /// tree are performed following \p s (in the default "forward"
- /// way).
+ /// It is very convenient since most processing routines upon
+ /// the parent tree are performed following \p s (in the default
+ /// "forward" way). Indeed that is the way to propagate
+ /// information from parents to children.
///
- /// FIXME: Put it more clearly...
///
/// The parent result image verifies: \n
/// - p is root iff parent(p) == p \n
/// - p is a node iff either p is root or f(parent(p)) != f(p).
-
+ ///
+ ///
+ ///
+ /// The choice "s means childhood" is consistent with labeling
+ /// in binary images. In that particular case, while browsing
+ /// the image in forward scan (video), we expect to find first a
+ /// tree root (a first point, representative of a component) and
+ /// then the other component points. Please note that it leads
+ /// to increasing values of labels in the "natural" video scan.
+ ///
+ /// Since mathematical morphology on functions is related to
+ /// morphology on sets, we clearly want to keep the equivalence
+ /// between "component labeling" and "component filtering" using
+ /// trees.
+ ///
+ ///
+ /// FIXME: Put it more clearly... Insert pictures!
+ ///
+ /// A binary image:
+ ///
+ /// - | | - - \n
+ /// - | | - | \n
+ /// - - - - - \n
+ /// - - | | - \n
+ ///
+ /// where '|' means true and '-' means false.
+ ///
+ /// Its labeling:
+ ///
+ /// 0 1 1 0 0 \n
+ /// 0 1 1 0 2 \n
+ /// 0 0 0 0 0 \n
+ /// 0 0 3 3 0 \n
+ ///
+ /// The corresponding forest:
+ ///
+ /// x o . x x \n
+ /// x . . x o \n
+ /// x x x x x \n
+ /// x x o . x \n
+ ///
+ /// where 'x' means "no data", 'o' is a tree root
+ /// (representative point for a component), and '.' is a tree
+ /// regular (non-root) point (in a component by not its
+ /// representative point).
+ ///
+ ///
+ /// The forest, with the parent relationship looks like:
+ ///
+ /// o < . \n
+ /// ^ r \n
+ /// . . o \n
+ /// \n
+ /// \n
+ /// o < . \n
+ ///
+ ///
template <typename I, typename N, typename S>
mln_ch_value(I, mln_psite(I))
compute_parent(const Image<I>& f, const Neighborhood<N>& nbh,
@@ -159,7 +221,7 @@
data::fill(deja_vu, false);
// Body.
- mln_bkd_piter(S) p(s);
+ mln_bkd_piter(S) p(s); // Backward.
mln_niter(N) n(nbh, p);
for_all(p)
{
@@ -183,7 +245,7 @@
// Canonization.
{
- mln_fwd_piter(S) p(s);
+ mln_fwd_piter(S) p(s); // Forward.
for_all(p)
{
P q = parent(p);
Index: mln/morpho/tree/data.hh
--- mln/morpho/tree/data.hh (revision 3494)
+++ mln/morpho/tree/data.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 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
@@ -31,6 +32,10 @@
/// \file mln/morpho/tree/data.hh
///
/// FIXME: First Attempt.
+///
+/// \todo Fix the issue pointed to by Edwin without modifying the way
+/// sites are browsed (see the documentation of compute_parent to
+/// learn why we want the 1st pass to be in forward scan of s).
# include <mln/morpho/tree/compute_parent.hh>
# include <mln/core/image/sub_image.hh>
Index: mln/canvas/labeling.hh
--- mln/canvas/labeling.hh (revision 3494)
+++ mln/canvas/labeling.hh (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 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
@@ -33,8 +33,8 @@
///
/// Connected component labeling of the object part in a binary image.
///
-/// \todo Make the fastest version work.
-/// FIXME: is 'status' useful?
+/// \todo Can we get rid of 'deja_vu' (while playing with the border)
+/// in the fastest video version?
# include <mln/core/concept/image.hh>
# include <mln/data/fill.hh>
@@ -139,7 +139,7 @@
// Output.
mln_ch_value(I, L) output;
- bool status;
+ bool status; // FIXME: Is-it useful?
// Initialization.
{
@@ -157,7 +157,7 @@
// First Pass.
{
- mln_fwd_piter(S) p(s);
+ mln_bkd_piter(S) p(s); // Backward.
mln_niter(N) n(nbh, p);
for_all(p) if (f.handles(p))
{
@@ -187,7 +187,7 @@
// Second Pass.
{
- mln_bkd_piter(S) p(s);
+ mln_fwd_piter(S) p(s); // Forward.
for_all(p) if (f.handles(p))
{
if (parent(p) == p) // if p is root
@@ -274,10 +274,10 @@
// First Pass.
{
- util::array<int> dp = negative_offsets_wrt(input, nbh);
+ util::array<int> dp = positive_offsets_wrt(input, nbh);
const unsigned n_nbhs = dp.nelements();
- mln_pixter(const I) px(input);
+ mln_bkd_pixter(const I) px(input); // Backward.
for_all(px)
{
unsigned p = px.offset();
@@ -311,7 +311,7 @@
// Second Pass.
{
- mln_bkd_pixter(const I) px(input);
+ mln_fwd_pixter(const I) px(input); // Forward.
for_all(px)
{
unsigned p = px.offset();
@@ -394,8 +394,7 @@
// First Pass.
{
-
- for (unsigned i = 0; i < n_points; ++i)
+ for (int i = n_points - 1; i >=0; --i) // Backward.
{
unsigned p = s[i];
if (! f.handles_(p))
@@ -425,13 +424,12 @@
f.do_no_union_(n, p);
}
deja_vu.element(p) = true;
-
}
}
// Second Pass.
{
- for (int i = n_points - 1; i >=0; --i)
+ for (unsigned i = 0; i < n_points; ++i) // Forward.
{
unsigned p = s[i];
if (! f.handles_(p))
Index: tests/level/sort_psites.cc
--- tests/level/sort_psites.cc (revision 3494)
+++ tests/level/sort_psites.cc (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 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
@@ -31,7 +31,7 @@
/// Tests on mln::level::sort_psites.
#include <mln/core/image/image2d.hh>
-#include <mln/debug/iota.hh>
+#include <mln/make/image2d.hh>
#include <mln/level/sort_psites.hh>
#include <mln/core/site_set/p_array.hh>
@@ -40,11 +40,20 @@
{
using namespace mln;
- image2d<int> ima(3, 3);
- debug::iota (ima);
+ int vals[] = { 0, 3, 4,
+ 2, 2, 2,
+ 0, 1, 4 };
+ image2d<int> ima = make::image2d(vals);
p_array<point2d> array_inc = level::sort_psites_increasing(ima);
p_array<point2d> array_dec = level::sort_psites_decreasing(ima);
+ {
+ p_array<point2d>::fwd_piter p1(array_inc);
+ p_array<point2d>::bkd_piter p2(array_dec);
+ for_all_2(p1, p2)
+ mln_assertion(ima(p1) == ima(p2));
+ }
+
p_array<point2d> array_inc_ref;
p_array<point2d> array_dec_ref;
Index: tests/morpho/tree/data.cc
--- tests/morpho/tree/data.cc (revision 3494)
+++ tests/morpho/tree/data.cc (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 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
@@ -62,9 +63,17 @@
{
std::cout << "nodes = ";
- tree_t::nodes_t::piter p(t.nodes());
+ tree_t::nodes_t::fwd_piter p(t.nodes());
for_all(p)
std::cout << p << ' ';
+ std::cout << std::endl;
+ }
+ {
+ std::cout << "nodes = ";
+ tree_t::fwd_piter p(t.domain());
+ for_all(p)
+ if (t.is_a_node(p))
+ std::cout << p << ' ';
std::cout << std::endl
<< std::endl;
}
@@ -73,7 +82,7 @@
{
image2d<unsigned> area(ima.domain());
data::fill(area, 1);
- tree_t::piter p(t.domain());
+ tree_t::fwd_piter p(t.domain());
for_all(p)
if (! t.is_root(p))
area(t.parent(p)) += area(p);
Index: tests/labeling/foreground.cc
--- tests/labeling/foreground.cc (revision 3494)
+++ tests/labeling/foreground.cc (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 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
@@ -25,14 +26,15 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/labeling/foreground.cc
- *
- * \brief Test on mln::labeling::foreground.
- */
+/// \file tests/labeling/foreground.cc
+///
+/// Test on mln::labeling::foreground.
#include <mln/core/image/image2d.hh>
+#include <mln/core/var.hh>
#include <mln/io/pbm/load.hh>
#include <mln/core/alias/neighb2d.hh>
+#include <mln/level/compare.hh>
#include <mln/labeling/foreground.hh>
#include "tests/data.hh"
@@ -42,8 +44,30 @@
{
using namespace mln;
- image2d<bool> pic = io::pbm::load(MLN_IMG_DIR "/picasso.pbm");
+ typedef image2d<bool> I;
+ mln_VAR(nbh, c4());
+
+ I pic = io::pbm::load(MLN_IMG_DIR "/picasso.pbm");
+ image2d<unsigned> out, ref;
+
unsigned n;
- labeling::foreground(pic, c4(), n);
+ out = labeling::foreground(pic, nbh, n); // Calls the fastest 'video'
+ // version.
mln_assertion(n == 33);
+
+ {
+ // Note that labeling::foreground actually is labeling::level
+ // which calls canvas::labeling_video and its generic dispatch
+ // leads to canvas::impl::generic::labeling.
+
+ labeling::impl::level_functor<I> f(pic, true);
+
+ unsigned n_;
+ ref = canvas::impl::generic::labeling(pic, nbh, n_,
+ pic.domain(),
+ f);
+ mln_invariant(n_ == n);
+ mln_invariant(ref == out);
+ }
+
}
1
0