* scribo/core/group_info.hh,
* scribo/core/internal/sort_comp_ids.hh: New.
* scribo/core/object_groups.hh,
* scribo/core/object_links.hh: Improve API.
* scribo/core/line_info.hh,
* scribo/core/line_set.hh,
* scribo/debug/decision_image.hh,
* scribo/estim/object_groups_mean_width.hh,
* scribo/filter/object_groups_mean_width.hh,
* scribo/filter/object_groups_size_ratio.hh,
* scribo/filter/object_groups_small.hh,
* scribo/filter/object_groups_with_holes.hh,
* scribo/filter/object_links_bbox_overlap.hh,
* scribo/filter/object_links_bbox_ratio.hh,
* scribo/filter/object_links_non_aligned_simple.hh,
* scribo/primitive/group/from_double_link_any.hh,
* scribo/primitive/group/from_single_link.hh,
* scribo/primitive/internal/is_link_valid.hh,
* scribo/primitive/link/internal/link_functor_base.hh,
* scribo/primitive/link/internal/link_several_dmax_base.hh,
* scribo/primitive/link/merge_double_link.hh,
* scribo/primitive/link/merge_double_link_closest_aligned.hh,
* tests/filter/object_groups_mean_width.cc,
* tests/filter/object_groups_size_ratio.cc,
* tests/filter/object_groups_small.cc,
* tests/filter/object_groups_with_holes.cc: Update code to take
API changes into account.
---
scribo/ChangeLog | 34 +++
scribo/scribo/core/group_info.hh | 184 ++++++++++++++++
.../sort_comp_ids.hh} | 57 +++---
scribo/scribo/core/line_info.hh | 140 ++++++++-----
scribo/scribo/core/line_set.hh | 66 ++++---
scribo/scribo/core/object_groups.hh | 228 +++++++++++++++-----
scribo/scribo/core/object_links.hh | 81 ++++++-
scribo/scribo/debug/decision_image.hh | 8 +-
scribo/scribo/estim/object_groups_mean_width.hh | 21 +--
scribo/scribo/filter/object_groups_mean_width.hh | 10 +-
scribo/scribo/filter/object_groups_size_ratio.hh | 16 +-
scribo/scribo/filter/object_groups_small.hh | 36 +---
scribo/scribo/filter/object_groups_with_holes.hh | 2 +-
scribo/scribo/filter/object_links_bbox_overlap.hh | 6 +-
scribo/scribo/filter/object_links_bbox_ratio.hh | 10 +-
.../filter/object_links_non_aligned_simple.hh | 6 +-
.../scribo/primitive/group/from_double_link_any.hh | 57 ++++--
scribo/scribo/primitive/group/from_single_link.hh | 13 --
scribo/scribo/primitive/internal/is_link_valid.hh | 12 +-
.../primitive/link/internal/link_functor_base.hh | 2 +-
.../link/internal/link_several_dmax_base.hh | 10 +-
scribo/scribo/primitive/link/merge_double_link.hh | 17 +-
.../link/merge_double_link_closest_aligned.hh | 6 +-
scribo/tests/filter/object_groups_mean_width.cc | 11 +-
scribo/tests/filter/object_groups_size_ratio.cc | 10 +-
scribo/tests/filter/object_groups_small.cc | 28 +--
scribo/tests/filter/object_groups_with_holes.cc | 10 +-
27 files changed, 743 insertions(+), 338 deletions(-)
create mode 100644 scribo/scribo/core/group_info.hh
copy scribo/scribo/core/{component_features_data.hh => internal/sort_comp_ids.hh}
(59%)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 8d95b3a..7bbfb9e 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,3 +1,37 @@
+2011-05-03 Guillaume Lazzara <lazzara(a)fidji.lrde.epita.fr>
+
+ Improve object_groups and object_links API.
+
+ * scribo/core/group_info.hh,
+ * scribo/core/internal/sort_comp_ids.hh: New.
+
+ * scribo/core/object_groups.hh,
+ * scribo/core/object_links.hh: Improve API.
+
+ * scribo/core/line_info.hh,
+ * scribo/core/line_set.hh,
+ * scribo/debug/decision_image.hh,
+ * scribo/estim/object_groups_mean_width.hh,
+ * scribo/filter/object_groups_mean_width.hh,
+ * scribo/filter/object_groups_size_ratio.hh,
+ * scribo/filter/object_groups_small.hh,
+ * scribo/filter/object_groups_with_holes.hh,
+ * scribo/filter/object_links_bbox_overlap.hh,
+ * scribo/filter/object_links_bbox_ratio.hh,
+ * scribo/filter/object_links_non_aligned_simple.hh,
+ * scribo/primitive/group/from_double_link_any.hh,
+ * scribo/primitive/group/from_single_link.hh,
+ * scribo/primitive/internal/is_link_valid.hh,
+ * scribo/primitive/link/internal/link_functor_base.hh,
+ * scribo/primitive/link/internal/link_several_dmax_base.hh,
+ * scribo/primitive/link/merge_double_link.hh,
+ * scribo/primitive/link/merge_double_link_closest_aligned.hh,
+ * tests/filter/object_groups_mean_width.cc,
+ * tests/filter/object_groups_size_ratio.cc,
+ * tests/filter/object_groups_small.cc,
+ * tests/filter/object_groups_with_holes.cc: Update code to take
+ API changes into account.
+
2011-04-07 Guillaume Lazzara <z(a)lrde.epita.fr>
Add test data in EXTRA_DIST.
diff --git a/scribo/scribo/core/group_info.hh b/scribo/scribo/core/group_info.hh
new file mode 100644
index 0000000..19a8ecc
--- /dev/null
+++ b/scribo/scribo/core/group_info.hh
@@ -0,0 +1,184 @@
+// Copyright (C) 2011 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_GROUP_INFO_HH
+# define SCRIBO_CORE_GROUP_INFO_HH
+
+/// \file
+///
+/// \brief Object groups representation.
+
+# include <mln/util/array.hh>
+
+# include <scribo/core/object_links.hh>
+# include <scribo/core/component_set.hh>
+
+# include <scribo/core/internal/sort_comp_ids.hh>
+# include <scribo/core/concept/serializable.hh>
+
+
+namespace scribo
+{
+
+ using namespace mln;
+
+ class group_info
+ {
+ public:
+ group_info();
+ group_info(unsigned id, const mln::util::array<component_id_t>& comps,
+ unsigned pixel_area, const box2d& bbox);
+ // used for incremental construction (xml loading).
+ group_info(unsigned id, unsigned pixel_area, const box2d& bbox,
+ bool valid = false);
+
+ const mln::util::array<component_id_t>& component_ids() const;
+
+ // Used for incremental construction (xml loading)
+ mln::util::array<component_id_t>& component_ids_();
+
+ bool is_valid() const;
+ void invalidate();
+
+ unsigned card() const;
+ unsigned id() const;
+ unsigned pixel_area() const;
+ const box2d& bbox() const;
+
+ private:
+ unsigned id_;
+ mln::util::array<component_id_t> comps_;
+ bool valid_;
+ unsigned pixel_area_;
+ box2d bbox_;
+ };
+
+ bool operator==(const group_info& lhs, const group_info& rhs);
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ group_info::group_info()
+ : valid_(false)
+ {
+ }
+
+ group_info::group_info(unsigned id, const mln::util::array<component_id_t>&
comps,
+ unsigned pixel_area, const box2d& bbox)
+ : id_(id), comps_(comps), valid_(true),
+ pixel_area_(pixel_area), bbox_(bbox)
+ {
+ }
+
+ group_info::group_info(unsigned id, unsigned pixel_area, const box2d& bbox, bool
valid)
+ : id_(id), valid_(valid),
+ pixel_area_(pixel_area), bbox_(bbox)
+ {
+ }
+
+ const mln::util::array<component_id_t>&
+ group_info::component_ids() const
+ {
+ return comps_;
+ }
+
+ mln::util::array<component_id_t>&
+ group_info::component_ids_()
+ {
+ return comps_;
+ }
+
+ bool group_info::is_valid() const
+ {
+ return valid_;
+ }
+
+ void
+ group_info::invalidate()
+ {
+ valid_ = false;
+ }
+
+ unsigned
+ group_info::card() const
+ {
+ return comps_.nelements();
+ }
+
+ unsigned
+ group_info::id() const
+ {
+ return id_;
+ }
+
+ unsigned
+ group_info::pixel_area() const
+ {
+ return pixel_area_;
+ }
+
+ const box2d&
+ group_info::bbox() const
+ {
+ return bbox_;
+ }
+
+ inline
+ std::ostream&
+ operator<<(std::ostream& ostr, const group_info& group_info)
+ {
+ ostr << "group_info[";
+
+ ostr << "id=" << group_info.id() << ", "
+ << "valid=" << group_info.is_valid() << ", "
+ << "pixel_area=" << group_info.pixel_area() << ",
"
+ << "bbox=" << group_info.bbox() << ", "
+ << "component_ids=" << group_info.component_ids();
+
+ ostr << "]";
+
+ return ostr;
+ }
+
+ inline
+ bool
+ operator==(const group_info& lhs, const group_info& rhs)
+ {
+ return
+ lhs.id() == rhs.id()
+ && lhs.component_ids() == rhs.component_ids()
+ && lhs.is_valid() == rhs.is_valid()
+ && lhs.pixel_area() == rhs.pixel_area()
+ && lhs.bbox() == rhs.bbox();
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_CORE_GROUP_INFO_HH
diff --git a/scribo/scribo/core/component_features_data.hh
b/scribo/scribo/core/internal/sort_comp_ids.hh
similarity index 59%
copy from scribo/scribo/core/component_features_data.hh
copy to scribo/scribo/core/internal/sort_comp_ids.hh
index 07b3e4a..83cd507 100644
--- a/scribo/scribo/core/component_features_data.hh
+++ b/scribo/scribo/core/internal/sort_comp_ids.hh
@@ -23,54 +23,55 @@
// 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_FEATURES_DATA_HH
-# define SCRIBO_CORE_COMPONENT_FEATURES_DATA_HH
+#ifndef SCRIBO_CORE_INTERNAL_SORT_COMP_IDS_HH
+# define SCRIBO_CORE_INTERNAL_SORT_COMP_IDS_HH
/// \file
///
-/// \brief Component features data structure.
+/// Functor ordering Components by location, from left to right.
-# include <scribo/core/def/color_type.hh>
+# include <scribo/core/component_set.hh>
+
namespace scribo
{
- struct component_features_data
+ namespace internal
{
- component_features_data();
-
- bool valid;
- scribo::def::color_type color;
- float boldness;
- };
+ template <typename L>
+ struct sort_comp_ids
+ {
+ sort_comp_ids(const component_set<L>& comp_set);
+ bool operator()(const component_id_t& l, const component_id_t& r) const;
- std::ostream&
- operator<<(std::ostream& ostr, const component_features_data& data);
+ component_set<L> comps_;
+ };
# ifndef MLN_INCLUDE_ONLY
- component_features_data::component_features_data()
- : valid(false)
- {
- }
+ template <typename L>
+ sort_comp_ids<L>::sort_comp_ids(const component_set<L>& comp_set)
+ : comps_(comp_set)
+ {
+ }
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const component_features_data& data)
- {
- return ostr << "features["
- << "valid=" << data.valid
- << ", color=" << data.color
- << ", boldness=" << data.boldness
- << "]" << std::endl;
- }
+ template <typename L>
+ bool
+ sort_comp_ids<L>::operator()(const component_id_t& l,
+ const component_id_t& r) const
+ {
+ return comps_(l).bbox().pmin().col() < comps_(r).bbox().pmin().col()
+ && comps_(l).bbox().pmax().col() < comps_(r).bbox().pmax().col();
+ }
# endif // ! MLN_INCLUDE_ONLY
+ } // end of namespace scribo::internal
+
} // end of namespace scribo
-#endif // ! SCRIBO_CORE_COMPONENT_FEATURES_DATA_HH
+#endif // ! SCRIBO_CORE_INTERNAL_SORT_COMP_IDS_HH
diff --git a/scribo/scribo/core/line_info.hh b/scribo/scribo/core/line_info.hh
index e925db7..b8a8be3 100644
--- a/scribo/scribo/core/line_info.hh
+++ b/scribo/scribo/core/line_info.hh
@@ -54,9 +54,11 @@
# include <scribo/core/tag/component.hh>
# include <scribo/core/tag/line.hh>
+# include <scribo/core/object_groups.hh>
# include <scribo/core/line_set.hh>
# include <scribo/core/component_set.hh>
+# include <scribo/core/internal/sort_comp_ids.hh>
# include <scribo/core/concept/serializable.hh>
@@ -79,14 +81,16 @@ namespace scribo
{
line_info_data();
line_info_data(const line_set<L>& holder,
- const mln::util::array<component_id_t>& comps);
-
+ const group_info& group);
+ // Used for incremental construction (xml loading)
+ line_info_data(const line_set<L>& holder,
+ const mln::util::array<component_id_t>& component_ids);
bool hidden_;
line::Tag tag_;
mln::box2d bbox_;
mln::box2d ebbox_;
- mln::util::array<component_id_t> components_;
+ mln::util::array<component_id_t> component_ids_;
// The number of pixels used for line characters.
unsigned pixel_area_;
@@ -138,21 +142,11 @@ namespace scribo
// Line set holding this element.
line_set<L> holder_;
- };
-
-
- // Functor used to sort components ids.
- // Order by location from left to right.
- template <typename L>
- struct sort_comp_ids
- {
- sort_comp_ids(const component_set<L>& comp_set);
- bool operator()(const component_id_t& l, const component_id_t& r) const;
+ private:
+ void init_();
- component_set<L> comps_;
};
-
} // end of namespace scribo::internal
@@ -176,7 +170,7 @@ namespace scribo
line_info(const line_set<L>& holder,
const line_id_t& id,
- const mln::util::array<component_id_t>& comps);
+ const group_info& group);
/// The line id of the target instance is preserved if it is valid.
line_info(const line_info<L>& other);
@@ -317,6 +311,10 @@ namespace scribo
std::ostream&
operator<<(std::ostream& ostr, const line_info<L>& info);
+ template <typename L>
+ bool
+ operator==(const line_info<L>& lhs, const line_info<L>& rhs);
+
# ifndef MLN_INCLUDE_ONLY
@@ -365,13 +363,28 @@ namespace scribo
hidden_ = false;
}
+ template <typename L>
+ line_info_data<L>::line_info_data(const line_set<L>& holder,
+ const group_info& group)
+ : hidden_(false), tag_(line::None), component_ids_(group.component_ids()),
+ type_(line::Undefined), holder_(holder)
+ {
+ init_();
+ }
template <typename L>
line_info_data<L>::line_info_data(const line_set<L>& holder,
- const mln::util::array<component_id_t>& comps)
- : hidden_(false), tag_(line::None), components_(comps),
+ const mln::util::array<component_id_t>& component_ids)
+ : hidden_(false), tag_(line::None), component_ids_(component_ids),
type_(line::Undefined), holder_(holder)
{
+ init_();
+ }
+
+ template <typename L>
+ void
+ line_info_data<L>::init_()
+ {
// FIXME: set valid information for these attributes in
// force_stats_update.
word_space_ = 0;
@@ -384,26 +397,6 @@ namespace scribo
indented_ = false;
}
-
-
- // sort_comp_ids functor
-
- template <typename L>
- sort_comp_ids<L>::sort_comp_ids(const component_set<L>& comp_set)
- : comps_(comp_set)
- {
- }
-
-
- template <typename L>
- bool
- sort_comp_ids<L>::operator()(const component_id_t& l,
- const component_id_t& r) const
- {
- return comps_(l).bbox().pmin().col() < comps_(r).bbox().pmin().col()
- && comps_(l).bbox().pmax().col() < comps_(r).bbox().pmax().col();
- }
-
} // end of namespace scribo::internal
@@ -480,10 +473,10 @@ namespace scribo
template <typename L>
line_info<L>::line_info(const line_set<L>& holder,
const line_id_t& id,
- const mln::util::array<component_id_t>& comps)
+ const group_info& group)
: id_(id)
{
- data_ = new data_t(holder, comps);
+ data_ = new data_t(holder, group);
force_stats_update();
}
@@ -540,7 +533,7 @@ namespace scribo
const mln::util::array<typename line_info<L>::component_id_t>&
line_info<L>::component_ids() const
{
- return data_->components_;
+ return data_->component_ids_;
}
@@ -548,7 +541,7 @@ namespace scribo
unsigned
line_info<L>::card() const
{
- return data_->components_.size();
+ return data_->component_ids_.size();
}
@@ -691,9 +684,9 @@ namespace scribo
void
line_info<L>::update_components_type(component::Type type)
{
- for_all_elements(i, data_->components_)
+ for_all_elements(i, data_->component_ids_)
{
- unsigned c = data_->components_[i];
+ unsigned c = data_->component_ids_[i];
data_->holder_.components_()(c).update_type(type);
}
}
@@ -954,7 +947,7 @@ namespace scribo
// Update bbox and ebbox
update_bbox_and_ebox(other);
- data_->components_.append(other.component_ids());
+ data_->component_ids_.append(other.component_ids());
}
@@ -1006,9 +999,9 @@ namespace scribo
// Workaround to avoid overflow with int_u<12> in median accumulators.
//
// FIXME: not optimal...
- for_all_elements(i, data_->components_)
+ for_all_elements(i, data_->component_ids_)
{
- unsigned c = data_->components_(i);
+ unsigned c = data_->component_ids_(i);
// Ignore punctuation for stats computation but not for bbox
// computation.
@@ -1020,9 +1013,9 @@ namespace scribo
unsigned used_comps = 0;
- for_all_elements(i, data_->components_)
+ for_all_elements(i, data_->component_ids_)
{
- unsigned c = data_->components_(i);
+ unsigned c = data_->component_ids_(i);
pixel_area += comp_set(c).card();
@@ -1111,8 +1104,8 @@ namespace scribo
// Order component ids according to component localization (left
// to right).
- std::sort(data_->components_.hook_std_vector_().begin(),
- data_->components_.hook_std_vector_().end(),
+ std::sort(data_->component_ids_.hook_std_vector_().begin(),
+ data_->component_ids_.hook_std_vector_().end(),
internal::sort_comp_ids<L>(comp_set));
// Boldness
@@ -1142,8 +1135,8 @@ namespace scribo
// Char width
if (card() == 2)
- data_->char_width_ = (comp_set(data_->components_[0]).bbox().width()
- + comp_set(data_->components_[1]).bbox().width()) / 2;
+ data_->char_width_ = (comp_set(data_->component_ids_[0]).bbox().width()
+ + comp_set(data_->component_ids_[1]).bbox().width()) / 2;
else
data_->char_width_ = char_width.to_result();
@@ -1218,6 +1211,47 @@ namespace scribo
}
+ template <typename L>
+ bool
+ operator==(const line_info<L>& lhs, const line_info<L>& rhs)
+ {
+ if (! lhs.is_valid() && ! rhs.is_valid())
+ return true;
+
+ return
+ lhs.is_valid() == rhs.is_valid()
+ && lhs.id() == rhs.id()
+ && lhs.pixel_area() == rhs.pixel_area()
+ && lhs.tag() == rhs.tag()
+ && lhs.type() == rhs.type()
+ && lhs.bbox() == rhs.bbox()
+ && lhs.ebbox() == rhs.ebbox()
+ && lhs.boldness() == rhs.boldness()
+ && lhs.boldness_reliability() == rhs.boldness_reliability()
+ && lhs.color() == rhs.color()
+ && lhs.color_reliability() == rhs.color_reliability()
+ && lhs.component_ids() == rhs.component_ids()
+ && lhs.baseline() == rhs.baseline()
+ && lhs.meanline() == rhs.meanline()
+ && lhs.ascent() == rhs.ascent()
+ && lhs.descent() == rhs.descent()
+ && lhs.x_height() == rhs.x_height()
+ && lhs.d_height() == rhs.d_height()
+ && lhs.a_height() == rhs.a_height()
+ && lhs.char_space() == rhs.char_space()
+ && lhs.char_width() == rhs.char_width()
+ && lhs.word_space() == rhs.word_space()
+ && lhs.reading_orientation() == rhs.reading_orientation()
+ && lhs.type() == rhs.type()
+ && lhs.reverse_video() == rhs.reverse_video()
+ && lhs.orientation() == rhs.orientation()
+ && lhs.reading_orientation() == rhs.reading_orientation()
+ && lhs.indented() == rhs.indented()
+ && lhs.is_hidden() == rhs.is_hidden()
+ && lhs.text() == rhs.text()
+ && lhs.html_text() == rhs.html_text();
+ }
+
# endif// ! MLN_INCLUDE_ONLY
diff --git a/scribo/scribo/core/line_set.hh b/scribo/scribo/core/line_set.hh
index f1e443b..db987e6 100644
--- a/scribo/scribo/core/line_set.hh
+++ b/scribo/scribo/core/line_set.hh
@@ -123,6 +123,9 @@ namespace scribo
/// Return line information for a given line id \p id.
const line_info<L>& operator()(const line_id_t& id) const;
+ /// Return all the line information.
+ const mln::util::array<line_info<L> >& infos() 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);
@@ -166,7 +169,6 @@ namespace scribo
void update_line_data_(const mln::util::array<line_info<L> >&
line_data);
-
private:
/// Duplicate the underlying image and create a new line_set.
void init_(const line_set<L>& model);
@@ -174,6 +176,11 @@ namespace scribo
mln::util::tracked_ptr< internal::line_set_data<L> > data_;
};
+
+ template <typename L>
+ bool
+ operator==(const line_set<L>& lhs, const line_set<L>& rhs);
+
template <typename L>
std::ostream&
operator<<(std::ostream& ostr, const line_set<L>& lines);
@@ -260,38 +267,14 @@ namespace scribo
{
data_ = new internal::line_set_data<L>(groups);
- typedef mln_site(L) P;
-
- 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'.
- mln::util::array< mln::util::array<component_id_t> >
- group_to_comps(value::next(n_groups));
-
-
- // 1st pass - Compute data.
- for_all_comps(i, data_->components_)
- if (data_->components_(i).is_valid())
- {
- unsigned group_id = packed_groups(i);
- if (group_id != 0) // Is this component part of a group?
- {
- // Component id.
- group_to_comps(group_id).append(i);
- }
- }
-
// 2nd pass - Store data.
- data_->infos_.reserve(group_to_comps.size());
+ data_->infos_.reserve(groups.nelements());
data_->infos_.append(line_info<L>()); // line with id 0 is invalid.
- for_all_groups(i, group_to_comps)
+ for_all_groups(i, groups)
{
// Add line info.
- line_info<L> info(*this, i, group_to_comps(i));
+ line_info<L> info(*this, i, groups(i));
data_->infos_.append(info);
}
}
@@ -339,6 +322,13 @@ namespace scribo
}
template <typename L>
+ const mln::util::array<line_info<L> >&
+ line_set<L>::infos() const
+ {
+ return this->data_->infos_;
+ }
+
+ template <typename L>
template <typename F>
inline
void
@@ -437,6 +427,26 @@ namespace scribo
data_ = new internal::line_set_data<L>(set.infos_(), set.groups());
}
+ template <typename L>
+ bool
+ operator==(const line_set<L>& lhs, const line_set<L>& rhs)
+ {
+ if (! (lhs.groups() == rhs.groups() && lhs.nelements() == rhs.nelements()))
+ {
+ std::cout << "line.group" << std::endl;
+ return false;
+ }
+
+ for_all_lines(l, lhs)
+ if ( ! (lhs(l) != rhs(l)))
+ {
+ std::cout << "line.info" << std::endl;
+ return false;
+ }
+
+ return true;
+ }
+
template <typename L>
diff --git a/scribo/scribo/core/object_groups.hh b/scribo/scribo/core/object_groups.hh
index 2a4b0b1..1cc8815 100644
--- a/scribo/scribo/core/object_groups.hh
+++ b/scribo/scribo/core/object_groups.hh
@@ -36,8 +36,13 @@
# include <scribo/core/object_links.hh>
# include <scribo/core/component_set.hh>
+# include <scribo/core/group_info.hh>
+# include <scribo/core/internal/sort_comp_ids.hh>
# include <scribo/core/concept/serializable.hh>
+// Not to include.
+//#include <scribo/core/line_info.hh>
+
namespace scribo
{
@@ -47,7 +52,6 @@ namespace scribo
// Forward declaration.
template <typename L> class object_groups;
-
namespace internal
{
/// Data structure for \c scribo::object_groups<I>.
@@ -56,9 +60,12 @@ namespace scribo
{
object_groups_data();
object_groups_data(const object_links<L>& links);
- object_groups_data(const object_links<L>& links, unsigned value);
+ object_groups_data(const object_links<L>& links,
+ const mln::util::array<group_info>& info);
mln::util::array<unsigned> comp_to_group_;
+ mln::util::array<group_info> group_info_;
+
component_set<L> components_;
object_links<L> links_;
};
@@ -78,26 +85,34 @@ namespace scribo
public:
object_groups();
object_groups(const object_links<L>& links);
- object_groups(const object_links<L>& links, unsigned value);
+ // Used for incremental construction (xml loading)
+ object_groups(const object_links<L>& links,
+ const mln::util::array<group_info>& info);
const component_set<L>& components() const;
const object_links<L>& links() const;
- void init_(const object_links<L>& links);
-
bool is_valid() const;
- bool is_valid(unsigned comp_id) const;
+
+ // Return the number of groups
unsigned nelements() const;
- unsigned& operator()(unsigned comp_id);
- const unsigned& operator()(unsigned comp_id) const;
+ /// Return the group id of the component \p comp_id.
+ const group_info& group_of(unsigned comp_id) const;
+ group_info& group_of(unsigned comp_id);
+
+ /// Return group info data for group with id \p group_id.
+ /// Valid id starts from 1.
+ const group_info& operator()(unsigned group_id) const;
+ group_info& operator()(unsigned group_id);
+
+ // Map component ids to group ids.
const mln::util::array<unsigned>& comp_to_group() const;
object_groups<L> duplicate() const;
- void init();
private: // attributes
mln::util::tracked_ptr<data_t> data_;
@@ -108,6 +123,10 @@ namespace scribo
std::ostream&
operator<<(std::ostream& ostr, const object_groups<L>& groups);
+ template <typename L>
+ bool
+ operator==(const object_groups<L>& lhs, const object_groups<L>&
rhs);
+
# ifndef MLN_INCLUDE_ONLY
@@ -127,17 +146,93 @@ namespace scribo
: comp_to_group_(unsigned(links.nelements())),
components_(links.components()), links_(links)
{
- };
-
+ comp_to_group_ = links.comp_to_link();
+
+ unsigned ngroups = 0;
+ util::array<unsigned> new_id(comp_to_group_.nelements(), 0);
+ mln::util::array<mln::util::array<component_id_t> > comp_ids(1);
+ mln::util::array<accu::shape::bbox<mln_site(L)> > bboxes(1);
+ mln::util::array<unsigned> pixel_areas(1);
+
+ // Remove potential loops in linking
+ // FIXME: we may try to avoid loops while linking...
+ {
+ util::array<bool> deja_vu(comp_to_group_.nelements());
+ for_all_elements(e, comp_to_group_)
+ if (comp_to_group_(e) != e && comp_to_group_(e) != 0)
+ {
+ deja_vu.fill(false); // FIXME: ugly!
+ unsigned cur = e;
+ deja_vu(cur) = true;
+ while (comp_to_group_(cur) != cur && !deja_vu(comp_to_group_(cur)))
+ {
+ cur = comp_to_group_(cur);
+ deja_vu(cur) = true;
+ }
+ // Break the loop!
+ if (comp_to_group_(cur) != cur && deja_vu(comp_to_group_(cur)))
+ comp_to_group_(cur) = cur;
+ }
+ }
+
+ for_all_elements(e, comp_to_group_)
+ if (comp_to_group_(e) != 0)
+ {
+ // Make sure there is no intermediate ids to reach the root.
+ // FIXME: useful?
+ unsigned e_root = internal::find_root(comp_to_group_, e);
+
+ if (! new_id(e_root))
+ {
+ new_id(e_root) = ++ngroups;
+ comp_ids.resize(comp_ids.size() + 1);
+ bboxes.resize(bboxes.size() + 1);
+ pixel_areas.resize(pixel_areas.size() + 1, 0);
+ }
+
+ unsigned nid = new_id(e_root);
+ comp_ids(nid).append(e);
+
+ bboxes(nid).take(components_(e).bbox());
+ pixel_areas(nid) += components_(e).card();
+ }
+
+ group_info_.resize(1);
+ group_info_.reserve(ngroups);
+ util::array<unsigned> group_idx(ngroups + 1, 0);
+
+ for (unsigned i = 1; i < new_id.nelements(); ++i)
+ if (new_id(i))
+ {
+ unsigned id = new_id(i);
+
+ // Order component ids according to component localization (left
+ // to right).
+ std::sort(comp_ids(id).hook_std_vector_().begin(),
+ comp_ids(id).hook_std_vector_().end(),
+ internal::sort_comp_ids<L>(components_));
+
+ group_idx(id) = group_info_.size();
+ group_info_.append(group_info(group_info_.size(), comp_ids(id), pixel_areas(id),
bboxes(id)));
+ }
+
+ // Update mapping comp/group with new ids. Note: group id is
+ // different from its location in group_info array during
+ // construction.
+ for (unsigned i = 0; i < comp_to_group_.nelements(); ++i)
+ comp_to_group_(i) = group_idx(new_id(comp_to_group_(i)));
+ }
template <typename L>
object_groups_data<L>::object_groups_data(const object_links<L>&
links,
- unsigned value)
- : comp_to_group_(unsigned(links.nelements()), value),
+ const mln::util::array<group_info>& info)
+ : comp_to_group_(unsigned(links.nelements())), group_info_(info),
components_(links.components()), links_(links)
{
- };
-
+ for_all_groups(g, group_info_)
+ for_all_elements(e, group_info_(g).component_ids())
+ comp_to_group_(group_info_(g).component_ids()(e)) = group_info_(g).id();
+ }
} // end of namespace scribo::internal
@@ -154,9 +249,10 @@ namespace scribo
}
template <typename L>
- object_groups<L>::object_groups(const object_links<L>& links, unsigned
value)
+ object_groups<L>::object_groups(const object_links<L>& links,
+ const mln::util::array<group_info>& info)
{
- data_ = new data_t(links, value);
+ data_ = new data_t(links, info);
}
template <typename L>
@@ -175,60 +271,66 @@ namespace scribo
}
template <typename L>
- void
- object_groups<L>::init_(const object_links<L>& links)
- {
- mln_assertion(data_ != 0);
- data_->comp_to_group_ = links.comp_to_link();
- }
-
- template <typename L>
bool
object_groups<L>::is_valid() const
{
- mln_assertion(data_->components_.nelements() == (nelements() - 1));
+ mln_assertion(data_->components_.nelements() ==
data_->comp_to_group_.nelements() - 1);
return data_->links_.is_valid();
}
template <typename L>
- bool
- object_groups<L>::is_valid(unsigned comp_id) const
+ unsigned
+ object_groups<L>::nelements() const
{
- mln_assertion(is_valid());
- mln_assertion(comp_id < data_->links_.nelements());
- return data_->links_(comp_id) != 0;
+ return data_->group_info_.nelements();
}
template <typename L>
- unsigned
- object_groups<L>::nelements() const
+ const group_info&
+ object_groups<L>::group_of(unsigned comp_id) const
{
- return data_->comp_to_group_.nelements();
+ mln_precondition(comp_id < data_->comp_to_group_.nelements());
+ mln_assertion(data_->group_info_(data_->comp_to_group_(comp_id)).id()
+ == data_->comp_to_group_(comp_id));
+ return data_->group_info_(data_->comp_to_group_(comp_id));
}
+ template <typename L>
+ group_info&
+ object_groups<L>::group_of(unsigned comp_id)
+ {
+ mln_precondition(comp_id < data_->comp_to_group_.nelements());
+ mln_assertion(data_->group_info_(data_->comp_to_group_(comp_id)).id()
+ == data_->comp_to_group_(comp_id));
+ return data_->group_info_(data_->comp_to_group_(comp_id));
+ }
template <typename L>
- unsigned&
- object_groups<L>::operator()(unsigned comp_id)
+ const util::array<unsigned>&
+ object_groups<L>::comp_to_group() const
{
- return data_->comp_to_group_(comp_id);
+ return data_->comp_to_group_;
}
template <typename L>
- const unsigned&
- object_groups<L>::operator()(unsigned comp_id) const
+ const group_info&
+ object_groups<L>::operator()(unsigned group_id) const
{
- return data_->comp_to_group_(comp_id);
+ mln_precondition(group_id < data_->group_info_.nelements());
+ return data_->group_info_(group_id);
}
+
template <typename L>
- const mln::util::array<unsigned>&
- object_groups<L>::comp_to_group() const
+ group_info&
+ object_groups<L>::operator()(unsigned group_id)
{
- return data_->comp_to_group_;
+ mln_precondition(group_id < data_->group_info_.nelements());
+ return data_->group_info_(group_id);
}
+
template <typename L>
inline
object_groups<L>
@@ -242,22 +344,15 @@ namespace scribo
}
template <typename L>
- void
- object_groups<L>::init()
- {
- for (unsigned i = 0; i < nelements(); ++i)
- data_->comp_to_group_(i) = i;
- }
-
-
- template <typename L>
std::ostream&
operator<<(std::ostream& ostr, const object_groups<L>& groups)
{
ostr << "object_groups[";
for_all_groups(g, groups)
- ostr << g << "->" << groups.comp_to_group()[g]
<< ", ";
+ ostr << groups(g) << ", ";
+
+ ostr << " | comp_to_group=" << groups.comp_to_group();
ostr << "]";
@@ -265,6 +360,33 @@ namespace scribo
}
+ template <typename L>
+ bool
+ operator==(const object_groups<L>& lhs, const object_groups<L>&
rhs)
+ {
+ if (! (lhs.components() == rhs.components()))
+ {
+ std::cout << "group.comp" << std::endl;
+ return false;
+ }
+
+ if (!( lhs.comp_to_group() == rhs.comp_to_group() && lhs.nelements() ==
rhs.nelements()))
+ {
+ std::cout << "group.comp_to_group" << std::endl;
+ return false;
+ }
+
+
+ for_all_groups(g, lhs)
+ if (! (lhs(g) == rhs(g)))
+ {
+ std::cout << "group.info" << std::endl;
+ return false;
+ }
+
+ return true;
+ }
+
# endif // ! MLN_INCLUDE_ONLY
diff --git a/scribo/scribo/core/object_links.hh b/scribo/scribo/core/object_links.hh
index 1fbcd5a..386de41 100644
--- a/scribo/scribo/core/object_links.hh
+++ b/scribo/scribo/core/object_links.hh
@@ -39,7 +39,6 @@
# include <scribo/core/concept/serializable.hh>
-
namespace scribo
{
@@ -51,6 +50,18 @@ namespace scribo
namespace internal
{
+
+ inline
+ unsigned
+ find_root(mln::util::array<unsigned>& parent, unsigned x)
+ {
+ if (parent(x) == x)
+ return x;
+ else
+ return parent(x) = find_root(parent, parent(x));
+ }
+
+
/// Data structure for \c scribo::object_links<I>.
template <typename L>
struct object_links_data
@@ -83,13 +94,36 @@ namespace scribo
const component_set<L>& components() const;
+ /// Return True if this object_links structure is correctly
+ /// constructed.
bool is_valid() const;
- bool is_valid(unsigned comp_id) const;
+
+ /// Return True if component \p comp_id can be linked to another
+ /// component.
+ bool has_linking_enabled(unsigned comp_id) const;
+
+ /// Return True if component \p comp_id has a link starting from
+ /// itself to another one.
+ bool is_linked(unsigned comp_id) const;
unsigned nelements() const;
- unsigned& operator()(unsigned comp_id);
+ /// Link related methods.
+ /// \{
+ /// Set link between component \p from_id and \p to_id.
+ void update(unsigned from_id, unsigned to_id);
+
+ /// Reset link for component with id \p id. This component can be
+ /// linked later.
+ void clear(unsigned id);
+
+ /// Do not allow component with id \p id to be linked to anyother
+ /// ones.
+ void disable_linking(unsigned id);
+
+ /// Get link id for component \p comp_id.
const unsigned& operator()(unsigned comp_id) const;
+ /// \}
const mln::util::array<unsigned>& comp_to_link() const;
@@ -183,13 +217,25 @@ namespace scribo
template <typename L>
bool
- object_links<L>::is_valid(unsigned comp_id) const
+ object_links<L>::has_linking_enabled(unsigned comp_id) const
{
mln_precondition(is_valid());
mln_precondition(comp_id < data_->comp_to_link_.nelements());
+
return data_->comp_to_link_(comp_id) != 0;
}
+ template <typename L>
+ bool
+ object_links<L>::is_linked(unsigned comp_id) const
+ {
+ mln_precondition(is_valid());
+ mln_precondition(comp_id < data_->comp_to_link_.nelements());
+
+ return has_linking_enabled(comp_id)
+ && data_->comp_to_link_(comp_id) != comp_id;
+ }
+
template <typename L>
unsigned
@@ -200,20 +246,32 @@ namespace scribo
template <typename L>
- unsigned&
- object_links<L>::operator()(unsigned comp_id)
+ const unsigned&
+ object_links<L>::operator()(unsigned comp_id) const
{
return data_->comp_to_link_(comp_id);
}
+ template <typename L>
+ void
+ object_links<L>::update(unsigned from_id, unsigned to_id)
+ {
+ data_->comp_to_link_(from_id) = to_id;
+ }
template <typename L>
- const unsigned&
- object_links<L>::operator()(unsigned comp_id) const
+ void
+ object_links<L>::clear(unsigned id)
{
- return data_->comp_to_link_(comp_id);
+ data_->comp_to_link_(id) = id;
}
+ template <typename L>
+ void
+ object_links<L>::disable_linking(unsigned id)
+ {
+ data_->comp_to_link_(id) = 0;
+ }
template <typename L>
const mln::util::array<unsigned>&
@@ -222,16 +280,15 @@ namespace scribo
return data_->comp_to_link_;
}
-
template <typename L>
void
object_links<L>::init()
{
for (unsigned i = 0; i < nelements(); ++i)
if (data_->components_(i).tag() == component::Ignored)
- data_->comp_to_link_(i) = 0;
+ disable_linking(i);
else
- data_->comp_to_link_(i) = i;
+ clear(i);
}
template <typename L>
diff --git a/scribo/scribo/debug/decision_image.hh
b/scribo/scribo/debug/decision_image.hh
index aa1a188..ff298e6 100644
--- a/scribo/scribo/debug/decision_image.hh
+++ b/scribo/scribo/debug/decision_image.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2009, 2010, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -150,10 +150,10 @@ namespace scribo
for_all_comps(i, comps)
mln::draw::box(decision_image, comps(i).bbox(), literal::blue);
- for (unsigned i = 1; i < links.nelements(); ++i)
+ for_all_links(i, links)
{
- if (links(i) != i)
+ if (links.is_linked(i))
{
mln_site(L)
p1 = primitive::link::internal::compute_anchor(comps, i, anchor),
diff --git a/scribo/scribo/estim/object_groups_mean_width.hh
b/scribo/scribo/estim/object_groups_mean_width.hh
index c74137a..65d843c 100644
--- a/scribo/scribo/estim/object_groups_mean_width.hh
+++ b/scribo/scribo/estim/object_groups_mean_width.hh
@@ -72,24 +72,17 @@ namespace scribo
const component_set<L>& components = groups.components();
- //FIXME: remove when object_groups will store the number of
- //elements per group.
- mln::util::array<unsigned> group_card(groups.nelements(), 0.0);
-
mln::util::array<float> output(groups.nelements(), 0.0);
- for_all_comps(i, components)
- if (components(i).is_valid())
- {
- output(groups(i)) += components(i).bbox().width();
- ++group_card(groups(i));
- }
+ for_all_groups(g, groups)
+ for_all_elements(e, groups(g).component_ids())
+ output(g) += components(groups(g).component_ids()(e)).bbox().width();
output(0) = 0;
- for_all_groups(i, output)
- if (components(i).is_valid())
- output(i) /= static_cast<float>(group_card(i));
+ for_all_groups(g, groups)
+ if (groups(g).is_valid())
+ output(g) /= groups(g).card();
else
- output(i) = 0;
+ output(g) = 0;
trace::exiting("scribo::estim::object_groups_mean_width");
return output;
diff --git a/scribo/scribo/filter/object_groups_mean_width.hh
b/scribo/scribo/filter/object_groups_mean_width.hh
index 0668205..b9c7b8a 100644
--- a/scribo/scribo/filter/object_groups_mean_width.hh
+++ b/scribo/scribo/filter/object_groups_mean_width.hh
@@ -77,11 +77,11 @@ namespace scribo
group_width = estim::object_groups_mean_width(groups);
object_groups<L> output = groups.duplicate();
- output(0) = 0;
- for (unsigned i = 1; i < output.nelements(); ++i)
- if (groups.components()(i).is_valid()
- && group_width[groups(i)] < width)
- output(i) = 0;
+
+ for_all_groups(g, groups)
+ if (groups(g).is_valid()
+ && group_width[g] < width)
+ output(g).invalidate();
trace::exiting("scribo::filter::object_groups_mean_width");
return output;
diff --git a/scribo/scribo/filter/object_groups_size_ratio.hh
b/scribo/scribo/filter/object_groups_size_ratio.hh
index 01676c4..6f2e33e 100644
--- a/scribo/scribo/filter/object_groups_size_ratio.hh
+++ b/scribo/scribo/filter/object_groups_size_ratio.hh
@@ -65,29 +65,23 @@ namespace scribo
const component_set<L>& comps = groups.components();
- // FIXME: estimating the group size should be removed once
- // available in the object_group structure.
// Counting the number of objects per group with a size ratio >
// max_ratio.
mln::util::array<unsigned>
- group_size(groups.nelements(), 0),
invalid_object_in_group(groups.nelements(), 0);
for_all_comps(i, comps)
{
if ((comps(i).bbox().height() / comps(i).bbox().width())
= max_size_ratio)
-
++invalid_object_in_group(groups(i));
-
- ++group_size(groups(i));
+ ++invalid_object_in_group(groups.group_of(i).id());
}
object_groups<L> output(groups);
- output(0) = 0;
- for (unsigned i = 1; i < output.nelements(); ++i)
- if ((invalid_object_in_group(groups(i)) /
static_cast<float>(group_size(groups(i)))) >= max_invalid_ratio_per_group
- || !comps(i).is_valid())
- output(i) = 0;
+ for_all_groups(g, groups)
+ if ((invalid_object_in_group(g) / static_cast<float>(groups(g).card())) >=
max_invalid_ratio_per_group
+ || !groups(g).is_valid())
+ output(g).invalidate();
trace::exiting("scribo::filter::object_groups_size_ratio");
return output;
diff --git a/scribo/scribo/filter/object_groups_small.hh
b/scribo/scribo/filter/object_groups_small.hh
index 8dd244c..dd92852 100644
--- a/scribo/scribo/filter/object_groups_small.hh
+++ b/scribo/scribo/filter/object_groups_small.hh
@@ -50,7 +50,6 @@ namespace scribo
\param[in] groups Information about object groups.
\param[in] n_links The minimum number of links per group.
- \param[out] group_size Return the group sizes _before_ filtering.
\return A copy of object group in which small groups have been
removed.
@@ -58,13 +57,6 @@ namespace scribo
template <typename L>
object_groups<L>
object_groups_small(const object_groups<L>& groups,
- unsigned n_links,
- mln::util::array<unsigned>& group_size);
-
- // \overload
- template <typename L>
- object_groups<L>
- object_groups_small(const object_groups<L>& groups,
unsigned n_links);
@@ -76,42 +68,22 @@ namespace scribo
inline
object_groups<L>
object_groups_small(const object_groups<L>& groups,
- unsigned n_links,
- mln::util::array<unsigned>& group_size)
+ unsigned n_links)
{
trace::entering("scribo::filter::object_groups_small");
mln_precondition(groups.is_valid());
- // Counting the number of objects per group.
- group_size = mln::util::array<unsigned>(groups.nelements(), 0);
- for_all_groups(i, group_size)
- ++group_size[groups(i)];
-
object_groups<L> output = groups.duplicate();
- output(0) = 0;
+
for_all_groups(i, output)
- if (group_size[groups(i)] < n_links
- || !groups.components()(i).is_valid())
- output(i) = 0;
+ if (output(i).is_valid() && output(i).card() < n_links)
+ output(i).invalidate();
trace::exiting("scribo::filter::object_groups_small");
return output;
}
-
- template <typename L>
- inline
- object_groups<L>
- object_groups_small(const object_groups<L>& groups,
- unsigned n_links)
- {
- mln::util::array<unsigned> group_size;
- return object_groups_small(groups, n_links, group_size);
- }
-
-
-
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace scribo::filter
diff --git a/scribo/scribo/filter/object_groups_with_holes.hh
b/scribo/scribo/filter/object_groups_with_holes.hh
index b86b10e..a59beec 100644
--- a/scribo/scribo/filter/object_groups_with_holes.hh
+++ b/scribo/scribo/filter/object_groups_with_holes.hh
@@ -298,7 +298,7 @@ namespace scribo
object_groups<L> output = groups.duplicate();
for_all_groups(c, groups)
if (! to_keep(group_2_comp(c)))
- output(c) = 0;
+ output(c).invalidate();
trace::exiting("scribo::filter::impl::generic::object_groups_with_holes");
return output;
diff --git a/scribo/scribo/filter/object_links_bbox_overlap.hh
b/scribo/scribo/filter/object_links_bbox_overlap.hh
index 995ad68..3bf3c50 100644
--- a/scribo/scribo/filter/object_links_bbox_overlap.hh
+++ b/scribo/scribo/filter/object_links_bbox_overlap.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2009, 2010, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -109,7 +109,7 @@ namespace scribo
if (ratio_i >= max_overlap_ratio
|| ratio_link_i >= max_overlap_ratio)
- output(i) = i;
+ output.clear(i);
}
trace::exiting("scribo::filter::object_links_bbox_overlap");
diff --git a/scribo/scribo/filter/object_links_bbox_ratio.hh
b/scribo/scribo/filter/object_links_bbox_ratio.hh
index 5318b57..d6c9286 100644
--- a/scribo/scribo/filter/object_links_bbox_ratio.hh
+++ b/scribo/scribo/filter/object_links_bbox_ratio.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2009, 2010, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -78,10 +78,10 @@ namespace scribo
mln_precondition(links.is_valid());
const component_set<L>& components = links.components();
-
object_links<L> output = links.duplicate();
+
for_all_links(i, links)
- if (links(i) && links(i) != i)
+ if (links.is_linked(i))
{
float
lmin = components(i).bbox().pmax()[dim]
@@ -93,7 +93,7 @@ namespace scribo
std::swap(lmin, lmax);
if ((lmax/ lmin) > max_ratio)
- output(i) = i;
+ output.clear(i);
}
trace::exiting("scribo::filter::object_links_bbox_ratio");
diff --git a/scribo/scribo/filter/object_links_non_aligned_simple.hh
b/scribo/scribo/filter/object_links_non_aligned_simple.hh
index 5abf598..f8db5cf 100644
--- a/scribo/scribo/filter/object_links_non_aligned_simple.hh
+++ b/scribo/scribo/filter/object_links_non_aligned_simple.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2009, 2010, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -112,7 +112,7 @@ namespace scribo
if (!::scribo::filter::internal::component_aligned_rad(comps, i, links(i),
anchor,
max_alpha_rad))
- output(i) = i;
+ output.clear(i);
trace::exiting("scribo::filter::object_links_non_aligned_simple");
diff --git a/scribo/scribo/primitive/group/from_double_link_any.hh
b/scribo/scribo/primitive/group/from_double_link_any.hh
index b3bd82a..7ed15e2 100644
--- a/scribo/scribo/primitive/group/from_double_link_any.hh
+++ b/scribo/scribo/primitive/group/from_double_link_any.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2010, 2011 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of Olena.
//
@@ -42,6 +43,7 @@
# include <scribo/core/macros.hh>
+# include <scribo/core/object_links.hh>
# include <scribo/core/object_groups.hh>
# include <scribo/core/component_set.hh>
# include <scribo/primitive/internal/find_root.hh>
@@ -73,6 +75,21 @@ namespace scribo
# ifndef MLN_INCLUDE_ONLY
+ namespace internal
+ {
+
+ template <typename L>
+ util::array<unsigned> make_parent(const object_links<L>& link)
+ {
+ mln::util::array<unsigned> parent = link.comp_to_link();
+ for_all_links(l, link)
+ parent(l) = scribo::internal::find_root(parent, l);
+
+ return parent;
+ }
+
+ } // end of namespace scribo::primitive::group::internal
+
template <typename L>
inline
@@ -82,40 +99,46 @@ namespace scribo
{
trace::entering("scribo::primitive::group::from_double_link_any");
- object_groups<L> parent(left_link);
- parent.init();
+ object_links<L> merged_link(left_link.components());
+ merged_link.init();
+
+ util::array<unsigned> lparent = internal::make_parent(left_link);
+ util::array<unsigned> rparent = internal::make_parent(right_link);
- for_all_comps(i, left_link.components())
+ for_all_links(i, merged_link)
{
+ // Looking for new left link
unsigned
- pi = internal::find_root(parent, i),
- pli = internal::find_root(parent, left_link(i));
+ pi = scribo::internal::find_root(lparent, i),
+ pli = scribo::internal::find_root(lparent, left_link(i));
if (pi != pli)
{
- if (pli < pi)
- parent(pli) = pi;
+ merged_link.update(i, left_link(i));
+ if (pi < pli)
+ lparent(pli) = pi;
else
- parent(pi) = pli;
+ lparent(pi) = pli;
}
- pi = internal::find_root(parent, i);
- unsigned pri = internal::find_root(parent, right_link(i));
+ // Looking for new right link
+ pi = scribo::internal::find_root(lparent, i);
+ unsigned pri = scribo::internal::find_root(rparent, right_link(i));
if (pi != pri)
{
- if (pri < pi)
- parent(pri) = pi;
+ merged_link.update(i, right_link(i));
+ if (pi < pli)
+ lparent(pli) = pi;
else
- parent(pi) = pri;
+ lparent(pi) = pli;
}
}
- for_all_groups(g, parent)
- internal::find_root(parent, g);
+ object_groups<L> output(merged_link);
trace::exiting("scribo::primitive::group::from_double_link_any");
- return parent;
+ return output;
}
diff --git a/scribo/scribo/primitive/group/from_single_link.hh
b/scribo/scribo/primitive/group/from_single_link.hh
index 05efdc7..0a2cca3 100644
--- a/scribo/scribo/primitive/group/from_single_link.hh
+++ b/scribo/scribo/primitive/group/from_single_link.hh
@@ -82,19 +82,6 @@ namespace scribo
mln_precondition(links.is_valid());
object_groups<L> parent(links);
- parent.init_(links);
-
- for_all_groups(i, parent)
- if (!links.components()(i).is_valid())
- parent(i) = 0;
- else
- ::scribo::primitive::internal::find_root(parent, i);
-
-
- // FIXME: useful?
- // Make sure the root is propagated.
- for_all_groups(g, parent)
- internal::find_root(parent, g);
trace::exiting("scribo::primitive::group::from_single_link");
return parent;
diff --git a/scribo/scribo/primitive/internal/is_link_valid.hh
b/scribo/scribo/primitive/internal/is_link_valid.hh
index b18e55c..30823cb 100644
--- a/scribo/scribo/primitive/internal/is_link_valid.hh
+++ b/scribo/scribo/primitive/internal/is_link_valid.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2009, 2010, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -51,9 +51,8 @@ namespace scribo
/// \param[in] i The component id.
///
/// \return True if the link is between the \p i-th component
- /// and it neighbor is validated.
template <typename L>
- mln::util::couple<bool,unsigned>
+ bool
is_link_valid(const object_links<L>& left_link,
const object_links<L>& right_link,
unsigned i);
@@ -61,13 +60,12 @@ namespace scribo
# ifndef MLN_INCLUDE_ONLY
template <typename L>
- mln::util::couple<bool,unsigned>
+ bool
is_link_valid(const object_links<L>& left_link,
const object_links<L>& right_link,
unsigned i)
{
- bool b = (right_link(left_link(i)) == i && left_link(i) != i);
- return mln::make::couple(b, left_link(i));
+ return left_link.is_linked(i) && right_link(left_link(i)) == i;
}
# endif // ! MLN_INCLUDE_ONLY
diff --git a/scribo/scribo/primitive/link/internal/link_functor_base.hh
b/scribo/scribo/primitive/link/internal/link_functor_base.hh
index 11066c5..a509126 100644
--- a/scribo/scribo/primitive/link/internal/link_functor_base.hh
+++ b/scribo/scribo/primitive/link/internal/link_functor_base.hh
@@ -477,7 +477,7 @@ namespace scribo
{
(void) start_point;
(void) anchor;
- this->links_(current_object) = this->labeled_image_(p);
+ this->links_.update(current_object, this->labeled_image_(p));
}
diff --git a/scribo/scribo/primitive/link/internal/link_several_dmax_base.hh
b/scribo/scribo/primitive/link/internal/link_several_dmax_base.hh
index 422eed9..08681c7 100644
--- a/scribo/scribo/primitive/link/internal/link_several_dmax_base.hh
+++ b/scribo/scribo/primitive/link/internal/link_several_dmax_base.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2009, 2010, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -248,15 +248,15 @@ namespace scribo
if (nratio == 1)
{
- this->links_(current_object)
- = labeled_image_(potential_links_(id_max_ratio).second());
+ this->links_.update(current_object,
+ labeled_image_(potential_links_(id_max_ratio).second()));
return potential_links_(id_max_ratio);
}
}
- this->links_(current_object) = current_object;
+ this->links_.clear(current_object);
return mln::make::couple(anchor::Invalid, P());
}
diff --git a/scribo/scribo/primitive/link/merge_double_link.hh
b/scribo/scribo/primitive/link/merge_double_link.hh
index e58c1ab..2416a77 100644
--- a/scribo/scribo/primitive/link/merge_double_link.hh
+++ b/scribo/scribo/primitive/link/merge_double_link.hh
@@ -93,19 +93,20 @@ namespace scribo
const component_set<L>& components = left_link.components();
- object_links<L> merge = left_link.duplicate();
+ object_links<L> merge(components);
+ merge.init();
- for_all_ncomponents(i, components.nelements())
+ for_all_comps(i, components)
{
if (components(i).tag() == component::Ignored)
- merge(i) = 0;
+ merge.disable_linking(i);
else
{
- mln::util::couple<bool, unsigned>
- nbh = primitive::internal::is_link_valid(left_link,
- right_link, i);
- if (!nbh.first())
- merge(i) = i;
+ if (primitive::internal::is_link_valid(left_link,
+ right_link, i))
+ merge.update(i, left_link(i));
+ else
+ merge.clear(i);
}
}
diff --git a/scribo/scribo/primitive/link/merge_double_link_closest_aligned.hh
b/scribo/scribo/primitive/link/merge_double_link_closest_aligned.hh
index 6c6e67f..d80fe85 100644
--- a/scribo/scribo/primitive/link/merge_double_link_closest_aligned.hh
+++ b/scribo/scribo/primitive/link/merge_double_link_closest_aligned.hh
@@ -129,14 +129,12 @@ namespace scribo
if (right(left(l)) == left(l))
{
- output(left(l)) = l;
- //output.update_link(left(l), l);
+ output.update(left(l), l);
}
else if ((dh < align_data(left(l)).first() * 0.66f)
|| (alpha < align_data(left(l)).second()))
{
- output(left(l)) = l;
- //output.update_link(left(l), l);
+ output.update(left(l), l);
align_data(left(l)).first() = dh;
align_data(left(l)).second() = alpha;
}
diff --git a/scribo/tests/filter/object_groups_mean_width.cc
b/scribo/tests/filter/object_groups_mean_width.cc
index 81da661..751649d 100644
--- a/scribo/tests/filter/object_groups_mean_width.cc
+++ b/scribo/tests/filter/object_groups_mean_width.cc
@@ -45,8 +45,8 @@ int main()
std::string img = SCRIBO_IMG_DIR "/the_valleys.pbm";
- const unsigned ref[] = { 0, 1, 7, 3, 4, 3, 3, 7, 7, 3, 3, 3, 3 };
- const unsigned filtered_ref[] = { 0, 0, 7, 3, 0, 3, 3, 7, 7, 3, 3, 3, 3 };
+ const bool ref[] = { false, true, true, true, true };
+ const unsigned filtered_ref[] = { false, false, true, false, true };
image2d<bool> input;
io::pbm::load(input, img.c_str());
@@ -61,12 +61,13 @@ int main()
object_groups<L> groups = primitive::group::from_single_link(links);
+ mln_assertion(groups.nelements() == 5);
for_all_groups(g, groups)
- mln_assertion(groups(g) == ref[g]);
+ mln_assertion(groups(g).is_valid() == ref[g]);
groups = filter::object_groups_mean_width(groups, 10);
+ mln_assertion(groups.nelements() == 5);
for_all_groups(g, groups)
- mln_assertion(groups(g) == filtered_ref[g]);
-
+ mln_assertion(groups(g).is_valid() == filtered_ref[g]);
}
diff --git a/scribo/tests/filter/object_groups_size_ratio.cc
b/scribo/tests/filter/object_groups_size_ratio.cc
index 90e353a..4051c71 100644
--- a/scribo/tests/filter/object_groups_size_ratio.cc
+++ b/scribo/tests/filter/object_groups_size_ratio.cc
@@ -45,8 +45,8 @@ int main()
std::string img = SCRIBO_IMG_DIR "/the_valleys.pbm";
- const unsigned ref[] = { 0, 1, 7, 3, 4, 3, 3, 7, 7, 3, 3, 3, 3 };
- const unsigned filtered_ref[] = { 0, 1, 0, 3, 0, 3, 3, 0, 0, 3, 3, 3, 3 };
+ const bool ref[] = { false, true, true, true, true };
+ const bool filtered_ref[] = { false, true, true, false, false };
image2d<bool> input;
io::pbm::load(input, img.c_str());
@@ -61,11 +61,13 @@ int main()
object_groups<L> groups = primitive::group::from_single_link(links);
+ mln_assertion(groups.nelements() == 5);
for_all_groups(g, groups)
- mln_assertion(groups(g) == ref[g]);
+ mln_assertion(groups(g).is_valid() == ref[g]);
groups = filter::object_groups_size_ratio(groups, 1.2, 0.3);
+ mln_assertion(groups.nelements() == 5);
for_all_groups(g, groups)
- mln_assertion(groups(g) == filtered_ref[g]);
+ mln_assertion(groups(g).is_valid() == filtered_ref[g]);
}
diff --git a/scribo/tests/filter/object_groups_small.cc
b/scribo/tests/filter/object_groups_small.cc
index 165634d..9812b70 100644
--- a/scribo/tests/filter/object_groups_small.cc
+++ b/scribo/tests/filter/object_groups_small.cc
@@ -45,9 +45,9 @@ int main()
std::string img = SCRIBO_IMG_DIR "/the_valleys.pbm";
- const unsigned ref[] = { 0, 1, 7, 3, 4, 3, 3, 7, 7, 3, 3, 3, 3 };
- const unsigned filtered_ref[] = { 0, 0, 0, 3, 0, 3, 3, 0, 0, 3, 3, 3, 3 };
- const unsigned size_ref[] = { 0, 1, 0, 7, 1, 0, 0, 3, 0, 0, 0, 0, 0 };
+ const bool ref[] = { false, true, true, true, true };
+ const bool filtered_ref[] = { false, false, true, false, false };
+ const unsigned size_ref[] = { 0, 1, 7, 1, 3 };
image2d<bool> input;
@@ -63,25 +63,17 @@ int main()
object_groups<L> groups = primitive::group::from_single_link(links);
+ mln_assertion(groups.nelements() == 5);
for_all_groups(g, groups)
- mln_assertion(groups(g) == ref[g]);
+ mln_assertion(groups(g).is_valid() == ref[g]);
- {
- object_groups<L> groups2 = filter::object_groups_small(groups, 4);
-
- for_all_groups(g, groups2)
- mln_assertion(groups2(g) == filtered_ref[g]);
- }
+ object_groups<L> groups2 = filter::object_groups_small(groups, 4);
+ for_all_groups(g, groups2)
{
- mln::util::array<unsigned> group_size;
- object_groups<L> groups2 = filter::object_groups_small(groups, 4, group_size);
-
- for_all_groups(g, groups2)
- {
- mln_assertion(groups2(g) == filtered_ref[g]);
- mln_assertion(group_size(g) == size_ref[g]);
- }
+ mln_assertion(groups2(g).is_valid() == filtered_ref[g]);
+ mln_assertion(groups2(g).card() == size_ref[g]);
}
+
}
diff --git a/scribo/tests/filter/object_groups_with_holes.cc
b/scribo/tests/filter/object_groups_with_holes.cc
index 3b5b29f..72f8464 100644
--- a/scribo/tests/filter/object_groups_with_holes.cc
+++ b/scribo/tests/filter/object_groups_with_holes.cc
@@ -45,8 +45,8 @@ int main()
std::string img = SCRIBO_IMG_DIR "/the_valleys.pbm";
- const unsigned ref[] = { 0, 1, 7, 3, 4, 3, 3, 7, 7, 3, 3, 3, 3 };
- const unsigned filtered_ref[] = { 0, 0, 7, 3, 0, 3, 3, 7, 7, 3, 3, 3, 3 };
+ const bool ref[] = { false, true, true, true, true };
+ const bool filtered_ref[] = { 0, false, true, true, false };
image2d<bool> input;
io::pbm::load(input, img.c_str());
@@ -61,11 +61,13 @@ int main()
object_groups<L> groups = primitive::group::from_single_link(links);
+ mln_assertion(groups.nelements() == 5);
for_all_groups(g, groups)
- mln_assertion(groups(g) == ref[g]);
+ mln_assertion(groups(g).is_valid() == ref[g]);
groups = filter::object_groups_with_holes(groups, 3);
+ mln_assertion(groups.nelements() == 5);
for_all_groups(g, groups)
- mln_assertion(groups(g) == filtered_ref[g]);
+ mln_assertion(groups(g).is_valid() == filtered_ref[g]);
}
--
1.5.6.5