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> 2010-02-19 Guillaume Lazzara <z@lrde.epita.fr>
* scribo/filter/objects_with_holes.hh: New component filter. * 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 ...@@ -52,15 +52,11 @@ namespace scribo
/*! \brief Return the proper anchor used to find a neighbor. /*! \brief Return the proper anchor used to find a neighbor.
\param[in] objects An object image. \param[in] objects An object image.
\param[in] mass_centers Object mass centers.
\param[in] current_object An object id. \param[in] current_object An object id.
\param[in] anchor The expected anchor. \param[in] anchor The expected anchor.
Anchor can take one of the following values: Anchor can take one of the values defined in the
- anchor::MassCenter, mass center anchor. scribo::anchor::Type enum.
- anchor::Top, top anchor.
- anchor::Bottom, bottom anchor.
- anchor::Center, center anchor.
Top and bottom anchors are respectively computed from the Top and bottom anchors are respectively computed from the
...@@ -76,64 +72,169 @@ namespace scribo ...@@ -76,64 +72,169 @@ namespace scribo
out.row = P.row - min(10, h /10) out.row = P.row - min(10, h /10)
*/ */
template <typename L, typename P> template <typename L>
mln_site(L) mln_site(L)
compute_anchor(const object_image(L)& objects, compute_anchor(const object_image(L)& objects,
const mln::util::array<P>& mass_centers,
unsigned current_object, anchor::Type anchor); unsigned current_object, anchor::Type anchor);
# ifndef MLN_INCLUDE_ONLY # ifndef MLN_INCLUDE_ONLY
template <typename L, typename P> template <typename L>
mln_site(L) mln_site(L)
compute_anchor(const object_image(L)& objects, compute_anchor(const object_image(L)& objects,
const mln::util::array<P>& mass_centers,
unsigned current_object, anchor::Type anchor) unsigned current_object, anchor::Type anchor)
{ {
typedef mln_site(L) P;
unsigned h = objects.bbox(current_object).pmax().row() unsigned h = objects.bbox(current_object).pmax().row()
- objects.bbox(current_object).pmin().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(); mln_site(L) sp = objects.bbox(current_object).center();
def::coord r = 0;
switch (anchor) switch (anchor)
{ {
// Masss Center // Component masss center
case anchor::MassCenter: case anchor::MassCenter:
return mass_centers(current_object); return objects.mass_center(current_object);
// Top // Bounding box top center
case anchor::Top: case anchor::Top:
if (h < 30) 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); + math::min(2u, (h + 1) / 2 - 1);
else else
r = objects.bbox(current_object).pmin().row() sp.row() = objects.bbox(current_object).pmin().row()
+ math::min(10u, h /10); + math::min(10u, h /10);
break; break;
// Bottom // Bounding box bottom center
case anchor::Bottom: case anchor::Bottom:
if (h < 30) 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); - math::min(2u, (h + 1) / 2 - 1);
else else
r = objects.bbox(current_object).pmax().row() sp.row() = objects.bbox(current_object).pmax().row()
- math::min(10u, h /10); - math::min(10u, h /10);
break; break;
// Bounding box center
case anchor::Center: case anchor::Center:
return objects.bbox(current_object).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: default:
trace::warning("Non handled anchor"); trace::warning("Non handled anchor");
mln_assertion(anchor > 2); mln_assertion(anchor < anchor::Invalid);
} }
sp.row() = r;
return sp; return sp;
} }
......
...@@ -75,12 +75,11 @@ namespace scribo ...@@ -75,12 +75,11 @@ namespace scribo
link_ms_dmax_base(const object_image(L)& objects, 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, bool verify_link_criterion_(unsigned current_object,
const P& start_point, const P& p) const; const P& start_point, const P& p) const;
mln_site(L) start_point_(unsigned current_object, mln_site(L) start_point_(unsigned current_object,
unsigned anchor); unsigned anchor);
...@@ -88,9 +87,9 @@ namespace scribo ...@@ -88,9 +87,9 @@ namespace scribo
void start_processing_object_(unsigned current_object); void start_processing_object_(unsigned current_object);
private: private:
mln::util::array<ms_t> mass_centers_;
float dmax_; float dmax_;
float neighb_max_distance_; float neighb_max_distance_;
anchor::Direction direction_;
}; };
...@@ -101,17 +100,17 @@ namespace scribo ...@@ -101,17 +100,17 @@ namespace scribo
inline inline
link_ms_dmax_base<L, E>::link_ms_dmax_base( link_ms_dmax_base<L, E>::link_ms_dmax_base(
const object_image(L)& objects, const object_image(L)& objects,
unsigned neighb_max_distance) unsigned neighb_max_distance,
anchor::Direction direction)
: super_(objects), : super_(objects),
dmax_(0), 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> template <typename L, typename E>
inline inline
bool bool
...@@ -121,7 +120,7 @@ namespace scribo ...@@ -121,7 +120,7 @@ namespace scribo
{ {
(void) current_object; (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 return dist <= dmax_; // Not too far
} }
...@@ -133,7 +132,7 @@ namespace scribo ...@@ -133,7 +132,7 @@ namespace scribo
unsigned anchor) unsigned anchor)
{ {
(void) anchor; (void) anchor;
return mass_centers_(current_object); return this->objects_.mass_center(current_object);
} }
...@@ -144,8 +143,8 @@ namespace scribo ...@@ -144,8 +143,8 @@ namespace scribo
unsigned current_object) unsigned current_object)
{ {
float float
midcol = (this->objects_.bbox(current_object).pmax().col() midcol = (this->objects_.bbox(current_object).pmax()[direction_]
- this->objects_.bbox(current_object).pmin().col()) / 2; - this->objects_.bbox(current_object).pmin()[direction_]) / 2;
dmax_ = midcol + neighb_max_distance_; dmax_ = midcol + neighb_max_distance_;
} }
......
...@@ -76,7 +76,8 @@ namespace scribo ...@@ -76,7 +76,8 @@ namespace scribo
link_ms_dmax_ratio_base(const object_image(L)& objects, 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 ...@@ -89,9 +90,9 @@ namespace scribo
void start_processing_object_(unsigned current_object); void start_processing_object_(unsigned current_object);
private: private:
mln::util::array<ms_t> mass_centers_;
float dmax_ratio_; float dmax_ratio_;
float dmax_; float dmax_;
anchor::Direction direction_;
}; };
...@@ -102,14 +103,14 @@ namespace scribo ...@@ -102,14 +103,14 @@ namespace scribo
inline inline
link_ms_dmax_ratio_base<L, E>::link_ms_dmax_ratio_base( link_ms_dmax_ratio_base<L, E>::link_ms_dmax_ratio_base(
const object_image(L)& objects, const object_image(L)& objects,
float dmax_ratio) float dmax_ratio,
anchor::Direction direction)
: super_(objects), : super_(objects),
dmax_ratio_(dmax_ratio), 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> template <typename L, typename E>
...@@ -120,9 +121,10 @@ namespace scribo ...@@ -120,9 +121,10 @@ namespace scribo
const P& start_point, const P& start_point,
const P& p) const const P& p) const
{ {
mln_assertion(dmax_ != 0);
(void) current_object; (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 return dist <= dmax_; // Not too far
} }
...@@ -134,7 +136,7 @@ namespace scribo ...@@ -134,7 +136,7 @@ namespace scribo
unsigned anchor) unsigned anchor)
{ {
(void) anchor; (void) anchor;
return mass_centers_(current_object); return this->objects_.mass_center(current_object);
} }
......
...@@ -76,7 +76,8 @@ namespace scribo ...@@ -76,7 +76,8 @@ namespace scribo
typedef mln_site(L) P; typedef mln_site(L) P;
link_single_dmax_base(const object_image(L)& objects, 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, bool verify_link_criterion_(unsigned current_object,
...@@ -90,7 +91,7 @@ namespace scribo ...@@ -90,7 +91,7 @@ namespace scribo
private: private:
float dmax_; float dmax_;
float neighb_max_distance_; float neighb_max_distance_;
// mln::util::array<ms_t> mass_centers_; anchor::Direction direction_;
};