
* 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@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@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@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