last-svn-commit-40-gb3822e8 Introduce new Scribo core classes and start using them.

* scribo/core/component_info.hh, * scribo/core/component_set.hh, * scribo/core/line_info.hh, * scribo/core/line_set.hh, * scribo/core/macros.hh, * scribo/core/object_groups.hh, * scribo/core/object_links.hh, * scribo/core/tag/anchor.hh, * scribo/core/tag/component.hh, * scribo/core/tag/line.hh: New core classes. * scribo/core/object_image.hh: Remove. * scribo/core/anchors.hh * scribo/primitive/extract/objects.hh: Rename as... * scribo/primitive/link/internal/compute_anchor.hh, * scribo/primitive/extract/components.hh: ... this. * scribo/draw/bounding_box_links.hh, * scribo/filter/object_links_bbox_h_ratio.hh, * scribo/filter/object_links_bbox_ratio.hh, * scribo/filter/objects_small.hh, * scribo/fun/v2b/objects_small_filter.hh, * scribo/primitive/group/apply.hh, * scribo/primitive/group/from_single_link.hh, * scribo/primitive/internal/find_root.hh, * scribo/primitive/internal/init_link_array.hh, * scribo/primitive/link/compute.hh, * scribo/primitive/link/internal/find_link.hh, * scribo/primitive/link/internal/find_several_links.hh, * scribo/primitive/link/internal/link_functor_base.hh, * scribo/primitive/link/internal/link_several_dmax_base.hh, * scribo/primitive/link/internal/link_single_dmax_base.hh, * scribo/primitive/link/internal/link_single_dmax_ratio_base.hh, * scribo/primitive/link/merge_double_link.hh, * scribo/primitive/link/with_single_left_link_dmax_ratio.hh, * scribo/primitive/link/with_single_right_link_bottom.hh, * scribo/primitive/link/with_single_right_link_dmax_ratio.hh, * scribo/primitive/link/with_single_right_link_top.hh: Make use of the new core classes. --- scribo/ChangeLog | 46 ++ scribo/core/component_info.hh | 151 +++++++ scribo/core/component_set.hh | 377 ++++++++++++++++ scribo/core/line_info.hh | 306 +++++++++++++ scribo/core/line_set.hh | 453 ++++++++++++++++++++ scribo/core/macros.hh | 11 + scribo/core/object_groups.hh | 88 +++-- scribo/core/object_image.hh | 377 ---------------- scribo/core/object_links.hh | 48 +-- scribo/core/{anchors.hh => tag/anchor.hh} | 20 + scribo/{draw/all.hh => core/tag/component.hh} | 28 +- scribo/core/{anchors.hh => tag/line.hh} | 30 +- scribo/draw/bounding_box_links.hh | 6 +- scribo/filter/object_links_bbox_h_ratio.hh | 14 +- scribo/filter/object_links_bbox_ratio.hh | 21 +- scribo/filter/objects_small.hh | 74 ++-- scribo/fun/v2b/objects_small_filter.hh | 39 +- .../extract/{objects.hh => components.hh} | 76 ++-- scribo/primitive/group/apply.hh | 63 ++-- scribo/primitive/group/from_single_link.hh | 19 +- scribo/primitive/internal/find_root.hh | 12 +- scribo/primitive/internal/init_link_array.hh | 15 +- scribo/primitive/link/compute.hh | 16 +- scribo/primitive/link/internal/compute_anchor.hh | 78 ++-- scribo/primitive/link/internal/find_link.hh | 10 +- .../primitive/link/internal/find_several_links.hh | 5 +- .../primitive/link/internal/link_functor_base.hh | 73 ++-- .../link/internal/link_several_dmax_base.hh | 2 +- .../link/internal/link_single_dmax_base.hh | 2 +- .../link/internal/link_single_dmax_ratio_base.hh | 18 +- scribo/primitive/link/merge_double_link.hh | 30 +- .../link/with_single_left_link_dmax_ratio.hh | 30 +- .../link/with_single_right_link_bottom.hh | 2 +- .../link/with_single_right_link_dmax_ratio.hh | 24 +- .../primitive/link/with_single_right_link_top.hh | 2 +- 35 files changed, 1793 insertions(+), 773 deletions(-) create mode 100644 scribo/core/component_info.hh create mode 100644 scribo/core/component_set.hh create mode 100644 scribo/core/line_info.hh create mode 100644 scribo/core/line_set.hh delete mode 100644 scribo/core/object_image.hh copy scribo/core/{anchors.hh => tag/anchor.hh} (77%) copy scribo/{draw/all.hh => core/tag/component.hh} (80%) rename scribo/core/{anchors.hh => tag/line.hh} (81%) rename scribo/primitive/extract/{objects.hh => components.hh} (62%) diff --git a/scribo/ChangeLog b/scribo/ChangeLog index 52a13dd..dfac25a 100644 --- a/scribo/ChangeLog +++ b/scribo/ChangeLog @@ -1,3 +1,49 @@ +2010-03-11 Guillaume Lazzara <z@lrde.epita.fr> + + Introduce new Scribo core classes and start using them. + + * scribo/core/component_info.hh, + * scribo/core/component_set.hh, + * scribo/core/line_info.hh, + * scribo/core/line_set.hh, + * scribo/core/macros.hh, + * scribo/core/object_groups.hh, + * scribo/core/object_links.hh, + * scribo/core/tag/anchor.hh, + * scribo/core/tag/component.hh, + * scribo/core/tag/line.hh: New core classes. + + * scribo/core/object_image.hh: Remove. + + * scribo/core/anchors.hh + * scribo/primitive/extract/objects.hh: Rename as... + + * scribo/primitive/link/internal/compute_anchor.hh, + * scribo/primitive/extract/components.hh: ... this. + + * scribo/draw/bounding_box_links.hh, + * scribo/filter/object_links_bbox_h_ratio.hh, + * scribo/filter/object_links_bbox_ratio.hh, + * scribo/filter/objects_small.hh, + * scribo/fun/v2b/objects_small_filter.hh, + * scribo/primitive/group/apply.hh, + * scribo/primitive/group/from_single_link.hh, + * scribo/primitive/internal/find_root.hh, + * scribo/primitive/internal/init_link_array.hh, + * scribo/primitive/link/compute.hh, + * scribo/primitive/link/internal/find_link.hh, + * scribo/primitive/link/internal/find_several_links.hh, + * scribo/primitive/link/internal/link_functor_base.hh, + * scribo/primitive/link/internal/link_several_dmax_base.hh, + * scribo/primitive/link/internal/link_single_dmax_base.hh, + * scribo/primitive/link/internal/link_single_dmax_ratio_base.hh, + * scribo/primitive/link/merge_double_link.hh, + * scribo/primitive/link/with_single_left_link_dmax_ratio.hh, + * scribo/primitive/link/with_single_right_link_bottom.hh, + * scribo/primitive/link/with_single_right_link_dmax_ratio.hh, + * scribo/primitive/link/with_single_right_link_top.hh: Make use of + the new core classes. + 2010-02-19 Guillaume Lazzara <z@lrde.epita.fr> Add anchor support in debug routines. diff --git a/scribo/core/component_info.hh b/scribo/core/component_info.hh new file mode 100644 index 0000000..0751fa2 --- /dev/null +++ b/scribo/core/component_info.hh @@ -0,0 +1,151 @@ +// 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_COMPONENT_INFO_HH +# define SCRIBO_CORE_COMPONENT_INFO_HH + +/// \file +/// +/// \brief Component information data structure. + + +# include <mln/core/alias/box2d.hh> +# include <mln/core/alias/point2d.hh> +# include <mln/util/object_id.hh> + +# include <scribo/core/tag/component.hh> +# include <scribo/core/tag/line.hh> + +namespace scribo +{ + + typedef mln::util::object_id<scribo::ComponentId, unsigned> component_id_t; + + class component_info + { + typedef mln::util::object_id<scribo::ComponentId, unsigned> component_id_t; + typedef mln::util::object_id<scribo::LineId, unsigned> line_id_t; + + public: + component_info(); + component_info(const component_id_t& id, + const mln::box2d& bbox, + const mln::point2d& mass_center, + unsigned card); + + component_id_t id() const; + const mln::box2d& bbox() const; + const mln::point2d& mass_center() const; + unsigned card() const; + component::Tag tag() const; + void update_tag(component::Tag tag); + + line_id_t line_id() const; + + private: + component_id_t id_; + mln::box2d bbox_; + mln::point2d mass_center_; + unsigned card_; + component::Tag tag_; + + line_id_t line_id_; + }; + + +# ifndef MLN_INCLUDE_ONLY + + + component_info::component_info() + { + + } + + + component_info::component_info(const component_id_t& id, + const mln::box2d& bbox, + const mln::point2d& mass_center, + unsigned card) + : id_(id), bbox_(bbox), mass_center_(mass_center), card_(card), + tag_(component::None), line_id_(0) + { + + } + + + component_info::component_id_t + component_info::id() const + { + return id_; + } + + + const mln::box2d& + component_info::bbox() const + { + return bbox_; + } + + + const mln::point2d& + component_info::mass_center() const + { + return mass_center_; + } + + unsigned + component_info::card() const + { + return card_; + } + + + component::Tag + component_info::tag() const + { + return tag_; + } + + + void + component_info::update_tag(component::Tag tag) + { + tag_ = tag; + } + + component_info::line_id_t + component_info::line_id() const + { + return line_id_; + } + + +# endif // ! MLN_INCLUDE_ONLY + + +} // end of namespace scribo + + +#endif // ! SCRIBO_CORE_COMPONENT_INFO_HH diff --git a/scribo/core/component_set.hh b/scribo/core/component_set.hh new file mode 100644 index 0000000..050f0ce --- /dev/null +++ b/scribo/core/component_set.hh @@ -0,0 +1,377 @@ +// 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_COMPONENT_SET_HH +# define SCRIBO_CORE_COMPONENT_SET_HH + +/// \file +/// +/// \brief Definition of a component set. + +# include <mln/util/array.hh> + +# include <mln/accu/pair.hh> +# include <mln/accu/center.hh> +# include <mln/accu/shape/bbox.hh> + +# include <mln/labeling/compute.hh> + +# include <mln/convert/from_to.hh> + + +# include <scribo/core/macros.hh> +# include <scribo/core/component_info.hh> + + +namespace scribo +{ + + // Forward declaration. + template <typename L> struct component_set; + + + namespace internal + { + /// Data structure for \c scribo::component_set<I>. + template <typename L> + struct component_set_data + { + typedef mln::accu::center<mln_site(L)> center_accu_t; + typedef mln::accu::shape::bbox<mln_site(L)> bbox_accu_t; + typedef mln::accu::pair<bbox_accu_t, center_accu_t> pair_accu_t; + + typedef mln_result(center_accu_t) center_t; + + component_set_data(); + component_set_data(const L& ima, const mln_value(L)& ncomps); + component_set_data(const L& ima, const mln_value(L)& ncomps, + const mln::util::array<pair_accu_t>& attribs); + + component_set_data(const L& ima, const mln_value(L)& ncomps, + const mln::util::array<scribo::component_info>& infos); + void fill_infos(const mln::util::array<pair_accu_t>& attribs); + + L ima_; + mln_value(L) ncomps_; + mln::util::array<scribo::component_info> infos_; + + }; + + } // end of namespace scribo::internal + + + template <typename L> + class component_set + { + typedef mln::accu::shape::bbox<mln_site(L)> bbox_accu_t; + typedef mln::accu::center<mln_site(L)> center_accu_t; + typedef mln::accu::pair<bbox_accu_t, center_accu_t> pair_accu_t; + + typedef mln_result(center_accu_t) center_t; + + public: + + /// Constructors + /// @{ + /// Constructor without argument. + component_set(); + + /// Constructor from an image \p ima and the number of labels \p ncomps. + component_set(const L& ima, const mln_value(L)& ncomps); + + /// Constructor from an image \p ima, the number of labels \p ncomps and + /// attributes values (bounding box and mass center). + component_set(const L& ima, const mln_value(L)& ncomps, + const mln::util::array<pair_accu_t>& attribs); + /// @} + + /// Return the component count. + mln_value(L) nelements() const; + + /// Return component information for a given component id \p id. + const component_info& info(const mln_value(L)& id) const; + + /// Return component information for a given component id \p id. + component_info& info(const mln_value(L)& id); + +// /// Return component information for a given component id \p id. +// component_info& operator()(const mln_value(L)& id); + +// /// Return component information for a given component id \p id. +// const component_info& operator()(const mln_value(L)& id) const; + + + /// Return component information for a given component id \p id. + component_info& operator()(const component_id_t& id); + + /// Return component information for a given component id \p id. + const component_info& operator()(const component_id_t& id) const; + + + /// Update tag of components set to 'false' in \p f with \p tag. + template <typename F> + void update_tags(const mln::Function_v2b<F>& f, component::Tag tag); + + /// Create a copy of this component_set<L> + component_set<L> duplicate() const; + + /// Return the underlying labeled image + const L& labeled_image() const; + + /// Internal methods + /// @{ + + /// Return all the component infos. + const mln::util::array<scribo::component_info>& infos_() const; + + /// @} + + private: + /// Duplicate the underlying image and create a new component_set. + void init_(const component_set<L>& model); + + mln::util::tracked_ptr< internal::component_set_data<L> > data_; + }; + + +# ifndef MLN_INCLUDE_ONLY + + + // component_set_data<L> > + + namespace internal + { + + // data< component_set<L> > + + + template <typename L> + inline + component_set_data<L>::component_set_data() + { + } + + + template <typename L> + inline + component_set_data<L>::component_set_data(const L& ima, + const mln_value(L)& ncomps) + : ima_(ima), ncomps_(ncomps) + { + typedef mln::accu::shape::bbox<mln_site(L)> bbox_accu_t; + typedef mln::accu::center<mln_site(L)> center_accu_t; + typedef mln::accu::pair<bbox_accu_t, center_accu_t> pair_accu_t; + + + mln::util::array<pair_accu_t> attribs; + mln::labeling::compute(attribs, ima_, ncomps_); + + fill_infos(attribs); + } + + + template <typename L> + inline + component_set_data<L>::component_set_data(const L& ima, + const mln_value(L)& ncomps, + const mln::util::array<pair_accu_t>& attribs) + : ima_(ima), ncomps_(ncomps) + { + fill_infos(attribs); + } + + template <typename L> + inline + component_set_data<L>::component_set_data(const L& ima, + const mln_value(L)& ncomps, + const mln::util::array<scribo::component_info>& infos) + : ima_(ima), ncomps_(ncomps), infos_(infos) + { + } + + + template <typename L> + inline + void + component_set_data<L>::fill_infos(const mln::util::array<pair_accu_t>& attribs) + { + typedef mln_site(L) P; + + infos_.reserve(static_cast<unsigned>(ncomps_) + 1); + + infos_.append(component_info()); // Component 0, i.e. the background. + for_all_components(i, attribs) + { + component_info info(i, attribs[i].first(), + attribs[i].second(), attribs[i].second_accu().nsites()); + infos_.append(info); + } + } + + } // end of namespace mln::internal + + + + + template <typename L> + inline + component_set<L>::component_set() + { + } + + template <typename L> + inline + component_set<L>::component_set(const L& ima, const mln_value(L)& ncomps) + { + data_ = new internal::component_set_data<L>(ima, ncomps); + } + + + template <typename L> + inline + component_set<L>::component_set(const L& ima, const mln_value(L)& ncomps, + const mln::util::array<pair_accu_t>& attribs) + { + data_ = new internal::component_set_data<L>(ima, ncomps, attribs); + } + + + template <typename L> + inline + mln_value(L) + component_set<L>::nelements() const + { + return data_->ncomps_; + } + + template <typename L> + inline + const component_info& + component_set<L>::info(const mln_value(L)& id) const + { + return this->data_->infos_[id]; + } + + template <typename L> + inline + component_info& + component_set<L>::info(const mln_value(L)& id) + { + return this->data_->infos_[id]; + } + +// template <typename L> +// inline +// const component_info& +// component_set<L>::operator()(const mln_value(L)& id) const +// { +// return this->data_->infos_[id]; +// } + +// template <typename L> +// inline +// component_info& +// component_set<L>::operator()(const mln_value(L)& id) +// { +// return this->data_->infos_[id]; +// } + + template <typename L> + inline + const component_info& + component_set<L>::operator()(const component_id_t& id) const + { + return this->data_->infos_[id]; + } + + template <typename L> + inline + component_info& + component_set<L>::operator()(const component_id_t& id) + { + return this->data_->infos_[id]; + } + + + template <typename L> + template <typename F> + inline + void + component_set<L>::update_tags(const mln::Function_v2b<F>& f_, + component::Tag tag) + { + const F& f = exact(f_); + + for_all_components(i, data_->infos_) + if (!f(i)) + data_->infos_[i].update_tag(tag); + } + + + template <typename L> + inline + component_set<L> + component_set<L>::duplicate() const + { + component_set<L> output; + output.init_(*this); + return output; + } + + + + template <typename L> + inline + const L& + component_set<L>::labeled_image() const + { + return this->data_->ima_; + } + + template <typename L> + inline + const mln::util::array<scribo::component_info>& + component_set<L>::infos_() const + { + return data_->infos_; + } + + template <typename L> + inline + void + component_set<L>::init_(const component_set<L>& set) + { + data_ = new internal::component_set_data<L>(); + data_->ima_ = set.object_image_(); + data_->ncomps_ = set.ncomps(); + data_->infos_ = set.infos_(); + } + + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace scribo + +#endif // ! SCRIBO_CORE_COMPONENT_SET_HH diff --git a/scribo/core/line_info.hh b/scribo/core/line_info.hh new file mode 100644 index 0000000..22eeea6 --- /dev/null +++ b/scribo/core/line_info.hh @@ -0,0 +1,306 @@ +// 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_LINE_INFO_HH +# define SCRIBO_CORE_LINE_INFO_HH + +/// \file +/// +/// \brief Line information data structure. + + +# include <mln/core/alias/box2d.hh> +# include <mln/core/alias/point2d.hh> +# include <mln/util/object_id.hh> + +# include <scribo/core/tag/component.hh> +# include <scribo/core/tag/line.hh> + +namespace scribo +{ + + typedef mln::util::object_id<scribo::LineId, unsigned> line_id_t; + + class line_info + { + typedef mln::util::object_id<scribo::ComponentId, unsigned> component_id_t; + typedef mln::util::object_id<scribo::LineId, unsigned> line_id_t; + + public: + line_info(); + line_info(const line_id_t& id, + const mln::box2d& bbox, + const mln::util::array<component_id_t>& comps, + unsigned absolute_median, + unsigned absolute_baseline, + unsigned char_space, + unsigned char_width); + + line_id_t id() const; + + line::Tag tag() const; + void update_tag(line::Tag tag); + + const mln::box2d& bbox() const; + + const mln::util::array<component_id_t>& components() const; + unsigned card() const; + + unsigned baseline() const; + unsigned median() const; + int x_height() const; + int d_height() const; + int a_height() const; + + unsigned char_space() const; + unsigned char_width() const; + + unsigned word_space() const; + + void merge(const line_info& line) const; + + bool is_valid() const; + + private: + line_id_t id_; + line::Tag tag_; + mln::box2d bbox_; + mln::util::array<component_id_t> components_; + + // Value relative to the line bbox. + unsigned baseline_; + unsigned median_; + + // Values relative to the baseline. + int x_height_; + int d_height_; + int a_height_; + + + // Character related stats. + unsigned char_space_; + unsigned char_width_; + + // Words related stats. + unsigned word_space_; + }; + + + std::ostream& + operator<<(std::ostream& ostr, const line_info& info); + + +# ifndef MLN_INCLUDE_ONLY + + + line_info::line_info() + : id_(0) + { + + } + + + /*! + + Exemple: + + --------------------- + | | | |x| | | | | | | ----> a_height = 4 + --------------------- + | | | |x| | | | | | | + --------------------- + | |x|x|x| | |x|x|x| | ----> Median = 2 ^ + --------------------- | + | |x| |x| | |x| |x| | | x_height = 3 + --------------------- | + | |x|x|x| | |x|x|x| | ----> Baseline = 4 v + --------------------- + | | | | | | |x| | | | + --------------------- + | | | | | | |x| | | | ----> d_height = -2 + --------------------- + + All the metrics are computed relatively to the Baseline. + + The baseline is computed relatively to the top left corner of the + line bounding box. + + */ + line_info::line_info(const line_id_t& id, + const mln::box2d& bbox, + const mln::util::array<component_id_t>& comps, + unsigned absolute_median, + unsigned absolute_baseline, + unsigned char_space, + unsigned char_width) + : id_(id), tag_(line::None), bbox_(bbox), components_(comps), + char_space_(char_space), char_width_(char_width) + { + baseline_ = absolute_baseline - bbox.pmin().row(); + median_ = absolute_median - bbox.pmin().row(); + x_height_ = absolute_baseline - absolute_median + 1; + d_height_ = bbox.pmax().row() - absolute_baseline; + a_height_ = absolute_baseline - bbox.pmin().row() + 1; + } + + + line_info::line_id_t + line_info::id() const + { + return id_; + } + + line::Tag + line_info::tag() const + { + return tag_; + } + + + void + line_info::update_tag(line::Tag tag) + { + tag_ = tag; + } + + const mln::box2d& + line_info::bbox() const + { + return bbox_; + } + + + const mln::util::array<line_info::component_id_t>& + line_info::components() const + { + return components_; + } + + unsigned + line_info::card() const + { + return components_.size(); + } + + + unsigned + line_info::baseline() const + { + return baseline_; + } + + + unsigned + line_info::median() const + { + return median_; + } + + int + line_info::x_height() const + { + return x_height_; + } + + + int + line_info::d_height() const + { + return d_height_; + } + + + int + line_info::a_height() const + { + return a_height_; + } + + + unsigned + line_info::char_space() const + { + return char_space_; + } + + + unsigned + line_info::char_width() const + { + return char_width_; + } + + + unsigned + line_info::word_space() const + { + return word_space_; + } + + + void + line_info::merge(const line_info& line) const + { + (void) line; + std::cout << "merge not implemented!" << std::endl; + abort(); + } + + + bool + line_info::is_valid() const + { + return id_ != 0u; + } + + + + std::ostream& + operator<<(std::ostream& ostr, const line_info& info) + { + return ostr << "line_info(" + << "id=" << info.id() + << ", tag=" << info.tag() + << ", bbox=" << info.bbox() + << ", components=" << info.components() + << ", baseline=" << info.baseline() + << ", median=" << info.median() + << ", x_height=" << info.x_height() + << ", d_height=" << info.d_height() + << ", a_height=" << info.a_height() + << ", char_space=" << info.char_space() + << ", char_width=" << info.char_width() + << ", word_space=" << info.word_space() + << ")" << std::endl; + } + + +# endif // ! MLN_INCLUDE_ONLY + + +} // end of namespace scribo + + +#endif // ! SCRIBO_CORE_LINE_INFO_HH diff --git a/scribo/core/line_set.hh b/scribo/core/line_set.hh new file mode 100644 index 0000000..655f03b --- /dev/null +++ b/scribo/core/line_set.hh @@ -0,0 +1,453 @@ +// 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_LINE_SET_HH +# define SCRIBO_CORE_LINE_SET_HH + +/// \file +/// +/// \brief Definition of a line set. + +# include <mln/util/array.hh> + +# include <mln/accu/pair.hh> +# include <mln/accu/center.hh> +# include <mln/accu/shape/bbox.hh> + +# include <mln/labeling/compute.hh> +# include <mln/make/relabelfun.hh> + +# include <mln/fun/i2v/array.hh> + +# include <mln/convert/from_to.hh> + + +# include <scribo/core/macros.hh> +# include <scribo/core/line_info.hh> +# include <scribo/core/line_stats_extra.hh> + + +namespace scribo +{ + + // Forward declaration. + template <typename L> struct line_set; + + + namespace internal + { + /// Data structure for \c scribo::line_set<I>. + template <typename L> + struct line_set_data + { + line_set_data(); + line_set_data(const mln::util::array<scribo::line_info>& infos, + const component_set<L>& comp_set); + + mln::util::array<scribo::line_info> infos_; + component_set<L> comp_set_; + }; + + } // end of namespace scribo::internal + + + + template <typename L> + class line_set + { + public: + + /// Constructors + /// @{ + /// Constructor without argument. + line_set(); + + /// Constructor from object groups. + line_set(const object_links<L>& links, const object_groups<L>& groups); + /// @} + + /// Compute line stats and fill the underlying information. + util::array<line_stats_extra> compute_lines(const object_links<L>& links, + const object_groups<L>& groups); + + /// Return the line count. + mln_value(L) nelements() const; + + /// Return line information for a given line id \p id. + const line_info& info(const mln_value(L)& id) const; + + /// Return line information for a given line id \p id. + line_info& info(const mln_value(L)& id); + + /// Return line information for a given line id \p id. + line_info& operator()(const line_id_t& id); + + /// Return line information for a given line id \p id. + const line_info& operator()(const line_id_t& id) const; + + /// Update tag of lines set to 'false' in \p f with \p tag. + template <typename F> + void update_tags(const mln::Function_v2b<F>& f, line::Tag tag); + + /// Create a copy of this line_set<L> + line_set<L> duplicate() const; + + /// Return the underlying component set. + const component_set<L>& component_set_() const; + + /// Internal methods + /// @{ + + /// Return all the line infos. + const mln::util::array<scribo::line_info>& infos_() const; + + /// @} + + private: + /// Duplicate the underlying image and create a new line_set. + void init_(const line_set<L>& model); + + mln::util::tracked_ptr< internal::line_set_data<L> > data_; + }; + + + namespace make + { + + template <typename L> + scribo::line_set<L> + line_set(const object_links<L>& links, + const object_groups<L>& groups); + + } // End of namespace scribo::make + + + +# ifndef MLN_INCLUDE_ONLY + + + // line_set_data<L> > + + namespace internal + { + + // data< line_set<L> > + + + template <typename L> + inline + line_set_data<L>::line_set_data() + { + } + + + template <typename L> + inline + line_set_data<L>::line_set_data(const mln::util::array<scribo::line_info>& infos, + const component_set<L>& comp_set) + : infos_(infos), comp_set_(comp_set) + { + } + + } // end of namespace mln::internal + + + + + template <typename L> + inline + line_set<L>::line_set() + { + } + + template <typename L> + inline + line_set<L>::line_set(const object_links<L>& links, + const object_groups<L>& groups) + { + compute_lines(links, groups); + } + + + // FIXME: groups should have a reference to the links data and we + // should only required groups as argument. + template <typename L> + util::array<line_stats_extra> + line_set<L>::compute_lines(const object_links<L>& links, + const object_groups<L>& groups) + { + data_ = new internal::line_set_data<L>(); + + typedef mln_site(L) P; + data_->comp_set_ = groups.component_set_(); + const component_set<L>& comp_set = groups.component_set_(); + + mln_value(L) n_groups = groups.nelements() - 1; + mln::fun::i2v::array<mln_value(L)> + packed_groups = mln::make::relabelfun(groups.comp_to_group(), + n_groups, n_groups); + + // FIXME: object_groups should store the relation 'group -> comp'. + // it would avoid the use of accumulator arrays. + + // FIXME: int_u<11> may not be enought but we can't use unsigned + // or any other larger types since there is no median + // implementation for high quantification types... + + // Init. + typedef mln::value::int_u<12> median_data_t; + typedef mln::accu::stat::median_h<median_data_t> median_t; + util::array<median_t> + absolute_median(static_cast<unsigned>(n_groups) + 1), + absolute_baseline(static_cast<unsigned>(n_groups) + 1), + char_space(static_cast<unsigned>(n_groups) + 1), + char_width(static_cast<unsigned>(n_groups) + 1); + + util::array<mln::accu::shape::bbox<P> > + bbox(static_cast<unsigned>(n_groups) + 1); + + util::array< util::array<component_id_t> > + comps(static_cast<unsigned>(n_groups) + 1); + + // 1st pass - Compute data. + for (unsigned i = 1; i < packed_groups.size(); ++i) + if (comp_set(i).tag() != component::Ignored) + { + unsigned group_id = packed_groups(i); + if (group_id != 0) // Is this component part of a group? + { + const box2d& bb = comp_set(i).bbox(); + + // Space between characters. + int space = bb.pmin().col() + - comp_set(links[i]).bbox().pmax().col(); + // -- Ignore overlapped characters. + if (space > 0) + char_space(group_id).take(space); + + // Character width + // -- Ignore too large components. + if (bb.width() <= 1000) + char_width(group_id).take(bb.width()); + + // Median (compute an absolute value, from the top left + // corner of the image). + absolute_median(group_id).take(bb.pmin().row()); + + // Baseline (compute an absolute value, from the top left + // corner of the image). + absolute_baseline(group_id).take(bb.pmax().row()); + + // Bounding box. + bbox(group_id).take(bb); + + // Component id. + comps(group_id).append(i); + } + } + + // 2nd pass - Store data. + data_->infos_.reserve(groups.nelements()); + data_->infos_.append(line_info()); // line with id 0 is invalid. + + util::array<line_stats_extra> stats_extra; + stats_extra.reserve(static_cast<unsigned>(n_groups) + 1); + stats_extra.append(line_stats_extra()); + + for (unsigned i = 1; i <= n_groups; ++i) + { + // FIXME: should be removable when object_group will store the + // relation 'group -> comp' + // Special cases for lines with 1 or 2 components. + // { + int + cspace, + cwidth; + if (comps(i).nelements() == 1) + cspace = 0; + else + cspace = char_space(i).to_result(); + if (comps(i).nelements() == 2) + cwidth = (comp_set(comps(i)[0]).bbox().width() + + comp_set(comps(i)[1]).bbox().width()) / 2; + else + cwidth = char_width(i).to_result(); + // } + + + // Add line info. + line_info info(i, + bbox(i).to_result(), + comps(i), + absolute_median(i).to_result(), + absolute_baseline(i).to_result(), + cspace, + cwidth); + data_->infos_.append(info); + + + // Prepare extra stats to be returned. + line_stats_extra stats(absolute_median(i) * absolute_median(i).card(), + absolute_median(i).card(), + absolute_baseline(i) * absolute_baseline(i).card(), + absolute_baseline(i).card(), + char_space(i) * char_space(i).card(), + char_space(i).card(), + char_width(i) * char_width(i).card(), + char_width(i).card()); + stats_extra.append(stats); + } + + return stats_extra; + } + + + + template <typename L> + inline + mln_value(L) + line_set<L>::nelements() const + { + return data_->infos_.nelements() - 1; + } + + template <typename L> + inline + const line_info& + line_set<L>::info(const mln_value(L)& id) const + { + return this->data_->infos_[id]; + } + + template <typename L> + inline + line_info& + line_set<L>::info(const mln_value(L)& id) + { + return this->data_->infos_[id]; + } + + template <typename L> + inline + const line_info& + line_set<L>::operator()(const line_id_t& id) const + { + return this->data_->infos_[id]; + } + + template <typename L> + inline + line_info& + line_set<L>::operator()(const line_id_t& id) + { + return this->data_->infos_[id]; + } + + template <typename L> + template <typename F> + inline + void + line_set<L>::update_tags(const mln::Function_v2b<F>& f_, + line::Tag tag) + { + const F& f = exact(f_); + + for_all_elements(i, data_->infos_) + if (!f(i)) + data_->infos_[i].update_tag(tag); + } + + + template <typename L> + inline + line_set<L> + line_set<L>::duplicate() const + { + line_set<L> output; + output.init_(*this); + return output; + } + + template <typename L> + inline + const component_set<L>& + line_set<L>::component_set_() const + { + return data_->comp_set_; + } + + + template <typename L> + inline + const mln::util::array<scribo::line_info>& + line_set<L>::infos_() const + { + return data_->infos_; + } + + template <typename L> + inline + void + line_set<L>::init_(const line_set<L>& set) + { + data_ = new internal::line_set_data<L>(set.infos_(), set.component_set_()); + } + + + // Make routines. + + namespace make + { + + template <typename L> + scribo::line_set<L> + line_set(const object_links<L>& links, + const object_groups<L>& groups) + { + mln_precondition(exact(ima).is_valid()); + scribo::line_set<L> tmp(links, groups); + return tmp; + } + + template <typename L> + scribo::line_set<L> + line_set(const object_links<L>& links, + const object_groups<L>& groups, + util::array<line_stats_extra>& line_stats) + { + mln_precondition(exact(ima).is_valid()); + scribo::line_set<L> tmp; + line_stats = tmp.compute_lines(links, groups); + return tmp; + } + + } // end of namespace scribo::make + + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace scribo + +#endif // ! SCRIBO_CORE_LINE_SET_HH diff --git a/scribo/core/macros.hh b/scribo/core/macros.hh index ffca9ad..b7c5253 100644 --- a/scribo/core/macros.hh +++ b/scribo/core/macros.hh @@ -35,4 +35,15 @@ # define for_all_elements(E, S) \ for (unsigned E = 0; E < S.nelements(); ++E) + +// FIXME: we want to replace previous macros by these ones. +# define for_all_comps(C, S) \ + for (unsigned C = 1; C <= S.nelements(); ++C) + +# define for_all_comp_data(E, S) \ + for (unsigned E = 1; E < S.nelements(); ++E) + +# define for_all_lines(E, S) \ + for_all_comps(E, S) + #endif // ! SCRIBO_CORE_MACROS_HH diff --git a/scribo/core/object_groups.hh b/scribo/core/object_groups.hh index 15e2004..74e7043 100644 --- a/scribo/core/object_groups.hh +++ b/scribo/core/object_groups.hh @@ -1,4 +1,5 @@ -// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory +// (LRDE) // // This file is part of Olena. // @@ -35,7 +36,7 @@ # include <mln/util/array.hh> # include <scribo/core/object_links.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/component_set.hh> namespace scribo { @@ -47,25 +48,31 @@ namespace scribo // template <typename L> class object_groups - : public mln::util::array<unsigned> + // : public mln::util::array<unsigned> { - typedef mln::util::array<unsigned> super_t; +// typedef mln::util::array<unsigned> super_t; public: object_groups(); - object_groups(const object_image(L)& objects); - object_groups(const object_image(L)& objects, unsigned n); - object_groups(const object_image(L)& objects, unsigned n, unsigned value); + object_groups(const component_set<L>& components); + object_groups(const component_set<L>& components, unsigned value); - const void* objects_id_() const; - const object_image(L)& object_image_() const; + const component_set<L>& component_set_() const; void init_(const object_links<L>& links); bool is_valid() const; + unsigned nelements() const; + + unsigned& operator()(unsigned comp_id); + const unsigned& operator()(unsigned comp_id) const; + + const util::array<unsigned>& comp_to_group() const; + private: - object_image(L) objects_; + mln::util::array<unsigned> comp_to_group_; + component_set<L> components_; }; @@ -77,59 +84,76 @@ namespace scribo } template <typename L> - object_groups<L>::object_groups(const object_image(L)& objects) - : objects_(objects) + object_groups<L>::object_groups(const component_set<L>& components) + // : super_t(static_cast<unsigned>(components.nelements()) + 1), + : comp_to_group_(static_cast<unsigned>(components.nelements()) + 1), + components_(components) { } - template <typename L> - object_groups<L>::object_groups(const object_image(L)& objects, unsigned n) - : super_t(n), objects_(objects) + object_groups<L>::object_groups(const component_set<L>& components, + unsigned value) + // : super_t(static_cast<unsigned>(components.nelements()) + 1, value), + : comp_to_group_(static_cast<unsigned>(components.nelements()) + 1), + components_(components) { } - template <typename L> - object_groups<L>::object_groups(const object_image(L)& objects, - unsigned n, unsigned value) - : super_t(n, value), objects_(objects) + const component_set<L>& + object_groups<L>::component_set_() const { + return components_; + } + + template <typename L> + void + object_groups<L>::init_(const object_links<L>& links) + { + components_ = links.component_set_(); + comp_to_group_.hook_std_vector_() = links.std_vector(); } template <typename L> - const void* - object_groups<L>::objects_id_() const + bool + object_groups<L>::is_valid() const { - return objects_.id_(); + return components_.is_valid() && components_.nelements() == (this->size() - 1); } template <typename L> - const object_image(L)& - object_groups<L>::object_image_() const + unsigned + object_groups<L>::nelements() const { - return objects_; + return comp_to_group_.nelements(); } template <typename L> - void - object_groups<L>::init_(const object_links<L>& links) + unsigned& + object_groups<L>::operator()(unsigned comp_id) { - objects_ = links.object_image_(); - this->hook_std_vector_() = links.std_vector(); + return comp_to_group_(comp_id); } + template <typename L> - bool - object_groups<L>::is_valid() const + const unsigned& + object_groups<L>::operator()(unsigned comp_id) const { - return objects_.is_valid() && objects_.nlabels() == (this->size() - 1); + return comp_to_group_(comp_id); } + template <typename L> + const util::array<unsigned>& + object_groups<L>::comp_to_group() const + { + return comp_to_group_; + } # endif // ! MLN_INCLUDE_ONLY diff --git a/scribo/core/object_image.hh b/scribo/core/object_image.hh deleted file mode 100644 index 5eaae67..0000000 --- a/scribo/core/object_image.hh +++ /dev/null @@ -1,377 +0,0 @@ -// 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_OBJECT_IMAGE_HH -# define SCRIBO_CORE_OBJECT_IMAGE_HH - -/// \file -/// -/// \brief Definition of a morpher on a labeled image. - -# include <mln/core/internal/labeled_image_base.hh> - -# include <mln/core/routine/duplicate.hh> - -# include <mln/util/array.hh> - -# include <mln/data/compute.hh> - -# include <mln/accu/center.hh> -# include <mln/accu/shape/bbox.hh> -# include <mln/accu/stat/max.hh> - -# include <mln/labeling/compute.hh> - -namespace mln -{ - - // Forward declarations. - template <typename I> struct object_image; - - namespace internal - { - using namespace mln; - - /// Data structure for \c mln::object_image<I>. - template <typename I> - struct data< object_image<I> > - : data< labeled_image_base<I, object_image<I> > > - { - typedef data< labeled_image_base<I, object_image<I> > > super_; - typedef mln_psite(I) ms_t; - typedef mln_result(accu::center<mln_site(I)>) accu_res_t; - - data(const I& ima, const mln_value(I)& nlabels); - data(const I& ima, const mln_value(I)& nlabels, - const util::array<mln_box(I)>& bboxes, - const util::array<ms_t>& mass_centers); - data(const I& ima, const mln_value(I)& nlabels, - const util::array<mln_box(I)>& bboxes, - const util::array<accu_res_t>& mass_centers); - - mutable util::array<ms_t> mass_centers_; - - util::array<accu::center<mln_psite(I)> > tmp_accus_; - }; - - } // end of namespace mln::internal - - - namespace trait - { - - template <typename I> - struct image_< object_image<I> > - : image_< labeled_image_base< I, object_image<I> > > - { - }; - - } // end of namespace mln::trait - - - - /// Morpher providing an improved interface for labeled image. - /// - /// \tparam I The label image type. - /// - /// This image type allows to access every site set at a given - /// label. - /// - /// This image type guaranties that labels are contiguous (from 1 to - /// n). - /// - /// \ingroup modimageidmorpher - // - template <typename I> - class object_image - : public mln::labeled_image_base<I, object_image<I> > - { - typedef mln::labeled_image_base<I, object_image<I> > super_; - - public: - - /// Skeleton. - typedef object_image< tag::image_<I> > skeleton; - - /// Mass center type. - typedef typename internal::data< object_image<I> >::ms_t ms_t; - typedef mln_result(accu::center<mln_site(I)>) accu_res_t; - - /// Constructors - /// @{ - /// Constructor without argument. - object_image(); - - /// Constructor from an image \p ima and the number of labels \p nlabels. - object_image(const I& ima, const mln_value(I)& nlabels); - - /// Constructor from an image \p ima, the number of labels \p - /// nlabels and the object bounding boxes. - template <typename P> - object_image(const I& ima, const mln_value(I)& nlabels, - const util::array<mln_box(I)>& bboxes, - const util::array<P>& mass_centers); - /// @} - - /// Deferred initialization from a labeled image \p ima and the number - /// of labels \p nlabels. - void init_(const I& ima, const mln_value(I)& nlabels); - - /// Duplicate the underlying image and create a new object_image. - void init_from_(const object_image<I>& model); - - /// Return an array of mass centers. - const util::array<ms_t>& mass_centers() const; - - /// Return the mass center of an object with label \p label. - const mln_psite(I)& mass_center(const mln_value(I)& label) const; - - /// Return the underlying labeled image - const I& labeled_image_() const; - - /// Update mass centers when objects are merged. - void init_update_data_(); - void prepare_update_data_(const mln_value(I)& lbl, - const mln_value(I)& new_lbl); - void update_data_(const fun::i2v::array<mln_value(I)>& relabel_fun); - }; - - - // init_ - - //FIXME: not enough generic? We would like 'J' instead of - // 'object_image<I>'. - template <typename I, typename J> - void init_(tag::image_t, object_image<I>& target, - const object_image<J>& model); - - - - namespace make - { - - template <typename I> - mln::object_image<I> - object_image(const Image<I>& ima, const mln_value(I)& nlabels); - - } // end of namespace mln::make - - - - -# ifndef MLN_INCLUDE_ONLY - - - // internal::data< object_image<I> > - - namespace internal - { - - - // data< object_image<I> > - - template <typename I> - inline - data< object_image<I> >::data(const I& ima, const mln_value(I)& nlabels) - : super_(ima, nlabels) - { - } - - template <typename I> - inline - data< object_image<I> >::data(const I& ima, const mln_value(I)& nlabels, - const util::array<mln_box(I)>& bboxes, - const util::array<ms_t>& mass_centers) - : super_(ima, nlabels, bboxes), mass_centers_(mass_centers) - { - } - - - template <typename I> - inline - data< object_image<I> >::data(const I& ima, const mln_value(I)& nlabels, - const util::array<mln_box(I)>& bboxes, - const util::array<accu_res_t>& mass_centers) - : super_(ima, nlabels, bboxes) - { - convert::from_to(mass_centers, mass_centers_); - } - - - } // end of namespace mln::internal - - - template <typename I> - inline - object_image<I>::object_image() - { - } - - template <typename I> - inline - object_image<I>::object_image(const I& ima, const mln_value(I)& nlabels) - { - init_(ima, nlabels); - } - - template <typename I> - template <typename P> - inline - object_image<I>::object_image(const I& ima, const mln_value(I)& nlabels, - const util::array<mln_box(I)>& bboxes, - const util::array<P>& mass_centers) - { - mln_precondition(data::compute(accu::meta::stat::max(), ima) == nlabels); - this->data_ = new internal::data< object_image<I> >(ima, nlabels, - bboxes, mass_centers); - } - - - template <typename I> - inline - void - object_image<I>::init_(const I& ima, const mln_value(I)& nlabels) - { - mln_precondition(data::compute(accu::meta::stat::max(), ima) == nlabels); - this->data_ = new internal::data< object_image<I> >(ima, nlabels); - - // FIXME: could be improved! - this->data_->bboxes_ = labeling::compute(accu::meta::shape::bbox(), - this->data_->ima_, - this->data_->nlabels_); - convert::from_to(labeling::compute(accu::meta::center(), - this->data_->ima_, - this->data_->nlabels_), - this->data_->mass_centers_); - } - - - template <typename I> - inline - void - object_image<I>::init_from_(const object_image<I>& model) - { - typedef internal::data< object_image<I> > data_t; - this->data_ - = new data_t(duplicate(model.hook_data_()->ima_), - model.nlabels(), - model.hook_data_()->bboxes_, - model.hook_data_()->mass_centers_); - } - - - template <typename I> - inline - const util::array<typename object_image<I>::ms_t>& - object_image<I>::mass_centers() const - { - return this->data_->mass_centers_; - } - - template <typename I> - inline - const mln_psite(I)& - object_image<I>::mass_center(const mln_value(I)& label) const - { - return this->data_->mass_centers_(label); - } - - - template <typename I> - inline - const I& - object_image<I>::labeled_image_() const - { - return this->data_->ima_; - } - - template <typename I> - inline - void - object_image<I>::init_update_data_() - { - // this->nlabels_ is supposed to be updated when this method is - // called. - this->data_->tmp_accus_.resize(static_cast<unsigned>(this->data_->nlabels_) + 1); - } - - - template <typename I> - inline - void - object_image<I>::prepare_update_data_(const mln_value(I)& lbl, - const mln_value(I)& new_lbl) - { - this->data_->tmp_accus_[new_lbl].take(this->data_->mass_centers_[lbl]); - } - - - template <typename I> - inline - void - object_image<I>::update_data_( - const fun::i2v::array<mln_value(I)>& relabel_fun) - { - (void) relabel_fun; - convert::from_to(this->data_->tmp_accus_, this->data_->mass_centers_); - } - - - // init_ - - template <typename I, typename J> - void init_(tag::image_t, object_image<I>& target, - const object_image<J>& model) - { - I ima; - init_(tag::image, ima, model); - target.init_(ima, model.nlabels()); - } - - - // Make routines. - - namespace make - { - - template <typename I> - mln::object_image<I> - object_image(const Image<I>& ima, const mln_value(I)& nlabels) - { - mln_precondition(exact(ima).is_valid()); - mln::object_image<I> tmp(exact(ima), nlabels); - return tmp; - } - - } // end of namespace mln::make - - -# endif // ! MLN_INCLUDE_ONLY - -} // end of namespace mln - -# define object_image(L) mln::object_image<L> - -#endif // ! SCRIBO_CORE_OBJECT_IMAGE_HH diff --git a/scribo/core/object_links.hh b/scribo/core/object_links.hh index 1c020dd..af6a3da 100644 --- a/scribo/core/object_links.hh +++ b/scribo/core/object_links.hh @@ -34,7 +34,7 @@ # include <mln/util/array.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/component_set.hh> namespace scribo @@ -52,18 +52,15 @@ namespace scribo public: object_links(); - object_links(const object_image(L)& objects); - object_links(const object_image(L)& objects, unsigned n); - object_links(const object_image(L)& objects, unsigned n, unsigned value); + object_links(const component_set<L>& components); + object_links(const component_set<L>& components, unsigned value); - - const void* objects_id_() const; - const object_image(L)& object_image_() const; + const component_set<L>& component_set_() const; bool is_valid() const; private: - object_image(L) objects_; + component_set<L> components_; }; @@ -75,41 +72,28 @@ namespace scribo } template <typename L> - object_links<L>::object_links(const object_image(L)& objects) - : objects_(objects) + object_links<L>::object_links(const component_set<L>& components) + : super_t(static_cast<unsigned>(components.nelements()) + 1), + components_(components) { } template <typename L> - object_links<L>::object_links(const object_image(L)& objects, unsigned n) - : super_t(n), objects_(objects) + object_links<L>::object_links(const component_set<L>& components, + unsigned value) + : super_t(static_cast<unsigned>(components.nelements()) + 1, value), + components_(components) { } template <typename L> - object_links<L>::object_links(const object_image(L)& objects, - unsigned n, unsigned value) - : super_t(n, value), objects_(objects) - { - - } - - - template <typename L> - const void * - object_links<L>::objects_id_() const - { - return objects_.id_(); - } - - template <typename L> - const object_image(L)& - object_links<L>::object_image_() const + const component_set<L>& + object_links<L>::component_set_() const { - return objects_; + return components_; } @@ -117,7 +101,7 @@ namespace scribo bool object_links<L>::is_valid() const { - return objects_.is_valid() && objects_.nlabels() == (this->size() - 1); + return components_.is_valid() && components_.nelements() == (this->size() - 1); } diff --git a/scribo/core/anchors.hh b/scribo/core/tag/anchor.hh similarity index 77% copy from scribo/core/anchors.hh copy to scribo/core/tag/anchor.hh index a2994b1..262a32d 100644 --- a/scribo/core/anchors.hh +++ b/scribo/core/tag/anchor.hh @@ -38,9 +38,29 @@ namespace scribo Top, Bottom, Center, + ActualLeft, + Left, + ActualRight, + Right, + TopLeft, + TopRight, + BottomLeft, + BottomRight, Invalid }; + /// Values are based on coordinates indexes in a mln::point. + /// + /// For vertical direction only rows are supposed to change. So + /// anchor::Vertical is set to 0, like the row indexes in a + /// mln::point. + // + enum Direction + { + Vertical = 0, + Horizontal, + None + }; } } // end of namespace scribo diff --git a/scribo/draw/all.hh b/scribo/core/tag/component.hh similarity index 80% copy from scribo/draw/all.hh copy to scribo/core/tag/component.hh index e8ff2a7..7998f08 100644 --- a/scribo/draw/all.hh +++ b/scribo/core/tag/component.hh @@ -23,25 +23,35 @@ // exception does not however invalidate any other reasons why the // executable file might be covered by the GNU General Public License. -#ifndef SCRIBO_DRAW_ALL_HH -# define SCRIBO_DRAW_ALL_HH +#ifndef SCRIBO_CORE_TAG_COMPONENT_HH +# define SCRIBO_CORE_TAG_COMPONENT_HH /// \file /// -/// Include all headers located in scribo/draw. +/// \brief Component tags. namespace scribo { - /// Namespace of drawing routines. - namespace draw + // Component id tag. + struct ComponentId; + + + + namespace component { - } // end of namespace scribo::draw + enum Tag + { + None = 0, + Separator, + Ignored + }; + + + } // end of namespace scribo::component } // end of namespace scribo -# include <scribo/draw/bounding_boxes.hh> -# include <scribo/draw/bounding_box_links.hh> -#endif // ! SCRIBO_DRAW_ALL_HH +#endif // ! SCRIBO_CORE_TAG_COMP_HH diff --git a/scribo/core/anchors.hh b/scribo/core/tag/line.hh similarity index 81% rename from scribo/core/anchors.hh rename to scribo/core/tag/line.hh index a2994b1..085a550 100644 --- a/scribo/core/anchors.hh +++ b/scribo/core/tag/line.hh @@ -23,26 +23,34 @@ // exception does not however invalidate any other reasons why the // executable file might be covered by the GNU General Public License. -#ifndef SCRIBO_CORE_ANCHORS_HH -# define SCRIBO_CORE_ANCHORS_HH +#ifndef SCRIBO_CORE_TAG_LINE_HH +# define SCRIBO_CORE_TAG_LINE_HH + +/// \file +/// +/// \brief Line tags. namespace scribo { - namespace anchor + // Line id tag. + struct LineId; + + + namespace line { - enum Type + enum Tag { - MassCenter = 0, - Top, - Bottom, - Center, - Invalid + None = 0, + Separator, + Ignored }; - } + + } // end of namespace scribo::line } // end of namespace scribo -#endif // ! SCRIBO_CORE_ANCHORS_HH + +#endif // ! SCRIBO_CORE_TAG_COMP_HH diff --git a/scribo/draw/bounding_box_links.hh b/scribo/draw/bounding_box_links.hh index ed6337d..b2c425a 100644 --- a/scribo/draw/bounding_box_links.hh +++ b/scribo/draw/bounding_box_links.hh @@ -245,13 +245,13 @@ namespace scribo mln_precondition(input.is_valid()); - const object_image(L)& objects = links.object_image_(); + const component_set<L>& comp_set = links.component_set_(); for_all_components(i, links) if (links[i] != i && links[i] != 0) { mln_site(L) - p1 = primitive::link::internal::compute_anchor(objects, i, anchor), - p2 = primitive::link::internal::compute_anchor(objects, links[i], anchor); + p1 = primitive::link::internal::compute_anchor(comp_set, i, anchor), + p2 = primitive::link::internal::compute_anchor(comp_set, links[i], anchor); mln::draw::line(input, p1, p2, value); } diff --git a/scribo/filter/object_links_bbox_h_ratio.hh b/scribo/filter/object_links_bbox_h_ratio.hh index e030a86..261fbcb 100644 --- a/scribo/filter/object_links_bbox_h_ratio.hh +++ b/scribo/filter/object_links_bbox_h_ratio.hh @@ -38,7 +38,7 @@ # include <scribo/core/macros.hh> # include <scribo/core/object_links.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/component_set.hh> # include <scribo/filter/object_links_bbox_ratio.hh> namespace scribo @@ -49,10 +49,10 @@ namespace scribo using namespace mln; - /*! \brief Invalidate links between two objects with too different + /*! \brief Invalidate links between two components with too different height. - \param[in] objects An object image. + \param[in] components A component set. \param[in] links Link objects information. \param[in] max_h_ratio The maximum height ratio of two linked bounding boxes. @@ -61,7 +61,7 @@ namespace scribo */ template <typename L> object_links<L> - object_links_bbox_h_ratio(const object_image(L)& objects, + object_links_bbox_h_ratio(const component_set<L>& components, const object_links<L>& links, float max_h_ratio); @@ -71,17 +71,17 @@ namespace scribo template <typename L> object_links<L> - object_links_bbox_h_ratio(const object_image(L)& objects, + object_links_bbox_h_ratio(const component_set<L>& components, const object_links<L>& links, float max_h_ratio) { trace::entering("scribo::filter::object_links_bbox_h_ratio"); - mln_precondition(objects.is_valid()); + mln_precondition(components.is_valid()); mln_precondition(links.is_valid()); object_links<L> - output = object_links_bbox_ratio(objects, links, 0, max_h_ratio); + output = object_links_bbox_ratio(components, links, 0, max_h_ratio); trace::exiting("scribo::filter::object_links_bbox_h_ratio"); return output; diff --git a/scribo/filter/object_links_bbox_ratio.hh b/scribo/filter/object_links_bbox_ratio.hh index 2d9e507..bc5523c 100644 --- a/scribo/filter/object_links_bbox_ratio.hh +++ b/scribo/filter/object_links_bbox_ratio.hh @@ -36,7 +36,7 @@ # include <scribo/core/macros.hh> # include <scribo/core/object_links.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/component_set.hh> namespace scribo { @@ -46,11 +46,11 @@ namespace scribo using namespace mln; - /*! \brief Invalidate links between two objects with too different + /*! \brief Invalidate links between two components with too different height or width. - \param[in] objects An object image. - \param[in] links Link objects information. + \param[in] components An object image. + \param[in] links Link components information. \param[in] dim The dimension to use to compare bbox length. \param[in] max_ratio The maximum length ratio of two linked bounding boxes. @@ -59,7 +59,7 @@ namespace scribo */ template <typename L> object_links<L> - object_links_bbox_ratio(const object_image(L)& objects, + object_links_bbox_ratio(const component_set<L>& components, const object_links<L>& links, unsigned dim, float max_ratio); @@ -70,14 +70,14 @@ namespace scribo template <typename L> object_links<L> - object_links_bbox_ratio(const object_image(L)& objects, + object_links_bbox_ratio(const component_set<L>& components, const object_links<L>& links, unsigned dim, float max_ratio) { trace::entering("scribo::filter::object_links_bbox_ratio"); - mln_precondition(objects.is_valid()); + mln_precondition(components.is_valid()); mln_precondition(links.is_valid()); object_links<L> output(links); @@ -85,9 +85,10 @@ namespace scribo if (links[i] != i) { float - lmin = objects.bbox(i).pmax()[dim] - objects.bbox(i).pmin()[dim], - lmax = objects.bbox(links(i)).pmax()[dim] - - objects.bbox(links(i)).pmin()[dim]; + lmin = components(i).bbox().pmax()[dim] + - components(i).bbox().pmin()[dim], + lmax = components(links(i)).bbox().pmax()[dim] + - components(links(i)).bbox().pmin()[dim]; if (lmin > lmax) std::swap(lmin, lmax); diff --git a/scribo/filter/objects_small.hh b/scribo/filter/objects_small.hh index d1a0cf3..31112c9 100644 --- a/scribo/filter/objects_small.hh +++ b/scribo/filter/objects_small.hh @@ -23,12 +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_FILTER_OBJECTS_SMALL_HH -# define SCRIBO_FILTER_OBJECTS_SMALL_HH +#ifndef SCRIBO_FILTER_COMPONENTS_SMALL_HH +# define SCRIBO_FILTER_COMPONENTS_SMALL_HH /// \file /// -/// Remove small objects in a binary image. +/// Remove small components in a binary image. # include <mln/core/concept/image.hh> @@ -50,9 +50,9 @@ # include <mln/set/compute.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/component_set.hh> # include <scribo/fun/v2b/objects_small_filter.hh> -# include <scribo/primitive/extract/objects.hh> +# include <scribo/primitive/extract/components.hh> namespace scribo @@ -64,33 +64,33 @@ namespace scribo using namespace mln; - /// Remove small objects in a binary image. - /// Set to 'false' all the removed objects. + /// Remove small components in a binary image. + /// Set to 'false' all the removed components. /// /// \param[in] input_ A binary image. /// \param[in] nbh_ A neighborhood used for labeling \p input_. /// \param[in] label_type The label type used for labeling. /// \param[in] min_size The minimum cardinality of an object. /// - /// \return A binary image without small objects. + /// \return A binary image without small components. template <typename I, typename N, typename V> mln_concrete(I) - objects_small(const Image<I>& input_, - const Neighborhood<N>& nbh_, - const V& label_type, - unsigned min_size); + components_small(const Image<I>& input_, + const Neighborhood<N>& nbh_, + const V& label_type, + unsigned min_size); - /// Remove too small objects. + /// Remove too small components. /// - /// \param[in] objects An object image. + /// \param[in] components An object image. /// \param[in] min_size The minimum cardinality of an object. /// - /// \return An object image without small objects. + /// \return An object image without small components. template <typename L> - object_image(L) - objects_small(const object_image(L)& objects, - unsigned min_size); + component_set<L> + components_small(const component_set<L>& components, + unsigned min_size); # ifndef MLN_INCLUDE_ONLY @@ -99,12 +99,12 @@ namespace scribo template <typename I, typename N, typename V> inline mln_concrete(I) - objects_small(const Image<I>& input_, - const Neighborhood<N>& nbh_, - const V& label_type, - unsigned min_size) + components_small(const Image<I>& input_, + const Neighborhood<N>& nbh_, + const V& label_type, + unsigned min_size) { - trace::entering("scribo::filter::objects_small"); + trace::entering("scribo::filter::components_small"); const I& input = exact(input_); const N& nbh = exact(nbh_); @@ -115,9 +115,10 @@ namespace scribo V nlabels; typedef mln_ch_value(I,V) lbl_t; - object_image(lbl_t) lbl = primitive::extract::objects(input, nbh, nlabels); + component_set<lbl_t> + lbl = primitive::extract::components(input, nbh, nlabels); - typedef fun::v2b::objects_small_filter<mln_ch_value(I,V)> func_t; + typedef fun::v2b::components_small_filter<mln_ch_value(I,V)> func_t; func_t fv2b(lbl, min_size); lbl.relabel(fv2b); @@ -125,28 +126,27 @@ namespace scribo data::fill((output | (pw::value(lbl) == pw::cst(literal::zero))).rw(), false); - trace::exiting("scribo::filter::objects_small"); + trace::exiting("scribo::filter::components_small"); return output; } template <typename L> inline - object_image(L) - objects_small(const object_image(L)& objects, - unsigned min_size) + component_set<L> + components_small(const component_set<L>& components, + unsigned min_size) { - trace::entering("scribo::filter::objects_small"); + trace::entering("scribo::filter::components_small"); - mln_precondition(objects.is_valid()); + mln_precondition(components.is_valid()); - fun::v2b::objects_small_filter<L> f(objects, min_size); + fun::v2b::components_small_filter<L> f(components, min_size); - object_image(L) output; - output.init_from_(objects); - output.relabel(f); + component_set<L> output = components; + output.update_tags(f, component::Ignored); - trace::exiting("scribo::filter::objects_small"); + trace::exiting("scribo::filter::components_small"); return output; } @@ -157,4 +157,4 @@ namespace scribo } // end of namespace scribo -#endif // ! SCRIBO_FILTER_OBJECTS_SMALL_HH +#endif // ! SCRIBO_FILTER_COMPONENTS_SMALL_HH diff --git a/scribo/fun/v2b/objects_small_filter.hh b/scribo/fun/v2b/objects_small_filter.hh index 1ccac12..8e0ae8a 100644 --- a/scribo/fun/v2b/objects_small_filter.hh +++ b/scribo/fun/v2b/objects_small_filter.hh @@ -23,12 +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_FUN_V2B_OBJECTS_SMALL_FILTER_HH -# define SCRIBO_FUN_V2B_OBJECTS_SMALL_FILTER_HH +#ifndef SCRIBO_FUN_V2B_COMPONENTS_SMALL_FILTER_HH +# define SCRIBO_FUN_V2B_COMPONENTS_SMALL_FILTER_HH /// \file /// -/// Remove small objects in a binary image. +/// Remove small components in a binary image. @@ -40,7 +40,7 @@ # include <mln/labeling/compute.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/component_set.hh> namespace scribo @@ -56,20 +56,20 @@ namespace scribo /// Filter Functor. - /// Return false for all objects which are too small. + /// Return false for all components which are too small. template <typename L> - struct objects_small_filter - : Function_v2b< objects_small_filter<L> > + struct components_small_filter + : Function_v2b< components_small_filter<L> > { typedef accu::math::count<mln_psite(L)> card_t; /// Constructor /// - /// \param[in] objects Component bounding boxes. + /// \param[in] components Component bounding boxes. /// \param[in] min_size Minimum component size. // - objects_small_filter(const object_image(L)& objects, - unsigned min_size); + components_small_filter(const component_set<L>& components, + unsigned min_size); /// Check if the component is large enough. @@ -81,11 +81,11 @@ namespace scribo // bool operator()(const mln_value(L)& l) const; - /// The component bounding boxes. - mln::util::array<mln_result(card_t)> card_; - /// The minimum area. unsigned min_size_; + + /// The component set to filter. + const component_set<L> components_; }; @@ -96,12 +96,11 @@ namespace scribo template <typename L> inline - objects_small_filter<L>::objects_small_filter( - const object_image(L)& objects, + components_small_filter<L>::components_small_filter( + const component_set<L>& components, unsigned min_size) + : min_size_(min_size), components_(components) { - card_ = labeling::compute(card_t(), objects, objects.nlabels()); - min_size_ = min_size; } @@ -109,11 +108,11 @@ namespace scribo template <typename L> inline bool - objects_small_filter<L>::operator()(const mln_value(L)& l) const + components_small_filter<L>::operator()(const mln_value(L)& l) const { if (l == literal::zero) return true; - return card_[l] >= min_size_; + return components_.info(l).card() >= min_size_; } @@ -126,4 +125,4 @@ namespace scribo } // end of namespace scribo -#endif // ! SCRIBO_FUN_V2B_OBJECTS_SMALL_FILTER_HH +#endif // ! SCRIBO_FUN_V2B_COMPONENTS_SMALL_FILTER_HH diff --git a/scribo/primitive/extract/objects.hh b/scribo/primitive/extract/components.hh similarity index 62% rename from scribo/primitive/extract/objects.hh rename to scribo/primitive/extract/components.hh index 3f1af7c..f13904f 100644 --- a/scribo/primitive/extract/objects.hh +++ b/scribo/primitive/extract/components.hh @@ -23,30 +23,28 @@ // exception does not however invalidate any other reasons why the // executable file might be covered by the GNU General Public License. -#ifndef SCRIBO_PRIMITIVE_EXTRACT_OBJECTS_HH -# define SCRIBO_PRIMITIVE_EXTRACT_OBJECTS_HH +#ifndef SCRIBO_PRIMITIVE_EXTRACT_COMPONENTS_HH +# define SCRIBO_PRIMITIVE_EXTRACT_COMPONENTS_HH /// \file /// -/// Extract objects in a binary image. +/// Extract components in a binary image. # include <mln/core/concept/neighborhood.hh> # include <mln/core/site_set/box.hh> # include <mln/accu/shape/bbox.hh> +# include <mln/accu/center.hh> +# include <mln/accu/pair.hh> # include <mln/labeling/blobs_and_compute.hh> # include <mln/labeling/compute.hh> # include <mln/util/array.hh> -# include <mln/debug/println.hh> +# include <scribo/core/component_set.hh> -# include <scribo/core/object_image.hh> - -#include <mln/accu/shape/bbox.hh> -#include <mln/accu/center.hh> namespace scribo @@ -60,21 +58,21 @@ namespace scribo using namespace mln; - /// Extract objects in a binary image. + /// Extract components in a binary image. /// - /// \param[in] input A binary image. Objects are must be set + /// \param[in] input A binary image. Components are must be set /// to 'true' /// and background to 'false'. /// \param[in] nbh A neighborhood to be used for labeling. - /// \param[in,out] nobjects Will store the numbers of objects found. + /// \param[in,out] ncomponents Will store the numbers of components found. /// - /// \return An image of labeled objects. + /// \return An image of labeled components. // template <typename I, typename N, typename V> inline - object_image(mln_ch_value(I,V)) - objects(const Image<I>& input, - const Neighborhood<N>& nbh, V& nobjects); + component_set<mln_ch_value(I,V)> + components(const Image<I>& input, + const Neighborhood<N>& nbh, V& ncomponents); # ifndef MLN_INCLUDE_ONLY @@ -86,8 +84,8 @@ namespace scribo template <typename I, typename N, typename V> inline void - objects_tests(const Image<I>& input, - const Neighborhood<N>& nbh, V& nobjects) + components_tests(const Image<I>& input, + const Neighborhood<N>& nbh, V& ncomponents) { mlc_equal(mln_value(I),bool)::check(); mlc_is_a(V, mln::value::Symbolic)::check(); @@ -95,7 +93,7 @@ namespace scribo mln_precondition(exact(nbh).is_valid()); (void) input; (void) nbh; - (void) nobjects; + (void) ncomponents; } @@ -104,31 +102,29 @@ namespace scribo template <typename I, typename N, typename V> inline - object_image(mln_ch_value(I,V)) - objects(const Image<I>& input, - const Neighborhood<N>& nbh, V& nobjects) + component_set<mln_ch_value(I,V)> + components(const Image<I>& input, + const Neighborhood<N>& nbh, V& ncomponents) { - trace::entering("scribo::objects"); + trace::entering("scribo::components"); - internal::objects_tests(input, nbh, nobjects); + internal::components_tests(input, nbh, ncomponents); typedef mln_ch_value(I,V) L; - typedef accu::shape::bbox<mln_psite(I)> accu_bbox; - - util::couple<L, util::array<mln_box(I)> > - results = labeling::blobs_and_compute(input, nbh, nobjects, - accu_bbox()); - - // FIXME: enable mass centers computation and maybe merge this - // computation with blobs computation above. - util::array<mln_result(accu::center<mln_site(I)>)> - mass_centers; - mass_centers = labeling::compute(accu::meta::center(), - results.first(), nobjects); - object_image(L) - output(results.first(), nobjects, results.second(), mass_centers); - - trace::exiting("scribo::objects"); + typedef mln::accu::shape::bbox<mln_site(L)> bbox_accu_t; + typedef mln::accu::center<mln_site(L)> center_accu_t; + typedef mln::accu::pair<bbox_accu_t, center_accu_t> pair_accu_t; + + util::couple<L, + util::couple<util::array<mln_result(pair_accu_t)>, + util::array<pair_accu_t> > > + results = labeling::blobs_and_compute(input, nbh, ncomponents, + pair_accu_t()); + + component_set<L> + output(results.first(), ncomponents, results.second().second()); + + trace::exiting("scribo::components"); return output; } @@ -141,4 +137,4 @@ namespace scribo } // end of namespace scribo -#endif // ! SCRIBO_PRIMITIVE_EXTRACT_OBJECTS_HH +#endif // ! SCRIBO_PRIMITIVE_EXTRACT_COMPONENTS_HH diff --git a/scribo/primitive/group/apply.hh b/scribo/primitive/group/apply.hh index 02e75cd..b074b82 100644 --- a/scribo/primitive/group/apply.hh +++ b/scribo/primitive/group/apply.hh @@ -30,9 +30,13 @@ /// /// Apply grouping in an object image. +# include <mln/fun/i2v/array.hh> +# include <mln/make/relabelfun.hh> +# include <mln/labeling/relabel.hh> + # include <scribo/core/object_links.hh> # include <scribo/core/object_groups.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/component_set.hh> # include <scribo/primitive/group/from_single_link.hh> @@ -49,20 +53,20 @@ namespace scribo /*! \brief Apply grouping in an object image. - \param objects An object image. - \param groups An object group structure. + \param components A component set. + \param groups An object group structure. - \return A copy of \p objects with grouped objects. + \return A copy of \p components with grouped components. */ template <typename L> - object_image(L) - apply(const object_image(L)& objects, + component_set<L> + apply(const component_set<L>& components, const object_groups<L>& groups); /// \overload template <typename L> - object_image(L) - apply(const object_image(L)& objects, + component_set<L> + apply(const component_set<L>& components, const object_links<L>& links); @@ -71,21 +75,30 @@ namespace scribo template <typename L> - object_image(L) - apply(const object_image(L)& objects, + component_set<L> + apply(const component_set<L>& components, const object_groups<L>& groups) { trace::entering("scribo::primitive::group::apply"); - mln_precondition(objects.is_valid()); - mln_precondition(groups.nelements() == objects.nlabels().next()); - mln_precondition(groups.nelements() == objects.bboxes().nelements()); - mln_precondition(groups.objects_id_() == objects.id_()); + mln_precondition(components.is_valid()); + mln_precondition(groups.nelements() == components.nlabels().next()); + mln_precondition(groups.nelements() == components.bboxes().nelements()); + mln_precondition(groups.components_id_() == components.id_()); + + L labeled_image = duplicate(components.labeled_image()); + + mln_value(L) new_nlabels; + fun::i2v::array<mln_value(L)> + packed_relabel_fun = mln::make::relabelfun(groups, + components.nelements(), + new_nlabels); + new_nlabels = components.nelements(); + labeling::relabel_inplace(labeled_image, new_nlabels, + packed_relabel_fun); - object_image(L) output; - output.init_from_(objects); - output.relabel(groups); + component_set<L> output(labeled_image, new_nlabels); trace::exiting("scribo::primitive::group::apply"); return output; @@ -93,22 +106,22 @@ namespace scribo template <typename L> - object_image(L) - apply(const object_image(L)& objects, + component_set<L> + apply(const component_set<L>& components, const object_links<L>& links) { trace::entering("scribo::primitive::group::apply"); - mln_precondition(objects.is_valid()); - mln_precondition(links.nelements() == objects.nlabels().next()); - mln_precondition(links.nelements() == objects.bboxes().nelements()); - mln_precondition(links.objects_id_() == objects.id_()); + mln_precondition(components.is_valid()); + mln_precondition(links.nelements() == components.nlabels().next()); + mln_precondition(links.nelements() == components.bboxes().nelements()); + mln_precondition(links.components_id_() == components.id_()); - object_groups<L> group = group::from_single_link(objects, links); + object_groups<L> group = group::from_single_link(components, links); - object_image(L) output = apply(objects, links); + component_set<L> output = apply(components, links); trace::exiting("scribo::primitive::group::apply"); return output; diff --git a/scribo/primitive/group/from_single_link.hh b/scribo/primitive/group/from_single_link.hh index 2b53b67..c369edb 100644 --- a/scribo/primitive/group/from_single_link.hh +++ b/scribo/primitive/group/from_single_link.hh @@ -42,7 +42,7 @@ # include <scribo/core/object_groups.hh> # include <scribo/core/object_links.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/component_set.hh> # include <scribo/core/macros.hh> @@ -58,17 +58,17 @@ namespace scribo using namespace mln; /*! - \brief Link text objects with their neighbor line if they + \brief Link text components with their neighbor line if they have one. - \param[in] objects An object image. + \param[in] components A component set. \param[in] link_array The neighbor line of each line. \return Object groups information. */ template <typename L> object_groups<L> - from_single_link(const object_image(L)& objects, + from_single_link(const component_set<L>& components, const object_links<L>& link_array); @@ -77,17 +77,16 @@ namespace scribo template <typename L> inline object_groups<L> - from_single_link(const object_image(L)& objects, + from_single_link(const component_set<L>& components, const object_links<L>& link_array) { trace::entering("scribo::primitive::group::from_single_link"); - mln_precondition(objects.is_valid()); - mln_precondition(link_array.nelements() == objects.nlabels().next()); - mln_precondition(link_array.nelements() == objects.bboxes().nelements()); - mln_precondition(link_array.objects_id_() == objects.id_()); + mln_precondition(components.is_valid()); + mln_precondition(link_array.nelements() == components.nelements().next()); + mln_precondition(link_array.components_id_() == components.id_()); - object_groups<L> parent_array(objects); + object_groups<L> parent_array(components); parent_array.init_(link_array); for_all_components(i, parent_array) diff --git a/scribo/primitive/internal/find_root.hh b/scribo/primitive/internal/find_root.hh index 70499ec..4fa6d20 100644 --- a/scribo/primitive/internal/find_root.hh +++ b/scribo/primitive/internal/find_root.hh @@ -31,7 +31,7 @@ /// Find root in a parent array arrays. -# include <mln/util/array.hh> +# include <scribo/core/object_groups.hh> namespace scribo @@ -44,19 +44,21 @@ namespace scribo { /// Find root in a parent array arrays. + template <typename L> unsigned - find_root(mln::util::array<unsigned>& parent, unsigned x); + find_root(object_groups<L>& parent, unsigned x); # ifndef MLN_INCLUDE_ONLY + template <typename L> inline unsigned - find_root(mln::util::array<unsigned>& parent, unsigned x) + find_root(object_groups<L>& parent, unsigned x) { - if (parent[x] == x) + if (parent(x) == x) return x; else - return parent[x] = find_root(parent, parent[x]); + return parent(x) = find_root(parent, parent(x)); } # endif // ! MLN_INCLUDE_ONLY diff --git a/scribo/primitive/internal/init_link_array.hh b/scribo/primitive/internal/init_link_array.hh index c46dca0..aa85175 100644 --- a/scribo/primitive/internal/init_link_array.hh +++ b/scribo/primitive/internal/init_link_array.hh @@ -31,7 +31,8 @@ /// Initialize a link array. -# include <mln/util/array.hh> +# include <scribo/core/object_links.hh> +# include <scribo/core/component_set.hh> namespace scribo @@ -46,17 +47,23 @@ namespace scribo { /// Initialize a link array. + template <typename L> void - init_link_array(mln::util::array<unsigned>& link_array); + init_link_array(object_links<L>& link_array); # ifndef MLN_INCLUDE_ONLY + template <typename L> inline void - init_link_array(mln::util::array<unsigned>& link_array) + init_link_array(object_links<L>& link_array) { + const component_set<L>& comp_set = link_array.component_set_(); for (unsigned i = 0; i < link_array.nelements(); ++i) - link_array[i] = i; + if (comp_set(i).tag() == component::Ignored) + link_array[i] = 0; + else + link_array[i] = i; } # endif // ! MLN_INCLUDE_ONLY diff --git a/scribo/primitive/link/compute.hh b/scribo/primitive/link/compute.hh index 349721c..3782a50 100644 --- a/scribo/primitive/link/compute.hh +++ b/scribo/primitive/link/compute.hh @@ -32,6 +32,7 @@ # include <scribo/core/macros.hh> +# include <scribo/core/component_set.hh> # include <scribo/core/object_links.hh> # include <scribo/core/concept/link_functor.hh> # include <scribo/primitive/link/internal/find_link.hh> @@ -97,12 +98,15 @@ namespace scribo 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, anchor); - } + const typename F::component_set_t& + comp_set = functor.components(); + + for_all_ncomponents(current_object, comp_set.nelements()) + if (comp_set(current_object).tag() != component::Ignored) + { + functor.start_processing_object(current_object); //<-- start_processing_object + primitive::internal::find_link(functor, current_object, anchor); + } trace::exiting("scribo::primitive::link::compute"); return functor.links(); diff --git a/scribo/primitive/link/internal/compute_anchor.hh b/scribo/primitive/link/internal/compute_anchor.hh index 0d3b6f2..b1ca77d 100644 --- a/scribo/primitive/link/internal/compute_anchor.hh +++ b/scribo/primitive/link/internal/compute_anchor.hh @@ -33,8 +33,6 @@ # include <mln/math/min.hh> # include <mln/util/array.hh> -# include <scribo/core/object_image.hh> - namespace scribo { @@ -51,7 +49,7 @@ namespace scribo /*! \brief Return the proper anchor used to find a neighbor. - \param[in] objects An object image. + \param[in] components A component set. \param[in] current_object An object id. \param[in] anchor The expected anchor. @@ -74,7 +72,7 @@ namespace scribo */ template <typename L> mln_site(L) - compute_anchor(const object_image(L)& objects, + compute_anchor(const component_set<L>& components, unsigned current_object, anchor::Type anchor); @@ -82,32 +80,32 @@ namespace scribo template <typename L> mln_site(L) - compute_anchor(const object_image(L)& objects, + compute_anchor(const component_set<L>& components, unsigned current_object, anchor::Type anchor) { typedef mln_site(L) P; - unsigned h = objects.bbox(current_object).pmax().row() - - objects.bbox(current_object).pmin().row(); - unsigned w = objects.bbox(current_object).pmax().col() - - objects.bbox(current_object).pmin().col(); + unsigned h = components(current_object).bbox().pmax().row() + - components(current_object).bbox().pmin().row(); + unsigned w = components(current_object).bbox().pmax().col() + - components(current_object).bbox().pmin().col(); - mln_site(L) sp = objects.bbox(current_object).center(); + mln_site(L) sp = components(current_object).bbox().pcenter(); switch (anchor) { // Component masss center case anchor::MassCenter: - return objects.mass_center(current_object); + return components(current_object).mass_center(); // Bounding box top center case anchor::Top: if (h < 30) - sp.row() = objects.bbox(current_object).pmin().row() + sp.row() = components(current_object).bbox().pmin().row() + math::min(2u, (h + 1) / 2 - 1); else - sp.row() = objects.bbox(current_object).pmin().row() + sp.row() = components(current_object).bbox().pmin().row() + math::min(10u, h /10); break; @@ -115,49 +113,49 @@ namespace scribo // Bounding box bottom center case anchor::Bottom: if (h < 30) - sp.row() = objects.bbox(current_object).pmax().row() + sp.row() = components(current_object).bbox().pmax().row() - math::min(2u, (h + 1) / 2 - 1); else - sp.row() = objects.bbox(current_object).pmax().row() + sp.row() = components(current_object).bbox().pmax().row() - math::min(10u, h /10); break; // Bounding box center case anchor::Center: - return objects.bbox(current_object).center(); + return components(current_object).bbox().pcenter(); // Bounding box actual left center case anchor::ActualLeft: - return P(objects.bbox(current_object).center().row(), - objects.bbox(current_object).pmin().col()); + return P(components(current_object).bbox().pcenter().row(), + components(current_object).bbox().pmin().col()); // Bounding box left center case anchor::Left: if (w < 30) - sp.col() = objects.bbox(current_object).pmin().col() + sp.col() = components(current_object).bbox().pmin().col() + math::min(2u, (w + 1) / 2 - 1); else - sp.col() = objects.bbox(current_object).pmin().col() + sp.col() = components(current_object).bbox().pmin().col() + math::min(10u, w /10); break; // Bounding box actual right center case anchor::ActualRight: - return P(objects.bbox(current_object).center().row(), - objects.bbox(current_object).pmax().col()); + return P(components(current_object).bbox().pcenter().row(), + components(current_object).bbox().pmax().col()); // Bounding box right center case anchor::Right: if (w < 30) - sp.col() = objects.bbox(current_object).pmax().col() + sp.col() = components(current_object).bbox().pmax().col() - math::min(2u, (w + 1) / 2 - 1); else - sp.col() = objects.bbox(current_object).pmax().col() + sp.col() = components(current_object).bbox().pmax().col() - math::min(10u, w /10); break; @@ -165,16 +163,16 @@ namespace scribo // Bounding box top left case anchor::TopLeft: if (h < 30) - sp.row() = objects.bbox(current_object).pmin().row() + sp.row() = components(current_object).bbox().pmin().row() + math::min(2u, (h + 1) / 2 - 1); else - sp.row() = objects.bbox(current_object).pmin().row() + sp.row() = components(current_object).bbox().pmin().row() + math::min(10u, h /10); if (w < 30) - sp.col() = objects.bbox(current_object).pmin().col() + sp.col() = components(current_object).bbox().pmin().col() + math::min(2u, (w + 1) / 2 - 1); else - sp.col() = objects.bbox(current_object).pmin().col() + sp.col() = components(current_object).bbox().pmin().col() + math::min(10u, w /10); break; @@ -182,16 +180,16 @@ namespace scribo // Bounding box top right case anchor::TopRight: if (h < 30) - sp.row() = objects.bbox(current_object).pmin().row() + sp.row() = components(current_object).bbox().pmin().row() + math::min(2u, (h + 1) / 2 - 1); else - sp.row() = objects.bbox(current_object).pmin().row() + sp.row() = components(current_object).bbox().pmin().row() + math::min(10u, h /10); if (w < 30) - sp.col() = objects.bbox(current_object).pmax().col() + sp.col() = components(current_object).bbox().pmax().col() - math::min(2u, (w + 1) / 2 - 1); else - sp.col() = objects.bbox(current_object).pmax().col() + sp.col() = components(current_object).bbox().pmax().col() - math::min(10u, w /10); break; @@ -199,32 +197,32 @@ namespace scribo // Bounding box bottom left case anchor::BottomLeft: if (h < 30) - sp.row() = objects.bbox(current_object).pmax().row() + sp.row() = components(current_object).bbox().pmax().row() - math::min(2u, (h + 1) / 2 - 1); else - sp.row() = objects.bbox(current_object).pmax().row() + sp.row() = components(current_object).bbox().pmax().row() - math::min(10u, h /10); if (w < 30) - sp.col() = objects.bbox(current_object).pmin().col() + sp.col() = components(current_object).bbox().pmin().col() + math::min(2u, (w + 1) / 2 - 1); else - sp.col() = objects.bbox(current_object).pmin().col() + sp.col() = components(current_object).bbox().pmin().col() + math::min(10u, w /10); break; // Bounding box bottom right case anchor::BottomRight: if (h < 30) - sp.row() = objects.bbox(current_object).pmax().row() + sp.row() = components(current_object).bbox().pmax().row() - math::min(2u, (h + 1) / 2 - 1); else - sp.row() = objects.bbox(current_object).pmax().row() + sp.row() = components(current_object).bbox().pmax().row() - math::min(10u, h /10); if (w < 30) - sp.col() = objects.bbox(current_object).pmax().col() + sp.col() = components(current_object).bbox().pmax().col() - math::min(2u, (w + 1) / 2 - 1); else - sp.col() = objects.bbox(current_object).pmax().col() + sp.col() = components(current_object).bbox().pmax().col() - math::min(10u, w /10); break; diff --git a/scribo/primitive/link/internal/find_link.hh b/scribo/primitive/link/internal/find_link.hh index b950280..dd0b308 100644 --- a/scribo/primitive/link/internal/find_link.hh +++ b/scribo/primitive/link/internal/find_link.hh @@ -38,12 +38,8 @@ # include <mln/util/couple.hh> # include <scribo/core/concept/link_functor.hh> -# include <scribo/core/anchors.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/tag/anchor.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 @@ -86,11 +82,9 @@ namespace scribo start_point = functor.start_point(current_object, anchor), // <-- start_point p = start_point; - mln_postcondition(p == start_point); - // is_potential_link // verify_link_criterion - while (functor.objects().domain().has(p) + while (functor.components().labeled_image().domain().has(p) && ! functor.is_potential_link(current_object, start_point, p) && functor.verify_link_criterion(current_object, start_point, p)) diff --git a/scribo/primitive/link/internal/find_several_links.hh b/scribo/primitive/link/internal/find_several_links.hh index a690f10..d379021 100644 --- a/scribo/primitive/link/internal/find_several_links.hh +++ b/scribo/primitive/link/internal/find_several_links.hh @@ -41,12 +41,9 @@ # include <mln/util/couple.hh> # include <scribo/core/concept/link_functor.hh> -# include <scribo/core/anchors.hh> +# include <scribo/core/tag/anchor.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 diff --git a/scribo/primitive/link/internal/link_functor_base.hh b/scribo/primitive/link/internal/link_functor_base.hh index dcc43d4..65f897c 100644 --- a/scribo/primitive/link/internal/link_functor_base.hh +++ b/scribo/primitive/link/internal/link_functor_base.hh @@ -40,14 +40,12 @@ # include <mln/labeling/compute.hh> # include <mln/accu/center.hh> -# include <scribo/core/anchors.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/tag/anchor.hh> +# include <scribo/core/component_set.hh> # include <scribo/core/object_links.hh> # include <scribo/core/concept/link_functor.hh> # include <scribo/primitive/link/internal/compute_anchor.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 @@ -70,15 +68,16 @@ namespace scribo { public: + typedef component_set<L> component_set_t; typedef L support; typedef mln_site(L) P; typedef mln::util::couple<anchor::Type, P> couple_t; - link_functor_base(const object_image(L)& objects, unsigned nanchors); + link_functor_base(const component_set<L>& components, unsigned nanchors); /// \overload /// \p nanchors is set to 1. - link_functor_base(const object_image(L)& objects); + link_functor_base(const component_set<L>& components); unsigned nanchors() const; @@ -86,7 +85,7 @@ namespace scribo const object_links<L>& links() const; unsigned link(unsigned object) const; - const object_image(L)& objects() const; + const component_set<L>& components() const; void initialize_link(unsigned current_object); @@ -114,7 +113,7 @@ namespace scribo anchor::Type anchor); /// \overload - /// \p anchor is set to 0. + /// \p anchor is set to anchor::MassCenter. void validate_link(unsigned current_object, const P& start_point, const P& p); @@ -123,22 +122,18 @@ namespace scribo anchor::Type anchor); /// \overload - /// \p anchor is set to 0 + /// \p anchor is set to anchor::MassCenter 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, anchor::Type anchor); /// \overload - /// \p anchor is set to 0. + /// \p anchor is set to anchor::MassCenter. mln_site(L) start_point(unsigned current_object); @@ -179,9 +174,9 @@ namespace scribo protected: object_links<L> links_; - const object_image(L) objects_; + const component_set<L> components_; + const L& labeled_image_; unsigned nanchors_; - util::array<mln_result(accu::center<mln_site(L)>)> mass_centers_; }; @@ -192,31 +187,27 @@ namespace scribo template <typename L, typename E> inline link_functor_base<L,E>::link_functor_base( - const object_image(L)& objects, + const component_set<L>& components, unsigned nanchors) - : links_(objects, static_cast<unsigned>(objects.nlabels()) + 1), - objects_(objects), + : links_(components), + components_(components), + labeled_image_(this->components_.labeled_image()), nanchors_(nanchors) { primitive::internal::init_link_array(links_); - - mass_centers_ = labeling::compute(accu::meta::center(), - objects, objects.nlabels()); } 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), + const component_set<L>& components) + : links_(components), + components_(components), + labeled_image_(this->components_.labeled_image()), nanchors_(1) { primitive::internal::init_link_array(links_); - - mass_centers_ = labeling::compute(accu::meta::center(), - objects, objects.nlabels()); } @@ -247,10 +238,10 @@ namespace scribo template <typename L, typename E> inline - const object_image(L)& - link_functor_base<L,E>::objects() const + const component_set<L>& + link_functor_base<L,E>::components() const { - return objects_; + return components_; } @@ -264,9 +255,11 @@ namespace scribo 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 + mln_value(L) v = this->labeled_image_(p); + return v != literal::zero // Not the background + && v != current_object // Not the current component + && this->links_[v] != current_object // No loops + && this->components_(v).tag() != component::Ignored; // Not ignored } @@ -306,7 +299,7 @@ namespace scribo const P& start_point, const P& p) { - return this->objects_.domain().has(p) + return this->labeled_image_.domain().has(p) && exact(this)->valid_link_(current_object, start_point, p); } @@ -331,7 +324,7 @@ namespace scribo const P& start_point, const P& p) { - validate_link(current_object, start_point, p, 0); + validate_link(current_object, start_point, p, anchor::MassCenter); } @@ -354,7 +347,7 @@ namespace scribo const P& start_point, const P& p) { - invalidate_link(current_object, start_point, p, 0); + invalidate_link(current_object, start_point, p, anchor::MassCenter); } @@ -386,7 +379,7 @@ namespace scribo mln_site(L) link_functor_base<L,E>::start_point(unsigned current_object) { - return start_point(current_object, 0); + return start_point(current_object, anchor::MassCenter); } @@ -478,7 +471,7 @@ namespace scribo { (void) start_point; (void) anchor; - this->links_[current_object] = this->objects_(p); + this->links_[current_object] = this->labeled_image_(p); } @@ -505,7 +498,7 @@ namespace scribo anchor::Type anchor) { (void) anchor; - return internal::compute_anchor(this->objects_, mass_centers_, + return internal::compute_anchor(this->components_, current_object, anchor); } diff --git a/scribo/primitive/link/internal/link_several_dmax_base.hh b/scribo/primitive/link/internal/link_several_dmax_base.hh index 3d4fbae..e1f42ff 100644 --- a/scribo/primitive/link/internal/link_several_dmax_base.hh +++ b/scribo/primitive/link/internal/link_several_dmax_base.hh @@ -38,7 +38,7 @@ # include <mln/util/array.hh> # include <scribo/core/macros.hh> -# include <scribo/core/anchors.hh> +# include <scribo/core/tag/anchor.hh> # include <scribo/core/object_image.hh> # include <scribo/core/object_links.hh> diff --git a/scribo/primitive/link/internal/link_single_dmax_base.hh b/scribo/primitive/link/internal/link_single_dmax_base.hh index 8d594f5..d4d9d29 100644 --- a/scribo/primitive/link/internal/link_single_dmax_base.hh +++ b/scribo/primitive/link/internal/link_single_dmax_base.hh @@ -38,7 +38,7 @@ # include <mln/util/array.hh> # include <scribo/core/macros.hh> -# include <scribo/core/anchors.hh> +# include <scribo/core/tag/anchor.hh> # include <scribo/core/object_image.hh> # include <scribo/core/object_links.hh> diff --git a/scribo/primitive/link/internal/link_single_dmax_ratio_base.hh b/scribo/primitive/link/internal/link_single_dmax_ratio_base.hh index ebe0b6a..65806cc 100644 --- a/scribo/primitive/link/internal/link_single_dmax_ratio_base.hh +++ b/scribo/primitive/link/internal/link_single_dmax_ratio_base.hh @@ -39,8 +39,8 @@ # include <mln/util/array.hh> # include <scribo/core/macros.hh> -# include <scribo/core/anchors.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/tag/anchor.hh> +# include <scribo/core/component_set.hh> # include <scribo/core/object_links.hh> # include <scribo/primitive/link/internal/compute_anchor.hh> @@ -77,7 +77,7 @@ namespace scribo typedef mln_site(L) P; - link_single_dmax_ratio_base(const object_image(L)& objects, + link_single_dmax_ratio_base(const component_set<L>& components, float dmax_ratio, anchor::Direction direction); @@ -104,11 +104,11 @@ namespace scribo template <typename L, typename E> inline link_single_dmax_ratio_base<L, E>::link_single_dmax_ratio_base( - const object_image(L)& objects, + const component_set<L>& components, float dmax_ratio, anchor::Direction direction) - : super_(objects), + : super_(components), dmax_ratio_(dmax_ratio), dmax_(0), direction_(direction) @@ -137,7 +137,7 @@ namespace scribo anchor::Type anchor) { (void) anchor; - return internal::compute_anchor(this->objects_, + return internal::compute_anchor(this->components_, current_object, anchor); } @@ -149,10 +149,8 @@ namespace scribo 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()); + w = this->components_.info(current_object).bbox().width(), + h = this->components_.info(current_object).bbox().height(); dmax_ = (w / 2.0f) + (dmax_ratio_ * math::max(w, h)); } diff --git a/scribo/primitive/link/merge_double_link.hh b/scribo/primitive/link/merge_double_link.hh index f826048..0628cd6 100644 --- a/scribo/primitive/link/merge_double_link.hh +++ b/scribo/primitive/link/merge_double_link.hh @@ -45,7 +45,7 @@ # include <scribo/core/macros.hh> # include <scribo/core/object_links.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/component_set.hh> # include <scribo/primitive/internal/find_root.hh> # include <scribo/primitive/internal/is_link_valid.hh> # include <scribo/primitive/internal/init_link_array.hh> @@ -64,7 +64,7 @@ namespace scribo \brief Validate and merge double link information. A link must exist in both ways to be validated. - \param[in] objects The Lines of text. + \param[in] components The Lines of text. \param[in] left_link The left neighbor of each line of text. \param[in] right_link The right neighbor of each line of text. @@ -72,7 +72,7 @@ namespace scribo */ template <typename L> object_links<L> - merge_double_link(const object_image(L)& objects, + merge_double_link(const component_set<L>& components, const object_links<L>& left_link, const object_links<L>& right_link); @@ -84,26 +84,32 @@ namespace scribo template <typename L> inline object_links<L> - merge_double_link(const object_image(L)& objects, + merge_double_link(const component_set<L>& components, const object_links<L>& left_link, const object_links<L>& right_link) { trace::entering("scribo::primitive::link::merge_double_link"); - mln_precondition(objects.is_valid()); + mln_precondition(components.is_valid()); mln_precondition(left_link.nelements() == right_link.nelements()); - mln_precondition(left_link.objects_id_() == objects.id_()); - mln_precondition(right_link.objects_id_() == objects.id_()); + mln_precondition(left_link.components_id_() == components.id_()); + mln_precondition(right_link.components_id_() == components.id_()); object_links<L> merge(left_link); - for_all_ncomponents(i, objects.nlabels()) + for_all_ncomponents(i, components.nelements()) { - mln::util::couple<bool, unsigned> - nbh = primitive::internal::is_link_valid(left_link, right_link, i); - if (!nbh.first()) - merge[i] = i; + if (components(i).tag() == component::Ignored) + merge[i] = 0; + else + { + mln::util::couple<bool, unsigned> + nbh = primitive::internal::is_link_valid(left_link, + right_link, i); + if (!nbh.first()) + merge[i] = i; + } } trace::exiting("scribo::primitive::link::merge_double_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 index d59bbc1..8be4ae2 100644 --- a/scribo/primitive/link/with_single_left_link_dmax_ratio.hh +++ b/scribo/primitive/link/with_single_left_link_dmax_ratio.hh @@ -40,7 +40,7 @@ # include <mln/util/array.hh> # include <scribo/core/macros.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/component_set.hh> # include <scribo/core/object_links.hh> # include <scribo/primitive/link/internal/find_link.hh> @@ -58,9 +58,9 @@ namespace scribo namespace link { - /*! \brief Link objects with their left neighbor if exists. + /*! \brief Link components with their left neighbor if exists. - \param[in] objects An object image. + \param[in] components An component image. \param[in] dmax_ratio \return Object links data. @@ -76,8 +76,8 @@ namespace scribo template <typename L> inline object_links<L> - with_single_left_link_dmax_ratio(const object_image(L)& objects, - float dmax_ratio); + with_single_left_link_dmax_ratio(const component_set<L>& components, + float dmax_ratio); /// \overload @@ -85,7 +85,7 @@ namespace scribo template <typename L> inline object_links<L> - with_single_left_link_dmax_ratio(const object_image(L)& objects); + with_single_left_link_dmax_ratio(const component_set<L>& components); @@ -108,9 +108,9 @@ namespace scribo public: typedef mln_site(L) P; - single_left_dmax_ratio_functor(const object_image(L)& objects, - unsigned dmax) - : super_(objects, dmax, anchor::Horizontal) + single_left_dmax_ratio_functor(const component_set<L>& components, + unsigned dmax) + : super_(components, dmax, anchor::Horizontal) { } @@ -130,15 +130,15 @@ namespace scribo template <typename L> inline object_links<L> - with_single_left_link_dmax_ratio(const object_image(L)& objects, - float dmax_ratio) + with_single_left_link_dmax_ratio(const component_set<L>& components, + float dmax_ratio) { trace::entering("scribo::primitive::link::with_single_left_link_dmax_ratio"); - mln_precondition(objects.is_valid()); + mln_precondition(components.is_valid()); internal::single_left_dmax_ratio_functor<L> - functor(objects, dmax_ratio); + functor(components, dmax_ratio); object_links<L> output = compute(functor); @@ -150,9 +150,9 @@ namespace scribo template <typename L> inline object_links<L> - with_single_left_link_dmax_ratio(const object_image(L)& objects) + with_single_left_link_dmax_ratio(const component_set<L>& components) { - return with_single_left_link_dmax_ratio(objects, 3); + return with_single_left_link_dmax_ratio(components, 3); } diff --git a/scribo/primitive/link/with_single_right_link_bottom.hh b/scribo/primitive/link/with_single_right_link_bottom.hh index 3b1f6e7..747e15c 100644 --- a/scribo/primitive/link/with_single_right_link_bottom.hh +++ b/scribo/primitive/link/with_single_right_link_bottom.hh @@ -40,7 +40,7 @@ # include <mln/util/array.hh> # include <scribo/core/macros.hh> -# include <scribo/core/anchors.hh> +# include <scribo/core/tag/anchor.hh> # include <scribo/core/object_image.hh> # include <scribo/core/object_links.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 index cd8360f..858346e 100644 --- a/scribo/primitive/link/with_single_right_link_dmax_ratio.hh +++ b/scribo/primitive/link/with_single_right_link_dmax_ratio.hh @@ -40,11 +40,11 @@ # include <mln/util/array.hh> # include <scribo/core/macros.hh> -# include <scribo/core/object_image.hh> +# include <scribo/core/component_set.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/internal/link_single_dmax_ratio_base.hh> # include <scribo/primitive/link/compute.hh> @@ -60,7 +60,7 @@ namespace scribo /*! \brief Link objects with their right neighbor if exists. - \param[in] objects An object image. + \param[in] components A component set. \param[in] dmax_ratio \return Object links data. @@ -76,7 +76,7 @@ namespace scribo template <typename L> inline object_links<L> - with_single_right_link_dmax_ratio(const object_image(L)& objects, + with_single_right_link_dmax_ratio(const component_set<L>& components, float dmax_ratio); @@ -85,7 +85,7 @@ namespace scribo template <typename L> inline object_links<L> - with_single_right_link_dmax_ratio(const object_image(L)& objects); + with_single_right_link_dmax_ratio(const component_set<L>& components); @@ -108,9 +108,9 @@ namespace scribo public: typedef mln_site(L) P; - single_right_dmax_ratio_functor(const object_image(L)& objects, + single_right_dmax_ratio_functor(const component_set<L>& components, unsigned dmax) - : super_(objects, dmax, anchor::Horizontal) + : super_(components, dmax, anchor::Horizontal) { } @@ -130,15 +130,15 @@ namespace scribo template <typename L> inline object_links<L> - with_single_right_link_dmax_ratio(const object_image(L)& objects, + with_single_right_link_dmax_ratio(const component_set<L>& components, float dmax_ratio) { trace::entering("scribo::primitive::link::with_single_right_link_dmax_ratio"); - mln_precondition(objects.is_valid()); + mln_precondition(components.is_valid()); internal::single_right_dmax_ratio_functor<L> - functor(objects, dmax_ratio); + functor(components, dmax_ratio); object_links<L> output = compute(functor); @@ -150,9 +150,9 @@ namespace scribo template <typename L> inline object_links<L> - with_single_right_link_dmax_ratio(const object_image(L)& objects) + with_single_right_link_dmax_ratio(const component_set<L>& components) { - return with_single_right_link_dmax_ratio(objects, 3); + return with_single_right_link_dmax_ratio(components, 3); } diff --git a/scribo/primitive/link/with_single_right_link_top.hh b/scribo/primitive/link/with_single_right_link_top.hh index 1e3e0df..14a4f37 100644 --- a/scribo/primitive/link/with_single_right_link_top.hh +++ b/scribo/primitive/link/with_single_right_link_top.hh @@ -40,7 +40,7 @@ # include <mln/util/array.hh> # include <scribo/core/macros.hh> -# include <scribo/core/anchors.hh> +# include <scribo/core/tag/anchor.hh> # include <scribo/core/object_image.hh> # include <scribo/core/object_links.hh> -- 1.5.6.5
participants (1)
-
Guillaume Lazzara