* 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(a)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(a)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