* scribo/src/primitive/extract/Makefile.am: Add a new target.
* scribo/src/primitive/extract/lines_pattern.cc: New.
---
scribo/ChangeLog | 8 +++
scribo/src/primitive/extract/Makefile.am | 4 +-
scribo/src/primitive/extract/lines_pattern.cc | 76 +++++++++++++++++++++++++
3 files changed, 87 insertions(+), 1 deletions(-)
create mode 100644 scribo/src/primitive/extract/lines_pattern.cc
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 279e1fd..4fed85c 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,13 @@
2009-11-03 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Add a new example in Scribo.
+
+ * scribo/src/primitive/extract/Makefile.am: Add a new target.
+
+ * scribo/src/primitive/extract/lines_pattern.cc: New.
+
+2009-11-03 Guillaume Lazzara <z(a)lrde.epita.fr>
+
First draft of multiscale Sauvola's binarization.
* scribo/src/binarization/Makefile.am: Add new target.
diff --git a/scribo/src/primitive/extract/Makefile.am b/scribo/src/primitive/extract/Makefile.am
index 636abc3..7e1ea78 100644
--- a/scribo/src/primitive/extract/Makefile.am
+++ b/scribo/src/primitive/extract/Makefile.am
@@ -25,11 +25,13 @@ bin_PROGRAMS = \
extract_discontinued_vlines \
extract_discontinued_hlines \
extract_thick_vlines \
- extract_thick_hlines
+ extract_thick_hlines \
+ lines_pattern
extract_discontinued_lines_SOURCES = extract_discontinued_lines.cc
extract_discontinued_vlines_SOURCES = extract_discontinued_vlines.cc
extract_discontinued_hlines_SOURCES = extract_discontinued_hlines.cc
extract_thick_vlines_SOURCES = extract_thick_vlines.cc
extract_thick_hlines_SOURCES = extract_thick_hlines.cc
+lines_pattern_SOURCES = lines_pattern.cc
diff --git a/scribo/src/primitive/extract/lines_pattern.cc b/scribo/src/primitive/extract/lines_pattern.cc
new file mode 100644
index 0000000..d794c71
--- /dev/null
+++ b/scribo/src/primitive/extract/lines_pattern.cc
@@ -0,0 +1,76 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/io/pbm/all.hh>
+#include <mln/pw/all.hh>
+#include <mln/data/fill.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+
+#include <scribo/primitive/extract/lines_h_pattern.hh>
+#include <scribo/primitive/extract/lines_v_pattern.hh>
+#include <scribo/debug/usage.hh>
+
+
+const char *args_desc[][2] =
+{
+ { "input.pbm", "A binary image." },
+ { "length", " Minimum line length. (Common value : 51)" },
+ { "delta", " Distance between the object pixel and the background pixel (Common value : 5)" },
+ {0, 0}
+};
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+
+ if (argc != 5)
+ return scribo::debug::usage(argv,
+ "Extract horizontal lines patterns",
+ "input.pbm length delta output.pbm",
+ args_desc,
+ "A binary image of lines.");
+
+ trace::entering("main");
+
+ image2d<bool> input;
+ io::pbm::load(input, argv[1]);
+
+ image2d<bool>
+ h_lines = scribo::primitive::extract::lines_h_pattern(input,
+ atoi(argv[2]),
+ atoi(argv[3]));
+ image2d<bool>
+ v_lines = scribo::primitive::extract::lines_v_pattern(input,
+ atoi(argv[2]),
+ atoi(argv[3]));
+
+ data::fill((v_lines | pw::value(h_lines)).rw(), true);
+
+ io::pbm::save(v_lines, argv[4]);
+
+ trace::exiting("main");
+}
--
1.5.6.5
---
milena/ChangeLog | 4 +++
milena/mln/value/label_32.hh | 52 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/value/label_32.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index a21863f..f8e112a 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,7 @@
+2009-11-03 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ * mln/value/label_32.hh: New.
+
2009-10-02 Roland Levillain <roland(a)lrde.epita.fr>
Add ISMM 2009 input images and generate outputs.
diff --git a/milena/mln/value/label_32.hh b/milena/mln/value/label_32.hh
new file mode 100644
index 0000000..a4603e1
--- /dev/null
+++ b/milena/mln/value/label_32.hh
@@ -0,0 +1,52 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_VALUE_LABEL_32_HH
+# define MLN_VALUE_LABEL_32_HH
+
+/// \file
+///
+/// Define the alias value::label_32.
+
+# include <mln/value/label.hh>
+
+
+namespace mln
+{
+
+ namespace value
+ {
+
+
+ /// Alias for 32-bit integers.
+ typedef label<32> label_32;
+
+
+ } // end of namespace mln::value
+
+} // end of namespace mln
+
+
+#endif // ! MLN_VALUE_LABEL_32_HH
--
1.5.6.5
* primitive/extract/lines_pattern.hh: Make it less tolerant.
---
scribo/ChangeLog | 6 ++++++
scribo/primitive/extract/lines_pattern.hh | 19 ++++++++++++++++---
2 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 42d59dd..b04de6a 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,11 @@
2009-11-03 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Improve line pattern recognition routine.
+
+ * primitive/extract/lines_pattern.hh: Make it less tolerant.
+
+2009-11-03 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Add new debug tools.
* src/debug/Makefile.am: Add new targets.
diff --git a/scribo/primitive/extract/lines_pattern.hh b/scribo/primitive/extract/lines_pattern.hh
index 6a69a4a..57958ec 100644
--- a/scribo/primitive/extract/lines_pattern.hh
+++ b/scribo/primitive/extract/lines_pattern.hh
@@ -62,6 +62,7 @@ namespace scribo
/// \param[in] win_ A window corresponding to the line pattern.
///
/// \return A image with lines of direction \p dir.
+ ///
//
template <typename I, typename W>
mln_concrete(I)
@@ -92,19 +93,31 @@ namespace scribo
mln_piter(I) p(input.domain());
mln_qiter(window2d) q(win, p);
+ bool is_foreground;
for_all(p)
{
+
+ // If the foreground part of the pattern has more than 20%
+ // of background pixels, the current pixel is considered as
+ // background pixel.
if (length - tmp(p) > (0.2f * length))
{
output(p) = false;
continue;
}
- unsigned bg_count = 0;
+ // If the background parts of the pattern have less than 95%
+ // of foreground pixels, the current pixel is considered as
+ // part of the background.
+ is_foreground = true;
for_all(q)
- bg_count += tmp(q);
+ if ((length - tmp(q)) < (length * 0.95f))
+ {
+ is_foreground = false;
+ break;
+ }
- output(p) = (2 * length - bg_count) > (2 * length * 0.90f);
+ output(p) = is_foreground;
}
--
1.5.6.5
* filter/internal/compute.hh: New routine to compute filter
results.
* filter/object_links_center_aligned.hh,
* filter/object_links_top_aligned.hh,
* filter/objects_h_thick.hh,
* filter/objects_v_thick.hh: New filters.
---
scribo/ChangeLog | 12 ++
scribo/filter/internal/compute.hh | 147 +++++++++++++++++++
scribo/filter/object_links_center_aligned.hh | 113 +++++++++++++++
scribo/filter/object_links_top_aligned.hh | 121 ++++++++++++++++
scribo/filter/objects_h_thick.hh | 196 ++++++++++++++++++++++++++
scribo/filter/objects_v_thick.hh | 196 ++++++++++++++++++++++++++
6 files changed, 785 insertions(+), 0 deletions(-)
create mode 100644 scribo/filter/internal/compute.hh
create mode 100644 scribo/filter/object_links_center_aligned.hh
create mode 100644 scribo/filter/object_links_top_aligned.hh
create mode 100644 scribo/filter/objects_h_thick.hh
create mode 100644 scribo/filter/objects_v_thick.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index bb22ef9..2a3c71e 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,17 @@
2009-11-03 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Add new link filters.
+
+ * filter/internal/compute.hh: New routine to compute filter
+ results.
+
+ * filter/object_links_center_aligned.hh,
+ * filter/object_links_top_aligned.hh,
+ * filter/objects_h_thick.hh,
+ * filter/objects_v_thick.hh: New filters.
+
+2009-11-03 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Revamp code related to object linking.
* core/concept/link_functor.hh: New concept.
diff --git a/scribo/filter/internal/compute.hh b/scribo/filter/internal/compute.hh
new file mode 100644
index 0000000..346cee8
--- /dev/null
+++ b/scribo/filter/internal/compute.hh
@@ -0,0 +1,147 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_FILTER_INTERNAL_COMPUTE_HH
+# define SCRIBO_FILTER_INTERNAL_COMPUTE_HH
+
+/// \file
+///
+/// Compute filters.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+# include <mln/util/array.hh>
+
+# include <scribo/core/object_image.hh>
+# include <scribo/primitive/extract/objects.hh>
+
+
+
+namespace scribo
+{
+
+ namespace filter
+ {
+
+ namespace internal
+ {
+
+
+ using namespace mln;
+
+ /// Apply a filter to an image.
+ ///
+ /// \param[in] input_ A binary image.
+ /// \param[in] nbh_ A neighborhood used in labeling algorithms.
+ /// \param[in] label_type The label type used for labeling.
+ /// \param[in] filter A filter.
+ ///
+ /// \result A filtered binary image.
+ //
+ template <typename I, typename N, typename V, typename F>
+ mln_concrete(I)
+ compute(const Image<I>& input_,
+ const Neighborhood<N>& nbh_,
+ const V& label_type,
+ const Function_v2b<F>& filter);
+
+
+ /// Filter an object image.
+ ///
+ /// \param[in] objects An object image.
+ /// \param[in] filter A filter functor.
+ ///
+ /// \result A filtered object image.
+ //
+ template <typename L, typename F>
+ object_image(L)
+ compute(const object_image(L)& objects,
+ const Function_v2b<F>& filter);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename I, typename N, typename V, typename F>
+ inline
+ mln_concrete(I)
+ compute(const Image<I>& input_,
+ const Neighborhood<N>& nbh_,
+ const V& label_type,
+ const Function_v2b<F>& filter)
+ {
+ trace::entering("scribo::filter::internal::compute");
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_precondition(input.is_valid());
+ mln_precondition(nbh.is_valid());
+
+ V nlabels;
+ typedef mln_ch_value(I,V) lbl_t;
+ object_image(lbl_t) objects
+ = primitive::extract::objects(input, nbh, nlabels);
+
+ filter.update_objects(objects);
+ objects.relabel(filter);
+
+ mln_concrete(I) output = duplicate(input);
+ data::fill((output | pw::value(objects) == literal::zero).rw(), false);
+
+ trace::exiting("scribo::filter::internal::compute");
+ return output;
+ }
+
+
+ template <typename L, typename F>
+ inline
+ object_image(L)
+ compute(const object_image(L)& objects,
+ const Function_v2b<F>& filter)
+ {
+ trace::entering("scribo::filter::internal::compute");
+
+ mln_precondition(objects.is_valid());
+
+ object_image(L) output;
+ output.init_from_(objects);
+ output.relabel(filter);
+
+ trace::exiting("scribo::filter::internal::compute");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::filter::internal
+
+ } // end of namespace scribo::filter
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_FILTER_INTERNAL_COMPUTE_HH
diff --git a/scribo/filter/object_links_center_aligned.hh b/scribo/filter/object_links_center_aligned.hh
new file mode 100644
index 0000000..e44f3cd
--- /dev/null
+++ b/scribo/filter/object_links_center_aligned.hh
@@ -0,0 +1,113 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_FILTER_OBJECT_LINKS_CENTER_ALIGNED_HH
+# define SCRIBO_FILTER_OBJECT_LINKS_CENTER_ALIGNED_HH
+
+/// \file
+///
+/// Invalidate links between two objects if their center are not
+/// aligned.
+
+
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/object_links.hh>
+# include <scribo/core/object_image.hh>
+
+# include <scribo/filter/object_links_non_aligned_simple.hh>
+
+namespace scribo
+{
+
+ namespace filter
+ {
+
+ using namespace mln;
+
+ /*! \brief Invalidate links between two objects if their center are not
+ aligned.
+
+ \param[in] objects An object image.
+ \param[in] links Object links information.
+ \param[in] max_alpha Maximum angle value (degrees).
+
+ \verbatim
+
+ ------ ------
+ | | | | v
+ | x ~| ~ ~ ~ | ~ ~|~ ~
+ | ~| ~ | | | => Alpha
+ | | ~ ~ | x ~|~ ~
+ ------ | | ^
+ object1 | |
+ ------
+ object2
+
+ \endverbatim
+
+ The angle between the two bottoms must be lower than \p max_alpha.
+
+ */
+ template <typename L>
+ object_links<L>
+ object_links_center_aligned(const object_image(L)& objects,
+ const object_links<L>& links,
+ float max_alpha);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename L>
+ object_links<L>
+ object_links_center_aligned(const object_image(L)& objects,
+ const object_links<L>& links,
+ float max_alpha)
+ {
+ trace::entering("scribo::filter::object_links_center_aligned");
+
+ mln_precondition(objects.is_valid());
+ mln_precondition(links.is_valid());
+
+ object_links<L>
+ output = object_links_non_aligned_simple(objects, links,
+ 2, max_alpha);
+
+ trace::exiting("scribo::filter::object_links_center_aligned");
+ return output;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::filter
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_FILTER_OBJECT_LINKS_CENTER_ALIGNED_HH
diff --git a/scribo/filter/object_links_top_aligned.hh b/scribo/filter/object_links_top_aligned.hh
new file mode 100644
index 0000000..47e26c8
--- /dev/null
+++ b/scribo/filter/object_links_top_aligned.hh
@@ -0,0 +1,121 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_FILTER_OBJECT_LINKS_TOP_ALIGNED_HH
+# define SCRIBO_FILTER_OBJECT_LINKS_TOP_ALIGNED_HH
+
+/// \file
+///
+/// Invalidate links between two objects if their top are not
+/// aligned.
+
+
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/object_links.hh>
+# include <scribo/core/object_image.hh>
+
+# include <scribo/filter/object_links_non_aligned_simple.hh>
+
+namespace scribo
+{
+
+ namespace filter
+ {
+
+ using namespace mln;
+
+ /*! \brief Invalidate links between two objects if their top are not
+ aligned.
+
+ \param[in] objects An object image.
+ \param[in] links Object links information.
+ \param[in] max_alpha Maximum angle value (degrees).
+
+ \verbatim
+
+
+ ~
+ ~ ^
+ ~ |
+ ~ |
+ ~------ | Alpha
+ ~ | | |
+ ~ | | |
+ ~ | | v
+ ------ ~ ~ ~ | ~ ~| ~
+ | | | |
+ | x------------x |
+ | | | |
+ ------ | |
+ object1 | |
+ ------
+ object2
+
+ \endverbatim
+
+ The angle between the two tops must be lower than \p max_alpha.
+ */
+ template <typename L>
+ object_links<L>
+ object_links_top_aligned(const object_image(L)& objects,
+ const object_links<L>& links,
+ float max_alpha);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename L>
+ object_links<L>
+ object_links_top_aligned(const object_image(L)& objects,
+ const object_links<L>& links,
+ float max_alpha)
+ {
+ trace::entering("scribo::filter::object_links_top_aligned");
+
+ mln_precondition(objects.is_valid());
+ mln_precondition(links.is_valid());
+
+ object_links<L>
+ output = object_links_non_aligned_simple(objects, links,
+ 0,
+ max_alpha);
+
+ trace::exiting("scribo::filter::object_links_top_aligned");
+ return output;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::filter
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_FILTER_OBJECT_LINKS_TOP_ALIGNED_HH
diff --git a/scribo/filter/objects_h_thick.hh b/scribo/filter/objects_h_thick.hh
new file mode 100644
index 0000000..9709346
--- /dev/null
+++ b/scribo/filter/objects_h_thick.hh
@@ -0,0 +1,196 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_FILTER_OBJECTS_H_THICK_HH
+# define SCRIBO_FILTER_OBJECTS_H_THICK_HH
+
+/// \file
+///
+/// Remove too horizontaly thick objects.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+# include <mln/util/array.hh>
+
+# include <scribo/core/object_image.hh>
+# include <scribo/primitive/extract/objects.hh>
+# include <scribo/filter/internal/compute.hh>
+
+
+namespace scribo
+{
+
+ namespace filter
+ {
+
+ using namespace mln;
+
+ /// Remove objects horizontaly thicker or equal to \p max_thickness.
+ ///
+ /// \param[in] input_ A binary image.
+ /// \param[in] nbh_ A neighborhood used in labeling algorithms.
+ /// \param[in] label_type The label type used for labeling.
+ /// \param[in] max_thickness The maximum thickness value.
+ ///
+ /// \result A binary image without thick objects.
+ //
+ template <typename I, typename N, typename V>
+ inline
+ mln_concrete(I)
+ objects_h_thick(const Image<I>& input_,
+ const Neighborhood<N>& nbh_,
+ const V& label_type,
+ unsigned max_thickness);
+
+
+ /// Remove objects horizontaly thicker or equal to \p max_thickness.
+ ///
+ /// \param[in] objects An object image.
+ /// \param[in] max_thickness The maximum thickness value.
+ ///
+ /// \result An object image without too thick objects.
+ //
+ template <typename L>
+ inline
+ object_image(L)
+ objects_h_thick(const object_image(L)& objects,
+ unsigned max_thickness);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace internal
+ {
+
+ /// Filter Functor. Return false for all objects which are too
+ /// large.
+ template <typename L>
+ struct h_thick_object_filter
+ : Function_v2b< h_thick_object_filter<L> >
+ {
+
+ /// Constructor
+ ///
+ /// \param[in] objects An object image.
+ /// \param[in] max_thickness the maximum thickness allowed.
+ //
+ h_thick_object_filter(const object_image(L)& objects,
+ unsigned max_thickness)
+ : objects_(objects), max_thickness_(max_thickness)
+ {
+ }
+
+ /// Constructor
+ ///
+ /// \param[in] max_thickness the maximum thickness allowed.
+ //
+ h_thick_object_filter(unsigned max_thickness)
+ : max_thickness_(max_thickness)
+ {
+ }
+
+ /// Set the underlying object image.
+ //
+ void update_objects(const object_image(L)& objects)
+ {
+ objects_ = objects;
+ }
+
+ /// Return false if the objects is thicker than
+ /// \p max_thickness_.
+ ///
+ /// \param[in] l An image value.
+ bool operator()(const mln_value(L)& l) const
+ {
+ if (l == literal::zero)
+ return true;
+ return objects_.bbox(l).nrows() < max_thickness_;
+ }
+
+
+ /// An object image.
+ object_image(L) objects_;
+
+ /// The maximum thickness.
+ unsigned max_thickness_;
+ };
+
+
+ } // end of namespace scribo::filter::internal
+
+
+ template <typename I, typename N, typename V>
+ inline
+ mln_concrete(I)
+ objects_thick(const Image<I>& input_,
+ const Neighborhood<N>& nbh_,
+ const V& label_type,
+ unsigned max_thickness)
+ {
+ trace::entering("scribo::filter::objects_h_thick");
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_precondition(input.is_valid());
+ mln_precondition(nbh.is_valid());
+
+ internal::h_thick_object_filter<V> functor(max_thickness);
+ mln_concrete(I)
+ output = internal::compute(input, nbh, label_type, functor);
+
+ trace::exiting("scribo::filter::objects_h_thick");
+ return output;
+ }
+
+
+ template <typename L>
+ inline
+ object_image(L)
+ objects_h_thick(const object_image(L)& objects,
+ unsigned max_thickness)
+ {
+ trace::entering("scribo::filter::objects_h_thick");
+
+ mln_precondition(objects.is_valid());
+
+ internal::h_thick_object_filter<L> functor(objects, max_thickness);
+ object_image(L) output = internal::compute(objects, functor);
+
+ trace::exiting("scribo::filter::objects_h_thick");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::filter
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_FILTER_OBJECTS_H_THICK_HH
diff --git a/scribo/filter/objects_v_thick.hh b/scribo/filter/objects_v_thick.hh
new file mode 100644
index 0000000..730e144
--- /dev/null
+++ b/scribo/filter/objects_v_thick.hh
@@ -0,0 +1,196 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_FILTER_OBJECTS_V_THICK_HH
+# define SCRIBO_FILTER_OBJECTS_V_THICK_HH
+
+/// \file
+///
+/// Remove too verticaly thick objects.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+# include <mln/util/array.hh>
+
+# include <scribo/core/object_image.hh>
+# include <scribo/primitive/extract/objects.hh>
+# include <scribo/filter/internal/compute.hh>
+
+
+namespace scribo
+{
+
+ namespace filter
+ {
+
+ using namespace mln;
+
+ /// Remove objects verticaly thicker or equal to \p max_thickness.
+ ///
+ /// \param[in] input_ A binary image.
+ /// \param[in] nbh_ A neighborhood used in labeling algorithms.
+ /// \param[in] label_type The label type used for labeling.
+ /// \param[in] max_thickness The maximum thickness value.
+ ///
+ /// \result A binary image without thick objects.
+ //
+ template <typename I, typename N, typename V>
+ inline
+ mln_concrete(I)
+ objects_v_thick(const Image<I>& input_,
+ const Neighborhood<N>& nbh_,
+ const V& label_type,
+ unsigned max_thickness);
+
+
+ /// Remove objects verticaly thicker or equal to \p max_thickness.
+ ///
+ /// \param[in] objects An object image.
+ /// \param[in] max_thickness The maximum thickness value.
+ ///
+ /// \result An object image without too thick objects.
+ //
+ template <typename L>
+ inline
+ object_image(L)
+ objects_v_thick(const object_image(L)& objects,
+ unsigned max_thickness);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace internal
+ {
+
+ /// Filter Functor. Return false for all objects which are too
+ /// large.
+ template <typename L>
+ struct v_thick_object_filter
+ : Function_v2b< v_thick_object_filter<L> >
+ {
+
+ /// Constructor
+ ///
+ /// \param[in] objects An object image.
+ /// \param[in] max_thickness the maximum thickness allowed.
+ //
+ v_thick_object_filter(const object_image(L)& objects,
+ unsigned max_thickness)
+ : objects_(objects), max_thickness_(max_thickness)
+ {
+ }
+
+ /// Constructor
+ ///
+ /// \param[in] max_thickness the maximum thickness allowed.
+ //
+ v_thick_object_filter(unsigned max_thickness)
+ : max_thickness_(max_thickness)
+ {
+ }
+
+ /// Set the underlying object image.
+ //
+ void update_objects(const object_image(L)& objects)
+ {
+ objects_ = objects;
+ }
+
+ /// Return false if the objects is thicker than
+ /// \p max_thickness_.
+ ///
+ /// \param[in] l An image value.
+ bool operator()(const mln_value(L)& l) const
+ {
+ if (l == literal::zero)
+ return true;
+ return objects_.bbox(l).nrows() < max_thickness_;
+ }
+
+
+ /// An object image.
+ object_image(L) objects_;
+
+ /// The maximum thickness.
+ unsigned max_thickness_;
+ };
+
+
+ } // end of namespace scribo::filter::internal
+
+
+ template <typename I, typename N, typename V>
+ inline
+ mln_concrete(I)
+ objects_thick(const Image<I>& input_,
+ const Neighborhood<N>& nbh_,
+ const V& label_type,
+ unsigned max_thickness)
+ {
+ trace::entering("scribo::filter::objects_v_thick");
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_precondition(input.is_valid());
+ mln_precondition(nbh.is_valid());
+
+ internal::v_thick_object_filter<V> functor(max_thickness);
+ mln_concrete(I)
+ output = internal::compute(input, nbh, label_type, functor);
+
+ trace::exiting("scribo::filter::objects_v_thick");
+ return output;
+ }
+
+
+ template <typename L>
+ inline
+ object_image(L)
+ objects_v_thick(const object_image(L)& objects,
+ unsigned max_thickness)
+ {
+ trace::entering("scribo::filter::objects_v_thick");
+
+ mln_precondition(objects.is_valid());
+
+ internal::v_thick_object_filter<L> functor(objects, max_thickness);
+ object_image(L) output = internal::compute(objects, functor);
+
+ trace::exiting("scribo::filter::objects_v_thick");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::filter
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_FILTER_OBJECTS_V_THICK_HH
--
1.5.6.5
* core/concept/link_functor.hh: New concept.
* core/internal/link_functor_base.hh: New Base class for link
functor.
* primitive/link/compute.hh,
* primitive/link/compute_several.hh,
* primitive/link/internal/anchors_3.hh,
* primitive/link/internal/find_link.hh,
* primitive/link/internal/find_several_links.hh,
* primitive/link/with_several_right_closest_links.hh,
* primitive/link/with_several_right_links_overlap.hh,
* primitive/link/with_single_left_link_dmax_ratio.hh,
* primitive/link/with_single_right_link_bottom.hh,
* primitive/link/with_single_right_link_dmax_ratio.hh,
* primitive/link/with_single_right_link_top.hh: New routines.
* primitive/link/internal/link_center_dmax_base.hh,
* primitive/link/internal/link_center_dmax_ratio_base.hh,
* primitive/link/internal/link_functor_base.hh,
* primitive/link/internal/link_ms_dmax_base.hh,
* primitive/link/internal/link_ms_dmax_ratio_base.hh: New functors.
* primitive/link/with_several_left_links.hh,
* primitive/link/with_several_right_links.hh: Use the new routines.
* primitive/link/with_single_left_link.hh,
* primitive/link/with_single_right_link.hh: Revamp and use the new
routines.
---
scribo/ChangeLog | 86 ++++
scribo/core/concept/link_functor.hh | 53 ++
scribo/core/internal/link_functor_base.hh | 119 +++++
scribo/primitive/link/compute.hh | 115 +++++
scribo/primitive/link/compute_several.hh | 117 +++++
scribo/primitive/link/internal/anchors_3.hh | 146 ++++++
scribo/primitive/link/internal/find_link.hh | 116 +++++
.../primitive/link/internal/find_several_links.hh | 124 +++++
.../link/internal/link_center_dmax_base.hh | 179 +++++++
.../link/internal/link_center_dmax_ratio_base.hh | 175 +++++++
.../primitive/link/internal/link_functor_base.hh | 518 ++++++++++++++++++++
.../primitive/link/internal/link_ms_dmax_base.hh | 165 +++++++
.../link/internal/link_ms_dmax_ratio_base.hh | 168 +++++++
scribo/primitive/link/with_several_left_links.hh | 32 +-
.../link/with_several_right_closest_links.hh | 215 ++++++++
scribo/primitive/link/with_several_right_links.hh | 27 +-
...inks.hh => with_several_right_links_overlap.hh} | 134 +++---
scribo/primitive/link/with_single_left_link.hh | 94 +++-
.../link/with_single_left_link_dmax_ratio.hh | 167 +++++++
scribo/primitive/link/with_single_right_link.hh | 98 +++--
...ht_link.hh => with_single_right_link_bottom.hh} | 115 +++--
.../link/with_single_right_link_dmax_ratio.hh | 167 +++++++
...right_link.hh => with_single_right_link_top.hh} | 113 +++--
23 files changed, 3030 insertions(+), 213 deletions(-)
create mode 100644 scribo/core/concept/link_functor.hh
create mode 100644 scribo/core/internal/link_functor_base.hh
create mode 100644 scribo/primitive/link/compute.hh
create mode 100644 scribo/primitive/link/compute_several.hh
create mode 100644 scribo/primitive/link/internal/anchors_3.hh
create mode 100644 scribo/primitive/link/internal/find_link.hh
create mode 100644 scribo/primitive/link/internal/find_several_links.hh
create mode 100644 scribo/primitive/link/internal/link_center_dmax_base.hh
create mode 100644 scribo/primitive/link/internal/link_center_dmax_ratio_base.hh
create mode 100644 scribo/primitive/link/internal/link_functor_base.hh
create mode 100644 scribo/primitive/link/internal/link_ms_dmax_base.hh
create mode 100644 scribo/primitive/link/internal/link_ms_dmax_ratio_base.hh
create mode 100644 scribo/primitive/link/with_several_right_closest_links.hh
copy scribo/primitive/link/{with_several_right_links.hh => with_several_right_links_overlap.hh} (53%)
create mode 100644 scribo/primitive/link/with_single_left_link_dmax_ratio.hh
copy scribo/primitive/link/{with_single_right_link.hh => with_single_right_link_bottom.hh} (55%)
create mode 100644 scribo/primitive/link/with_single_right_link_dmax_ratio.hh
copy scribo/primitive/link/{with_single_right_link.hh => with_single_right_link_top.hh} (57%)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 5e2d69e..bb22ef9 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,3 +1,89 @@
+2009-11-03 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Revamp code related to object linking.
+
+ * core/concept/link_functor.hh: New concept.
+
+ * core/internal/link_functor_base.hh: New Base class for link
+ functor.
+
+ * primitive/link/compute.hh,
+ * primitive/link/compute_several.hh,
+ * primitive/link/internal/anchors_3.hh,
+ * primitive/link/internal/find_link.hh,
+ * primitive/link/internal/find_several_links.hh,
+ * primitive/link/with_several_right_closest_links.hh,
+ * primitive/link/with_several_right_links_overlap.hh,
+ * primitive/link/with_single_left_link_dmax_ratio.hh,
+ * primitive/link/with_single_right_link_bottom.hh,
+ * primitive/link/with_single_right_link_dmax_ratio.hh,
+ * primitive/link/with_single_right_link_top.hh: New routines.
+
+ * primitive/link/internal/link_center_dmax_base.hh,
+ * primitive/link/internal/link_center_dmax_ratio_base.hh,
+ * primitive/link/internal/link_functor_base.hh,
+ * primitive/link/internal/link_ms_dmax_base.hh,
+ * primitive/link/internal/link_ms_dmax_ratio_base.hh: New functors.
+
+ * primitive/link/with_several_left_links.hh,
+ * primitive/link/with_several_right_links.hh: Use the new routines.
+
+ * primitive/link/with_single_left_link.hh,
+ * primitive/link/with_single_right_link.hh: Revamp and use the new
+ routines.
+
+2009-11-03 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Small fixes in Scribo.
+
+ * debug/decision_image.hh: Fix precondition.
+
+ * filter/object_links_bbox_h_ratio.hh,
+ * filter/objects_thick.hh,
+ * primitive/internal/have_link_valid.hh,
+ * primitive/internal/is_link_valid.hh: Fix doc.
+
+ * filter/object_links_bbox_ratio.hh: Fix doc and invert ratio.
+
+ * filter/object_links_bottom_aligned.hh: Fix doc and use a float
+ angle value.
+
+ * filter/object_links_non_aligned.hh: Use absolute values.
+
+ * filter/object_links_non_aligned_simple.hh: Add special cases.
+
+ * filter/object_links_non_h_aligned.hh: Fix call to an underlying
+ routine.
+
+ * filter/objects_small.hh,
+ * filter/objects_thin.hh,
+ * filter/objects_v_thin.hh,
+ * primitive/extract/lines_discontinued.hh,
+ * primitive/extract/lines_h_single.hh,
+ * primitive/extract/lines_h_thick_and_single.hh,
+ * primitive/extract/lines_thick.hh,
+ * primitive/extract/lines_v_discontinued.hh,
+ * primitive/extract/lines_v_single.hh,
+ * primitive/extract/lines_v_thick_and_single.hh,
+ * primitive/internal/is_invalid_link.hh,
+ * src/multi_scale/find_lines.cc,
+ * src/primitive/group/group_from_rag.cc,
+ * src/table/rebuild_opening.cc,
+ * src/table/rebuild_rank.cc,
+ * text/clean.hh: Avoid warnings.
+
+ * primitive/internal/find_left_link.hh,
+ * primitive/internal/find_right_link.hh,
+ * primitive/internal/update_link_array.hh: Make the routine return
+ a value.
+
+ * src/binarization/sauvola.cc,
+ * src/binarization/sauvola_pgm.cc: Fix call to Sauvola's algorithm.
+
+ * src/primitive/group/group_from_graph.cc,
+ * src/primitive/group/group_from_several_graph.cc: Change
+ arguments values while calling with_several_graphes.
+
2009-10-22 Guillaume Lazzara <z(a)lrde.epita.fr>
Add new debug routines.
diff --git a/scribo/core/concept/link_functor.hh b/scribo/core/concept/link_functor.hh
new file mode 100644
index 0000000..f51843a
--- /dev/null
+++ b/scribo/core/concept/link_functor.hh
@@ -0,0 +1,53 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_CORE_INTERNAL_LINK_FUNCTOR_HH
+# define SCRIBO_CORE_INTERNAL_LINK_FUNCTOR_HH
+
+/// \file
+///
+/// Link functor concept.
+
+# include <mln/core/concept/object.hh>
+
+# define scribo_support(T) typename T::support
+# define scribo_support_(T) T::support
+
+namespace scribo
+{
+
+ /// \brief Link functor concept.
+ template <typename E>
+ class Link_Functor : public mln::Object<E>
+ {
+
+ // typedef L support
+
+ };
+
+
+} // end of namespace scribo
+
+#endif // SCRIBO_CORE_INTERNAL_LINK_FUNCTOR_HH
diff --git a/scribo/core/internal/link_functor_base.hh b/scribo/core/internal/link_functor_base.hh
new file mode 100644
index 0000000..addba06
--- /dev/null
+++ b/scribo/core/internal/link_functor_base.hh
@@ -0,0 +1,119 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_FUNCTOR_BASE_HH
+# define SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_FUNCTOR_BASE_HH
+
+/// \file
+///
+/// Base class for link functors.
+
+# include <mln/core/concept/image.hh>
+
+# include <mln/math/abs.hh>
+
+# include <mln/util/array.hh>
+# include <mln/util/couple.hh>
+
+# include <scribo/core/concept/link_functor.hh>
+
+# include <scribo/core/object_image.hh>
+# include <scribo/core/object_links.hh>
+
+# include <scribo/primitive/internal/init_link_array.hh>
+
+
+namespace scribo
+{
+
+ namespace internal
+ {
+
+ /// \brief Base class for link functors.
+ template <typename L, typename E>
+ class link_functor_base : public Link_Functor<E>
+ {
+ public:
+
+ typedef L support;
+
+ link_functor_base(const object_image(L)& objects);
+
+ const object_links<L>& links() const;
+
+ unsigned link(unsigned object) const;
+ const object_image(L)& objects() const;
+
+ protected:
+ object_links<L> links_;
+ const object_image(L) objects_;
+ };
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename L, typename E>
+ inline
+ link_functor_base<L,E>::link_functor_base(const object_image(L)& objects)
+ : links_(objects, static_cast<unsigned>(objects.nlabels()) + 1),
+ objects_(objects)
+ {
+ primitive::internal::init_link_array(links_);
+ }
+
+ template <typename L, typename E>
+ inline
+ const object_links<L>&
+ link_functor_base<L,E>::links() const
+ {
+ return links_;
+ }
+
+ template <typename L, typename E>
+ inline
+ unsigned
+ link_functor_base<L,E>::link(unsigned object) const
+ {
+ return links_[object];
+ }
+
+ template <typename L, typename E>
+ inline
+ const object_image(L)&
+ link_functor_base<L,E>::objects() const
+ {
+ return objects_;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::internal
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_FUNCTOR_BASE_HH
diff --git a/scribo/primitive/link/compute.hh b/scribo/primitive/link/compute.hh
new file mode 100644
index 0000000..bf94787
--- /dev/null
+++ b/scribo/primitive/link/compute.hh
@@ -0,0 +1,115 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_PRIMITIVE_LINK_COMPUTE_HH
+# define SCRIBO_PRIMITIVE_LINK_COMPUTE_HH
+
+/// \file
+///
+/// Compute links between objects according a given functor.
+
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/object_links.hh>
+# include <scribo/core/concept/link_functor.hh>
+# include <scribo/primitive/link/internal/find_link.hh>
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace link
+ {
+
+ /*! \brief Compute links between objects according a given functor.
+
+ \param[in,out] functor Linking policy.
+
+ \return Object links.
+
+
+ Functors must implement the following interface :
+
+
+ bool is_potential_link(unsigned current_object,
+ const P& start_point, const P& p) const
+
+ bool valid_link(unsigned current_object,
+ const P& start_point, const P& p)
+
+ bool verify_link_criterion(unsigned current_object,
+ const P& start_point, const P& p)
+
+ void validate_link(unsigned current_object,
+ const P& start_point, const P& p)
+
+ void invalidate_link(unsigned current_object,
+ const P& start_point, const P& p)
+
+ void compute_next_site(P& p)
+
+ const mln_site(L)& start_point(unsigned current_object)
+
+ void start_processing_object(unsigned current_object)
+
+ */
+ template <typename F>
+ object_links<scribo_support(F)>
+ compute(Link_Functor<F>& functor);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename F>
+ object_links<scribo_support(F)>
+ compute(Link_Functor<F>& functor_)
+ {
+ trace::entering("scribo::primitive::link::compute");
+
+ F& functor = exact(functor_);
+
+ for_all_ncomponents(current_object, functor.objects().nlabels())
+ {
+ functor.start_processing_object(current_object); //<-- start_processing_object
+ primitive::internal::find_link(functor, current_object);
+ }
+
+ trace::exiting("scribo::primitive::link::compute");
+ return functor.links();
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::primitive::link
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_LINK_COMPUTE_HH
diff --git a/scribo/primitive/link/compute_several.hh b/scribo/primitive/link/compute_several.hh
new file mode 100644
index 0000000..0597d99
--- /dev/null
+++ b/scribo/primitive/link/compute_several.hh
@@ -0,0 +1,117 @@
+
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_PRIMITIVE_LINK_COMPUTE_SEVERAL_HH
+# define SCRIBO_PRIMITIVE_LINK_COMPUTE_SEVERAL_HH
+
+/// \file
+///
+/// Compute_Several links between objects according a given functor.
+
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/object_links.hh>
+# include <scribo/core/concept/link_functor.hh>
+# include <scribo/primitive/link/internal/find_several_links.hh>
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace link
+ {
+
+ /*! \brief Compute_Several links between objects according a given functor.
+
+ \param[in,out] functor Linking policy.
+
+ \return Object links.
+
+
+ Functors must implement the following interface :
+
+
+ bool verify_link_criterion_(unsigned current_object,
+ const P& start_point, const P& p) const;
+
+ void start_processing_object_(unsigned current_object);
+
+
+ mln_site(L) start_point_(unsigned current_object, unsigned anchor);
+
+
+ void validate_link_(unsigned current_object, const P& start_point,
+ const P& p, unsigned anchor);
+ void invalidate_link_(unsigned current_object, const P& start_point,
+ const P& p, unsigned anchor);
+
+ void initialize_link_(unsigned current_object);
+ void finalize_link_(unsigned current_object);
+
+ bool is_potential_link(unsigned current_object,
+ const P& start_point, const P& p) const
+
+ void compute_next_site(P& p)
+
+ */
+ template <typename F>
+ object_links<scribo_support(F)>
+ compute_several(Link_Functor<F>& functor);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename F>
+ object_links<scribo_support(F)>
+ compute_several(Link_Functor<F>& functor_)
+ {
+ trace::entering("scribo::primitive::link::compute_several");
+
+ F& functor = exact(functor_);
+
+ for_all_ncomponents(current_object, functor.objects().nlabels())
+ {
+ functor.start_processing_object(current_object); //<-- start_processing_object
+ primitive::internal::find_several_links(functor, current_object);
+ }
+
+ trace::exiting("scribo::primitive::link::compute_several");
+ return functor.links();
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::primitive::link
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_LINK_COMPUTE_SEVERAL_HH
diff --git a/scribo/primitive/link/internal/anchors_3.hh b/scribo/primitive/link/internal/anchors_3.hh
new file mode 100644
index 0000000..85fa80b
--- /dev/null
+++ b/scribo/primitive/link/internal/anchors_3.hh
@@ -0,0 +1,146 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_PRIMITIVE_LINK_INTERNAL_ANCHORS_3_HH
+# define SCRIBO_PRIMITIVE_LINK_INTERNAL_ANCHORS_3_HH
+
+/// \file
+///
+/// Routine providing 3 anchors for neighbor seeking.
+
+# include <mln/math/min.hh>
+
+# include <scribo/core/object_image.hh>
+
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace link
+ {
+
+ namespace internal
+ {
+
+ /*! \brief Return the proper anchor used to find a neighbor.
+
+ This routine provides up to 3 different anchors.
+
+ \param[in] objects An object image.
+ \param[in] mass_centers Object mass centers.
+ \param[in] current_object An object id.
+ \param[in] anchor The expected anchor.
+
+ Anchor can take one of the following values:
+ - 0, top anchor.
+ - 1, center anchor. It is the mass center.
+ - 2, bottom anchor.
+
+
+ Top and bottom anchors are respectively computed from the
+ bbox pmin and the bbox pmax, P.
+
+ Then the output anchor coordinates are computed as follows:
+
+ out.col = bbox.center.col
+
+ if object height, h, is lower than 30.
+ out.row = P.row + min(2, (h + 1) / 2 - 1)
+ else
+ out.row = P.row - min(10, h /10)
+
+ */
+ template <typename L, typename P>
+ mln_site(L)
+ anchors_3(const object_image(L)& objects,
+ const mln::util::array<P>& mass_centers,
+ unsigned current_object, unsigned anchor);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename L, typename P>
+ mln_site(L)
+ anchors_3(const object_image(L)& objects,
+ const mln::util::array<P>& mass_centers,
+ unsigned current_object, unsigned anchor)
+ {
+ unsigned h = objects.bbox(current_object).pmax().row()
+ - objects.bbox(current_object).pmin().row();
+
+ mln_site(L) sp = objects.bbox(current_object).center();
+ def::coord r;
+
+ switch (anchor)
+ {
+ // Top
+ case 0:
+ if (h < 30)
+ r = objects.bbox(current_object).pmin().row()
+ + math::min(2u, (h + 1) / 2 - 1);
+ else
+ r = objects.bbox(current_object).pmin().row()
+ - math::min(10u, h /10);
+ break;
+
+
+ // Center
+ case 1:
+ return mass_centers(current_object);
+
+
+ // Bottom
+ case 2:
+ if (h < 30)
+ r = objects.bbox(current_object).pmax().row()
+ + math::min(2u, (h + 1) / 2 - 1);
+ else
+ r = objects.bbox(current_object).pmax().row()
+ - math::min(10u, h /10);
+ break;
+
+ default:
+ trace::warning("Non handled anchor");
+ mln_assertion(anchor > 2);
+ }
+
+ sp.row() = r;
+ return sp;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::primitive::link::internal
+
+ } // end of namespace scribo::primitive::link
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_LINK_INTERNAL_ANCHORS_3_HH
diff --git a/scribo/primitive/link/internal/find_link.hh b/scribo/primitive/link/internal/find_link.hh
new file mode 100644
index 0000000..8a2544e
--- /dev/null
+++ b/scribo/primitive/link/internal/find_link.hh
@@ -0,0 +1,116 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_PRIMITIVE_INTERNAL_FIND_LINK_HH
+# define SCRIBO_PRIMITIVE_INTERNAL_FIND_LINK_HH
+
+/// \file
+///
+/// Find the neighbor of a line of text if exists.
+
+# include <mln/core/concept/image.hh>
+
+# include <mln/math/abs.hh>
+
+# include <mln/util/array.hh>
+# include <mln/util/couple.hh>
+
+# include <scribo/core/concept/link_functor.hh>
+# include <scribo/core/object_image.hh>
+# include <scribo/core/object_links.hh>
+# include <scribo/primitive/internal/update_link_array.hh>
+# include <scribo/primitive/internal/init_link_array.hh>
+# include <scribo/primitive/internal/is_invalid_link.hh>
+
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace internal
+ {
+
+ /*! \brief Find the neighbor of a line of text if exists.
+
+ \param[in,out] functor Functor used to compute the
+ links. Stores the results.
+ \param[in] current_object Current object id.
+
+ \return A couple. The first argument tells whether a valid
+ link has been found, the second one is link anchor if exists.
+ */
+ template <typename F>
+ mln::util::couple<bool, mln_site(scribo_support_(F))>
+ find_link(Link_Functor<F>& functor, unsigned current_object);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename F>
+ mln::util::couple<bool, mln_site(scribo_support_(F))>
+ find_link(Link_Functor<F>& functor_, unsigned current_object)
+ {
+ F& functor = exact(functor_);
+
+ functor.initialize_link(current_object); // <-- initialize_link
+
+ mln_site(scribo_support_(F))
+ start_point = functor.start_point(current_object),
+ p = start_point;
+
+ mln_postcondition(p == start_point);
+
+ // is_potential_link
+ // verify_link_criterion
+ while (functor.objects().domain().has(p)
+ && ! functor.is_potential_link(current_object,
+ start_point, p)
+ && functor.verify_link_criterion(current_object, start_point, p))
+ functor.compute_next_site(p); // <-- compute_next_site
+
+ if (functor.valid_link(current_object, start_point, p)) // <-- valid_link
+ functor.validate_link(current_object, start_point, p); // <-- validate_link
+ else
+ functor.invalidate_link(current_object, start_point, p); // <-- invalidate_link
+
+ functor.finalize_link(current_object); // <-- finalize_link
+
+ bool b = (functor.link(current_object) != current_object);
+ return mln::make::couple(b, p);
+ }
+
+# endif // MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::primitive::internal
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_PRIMITIVE_INTERNAL_FIND_LINK_HH
diff --git a/scribo/primitive/link/internal/find_several_links.hh b/scribo/primitive/link/internal/find_several_links.hh
new file mode 100644
index 0000000..a07ee70
--- /dev/null
+++ b/scribo/primitive/link/internal/find_several_links.hh
@@ -0,0 +1,124 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_PRIMITIVE_INTERNAL_FIND_SEVERAL_LINKS_HH
+# define SCRIBO_PRIMITIVE_INTERNAL_FIND_SEVERAL_LINKS_HH
+
+/// \file
+///
+/// Find the neighbor of a line of text if exists.
+
+# include <mln/core/concept/image.hh>
+
+# include <mln/math/abs.hh>
+
+# include <mln/util/array.hh>
+# include <mln/util/couple.hh>
+
+# include <scribo/core/concept/link_functor.hh>
+# include <scribo/core/object_image.hh>
+# include <scribo/core/object_links.hh>
+# include <scribo/primitive/internal/update_link_array.hh>
+# include <scribo/primitive/internal/init_link_array.hh>
+# include <scribo/primitive/internal/is_invalid_link.hh>
+
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace internal
+ {
+
+ /*! Find the neighbor of a line of text if exists.
+
+ \param[in,out] functor Functor used to compute the
+ links. Stores the results.
+ \param current_object Current object id.
+
+ \return A couple. The first argument tells whether a valid
+ link has been found, the second one is link anchor if exists.
+ */
+ template <typename F>
+ mln::util::couple<bool, mln_site(scribo_support_(F))>
+ find_several_links(Link_Functor<F>& functor,
+ unsigned current_object);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename F>
+ mln::util::couple<bool, mln_site(scribo_support_(F))>
+ find_several_links(Link_Functor<F>& functor_,
+ unsigned current_object)
+ {
+ F& functor = exact(functor_);
+
+ typedef mln_site(scribo_support_(F)) P;
+ typedef mln::util::couple<unsigned, P> link_t;
+
+ P lp = functor.initialize_link(current_object); // <-- initialize_link
+
+ for (unsigned anchor = 0; anchor < functor.nanchors(); ++anchor) // <-- nanchor
+ {
+ mln_site(scribo_support_(F))
+ start_point = functor.start_point(current_object, anchor), // <-- start_point
+ p = start_point;
+
+ mln_postcondition(p == start_point);
+
+ while (functor.objects().domain().has(p)
+ && ! functor.is_potential_link(current_object,
+ start_point, p) // <-- is_potential_link
+ && functor.verify_link_criterion(current_object,
+ start_point, p)) // <-- verify_link_criterion
+ functor.compute_next_site(p); // <-- compute_next_site
+
+ if (functor.valid_link(current_object, start_point, p)) // <-- valid_link
+ functor.validate_link(current_object, start_point, p, anchor); // <-- validate_link
+ else
+ functor.invalidate_link(current_object, start_point, p, anchor); // <-- invalidate_link
+
+ }
+
+ P lp = functor.finalize_link(current_object);
+
+ bool b = (functor.link(current_object) != current_object); // <-- link
+ return mln::make::couple(b, lp);
+ }
+
+# endif // MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::primitive::internal
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_PRIMITIVE_INTERNAL_FIND_SEVERAL_LINKS_HH
diff --git a/scribo/primitive/link/internal/link_center_dmax_base.hh b/scribo/primitive/link/internal/link_center_dmax_base.hh
new file mode 100644
index 0000000..1a7a48d
--- /dev/null
+++ b/scribo/primitive/link/internal/link_center_dmax_base.hh
@@ -0,0 +1,179 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_CENTER_DMAX_HH_
+# define SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_CENTER_DMAX_HH_
+
+/// \file
+///
+/// Base class for link functors using center sites and a given max
+/// distance.
+
+
+# include <mln/accu/center.hh>
+# include <mln/labeling/compute.hh>
+# include <mln/math/abs.hh>
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/object_image.hh>
+# include <scribo/core/object_links.hh>
+
+# include <scribo/primitive/link/internal/find_link.hh>
+# include <scribo/primitive/link/internal/link_functor_base.hh>
+
+# include <scribo/primitive/link/compute.hh>
+
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace link
+ {
+
+ namespace internal
+ {
+
+ /// \brief Base class for link functors using mass centers and
+ /// a given max distance.
+ //
+ template <typename L, typename E>
+ class link_center_dmax_base
+ : public link_functor_base<L, E>
+ {
+ typedef link_functor_base<L,E> super_;
+
+ public:
+
+ typedef mln_site(L) P;
+
+
+ /*!
+
+ center_type can have the following values:
+ 0 - top bounding box center
+ 1 - bounding box center
+ 2 - bottom bounding box center
+
+ */
+ link_center_dmax_base(const object_image(L)& objects,
+ unsigned neighb_max_distance,
+ unsigned center_type);
+
+
+ bool verify_link_criterion_(unsigned current_object,
+ const P& start_point, const P& p) const;
+
+ mln_site(L) start_point_(unsigned current_object,
+ unsigned anchor);
+
+ void start_processing_object_(unsigned current_object);
+
+ private:
+ float dmax_;
+ float neighb_max_distance_;
+ unsigned center_type_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename L, typename E>
+ inline
+ link_center_dmax_base<L, E>::link_center_dmax_base(
+ const object_image(L)& objects,
+ unsigned neighb_max_distance,
+ unsigned center_type)
+
+ : super_(objects),
+ dmax_(0),
+ neighb_max_distance_(neighb_max_distance),
+ center_type_(center_type)
+ {
+ }
+
+
+ template <typename L, typename E>
+ inline
+ bool
+ link_center_dmax_base<L, E>::verify_link_criterion_(
+ unsigned current_object,
+ const P& start_point,
+ const P& p) const
+ {
+ (void) current_object;
+
+ float dist = math::abs(p.col() - start_point.col());
+ return dist <= dmax_; // Not too far
+ }
+
+
+ template <typename L, typename E>
+ inline
+ mln_site(L)
+ link_center_dmax_base<L, E>::start_point_(unsigned current_object,
+ unsigned anchor)
+ {
+ (void) anchor;
+ mln_site(L) sp = this->objects_.bbox(current_object).center();
+ if (center_type_ == 0)
+ sp.row() = this->objects_.bbox(current_object).pmin().row();
+ else if (center_type_ == 2)
+ sp.row() = this->objects_.bbox(current_object).pmax().row();
+
+ return sp;
+ }
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_center_dmax_base<L, E>::start_processing_object_(
+ unsigned current_object)
+ {
+ float
+ midcol = (this->objects_.bbox(current_object).pmax().col()
+ - this->objects_.bbox(current_object).pmin().col()) / 2;
+ dmax_ = midcol + neighb_max_distance_;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::primitive::link::internal
+
+ } // end of namespace scribo::primitive::link
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+
+#endif // SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_CENTER_DMAX_HH_
diff --git a/scribo/primitive/link/internal/link_center_dmax_ratio_base.hh b/scribo/primitive/link/internal/link_center_dmax_ratio_base.hh
new file mode 100644
index 0000000..0740ec9
--- /dev/null
+++ b/scribo/primitive/link/internal/link_center_dmax_ratio_base.hh
@@ -0,0 +1,175 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_CENTER_DMAX_RATIO_BASE_HH_
+# define SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_CENTER_DMAX_RATIO_BASE_HH_
+
+/// \file
+///
+/// \brief Base class for link functors using bounding box center and
+/// a proportional max distance.
+
+
+# include <mln/accu/center.hh>
+# include <mln/labeling/compute.hh>
+# include <mln/math/abs.hh>
+# include <mln/math/max.hh>
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/object_image.hh>
+# include <scribo/core/object_links.hh>
+
+# include <scribo/primitive/link/internal/find_link.hh>
+# include <scribo/primitive/link/internal/link_functor_base.hh>
+
+# include <scribo/primitive/link/compute.hh>
+
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace link
+ {
+
+ namespace internal
+ {
+
+ /// \brief Base class for link functors using bounding box
+ /// center and a proportional max distance.
+ //
+ template <typename L, typename E>
+ class link_center_dmax_ratio_base
+ : public link_functor_base<L, E>
+ {
+ typedef link_functor_base<L,E> super_;
+ typedef mln_result(accu::center<mln_psite(L)>) ms_t;
+
+ public:
+
+ typedef mln_site(L) P;
+
+
+ link_center_dmax_ratio_base(const object_image(L)& objects,
+ float dmax_ratio,
+ unsigned center_type_);
+
+
+
+ bool verify_link_criterion_(unsigned current_object,
+ const P& start_point, const P& p) const;
+
+ mln_site(L) start_point_(unsigned current_object,
+ unsigned anchor);
+
+ void start_processing_object_(unsigned current_object);
+
+ private:
+ float dmax_ratio_;
+ float dmax_;
+ unsigned center_type_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename L, typename E>
+ inline
+ link_center_dmax_ratio_base<L, E>::link_center_dmax_ratio_base(
+ const object_image(L)& objects,
+ float dmax_ratio,
+ unsigned center_type)
+
+ : super_(objects),
+ dmax_ratio_(dmax_ratio),
+ dmax_(0),
+ center_type_(center_type)
+ {
+ }
+
+ template <typename L, typename E>
+ inline
+ bool
+ link_center_dmax_ratio_base<L, E>::verify_link_criterion_(
+ unsigned current_object,
+ const P& start_point,
+ const P& p) const
+ {
+ (void) current_object;
+
+ float dist = math::abs(p.col() - start_point.col());
+ return dist <= dmax_; // Not too far
+ }
+
+
+ template <typename L, typename E>
+ inline
+ mln_site(L)
+ link_center_dmax_ratio_base<L, E>::start_point_(unsigned current_object,
+ unsigned anchor)
+ {
+ (void) anchor;
+ mln_site(L) sp = this->objects_.bbox(current_object).center();
+ if (center_type_ == 0)
+ sp.row() = this->objects_.bbox(current_object).pmin().row();
+ else if (center_type_ == 2)
+ sp.row() = this->objects_.bbox(current_object).pmax().row();
+
+ return sp;
+ }
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_center_dmax_ratio_base<L, E>::start_processing_object_(
+ unsigned current_object)
+ {
+ float
+ w = (this->objects_.bbox(current_object).pmax().col()
+ - this->objects_.bbox(current_object).pmin().col()),
+ h = (this->objects_.bbox(current_object).pmax().row()
+ - this->objects_.bbox(current_object).pmin().row());
+ dmax_ = (w / 2.0f) + (dmax_ratio_ * math::max(w, h));
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::primitive::link::internal
+
+ } // end of namespace scribo::primitive::link
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+
+#endif // SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_CENTER_DMAX_RATIO_BASE_HH_
diff --git a/scribo/primitive/link/internal/link_functor_base.hh b/scribo/primitive/link/internal/link_functor_base.hh
new file mode 100644
index 0000000..e35f52d
--- /dev/null
+++ b/scribo/primitive/link/internal/link_functor_base.hh
@@ -0,0 +1,518 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_CORE_INTERNAL_LINK_FUNCTOR_BASE_HH
+# define SCRIBO_CORE_INTERNAL_LINK_FUNCTOR_BASE_HH
+
+/// \file
+///
+/// Base class for link functors.
+
+# include <mln/core/concept/image.hh>
+
+# include <mln/math/abs.hh>
+
+# include <mln/util/array.hh>
+# include <mln/util/couple.hh>
+
+# include <scribo/core/object_image.hh>
+# include <scribo/core/object_links.hh>
+# include <scribo/core/concept/link_functor.hh>
+# include <scribo/primitive/internal/update_link_array.hh>
+# include <scribo/primitive/internal/init_link_array.hh>
+# include <scribo/primitive/internal/is_invalid_link.hh>
+
+
+# define scribo_support(T) typename T::support
+# define scribo_support_(T) T::support
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace link
+ {
+
+ namespace internal
+ {
+
+ /// \brief Base class for link functors.
+ template <typename L, typename E>
+ class link_functor_base : public Link_Functor<E>
+ {
+ public:
+
+ typedef L support;
+ typedef mln_site(L) P;
+
+ link_functor_base(const object_image(L)& objects, unsigned nanchors);
+
+ /// \overload
+ /// \p nanchors is set to 1.
+ link_functor_base(const object_image(L)& objects);
+
+
+ unsigned nanchors() const;
+
+ const object_links<L>& links() const;
+
+ unsigned link(unsigned object) const;
+ const object_image(L)& objects() const;
+
+
+ void initialize_link(unsigned current_object);
+ mln_site(L) finalize_link(unsigned current_object);
+
+
+ bool verify_link_criterion(unsigned current_object,
+ const P& start_point, const P& p) const;
+
+ bool is_potential_link(unsigned current_object,
+ const P& start_point, const P& p) const;
+
+ bool valid_link(unsigned current_object,
+ const P& start_point, const P& p);
+
+
+
+ //FIXME: there's a probleme here. We may not want to provide
+ //both interfaces (with multiple and single anchors)for
+ //every functors...
+
+ void validate_link(unsigned current_object,
+ const P& start_point,
+ const P& p,
+ unsigned anchor);
+
+ /// \overload
+ /// \p anchor is set to 0.
+ void validate_link(unsigned current_object,
+ const P& start_point, const P& p);
+
+ void invalidate_link(unsigned current_object,
+ const P& start_point, const P& p,
+ unsigned anchor);
+
+ /// \overload
+ /// \p anchor is set to 0
+ void invalidate_link(unsigned current_object,
+ const P& start_point, const P& p);
+
+
+
+
+
+
+ void compute_next_site(P& p);
+
+
+ mln_site(L) start_point(unsigned current_object, unsigned anchor);
+
+ /// \overload
+ /// \p anchor is set to 0.
+ mln_site(L) start_point(unsigned current_object);
+
+
+ void start_processing_object(unsigned current_object);
+
+
+
+
+ // Default implementation for possibly not overridden
+ // methods.
+
+ void initialize_link_(unsigned current_object);
+ mln_site(L) finalize_link_(unsigned current_object);
+
+ bool is_potential_link_(unsigned current_object,
+ const P& start_point, const P& p) const;
+
+ bool verify_link_criterion_(unsigned current_object,
+ const P& start_point, const P& p) const;
+
+ bool valid_link_(unsigned current_object,
+ const P& start_point, const P& p);
+
+ void validate_link_(unsigned current_object,
+ const P& start_point, const P& p,
+ unsigned anchor);
+
+ void invalidate_link_(unsigned current_object,
+ const P& start_point, const P& p,
+ unsigned anchor);
+
+ void compute_next_site_(P& p);
+
+ void start_processing_object_(unsigned current_object);
+
+
+ protected:
+ object_links<L> links_;
+ const object_image(L) objects_;
+ unsigned nanchors_;
+ };
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename L, typename E>
+ inline
+ link_functor_base<L,E>::link_functor_base(
+ const object_image(L)& objects,
+ unsigned nanchors)
+ : links_(objects, static_cast<unsigned>(objects.nlabels()) + 1),
+ objects_(objects),
+ nanchors_(nanchors)
+ {
+ primitive::internal::init_link_array(links_);
+ }
+
+
+ template <typename L, typename E>
+ inline
+ link_functor_base<L,E>::link_functor_base(
+ const object_image(L)& objects)
+ : links_(objects, static_cast<unsigned>(objects.nlabels()) + 1),
+ objects_(objects),
+ nanchors_(1)
+ {
+ primitive::internal::init_link_array(links_);
+ }
+
+
+ template <typename L, typename E>
+ inline
+ unsigned
+ link_functor_base<L,E>::nanchors() const
+ {
+ return nanchors_;
+ }
+
+
+ template <typename L, typename E>
+ inline
+ const object_links<L>&
+ link_functor_base<L,E>::links() const
+ {
+ return links_;
+ }
+
+ template <typename L, typename E>
+ inline
+ unsigned
+ link_functor_base<L,E>::link(unsigned object) const
+ {
+ return links_[object];
+ }
+
+ template <typename L, typename E>
+ inline
+ const object_image(L)&
+ link_functor_base<L,E>::objects() const
+ {
+ return objects_;
+ }
+
+
+
+
+ template <typename L, typename E>
+ inline
+ bool
+ link_functor_base<L,E>::is_potential_link(unsigned current_object,
+ const P& start_point,
+ const P& p) const
+ {
+ (void) start_point;
+ return this->objects_(p) != literal::zero // Not the background
+ && this->objects_(p) != current_object // Not the current component
+ && this->links_[this->objects_(p)] != current_object; // No loops
+ }
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_functor_base<L,E>::initialize_link(unsigned current_object)
+ {
+ exact(this)->initialize_link_(current_object);
+ }
+
+ template <typename L, typename E>
+ inline
+ mln_site(L)
+ link_functor_base<L,E>::finalize_link(unsigned current_object)
+ {
+ return exact(this)->finalize_link_(current_object);
+ }
+
+
+
+ template <typename L, typename E>
+ inline
+ bool
+ link_functor_base<L,E>::verify_link_criterion(unsigned current_object,
+ const P& start_point,
+ const P& p) const
+ {
+ return exact(this)->verify_link_criterion_(current_object,
+ start_point, p);
+ }
+
+ template <typename L, typename E>
+ inline
+ bool
+ link_functor_base<L,E>::valid_link(unsigned current_object,
+ const P& start_point,
+ const P& p)
+ {
+ return this->objects_.domain().has(p)
+ && exact(this)->valid_link_(current_object, start_point, p);
+ }
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_functor_base<L,E>::validate_link(unsigned current_object,
+ const P& start_point,
+ const P& p,
+ unsigned anchor)
+ {
+ exact(this)->validate_link_(current_object, start_point, p, anchor);
+ }
+
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_functor_base<L,E>::validate_link(unsigned current_object,
+ const P& start_point,
+ const P& p)
+ {
+ validate_link(current_object, start_point, p, 0);
+ }
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_functor_base<L,E>::invalidate_link(unsigned current_object,
+ const P& start_point,
+ const P& p,
+ unsigned anchor)
+ {
+ exact(this)->invalidate_link_(current_object, start_point, p, anchor);
+ }
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_functor_base<L,E>::invalidate_link(unsigned current_object,
+ const P& start_point,
+ const P& p)
+ {
+ invalidate_link(current_object, start_point, p, 0);
+ }
+
+
+
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_functor_base<L,E>::compute_next_site(P& p)
+ {
+ // No-op
+ exact(this)->compute_next_site_(p);
+ }
+
+
+ template <typename L, typename E>
+ inline
+ mln_site(L)
+ link_functor_base<L,E>::start_point(unsigned current_object,
+ unsigned anchor)
+ {
+ return exact(this)->start_point_(current_object, anchor);
+ }
+
+
+ template <typename L, typename E>
+ inline
+ mln_site(L)
+ link_functor_base<L,E>::start_point(unsigned current_object)
+ {
+ return start_point(current_object, 0);
+ }
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_functor_base<L,E>::start_processing_object(
+ unsigned current_object)
+ {
+ (void) current_object;
+ // No-Op
+ exact(this)->start_processing_object_(current_object);
+ }
+
+
+
+
+ // Default implementation for delegated methods.
+
+ template <typename L, typename E>
+ inline
+ void
+ link_functor_base<L,E>::initialize_link_(unsigned current_object)
+ {
+ (void) current_object;
+ // No-Op
+ }
+
+
+ template <typename L, typename E>
+ inline
+ mln_site(L)
+ link_functor_base<L,E>::finalize_link_(unsigned current_object)
+ {
+ (void) current_object;
+ // No-Op
+ return P();
+ }
+
+
+ template <typename L, typename E>
+ inline
+ bool
+ link_functor_base<L,E>::is_potential_link_(unsigned current_object,
+ const P& start_point,
+ const P& p) const
+ {
+ (void) current_object;
+ (void) start_point;
+ (void) p;
+ // No-Op
+ return true;
+ }
+
+ template <typename L, typename E>
+ inline
+ bool
+ link_functor_base<L,E>::verify_link_criterion_(unsigned current_object,
+ const P& start_point,
+ const P& p) const
+ {
+ (void) current_object;
+ (void) start_point;
+ (void) p;
+ // No-Op
+ return true;
+ }
+
+
+ template <typename L, typename E>
+ inline
+ bool
+ link_functor_base<L,E>::valid_link_(unsigned current_object,
+ const P& start_point,
+ const P& p)
+ {
+ return is_potential_link(current_object, start_point, p)
+ && verify_link_criterion(current_object, start_point, p);
+ }
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_functor_base<L,E>::validate_link_(unsigned current_object,
+ const P& start_point,
+ const P& p,
+ unsigned anchor)
+ {
+ (void) start_point;
+ (void) anchor;
+ this->links_[current_object] = this->objects_(p);
+ }
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_functor_base<L,E>::invalidate_link_(unsigned current_object,
+ const P& start_point,
+ const P& p,
+ unsigned anchor)
+ {
+ (void) current_object;
+ (void) start_point;
+ (void) p;
+ (void) anchor;
+ // No-op
+ }
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_functor_base<L,E>::compute_next_site_(P& p)
+ {
+ (void) p;
+ // No-Op
+ }
+
+ template <typename L, typename E>
+ inline
+ void
+ link_functor_base<L,E>::start_processing_object_(
+ unsigned current_object)
+ {
+ // No-Op
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::primitive::link::internal
+
+ } // end of namespace scribo::primitive::link
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_CORE_INTERNAL_LINK_FUNCTOR_BASE_HH
diff --git a/scribo/primitive/link/internal/link_ms_dmax_base.hh b/scribo/primitive/link/internal/link_ms_dmax_base.hh
new file mode 100644
index 0000000..80a9a13
--- /dev/null
+++ b/scribo/primitive/link/internal/link_ms_dmax_base.hh
@@ -0,0 +1,165 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_MS_DMAX_HH_
+# define SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_MS_DMAX_HH_
+
+/// \file
+///
+/// Base class for link functors using mass centers and a given max
+/// distance.
+
+
+# include <mln/accu/center.hh>
+# include <mln/labeling/compute.hh>
+# include <mln/math/abs.hh>
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/object_image.hh>
+# include <scribo/core/object_links.hh>
+
+# include <scribo/primitive/link/internal/find_link.hh>
+# include <scribo/primitive/link/internal/link_functor_base.hh>
+
+# include <scribo/primitive/link/compute.hh>
+
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace link
+ {
+
+ namespace internal
+ {
+
+ /// \brief Base class for link functors using mass centers and
+ /// a given max distance.
+ //
+ template <typename L, typename E>
+ class link_ms_dmax_base
+ : public link_functor_base<L, E>
+ {
+ typedef link_functor_base<L,E> super_;
+ typedef mln_result(accu::center<mln_psite(L)>) ms_t;
+
+ public:
+
+ typedef mln_site(L) P;
+
+
+ link_ms_dmax_base(const object_image(L)& objects,
+ unsigned neighb_max_distance);
+
+
+
+ bool verify_link_criterion_(unsigned current_object,
+ const P& start_point, const P& p) const;
+
+ mln_site(L) start_point_(unsigned current_object,
+ unsigned anchor);
+
+ void start_processing_object_(unsigned current_object);
+
+ private:
+ mln::util::array<ms_t> mass_centers_;
+ float dmax_;
+ float neighb_max_distance_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename L, typename E>
+ inline
+ link_ms_dmax_base<L, E>::link_ms_dmax_base(
+ const object_image(L)& objects,
+ unsigned neighb_max_distance)
+
+ : super_(objects),
+ dmax_(0),
+ neighb_max_distance_(neighb_max_distance)
+ {
+
+ mass_centers_ = labeling::compute(accu::meta::center(),
+ objects, objects.nlabels());
+ }
+
+ template <typename L, typename E>
+ inline
+ bool
+ link_ms_dmax_base<L, E>::verify_link_criterion_(unsigned current_object,
+ const P& start_point,
+ const P& p) const
+ {
+ (void) current_object;
+
+ float dist = math::abs(p.col() - start_point.col());
+ return dist <= dmax_; // Not too far
+ }
+
+
+ template <typename L, typename E>
+ inline
+ mln_site(L)
+ link_ms_dmax_base<L, E>::start_point_(unsigned current_object,
+ unsigned anchor)
+ {
+ (void) anchor;
+ return mass_centers_(current_object);
+ }
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_ms_dmax_base<L, E>::start_processing_object_(
+ unsigned current_object)
+ {
+ float
+ midcol = (this->objects_.bbox(current_object).pmax().col()
+ - this->objects_.bbox(current_object).pmin().col()) / 2;
+ dmax_ = midcol + neighb_max_distance_;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::primitive::link::internal
+
+ } // end of namespace scribo::primitive::link
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+
+#endif // SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_MS_DMAX_HH_
diff --git a/scribo/primitive/link/internal/link_ms_dmax_ratio_base.hh b/scribo/primitive/link/internal/link_ms_dmax_ratio_base.hh
new file mode 100644
index 0000000..414e0b2
--- /dev/null
+++ b/scribo/primitive/link/internal/link_ms_dmax_ratio_base.hh
@@ -0,0 +1,168 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_MS_DMAX_RATIO_BASE_HH_
+# define SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_MS_DMAX_RATIO_BASE_HH_
+
+/// \file
+///
+/// \brief Base class for link functors using mass centers and a
+/// proportional max distance.
+
+
+# include <mln/accu/center.hh>
+# include <mln/labeling/compute.hh>
+# include <mln/math/abs.hh>
+# include <mln/math/max.hh>
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/object_image.hh>
+# include <scribo/core/object_links.hh>
+
+# include <scribo/primitive/link/internal/find_link.hh>
+# include <scribo/primitive/link/internal/link_functor_base.hh>
+
+# include <scribo/primitive/link/compute.hh>
+
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace link
+ {
+
+ namespace internal
+ {
+
+ /// \brief Base class for link functors using mass centers and
+ /// a proportional max distance.
+ //
+ template <typename L, typename E>
+ class link_ms_dmax_ratio_base
+ : public link_functor_base<L, E>
+ {
+ typedef link_functor_base<L,E> super_;
+ typedef mln_result(accu::center<mln_psite(L)>) ms_t;
+
+ public:
+
+ typedef mln_site(L) P;
+
+
+ link_ms_dmax_ratio_base(const object_image(L)& objects,
+ float dmax_ratio);
+
+
+
+ bool verify_link_criterion_(unsigned current_object,
+ const P& start_point, const P& p) const;
+
+ mln_site(L) start_point_(unsigned current_object,
+ unsigned anchor);
+
+ void start_processing_object_(unsigned current_object);
+
+ private:
+ mln::util::array<ms_t> mass_centers_;
+ float dmax_ratio_;
+ float dmax_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename L, typename E>
+ inline
+ link_ms_dmax_ratio_base<L, E>::link_ms_dmax_ratio_base(
+ const object_image(L)& objects,
+ float dmax_ratio)
+
+ : super_(objects),
+ dmax_ratio_(dmax_ratio),
+ dmax_(0)
+ {
+ mass_centers_ = labeling::compute(accu::meta::center(),
+ objects, objects.nlabels());
+ }
+
+ template <typename L, typename E>
+ inline
+ bool
+ link_ms_dmax_ratio_base<L, E>::verify_link_criterion_(
+ unsigned current_object,
+ const P& start_point,
+ const P& p) const
+ {
+ (void) current_object;
+
+ float dist = math::abs(p.col() - start_point.col());
+ return dist <= dmax_; // Not too far
+ }
+
+
+ template <typename L, typename E>
+ inline
+ mln_site(L)
+ link_ms_dmax_ratio_base<L, E>::start_point_(unsigned current_object,
+ unsigned anchor)
+ {
+ (void) anchor;
+ return mass_centers_(current_object);
+ }
+
+
+ template <typename L, typename E>
+ inline
+ void
+ link_ms_dmax_ratio_base<L, E>::start_processing_object_(
+ unsigned current_object)
+ {
+ float
+ w = (this->objects_.bbox(current_object).pmax().col()
+ - this->objects_.bbox(current_object).pmin().col()),
+ h = (this->objects_.bbox(current_object).pmax().row()
+ - this->objects_.bbox(current_object).pmin().row());
+ dmax_ = (w / 2.0f) + (dmax_ratio_ * math::max(w, h));
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::primitive::link::internal
+
+ } // end of namespace scribo::primitive::link
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+
+#endif // SCRIBO_PRIMITIVE_LINK_INTERNAL_LINK_MS_DMAX_RATIO_BASE_HH_
diff --git a/scribo/primitive/link/with_several_left_links.hh b/scribo/primitive/link/with_several_left_links.hh
index c2c6c83..2de4cee 100644
--- a/scribo/primitive/link/with_several_left_links.hh
+++ b/scribo/primitive/link/with_several_left_links.hh
@@ -29,8 +29,6 @@
/// \file
///
/// Link text bounding boxes with their left neighbor.
-///
-/// Merge code with primitive::link::with_single_right_link.hh
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
@@ -64,6 +62,14 @@ namespace scribo
with_several_left_links(const object_image(L)& objects,
unsigned neighb_max_distance);
+
+ /// \overload
+ template <typename L>
+ inline
+ object_links<L>
+ with_several_left_links(const object_image(L)& objects);
+
+
# ifndef MLN_INCLUDE_ONLY
template <typename L>
@@ -82,9 +88,9 @@ namespace scribo
link_3(objects, objects.nlabels().next()),
final_link(objects, objects.nlabels().next());
- internal::init_link_array(link_1);
- internal::init_link_array(link_2);
- internal::init_link_array(link_3);
+ primitive::internal::init_link_array(link_1);
+ primitive::internal::init_link_array(link_2);
+ primitive::internal::init_link_array(link_3);
mln::util::array<mln_result(accu::center<mln_psite(L)>)>
mass_centers = labeling::compute(accu::meta::center(),
@@ -110,15 +116,16 @@ namespace scribo
/// Left link from the top anchor.
mln_site(L) a1 = c;
a1.row() = objects.bbox(i).pmin().row() + (c.row() - objects.bbox(i).pmin().row()) / 4;
- internal::find_left_link(objects, link_1, i, dmax, a1);
+ primitive::internal::find_left_link(objects, link_1, i, dmax, a1);
/// Left link from the central site
- internal::find_left_link(objects, link_2, i, dmax, mass_centers[i]);
+ primitive::internal::find_left_link(objects, link_2, i,
+ dmax, mass_centers[i]);
/// Left link from the bottom anchor.
mln_site(L) a2 = c;
a2.row() = objects.bbox(i).pmax().row() - (c.row() - objects.bbox(i).pmin().row()) / 4;
- internal::find_left_link(objects, link_3, i, dmax, a2);
+ primitive::internal::find_left_link(objects, link_3, i, dmax, a2);
}
for_all_ncomponents(i, objects.nlabels())
@@ -139,6 +146,15 @@ namespace scribo
return final_link;
}
+
+ template <typename L>
+ inline
+ object_links<L>
+ with_several_left_links(const object_image(L)& objects)
+ {
+ return with_several_left_links(objects);
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace scribo::primitive::link
diff --git a/scribo/primitive/link/with_several_right_closest_links.hh b/scribo/primitive/link/with_several_right_closest_links.hh
new file mode 100644
index 0000000..629d0b0
--- /dev/null
+++ b/scribo/primitive/link/with_several_right_closest_links.hh
@@ -0,0 +1,215 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_PRIMITIVE_LINK_WITH_SEVERAL_RIGHT_CLOSEST_LINKS_HH
+# define SCRIBO_PRIMITIVE_LINK_WITH_SEVERAL_RIGHT_CLOSEST_LINKS_HH
+
+/// \file
+///
+/// Link text bounding boxes with their right neighbor.
+///
+/// Merge code with primitive::link::with_single_right_link.hh
+///
+/// \todo Factor code with primitive::link::with_several_right_links
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+# include <mln/extension/fill.hh>
+
+# include <mln/util/array.hh>
+
+# include <scribo/core/object_links.hh>
+# include <scribo/core/object_image.hh>
+# include <scribo/core/macros.hh>
+# include <scribo/primitive/internal/init_link_array.hh>
+# include <scribo/primitive/internal/find_right_link.hh>
+# include <scribo/util/text.hh>
+
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace link
+ {
+
+ using namespace mln;
+
+
+ /// Map each character bounding box to its right bounding box
+ /// neighbor if possible. If there are several right neighbor,
+ /// the closest one is chosen.
+ ///
+ /// \return an mln::util::array. Map a bounding box to its right
+ /// neighbor.
+ //
+ template <typename L>
+ inline
+ object_links<L>
+ with_several_right_closest_links(const object_image(L)& objects,
+ unsigned neighb_max_distance);
+
+ /// \overload
+ template <typename L>
+ inline
+ object_links<L>
+ with_several_right_closest_links(const object_image(L)& objects);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+
+ namespace internal
+ {
+
+ template <unsigned n, typename P>
+ inline
+ unsigned
+ find_closest(const algebra::vec<n,
+ mln::util::couple<bool, P> >& res,
+ const P& c)
+ {
+ algebra::vec<3, unsigned> dist;
+ for (unsigned j = 0; j < 3; ++j)
+ dist[j] = math::abs(res[j].second().col() - c.col());
+
+ unsigned idx = 0;
+ for (unsigned i = 1; i < n; ++i)
+ if (dist[i] < dist[idx])
+ idx = i;
+
+ return idx;
+ }
+
+ } // end of namespace scribo::primitive::link::internal
+
+
+
+ template <typename L>
+ inline
+ object_links<L>
+ with_several_right_closest_links(const object_image(L)& objects,
+ unsigned neighb_max_distance)
+ {
+ trace::entering("scribo::primitive::link::with_several_right_closest_links");
+
+ mln_precondition(objects.is_valid());
+
+ extension::fill(objects, 0);
+
+ object_links<L>
+ link_1(objects, objects.nlabels().next()),
+ link_2(objects, objects.nlabels().next()),
+ link_3(objects, objects.nlabels().next()),
+ final_link(objects, objects.nlabels().next());
+
+ primitive::internal::init_link_array(link_1);
+ primitive::internal::init_link_array(link_2);
+ primitive::internal::init_link_array(link_3);
+
+ mln::util::array<mln_result(accu::center<mln_psite(L)>)>
+ mass_centers = labeling::compute(accu::meta::center(),
+ objects, objects.nlabels());
+
+
+ for_all_ncomponents(i, objects.nlabels())
+ {
+ // -------
+ // | a1------->
+ // | |
+ // | |
+ // | mc------->
+ // | |
+ // | |
+ // | a2------->
+ // -------
+
+ float midcol = (objects.bbox(i).pmax().col()
+ - objects.bbox(i).pmin().col()) / 2;
+ float dmax = midcol + neighb_max_distance;
+
+ mln_site(L) c = objects.bbox(i).center();
+
+ algebra::vec<3, mln::util::couple<bool, mln_site(L)> > res;
+
+ // Right link from the top anchor.
+ mln_site(L) a1 = c;
+ a1.row() = objects.bbox(i).pmin().row()
+ + (c.row() - objects.bbox(i).pmin().row()) / 4;
+ res[0] = primitive::internal::find_right_link(objects, link_1,
+ i, dmax, a1);
+
+ // Right link from the central site
+ res[1] = primitive::internal::find_right_link(objects, link_2,
+ i, dmax,
+ mass_centers[i]);
+
+ // Right link from the bottom anchor.
+ mln_site(L) a2 = c;
+ a2.row() = objects.bbox(i).pmax().row()
+ - (c.row() - objects.bbox(i).pmin().row()) / 4;
+ res[2] = primitive::internal::find_right_link(objects, link_3,
+ i, dmax, a2);
+
+ // Try to find the closest object.
+
+ unsigned closest_idx = internal::find_closest(res, c);
+
+
+ // If there exists a link and the site is not outside the
+ // image domain.
+ if (res[closest_idx].first())
+ final_link[i] = objects(res[closest_idx].second());
+ else
+ final_link[i] = i;
+ }
+
+ trace::exiting("scribo::primitive::link::with_several_right_closest_links");
+ return final_link;
+ }
+
+
+ template <typename L>
+ inline
+ object_links<L>
+ with_several_right_closest_links(const object_image(L)& objects)
+ {
+ return with_several_right_closest_links(objects, mln_max(unsigned));
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::primitive::link
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_LINK_WITH_SEVERAL_RIGHT_CLOSEST_LINKS_HH
diff --git a/scribo/primitive/link/with_several_right_links.hh b/scribo/primitive/link/with_several_right_links.hh
index 17e00cc..b302dcb 100644
--- a/scribo/primitive/link/with_several_right_links.hh
+++ b/scribo/primitive/link/with_several_right_links.hh
@@ -67,6 +67,13 @@ namespace scribo
with_several_right_links(const object_image(L)& objects,
unsigned neighb_max_distance);
+ /// \overload
+ template <typename L>
+ inline
+ object_links<L>
+ with_several_right_links(const object_image(L)& objects);
+
+
# ifndef MLN_INCLUDE_ONLY
template <typename L>
@@ -105,9 +112,9 @@ namespace scribo
// | |
// | X------->
// -------
- unsigned midcol = (objects.bbox(i).pmax().col()
- - objects.bbox(i).pmin().col()) / 2;
- int dmax = midcol + neighb_max_distance;
+ float midcol = (objects.bbox(i).pmax().col()
+ - objects.bbox(i).pmin().col()) / 2;
+ float dmax = midcol + neighb_max_distance;
mln_site(L) c = objects.bbox(i).center();
@@ -123,10 +130,8 @@ namespace scribo
mln_site(L) a2 = c;
a2.row() = objects.bbox(i).pmax().row() - (c.row() - objects.bbox(i).pmin().row()) / 4;
internal::find_right_link(objects, link_3, i, dmax, a2);
- }
- for_all_ncomponents(i, objects.nlabels())
- {
+
if (link_2[i] != i)
final_link[i] = link_2[i];
else if (link_1[i] == link_3[i])
@@ -143,6 +148,16 @@ namespace scribo
return final_link;
}
+
+ template <typename L>
+ inline
+ object_links<L>
+ with_several_right_links(const object_image(L)& objects)
+ {
+ return with_several_right_links(objects, mln_max(unsigned));
+ }
+
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace scribo::primitive::link
diff --git a/scribo/primitive/link/with_several_right_links.hh b/scribo/primitive/link/with_several_right_links_overlap.hh
similarity index 53%
copy from scribo/primitive/link/with_several_right_links.hh
copy to scribo/primitive/link/with_several_right_links_overlap.hh
index 17e00cc..27d9d49 100644
--- a/scribo/primitive/link/with_several_right_links.hh
+++ b/scribo/primitive/link/with_several_right_links_overlap.hh
@@ -23,14 +23,12 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef SCRIBO_PRIMITIVE_LINK_WITH_SEVERAL_RIGHT_LINKS_HH
-# define SCRIBO_PRIMITIVE_LINK_WITH_SEVERAL_RIGHT_LINKS_HH
+#ifndef SCRIBO_PRIMITIVE_LINK_WITH_SEVERAL_RIGHT_LINKS_OVERLAP_HH
+# define SCRIBO_PRIMITIVE_LINK_WITH_SEVERAL_RIGHT_LINKS_OVERLAP_HH
/// \file
///
/// Link text bounding boxes with their right neighbor.
-///
-/// Merge code with primitive::link::with_single_right_link.hh
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
@@ -64,85 +62,85 @@ namespace scribo
template <typename L>
inline
object_links<L>
- with_several_right_links(const object_image(L)& objects,
- unsigned neighb_max_distance);
+ with_several_right_links_overlap(const object_image(L)& objects,
+ unsigned neighb_max_distance);
+
+ /// \overload
+ template <typename L>
+ inline
+ object_links<L>
+ with_several_right_links_overlap(const object_image(L)& objects);
+
# ifndef MLN_INCLUDE_ONLY
+ namespace internal
+ {
+
+ template <typename L>
+ class several_right_overlap_functor
+ : public link_several_dmax_base<L, several_right_overlap_functor<L> >
+ {
+ typedef
+ link_several_dmax_base<L, several_right_overlap_functor<L> >
+ super_;
+
+ public:
+ typedef mln_site(L) P;
+
+ several_right_overlap_functor(const object_image(L)& objects,
+ unsigned dmax)
+ : super_(objects, dmax, 3)
+ {
+ }
+
+ template <typename L, typename E>
+ inline
+ mln_site(L)
+ start_point_(unsigned current_object, unsigned anchor)
+ {
+ return anchors_3(this->objects_, this->mass_centers_,
+ current_object, anchor);
+ }
+
+
+ void compute_next_site_(P& p)
+ {
+ ++p.col();
+ }
+
+ } // end of namespace scribo::primitive::link::internal
+
+
template <typename L>
inline
object_links<L>
- with_several_right_links(const object_image(L)& objects,
- unsigned neighb_max_distance)
+ with_several_right_links_overlap(const object_image(L)& objects,
+ unsigned neighb_max_distance)
{
- trace::entering("scribo::primitive::link::with_several_right_links");
+ trace::entering("scribo::primitive::link::with_several_right_links_overlap");
mln_precondition(objects.is_valid());
- object_links<L>
- link_1(objects, objects.nlabels().next()),
- link_2(objects, objects.nlabels().next()),
- link_3(objects, objects.nlabels().next()),
- final_link(objects, objects.nlabels().next());
+ several_right_overlap_functor<L> functor(objects, neighb_max_distance);
- internal::init_link_array(link_1);
- internal::init_link_array(link_2);
- internal::init_link_array(link_3);
+ for_all_ncomponents(current_object, objects.nlabels())
+ internal::find_several_links(functor, current_object);
- mln::util::array<mln_result(accu::center<mln_psite(L)>)>
- mass_centers = labeling::compute(accu::meta::center(),
- objects, objects.nlabels());
+ trace::exiting("scribo::primitive::link::with_several_right_links_overlap");
+ return functor.links();
+ }
- for_all_ncomponents(i, objects.nlabels())
- {
- // -------
- // | X------->
- // | |
- // | |
- // | X------->
- // | |
- // | |
- // | X------->
- // -------
- unsigned midcol = (objects.bbox(i).pmax().col()
- - objects.bbox(i).pmin().col()) / 2;
- int dmax = midcol + neighb_max_distance;
-
- mln_site(L) c = objects.bbox(i).center();
-
- /// Right link from the top anchor.
- mln_site(L) a1 = c;
- a1.row() = objects.bbox(i).pmin().row() + (c.row() - objects.bbox(i).pmin().row()) / 4;
- internal::find_right_link(objects, link_1, i, dmax, a1);
-
- /// Right link from the central site
- internal::find_right_link(objects, link_2, i, dmax, mass_centers[i]);
-
- /// Right link from the bottom anchor.
- mln_site(L) a2 = c;
- a2.row() = objects.bbox(i).pmax().row() - (c.row() - objects.bbox(i).pmin().row()) / 4;
- internal::find_right_link(objects, link_3, i, dmax, a2);
- }
-
- for_all_ncomponents(i, objects.nlabels())
- {
- if (link_2[i] != i)
- final_link[i] = link_2[i];
- else if (link_1[i] == link_3[i])
- final_link[i] = link_1[i];
- else if (link_1[i] != i && link_3[i] == i)
- final_link[i] = link_1[i];
- else if (link_3[i] != i && link_1[i] == i)
- final_link[i] = link_3[i];
- else
- final_link[i] = i;
- }
-
- trace::exiting("scribo::primitive::link::with_several_right_links");
- return final_link;
+ template <typename L>
+ inline
+ object_links<L>
+ with_several_right_links_overlap(const object_image(L)& objects)
+ {
+ return with_several_right_links_overlap(objects, mln_max(unsigned));
}
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace scribo::primitive::link
@@ -151,4 +149,4 @@ namespace scribo
} // end of namespace scribo
-#endif // ! SCRIBO_PRIMITIVE_LINK_WITH_SEVERAL_RIGHT_LINKS_HH
+#endif // ! SCRIBO_PRIMITIVE_LINK_WITH_SEVERAL_RIGHT_LINKS_OVERLAP_HH
diff --git a/scribo/primitive/link/with_single_left_link.hh b/scribo/primitive/link/with_single_left_link.hh
index 03cb870..bef9ea3 100644
--- a/scribo/primitive/link/with_single_left_link.hh
+++ b/scribo/primitive/link/with_single_left_link.hh
@@ -29,8 +29,6 @@
/// \file
///
/// Link text objects with their left neighbor.
-///
-/// Merge code with primitive::link::with_single_right_link.hh
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
@@ -43,14 +41,16 @@
# include <mln/util/array.hh>
-# include <scribo/core/object_links.hh>
+
# include <scribo/core/macros.hh>
# include <scribo/core/object_image.hh>
-# include <scribo/primitive/internal/init_link_array.hh>
-# include <scribo/primitive/internal/find_left_link.hh>
+# include <scribo/core/object_links.hh>
+
+# include <scribo/primitive/link/internal/find_link.hh>
+# include <scribo/primitive/link/internal/link_ms_dmax_base.hh>
+
+# include <scribo/primitive/link/compute.hh>
-//FIXME: not generic.
-# include <mln/core/alias/dpoint2d.hh>
namespace scribo
{
@@ -61,14 +61,12 @@ namespace scribo
namespace link
{
- /// Map each text object to its left bounding box neighbor
- /// if possible.
- /// Iterate to the right but link boxes to the left.
+ /// \brief Link objects with their left neighbor if exists.
///
/// \param[in] objects An object image.
/// \param[in] The maximum distance allowed to seach a neighbor object.
///
- /// \return an mln::util::array. Map a bounding box to its left neighbor.
+ /// \return Object links data.
//
template <typename L>
inline
@@ -76,40 +74,80 @@ namespace scribo
with_single_left_link(const object_image(L)& objects,
unsigned neighb_max_distance);
+
+ /// \overload
+ /// Max distance is set to mln_max(unsigned).
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_left_link(const object_image(L)& objects);
+
+
# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ // Functor
+
+ template <typename L>
+ class single_left_functor
+ : public internal::link_ms_dmax_base<L, single_left_functor<L> >
+ {
+ typedef
+ internal::link_ms_dmax_base<L, single_left_functor<L> > super_;
+
+ public:
+ typedef mln_site(L) P;
+
+ single_left_functor(const object_image(L)& objects, unsigned dmax)
+ : super_(objects, dmax)
+ {
+ }
+
+ void compute_next_site_(P& p)
+ {
+ --p.col();
+ }
+
+ };
+
+ } // end of namespace scribo::primitive::link::internal
+
+
+
+ // Facades
+
template <typename L>
inline
object_links<L>
with_single_left_link(const object_image(L)& objects,
- unsigned neighb_max_distance)
+ unsigned neighb_max_distance)
{
trace::entering("scribo::primitive::link::with_single_left_link");
mln_precondition(objects.is_valid());
- object_links<L> left_link(objects, objects.nlabels().next());
- internal::init_link_array(left_link);
+ internal::single_left_functor<L>
+ functor(objects, neighb_max_distance);
- mln::util::array<mln_result(accu::center<mln_psite(L)>)>
- mass_centers = labeling::compute(accu::meta::center(),
- objects, objects.nlabels());
+ object_links<L> output = compute(functor);
- for_all_ncomponents(i, objects.nlabels())
- {
- unsigned midcol = (objects.bbox(i).pmax().col()
- - objects.bbox(i).pmin().col()) / 2;
- int dmax = midcol + neighb_max_distance;
- mln_site(L) c = mass_centers(i);
+ trace::exiting("scribo::primitive::link::with_single_left_link");
+ return output;
+ }
- /// Find a neighbor on the left
- internal::find_left_link(objects, left_link, i, dmax, c);
- }
- trace::exiting("scribo::primitive::link::with_single_left_link");
- return left_link;
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_left_link(const object_image(L)& objects)
+ {
+ return with_single_left_link(objects, mln_max(unsigned));
}
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace scribo::primitive::link
diff --git a/scribo/primitive/link/with_single_left_link_dmax_ratio.hh b/scribo/primitive/link/with_single_left_link_dmax_ratio.hh
new file mode 100644
index 0000000..587fb6c
--- /dev/null
+++ b/scribo/primitive/link/with_single_left_link_dmax_ratio.hh
@@ -0,0 +1,167 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_LEFT_LINK_DMAX_RATIO_HH
+# define SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_LEFT_LINK_DMAX_RATIO_HH
+
+/// \file
+///
+/// Link text objects with their left neighbor according to a maximum
+/// distance.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+# include <mln/accu/center.hh>
+# include <mln/labeling/compute.hh>
+# include <mln/math/abs.hh>
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/object_image.hh>
+# include <scribo/core/object_links.hh>
+
+# include <scribo/primitive/link/internal/find_link.hh>
+# include <scribo/primitive/link/internal/link_ms_dmax_ratio_base.hh>
+
+# include <scribo/primitive/link/compute.hh>
+
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace link
+ {
+
+ /*! \brief Link objects with their left neighbor if exists.
+
+ \param[in] objects An object image.
+ \param[in] dmax_ratio
+
+ \return Object links data.
+
+
+ Look for a neighbor until a maximum distance defined by :
+
+ dmax = w / 2 + dmax_ratio * max(h, w)
+
+ where w is the bounding box width and h the bounding box height.
+
+ */
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_left_link_dmax_ratio(const object_image(L)& objects,
+ float dmax_ratio);
+
+
+ /// \overload
+ /// dmax_ratio is set to 3.
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_left_link_dmax_ratio(const object_image(L)& objects);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace internal
+ {
+
+ // Functor
+
+ template <typename L>
+ class single_left_dmax_ratio_functor
+ : public internal::link_ms_dmax_ratio_base<L,
+ single_left_dmax_ratio_functor<L> >
+ {
+ typedef single_left_dmax_ratio_functor<L> self_t;
+ typedef internal::link_ms_dmax_ratio_base<L, self_t> super_;
+
+ public:
+ typedef mln_site(L) P;
+
+ single_left_dmax_ratio_functor(const object_image(L)& objects,
+ unsigned dmax)
+ : super_(objects, dmax)
+ {
+ }
+
+ void compute_next_site_(P& p)
+ {
+ --p.col();
+ }
+
+ };
+
+ } // end of namespace scribo::primitive::link::internal
+
+
+
+ // Facades
+
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_left_link_dmax_ratio(const object_image(L)& objects,
+ float dmax_ratio)
+ {
+ trace::entering("scribo::primitive::link::with_single_left_link_dmax_ratio");
+
+ mln_precondition(objects.is_valid());
+
+ internal::single_left_dmax_ratio_functor<L>
+ functor(objects, dmax_ratio);
+
+ object_links<L> output = compute(functor);
+
+ trace::exiting("scribo::primitive::link::with_single_left_link_dmax_ratio");
+ return output;
+ }
+
+
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_left_link_dmax_ratio(const object_image(L)& objects)
+ {
+ return with_single_left_link_dmax_ratio(objects, 3);
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::primitive::link
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_LEFT_LINK_DMAX_RATIO_HH
diff --git a/scribo/primitive/link/with_single_right_link.hh b/scribo/primitive/link/with_single_right_link.hh
index bd15698..236884b 100644
--- a/scribo/primitive/link/with_single_right_link.hh
+++ b/scribo/primitive/link/with_single_right_link.hh
@@ -29,28 +29,25 @@
/// \file
///
/// Link text objects with their right neighbor.
-///
-/// \todo Merge code with primitive::link::with_single_right_link.hh
+
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
# include <mln/accu/center.hh>
-
# include <mln/labeling/compute.hh>
-
# include <mln/math/abs.hh>
-
# include <mln/util/array.hh>
-# include <scribo/core/object_links.hh>
# include <scribo/core/macros.hh>
# include <scribo/core/object_image.hh>
-# include <scribo/primitive/internal/init_link_array.hh>
-# include <scribo/primitive/internal/find_right_link.hh>
+# include <scribo/core/object_links.hh>
+
+# include <scribo/primitive/link/internal/find_link.hh>
+# include <scribo/primitive/link/internal/link_ms_dmax_base.hh>
+
+# include <scribo/primitive/link/compute.hh>
-//FIXME: not generic.
-# include <mln/core/alias/dpoint2d.hh>
namespace scribo
{
@@ -61,22 +58,66 @@ namespace scribo
namespace link
{
- /// Map each text object to its right bounding box neighbor
- /// if possible.
- /// Iterate to the right but link boxes to the right.
+ /// \brief Link objects with their right neighbor if exists.
+ /// Lookup startup point is the object mass center.
///
/// \param[in] objects An object image.
/// \param[in] The maximum distance allowed to seach a neighbor object.
///
- /// \return an mln::util::array. Map a bounding box to its right neighbor.
+ /// \return Object links data.
+ //
template <typename L>
inline
object_links<L>
with_single_right_link(const object_image(L)& objects,
unsigned neighb_max_distance);
+
+ /// \overload
+ /// Max distance is set to mln_max(unsigned).
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_right_link(const object_image(L)& objects);
+
+
+
# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ // Functor
+
+ template <typename L>
+ class single_right_functor
+ : public internal::link_ms_dmax_base<L, single_right_functor<L> >
+ {
+ typedef
+ internal::link_ms_dmax_base<L, single_right_functor<L> > super_;
+
+ public:
+ typedef mln_site(L) P;
+
+ single_right_functor(const object_image(L)& objects, unsigned dmax)
+ : super_(objects, dmax)
+ {
+ }
+
+ void compute_next_site_(P& p)
+ {
+ ++p.col();
+ }
+
+ };
+
+ } // end of namespace scribo::primitive::link::internal
+
+
+
+ // Facades
+
template <typename L>
inline
object_links<L>
@@ -87,28 +128,25 @@ namespace scribo
mln_precondition(objects.is_valid());
- object_links<L> right_link(objects, objects.nlabels().next());
- internal::init_link_array(right_link);
+ internal::single_right_functor<L>
+ functor(objects, neighb_max_distance);
- mln::util::array<mln_result(accu::center<mln_psite(L)>)>
- mass_centers = labeling::compute(accu::meta::center(),
- objects, objects.nlabels());
+ object_links<L> output = compute(functor);
- for_all_ncomponents(i, objects.nlabels())
- {
- unsigned midcol = (objects.bbox(i).pmax().col()
- - objects.bbox(i).pmin().col()) / 2;
- int dmax = midcol + neighb_max_distance;
- mln_site(L) c = mass_centers(i);
+ trace::exiting("scribo::primitive::link::with_single_right_link");
+ return output;
+ }
- /// Find a neighbor on the right
- internal::find_right_link(objects, right_link, i, dmax, c);
- }
- trace::exiting("scribo::primitive::link::with_single_right_link");
- return right_link;
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_right_link(const object_image(L)& objects)
+ {
+ return with_single_right_link(objects, mln_max(unsigned));
}
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace scribo::primitive::link
diff --git a/scribo/primitive/link/with_single_right_link.hh b/scribo/primitive/link/with_single_right_link_bottom.hh
similarity index 55%
copy from scribo/primitive/link/with_single_right_link.hh
copy to scribo/primitive/link/with_single_right_link_bottom.hh
index bd15698..5976f22 100644
--- a/scribo/primitive/link/with_single_right_link.hh
+++ b/scribo/primitive/link/with_single_right_link_bottom.hh
@@ -23,34 +23,31 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_HH
-# define SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_HH
+#ifndef SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_BOTTOM_HH
+# define SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_BOTTOM_HH
/// \file
///
/// Link text objects with their right neighbor.
-///
-/// \todo Merge code with primitive::link::with_single_right_link.hh
+
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
# include <mln/accu/center.hh>
-
# include <mln/labeling/compute.hh>
-
# include <mln/math/abs.hh>
-
# include <mln/util/array.hh>
-# include <scribo/core/object_links.hh>
# include <scribo/core/macros.hh>
# include <scribo/core/object_image.hh>
-# include <scribo/primitive/internal/init_link_array.hh>
-# include <scribo/primitive/internal/find_right_link.hh>
+# include <scribo/core/object_links.hh>
+
+# include <scribo/primitive/link/internal/find_link.hh>
+# include <scribo/primitive/link/internal/link_center_dmax_base.hh>
+
+# include <scribo/primitive/link/compute.hh>
-//FIXME: not generic.
-# include <mln/core/alias/dpoint2d.hh>
namespace scribo
{
@@ -61,54 +58,98 @@ namespace scribo
namespace link
{
- /// Map each text object to its right bounding box neighbor
- /// if possible.
- /// Iterate to the right but link boxes to the right.
+ /// \brief Link objects with their right neighbor if exists.
+ /// Lookup startup point is the object bottom center.
///
/// \param[in] objects An object image.
/// \param[in] The maximum distance allowed to seach a neighbor object.
///
- /// \return an mln::util::array. Map a bounding box to its right neighbor.
+ /// \return Object links data.
+ //
template <typename L>
inline
object_links<L>
- with_single_right_link(const object_image(L)& objects,
+ with_single_right_link_bottom(const object_image(L)& objects,
unsigned neighb_max_distance);
+
+ /// \overload
+ /// Max distance is set to mln_max(unsigned).
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_right_link_bottom(const object_image(L)& objects);
+
+
+
# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ // Functor
+
+ template <typename L>
+ class single_right_bottom_functor
+ : public link_center_dmax_base<L,
+ single_right_bottom_functor<L> >
+ {
+ typedef
+ link_center_dmax_base<L, single_right_bottom_functor<L> >
+ super_;
+
+ public:
+ typedef mln_site(L) P;
+
+ single_right_bottom_functor(const object_image(L)& objects,
+ unsigned dmax)
+ : super_(objects, dmax, 2)
+ {
+ }
+
+ void compute_next_site_(P& p)
+ {
+ ++p.col();
+ }
+
+ };
+
+ } // end of namespace scribo::primitive::link::internal
+
+
+
+ // Facades
+
template <typename L>
inline
object_links<L>
- with_single_right_link(const object_image(L)& objects,
- unsigned neighb_max_distance)
+ with_single_right_link_bottom(const object_image(L)& objects,
+ unsigned neighb_max_distance)
{
- trace::entering("scribo::primitive::link::with_single_right_link");
+ trace::entering("scribo::primitive::link::with_single_right_link_bottom");
mln_precondition(objects.is_valid());
- object_links<L> right_link(objects, objects.nlabels().next());
- internal::init_link_array(right_link);
+ internal::single_right_bottom_functor<L>
+ functor(objects, neighb_max_distance);
- mln::util::array<mln_result(accu::center<mln_psite(L)>)>
- mass_centers = labeling::compute(accu::meta::center(),
- objects, objects.nlabels());
+ object_links<L> output = compute(functor);
- for_all_ncomponents(i, objects.nlabels())
- {
- unsigned midcol = (objects.bbox(i).pmax().col()
- - objects.bbox(i).pmin().col()) / 2;
- int dmax = midcol + neighb_max_distance;
- mln_site(L) c = mass_centers(i);
+ trace::exiting("scribo::primitive::link::with_single_right_link_bottom");
+ return output;
+ }
- /// Find a neighbor on the right
- internal::find_right_link(objects, right_link, i, dmax, c);
- }
- trace::exiting("scribo::primitive::link::with_single_right_link");
- return right_link;
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_right_link_bottom(const object_image(L)& objects)
+ {
+ return with_single_right_link_bottom(objects, mln_max(unsigned));
}
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace scribo::primitive::link
@@ -117,4 +158,4 @@ namespace scribo
} // end of namespace scribo
-#endif // ! SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_HH
+#endif // ! SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_BOTTOM_HH
diff --git a/scribo/primitive/link/with_single_right_link_dmax_ratio.hh b/scribo/primitive/link/with_single_right_link_dmax_ratio.hh
new file mode 100644
index 0000000..ac6ef31
--- /dev/null
+++ b/scribo/primitive/link/with_single_right_link_dmax_ratio.hh
@@ -0,0 +1,167 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_DMAX_RATIO_HH
+# define SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_DMAX_RATIO_HH
+
+/// \file
+///
+/// Link text objects with their right neighbor according to a maximum
+/// distance.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+# include <mln/accu/center.hh>
+# include <mln/labeling/compute.hh>
+# include <mln/math/abs.hh>
+# include <mln/util/array.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/object_image.hh>
+# include <scribo/core/object_links.hh>
+
+# include <scribo/primitive/link/internal/find_link.hh>
+# include <scribo/primitive/link/internal/link_ms_dmax_ratio_base.hh>
+
+# include <scribo/primitive/link/compute.hh>
+
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace link
+ {
+
+ /*! \brief Link objects with their right neighbor if exists.
+
+ \param[in] objects An object image.
+ \param[in] dmax_ratio
+
+ \return Object links data.
+
+
+ Look for a neighbor until a maximum distance defined by :
+
+ dmax = w / 2 + dmax_ratio * max(h, w)
+
+ where w is the bounding box width and h the bounding box height.
+
+ */
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_right_link_dmax_ratio(const object_image(L)& objects,
+ float dmax_ratio);
+
+
+ /// \overload
+ /// dmax_ratio is set to 3.
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_right_link_dmax_ratio(const object_image(L)& objects);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace internal
+ {
+
+ // Functor
+
+ template <typename L>
+ class single_right_dmax_ratio_functor
+ : public link_ms_dmax_ratio_base<L,
+ single_right_dmax_ratio_functor<L> >
+ {
+ typedef single_right_dmax_ratio_functor<L> self_t;
+ typedef link_ms_dmax_ratio_base<L, self_t> super_;
+
+ public:
+ typedef mln_site(L) P;
+
+ single_right_dmax_ratio_functor(const object_image(L)& objects,
+ unsigned dmax)
+ : super_(objects, dmax)
+ {
+ }
+
+ void compute_next_site_(P& p)
+ {
+ ++p.col();
+ }
+
+ };
+
+ } // end of namespace scribo::primitive::link::internal
+
+
+
+ // Facades
+
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_right_link_dmax_ratio(const object_image(L)& objects,
+ float dmax_ratio)
+ {
+ trace::entering("scribo::primitive::link::with_single_right_link_dmax_ratio");
+
+ mln_precondition(objects.is_valid());
+
+ internal::single_right_dmax_ratio_functor<L>
+ functor(objects, dmax_ratio);
+
+ object_links<L> output = compute(functor);
+
+ trace::exiting("scribo::primitive::link::with_single_right_link_dmax_ratio");
+ return output;
+ }
+
+
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_right_link_dmax_ratio(const object_image(L)& objects)
+ {
+ return with_single_right_link_dmax_ratio(objects, 3);
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::primitive::link
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_DMAX_RATIO_HH
diff --git a/scribo/primitive/link/with_single_right_link.hh b/scribo/primitive/link/with_single_right_link_top.hh
similarity index 57%
copy from scribo/primitive/link/with_single_right_link.hh
copy to scribo/primitive/link/with_single_right_link_top.hh
index bd15698..13bb583 100644
--- a/scribo/primitive/link/with_single_right_link.hh
+++ b/scribo/primitive/link/with_single_right_link_top.hh
@@ -23,34 +23,31 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_HH
-# define SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_HH
+#ifndef SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_TOP_HH
+# define SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_TOP_HH
/// \file
///
/// Link text objects with their right neighbor.
-///
-/// \todo Merge code with primitive::link::with_single_right_link.hh
+
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
# include <mln/accu/center.hh>
-
# include <mln/labeling/compute.hh>
-
# include <mln/math/abs.hh>
-
# include <mln/util/array.hh>
-# include <scribo/core/object_links.hh>
# include <scribo/core/macros.hh>
# include <scribo/core/object_image.hh>
-# include <scribo/primitive/internal/init_link_array.hh>
-# include <scribo/primitive/internal/find_right_link.hh>
+# include <scribo/core/object_links.hh>
+
+# include <scribo/primitive/link/internal/find_link.hh>
+# include <scribo/primitive/link/internal/link_center_dmax_base.hh>
+
+# include <scribo/primitive/link/compute.hh>
-//FIXME: not generic.
-# include <mln/core/alias/dpoint2d.hh>
namespace scribo
{
@@ -61,54 +58,98 @@ namespace scribo
namespace link
{
- /// Map each text object to its right bounding box neighbor
- /// if possible.
- /// Iterate to the right but link boxes to the right.
+ /// \brief Link objects with their right neighbor if exists.
+ /// Lookup startup point is the object top center.
///
/// \param[in] objects An object image.
/// \param[in] The maximum distance allowed to seach a neighbor object.
///
- /// \return an mln::util::array. Map a bounding box to its right neighbor.
+ /// \return Object links data.
+ //
template <typename L>
inline
object_links<L>
- with_single_right_link(const object_image(L)& objects,
+ with_single_right_link_top(const object_image(L)& objects,
unsigned neighb_max_distance);
+
+ /// \overload
+ /// Max distance is set to mln_max(unsigned).
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_right_link_top(const object_image(L)& objects);
+
+
+
# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ // Functor
+
+ template <typename L>
+ class single_right_top_functor
+ : public link_center_dmax_base<L,
+ single_right_top_functor<L> >
+ {
+ typedef
+ link_center_dmax_base<L, single_right_top_functor<L> >
+ super_;
+
+ public:
+ typedef mln_site(L) P;
+
+ single_right_top_functor(const object_image(L)& objects,
+ unsigned dmax)
+ : super_(objects, dmax, 0)
+ {
+ }
+
+ void compute_next_site_(P& p)
+ {
+ ++p.col();
+ }
+
+ };
+
+ } // end of namespace scribo::primitive::link::internal
+
+
+
+ // Facades
+
template <typename L>
inline
object_links<L>
- with_single_right_link(const object_image(L)& objects,
+ with_single_right_link_top(const object_image(L)& objects,
unsigned neighb_max_distance)
{
- trace::entering("scribo::primitive::link::with_single_right_link");
+ trace::entering("scribo::primitive::link::with_single_right_link_top");
mln_precondition(objects.is_valid());
- object_links<L> right_link(objects, objects.nlabels().next());
- internal::init_link_array(right_link);
+ internal::single_right_top_functor<L>
+ functor(objects, neighb_max_distance);
- mln::util::array<mln_result(accu::center<mln_psite(L)>)>
- mass_centers = labeling::compute(accu::meta::center(),
- objects, objects.nlabels());
+ object_links<L> output = compute(functor);
- for_all_ncomponents(i, objects.nlabels())
- {
- unsigned midcol = (objects.bbox(i).pmax().col()
- - objects.bbox(i).pmin().col()) / 2;
- int dmax = midcol + neighb_max_distance;
- mln_site(L) c = mass_centers(i);
+ trace::exiting("scribo::primitive::link::with_single_right_link_top");
+ return output;
+ }
- /// Find a neighbor on the right
- internal::find_right_link(objects, right_link, i, dmax, c);
- }
- trace::exiting("scribo::primitive::link::with_single_right_link");
- return right_link;
+ template <typename L>
+ inline
+ object_links<L>
+ with_single_right_link_top(const object_image(L)& objects)
+ {
+ return with_single_right_link_top(objects, mln_max(unsigned));
}
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace scribo::primitive::link
@@ -117,4 +158,4 @@ namespace scribo
} // end of namespace scribo
-#endif // ! SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_HH
+#endif // ! SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_RIGHT_LINK_TOP_HH
--
1.5.6.5