Commit 3894a51d authored by Guillaume Lazzara's avatar Guillaume Lazzara
Browse files

Improve object linking backend.

	* scribo/primitive/internal/find_left_link.hh,
	* scribo/primitive/internal/find_right_link.hh,
	* scribo/primitive/internal/is_invalid_link.hh: Remove.

	* scribo/primitive/link/internal/compute_anchor.hh,
	* scribo/primitive/link/internal/link_ms_dmax_base.hh,
	* scribo/primitive/link/internal/link_ms_dmax_ratio_base.hh,
	* scribo/primitive/link/internal/link_single_dmax_base.hh,
	* scribo/primitive/link/internal/link_single_dmax_ratio_base.hh,
	* scribo/primitive/link/with_single_down_link.hh,
	* scribo/primitive/link/with_single_left_link.hh,
	* scribo/primitive/link/with_single_left_link_dmax_ratio.hh,
	* scribo/primitive/link/with_single_right_link.hh,
	* scribo/primitive/link/with_single_right_link_dmax_ratio.hh,
	* scribo/primitive/link/with_single_up_link.hh: Introduce the
	anchor concept and make use of it.
parent 4e5a8aea
2010-02-19 Guillaume Lazzara <z@lrde.epita.fr>
Improve object linking backend.
* scribo/primitive/internal/find_left_link.hh,
* scribo/primitive/internal/find_right_link.hh,
* scribo/primitive/internal/is_invalid_link.hh: Remove.
* scribo/primitive/link/internal/compute_anchor.hh,
* scribo/primitive/link/internal/link_ms_dmax_base.hh,
* scribo/primitive/link/internal/link_ms_dmax_ratio_base.hh,
* scribo/primitive/link/internal/link_single_dmax_base.hh,
* scribo/primitive/link/internal/link_single_dmax_ratio_base.hh,
* scribo/primitive/link/with_single_down_link.hh,
* scribo/primitive/link/with_single_left_link.hh,
* scribo/primitive/link/with_single_left_link_dmax_ratio.hh,
* scribo/primitive/link/with_single_right_link.hh,
* scribo/primitive/link/with_single_right_link_dmax_ratio.hh,
* scribo/primitive/link/with_single_up_link.hh: Introduce the
anchor concept and make use of it.
2010-02-19 Guillaume Lazzara <z@lrde.epita.fr>
* scribo/filter/objects_with_holes.hh: New component filter.
......
// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
// Olena is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, version 2 of the License.
//
// Olena is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Olena. If not, see <http://www.gnu.org/licenses/>.
//
// As a special exception, you may use this file as part of a free
// software project without restriction. Specifically, if other files
// instantiate templates or use macros or inline functions from this
// file, or you compile this file and link it with other files to produce
// an executable, this file does not by itself cause the resulting
// executable to be covered by the GNU General Public License. This
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
#ifndef SCRIBO_PRIMITIVE_INTERNAL_IS_INVALID_LINK_HH
# define SCRIBO_PRIMITIVE_INTERNAL_IS_INVALID_LINK_HH
/// \file
///
/// Check whether an objects link is invalid or not.
///
/// \todo To be deleted.
# include <mln/math/abs.hh>
# include <mln/literal/zero.hh>
# include <scribo/core/object_image.hh>
namespace scribo
{
namespace primitive
{
namespace internal
{
using namespace mln;
/// Check whether an objects link is invalid or not.
///
/// \param objects An image of objects.
/// \param left_link The left neighbors.
/// \param p The current site.
/// \param current_comp The current object id.
/// \param c The left link start point.
/// \param dmax The maximum lookup distance.
//
template <typename L>
bool
is_invalid_link(const object_image(L)& objects_,
mln::util::array<unsigned>& link_array,
const mln_site(L)& p,
unsigned current_comp,
const mln_site(L)& c,
float dmax);
# ifndef MLN_INCLUDE_ONLY
template <typename L>
inline
bool
is_invalid_link(const object_image(L)& objects,
mln::util::array<unsigned>& link_array,
const mln_site(L)& p,
unsigned current_comp,
const mln_site(L)& c,
float dmax)
{
return (objects.domain().has(p) // Not outside image domain
&& (objects(p) == literal::zero // Is the background
|| objects(p) == current_comp // Is the current component
|| link_array[objects(p)] == current_comp) // Creates a loop
&& static_cast<float>(math::abs(p.col() - c.col())) < dmax); // Not too far
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace scribo::primitive::internal
} // end of namespace scribo::primitive
} // end of namespace scribo
#endif // ! SCRIBO_PRIMITIVE_INTERNAL_IS_INVALID_LINK_HH
......@@ -52,15 +52,11 @@ namespace scribo
/*! \brief Return the proper anchor used to find a neighbor.
\param[in] objects An object image.
\param[in] mass_centers Object mass centers.
\param[in] current_object An object id.
\param[in] anchor The expected anchor.
Anchor can take one of the following values:
- anchor::MassCenter, mass center anchor.
- anchor::Top, top anchor.
- anchor::Bottom, bottom anchor.
- anchor::Center, center anchor.
Anchor can take one of the values defined in the
scribo::anchor::Type enum.
Top and bottom anchors are respectively computed from the
......@@ -76,64 +72,169 @@ namespace scribo
out.row = P.row - min(10, h /10)
*/
template <typename L, typename P>
template <typename L>
mln_site(L)
compute_anchor(const object_image(L)& objects,
const mln::util::array<P>& mass_centers,
unsigned current_object, anchor::Type anchor);
# ifndef MLN_INCLUDE_ONLY
template <typename L, typename P>
template <typename L>
mln_site(L)
compute_anchor(const object_image(L)& objects,
const mln::util::array<P>& mass_centers,
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();
mln_site(L) sp = objects.bbox(current_object).center();
def::coord r = 0;
switch (anchor)
{
// Masss Center
// Component masss center
case anchor::MassCenter:
return mass_centers(current_object);
return objects.mass_center(current_object);
// Top
// Bounding box top center
case anchor::Top:
if (h < 30)
r = objects.bbox(current_object).pmin().row()
sp.row() = objects.bbox(current_object).pmin().row()
+ math::min(2u, (h + 1) / 2 - 1);
else
r = objects.bbox(current_object).pmin().row()
sp.row() = objects.bbox(current_object).pmin().row()
+ math::min(10u, h /10);
break;
// Bottom
// Bounding box bottom center
case anchor::Bottom:
if (h < 30)
r = objects.bbox(current_object).pmax().row()
sp.row() = objects.bbox(current_object).pmax().row()
- math::min(2u, (h + 1) / 2 - 1);
else
r = objects.bbox(current_object).pmax().row()
sp.row() = objects.bbox(current_object).pmax().row()
- math::min(10u, h /10);
break;
// Bounding box center
case anchor::Center:
return objects.bbox(current_object).center();
// Bounding box actual left center
case anchor::ActualLeft:
return P(objects.bbox(current_object).center().row(),
objects.bbox(current_object).pmin().col());
// Bounding box left center
case anchor::Left:
if (w < 30)
sp.col() = objects.bbox(current_object).pmin().col()
+ math::min(2u, (w + 1) / 2 - 1);
else
sp.col() = objects.bbox(current_object).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());
// Bounding box right center
case anchor::Right:
if (w < 30)
sp.col() = objects.bbox(current_object).pmax().col()
- math::min(2u, (w + 1) / 2 - 1);
else
sp.col() = objects.bbox(current_object).pmax().col()
- math::min(10u, w /10);
break;
// Bounding box top left
case anchor::TopLeft:
if (h < 30)
sp.row() = objects.bbox(current_object).pmin().row()
+ math::min(2u, (h + 1) / 2 - 1);
else
sp.row() = objects.bbox(current_object).pmin().row()
+ math::min(10u, h /10);
if (w < 30)
sp.col() = objects.bbox(current_object).pmin().col()
+ math::min(2u, (w + 1) / 2 - 1);
else
sp.col() = objects.bbox(current_object).pmin().col()
+ math::min(10u, w /10);
break;
// Bounding box top right
case anchor::TopRight:
if (h < 30)
sp.row() = objects.bbox(current_object).pmin().row()
+ math::min(2u, (h + 1) / 2 - 1);
else
sp.row() = objects.bbox(current_object).pmin().row()
+ math::min(10u, h /10);
if (w < 30)
sp.col() = objects.bbox(current_object).pmax().col()
- math::min(2u, (w + 1) / 2 - 1);
else
sp.col() = objects.bbox(current_object).pmax().col()
- math::min(10u, w /10);
break;
// Bounding box bottom left
case anchor::BottomLeft:
if (h < 30)
sp.row() = objects.bbox(current_object).pmax().row()
- math::min(2u, (h + 1) / 2 - 1);
else
sp.row() = objects.bbox(current_object).pmax().row()
- math::min(10u, h /10);
if (w < 30)
sp.col() = objects.bbox(current_object).pmin().col()
+ math::min(2u, (w + 1) / 2 - 1);
else
sp.col() = objects.bbox(current_object).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()
- math::min(2u, (h + 1) / 2 - 1);
else
sp.row() = objects.bbox(current_object).pmax().row()
- math::min(10u, h /10);
if (w < 30)
sp.col() = objects.bbox(current_object).pmax().col()
- math::min(2u, (w + 1) / 2 - 1);
else
sp.col() = objects.bbox(current_object).pmax().col()
- math::min(10u, w /10);
break;
default:
trace::warning("Non handled anchor");
mln_assertion(anchor > 2);
mln_assertion(anchor < anchor::Invalid);
}
sp.row() = r;
return sp;
}
......
......@@ -75,9 +75,8 @@ namespace scribo
link_ms_dmax_base(const object_image(L)& objects,
unsigned neighb_max_distance);
unsigned neighb_max_distance,
anchor::Direction direction);
bool verify_link_criterion_(unsigned current_object,
const P& start_point, const P& p) const;
......@@ -88,9 +87,9 @@ namespace scribo
void start_processing_object_(unsigned current_object);
private:
mln::util::array<ms_t> mass_centers_;
float dmax_;
float neighb_max_distance_;
anchor::Direction direction_;
};
......@@ -101,17 +100,17 @@ namespace scribo
inline
link_ms_dmax_base<L, E>::link_ms_dmax_base(
const object_image(L)& objects,
unsigned neighb_max_distance)
unsigned neighb_max_distance,
anchor::Direction direction)
: super_(objects),
dmax_(0),
neighb_max_distance_(neighb_max_distance)
neighb_max_distance_(neighb_max_distance),
direction_(direction)
{
mass_centers_ = labeling::compute(accu::meta::center(),
objects, objects.nlabels());
}
template <typename L, typename E>
inline
bool
......@@ -121,7 +120,7 @@ namespace scribo
{
(void) current_object;
float dist = math::abs(p.col() - start_point.col());
float dist = math::abs(p[direction_] - start_point[direction_]);
return dist <= dmax_; // Not too far
}
......@@ -133,7 +132,7 @@ namespace scribo
unsigned anchor)
{
(void) anchor;
return mass_centers_(current_object);
return this->objects_.mass_center(current_object);
}
......@@ -144,8 +143,8 @@ namespace scribo
unsigned current_object)
{
float
midcol = (this->objects_.bbox(current_object).pmax().col()
- this->objects_.bbox(current_object).pmin().col()) / 2;
midcol = (this->objects_.bbox(current_object).pmax()[direction_]
- this->objects_.bbox(current_object).pmin()[direction_]) / 2;
dmax_ = midcol + neighb_max_distance_;
}
......
......@@ -76,7 +76,8 @@ namespace scribo
link_ms_dmax_ratio_base(const object_image(L)& objects,
float dmax_ratio);
float dmax_ratio,
anchor::Direction direction);
......@@ -89,9 +90,9 @@ namespace scribo
void start_processing_object_(unsigned current_object);
private:
mln::util::array<ms_t> mass_centers_;
float dmax_ratio_;
float dmax_;
anchor::Direction direction_;
};
......@@ -102,14 +103,14 @@ namespace scribo
inline
link_ms_dmax_ratio_base<L, E>::link_ms_dmax_ratio_base(
const object_image(L)& objects,
float dmax_ratio)
float dmax_ratio,
anchor::Direction direction)
: super_(objects),
dmax_ratio_(dmax_ratio),
dmax_(0)
dmax_(0),
direction_(direction)
{
mass_centers_ = labeling::compute(accu::meta::center(),
objects, objects.nlabels());
}
template <typename L, typename E>
......@@ -120,9 +121,10 @@ namespace scribo
const P& start_point,
const P& p) const
{
mln_assertion(dmax_ != 0);
(void) current_object;
float dist = math::abs(p.col() - start_point.col());
float dist = math::abs(p[direction_] - start_point[direction_]);
return dist <= dmax_; // Not too far
}
......@@ -134,7 +136,7 @@ namespace scribo
unsigned anchor)
{
(void) anchor;
return mass_centers_(current_object);
return this->objects_.mass_center(current_object);
}
......
......@@ -76,7 +76,8 @@ namespace scribo
typedef mln_site(L) P;
link_single_dmax_base(const object_image(L)& objects,
unsigned neighb_max_distance);
unsigned neighb_max_distance,
anchor::Direction direction);
bool verify_link_criterion_(unsigned current_object,
......@@ -90,7 +91,7 @@ namespace scribo
private:
float dmax_;
float neighb_max_distance_;
// mln::util::array<ms_t> mass_centers_;
anchor::Direction direction_;
};
......@@ -101,14 +102,14 @@ namespace scribo
inline
link_single_dmax_base<L, E>::link_single_dmax_base(
const object_image(L)& objects,
unsigned neighb_max_distance)
unsigned neighb_max_distance,
anchor::Direction direction)
: super_(objects),
dmax_(0),
neighb_max_distance_(neighb_max_distance)
neighb_max_distance_(neighb_max_distance),
direction_(direction)
{
// mass_centers_ = labeling::compute(accu::meta::center(),
// objects, objects.nlabels());
}
......@@ -122,7 +123,7 @@ namespace scribo
{
(void) current_object;
float dist = math::abs(p.col() - start_point.col());
float dist = math::abs(p[direction_] - start_point[direction_]);
return dist <= dmax_; // Not too far
}
......@@ -133,7 +134,7 @@ namespace scribo
link_single_dmax_base<L, E>::start_point_(unsigned current_object,
anchor::Type anchor)
{
return internal::compute_anchor(this->objects_, this->objects_.mass_centers(),//mass_centers_,
return internal::compute_anchor(this->objects_,
current_object, anchor);
}
......@@ -145,8 +146,8 @@ namespace scribo
unsigned current_object)
{
float
midcol = (this->objects_.bbox(current_object).pmax().col()
- this->objects_.bbox(current_object).pmin().col()) / 2;
midcol = (this->objects_.bbox(current_object).pmax()[direction_]
- this->objects_.bbox(current_object).pmin()[direction_]) / 2;
dmax_ = midcol + neighb_max_distance_;
}
......
......@@ -79,7 +79,7 @@ namespace scribo
link_single_dmax_ratio_base(const object_image(L)& objects,
float dmax_ratio,
unsigned center_type_);
anchor::Direction direction);
......@@ -94,7 +94,7 @@ namespace scribo
private:
float dmax_ratio_;
float dmax_;
mln::util::array<ms_t> mass_centers_;
anchor::Direction direction_;
};
......@@ -105,14 +105,14 @@ namespace scribo
inline
link_single_dmax_ratio_base<L, E>::link_single_dmax_ratio_base(
const object_image(L)& objects,
float dmax_ratio)
float dmax_ratio,
anchor::Direction direction)
: super_(objects),
dmax_ratio_(dmax_ratio),
dmax_(0)
dmax_(0),
direction_(direction)
{
mass_centers_ = labeling::compute(accu::meta::center(),
objects, objects.nlabels());
}
template <typename L, typename E>
......@@ -125,7 +125,7 @@ namespace scribo
{
(void) current_object;
float dist = math::abs(p.col() - start_point.col());
float dist = math::abs(p[direction_] - start_point[direction_]);
return dist <= dmax_; // Not too far
}
......@@ -137,7 +137,7 @@ namespace scribo
anchor::Type anchor)
{
(void) anchor;
return internal::compute_anchors(this->objects_, mass_centers_,
return internal::compute_anchor(this->objects_,
current_object, anchor);
}
......
......@@ -23,28 +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_PRIMITIVE_INTERNAL_FIND_RIGHT_LINK_HH
# define SCRIBO_PRIMITIVE_INTERNAL_FIND_RIGHT_LINK_HH
#ifndef SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_DOWN_LINK_HH
# define SCRIBO_PRIMITIVE_LINK_WITH_SINGLE_DOWN_LINK_HH
/// \file
///
/// Find the right neighbor of a line of text if exists.
///
/// \todo To be deleted.
/// Link text objects with their down neighbor.
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>