Commit 906f2366 authored by Guillaume Lazzara's avatar Guillaume Lazzara
Browse files

Improve linking routines.

	* core/anchors.hh: New. Add anchor types.

	* filter/objects_thin.hh: Use filter::internal::compute.

	* primitive/link/internal/find_several_links.hh,
	* primitive/link/internal/find_link.hh,
	* primitive/link/compute.hh: Update functor interface in order to
	specify anchors.

	* primitive/link/compute_several.hh: Fix an invalid namespace.

	* primitive/link/internal/anchors_3.hh: Move...

	* primitive/link/internal/compute_anchor.hh: ... here.

	* primitive/link/internal/link_functor_base.hh: Use anchor type.

	* primitive/link/internal/link_several_dmax_base.hh: New.

	* primitive/link/internal/link_center_dmax_base.hh,
	* primitive/link/internal/link_center_dmax_ratio_base.hh: Removed.

	* primitive/link/with_several_right_links_overlap.hh: Fix includes.

	* primitive/link/with_single_right_link_bottom.hh,
	* primitive/link/with_single_right_link_top.hh,
	* primitive/link/with_single_left_link.hh,
	* primitive/link/with_single_right_link.hh: Use
	link_single_dmax_base functor.

	* src/debug/show_links_several_right_overlap.cc,
	* src/debug/show_links_single_left.cc,
	* src/debug/show_links_single_left_dmax_ratio.cc,
	* src/debug/show_links_single_right.cc,
	* src/debug/show_links_single_right_dmax_ratio.cc: Update functor
	interface.
parent f7773bdb
2009-12-14 Guillaume Lazzara <z@lrde.epita.fr>
Improve linking routines.
* core/anchors.hh: New. Add anchor types.
* filter/objects_thin.hh: Use filter::internal::compute.
* primitive/link/internal/find_several_links.hh,
* primitive/link/internal/find_link.hh,
* primitive/link/compute.hh: Update functor interface in order to
specify anchors.
* primitive/link/compute_several.hh: Fix an invalid namespace.
* primitive/link/internal/anchors_3.hh: Move...
* primitive/link/internal/compute_anchor.hh: ... here.
* primitive/link/internal/link_functor_base.hh: Use anchor type.
* primitive/link/internal/link_several_dmax_base.hh: New.
* primitive/link/internal/link_center_dmax_base.hh,
* primitive/link/internal/link_center_dmax_ratio_base.hh: Removed.
* primitive/link/with_several_right_links_overlap.hh: Fix includes.
* primitive/link/with_single_right_link_bottom.hh,
* primitive/link/with_single_right_link_top.hh,
* primitive/link/with_single_left_link.hh,
* primitive/link/with_single_right_link.hh: Use
link_single_dmax_base functor.
* src/debug/show_links_several_right_overlap.cc,
* src/debug/show_links_single_left.cc,
* src/debug/show_links_single_left_dmax_ratio.cc,
* src/debug/show_links_single_right.cc,
* src/debug/show_links_single_right_dmax_ratio.cc: Update functor
interface.
2009-12-11 Guillaume Lazzara <z@lrde.epita.fr> 2009-12-11 Guillaume Lazzara <z@lrde.epita.fr>
Improve Sauvola Multi-scale. Improve Sauvola Multi-scale.
......
// 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_ANCHORS_HH
# define SCRIBO_CORE_ANCHORS_HH
namespace scribo
{
namespace anchor
{
enum Type
{
MassCenter = 0,
Top,
Bottom,
Center,
Invalid
};
}
} // end of namespace scribo
#endif // ! SCRIBO_CORE_ANCHORS_HH
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
# include <scribo/core/object_image.hh> # include <scribo/core/object_image.hh>
# include <scribo/primitive/extract/objects.hh> # include <scribo/primitive/extract/objects.hh>
# include <scribo/filter/internal/compute.hh>
namespace scribo namespace scribo
{ {
...@@ -91,8 +92,6 @@ namespace scribo ...@@ -91,8 +92,6 @@ namespace scribo
struct objects_thin_filter struct objects_thin_filter
: Function_v2b< objects_thin_filter<L> > : Function_v2b< objects_thin_filter<L> >
{ {
typedef accu::shape::bbox<mln_psite(L)> box_accu_t;
/// Constructor /// Constructor
/// ///
/// \param[in] objects object bounding boxes. /// \param[in] objects object bounding boxes.
...@@ -175,9 +174,7 @@ namespace scribo ...@@ -175,9 +174,7 @@ namespace scribo
typedef internal::objects_thin_filter<L> func_t; typedef internal::objects_thin_filter<L> func_t;
func_t is_not_too_thin(objects, min_thickness); func_t is_not_too_thin(objects, min_thickness);
object_image(L) output; object_image(L) output = internal::compute(objects, is_not_too_thin);
output.init_from_(objects);
output.relabel(is_not_too_thin);
trace::exiting("scribo::filter::objects_thin"); trace::exiting("scribo::filter::objects_thin");
return output; return output;
......
...@@ -55,39 +55,44 @@ namespace scribo ...@@ -55,39 +55,44 @@ namespace scribo
Functors must implement the following interface : Functors must implement the following interface :
bool is_potential_link(unsigned current_object, bool is_potential_link_(unsigned current_object,
const P& start_point, const P& p) const const P& start_point, const P& p) const
bool valid_link(unsigned current_object, bool valid_link_(unsigned current_object,
const P& start_point, const P& p) const P& start_point, const P& p)
bool verify_link_criterion(unsigned current_object, bool verify_link_criterion_(unsigned current_object,
const P& start_point, const P& p) const P& start_point, const P& p)
void validate_link(unsigned current_object, void validate_link_(unsigned current_object,
const P& start_point, const P& p) const P& start_point, const P& p, unsigned anchor)
void invalidate_link(unsigned current_object, void invalidate_link_(unsigned current_object,
const P& start_point, const P& p) const P& start_point, const P& p, unsigned anchor)
void compute_next_site(P& p) void compute_next_site_(P& p)
const mln_site(L)& start_point(unsigned current_object) const mln_site(L)& start_point_(unsigned current_object, unsigned anchor)
void start_processing_object(unsigned current_object) void start_processing_object_(unsigned current_object)
*/ */
template <typename F> template <typename F>
object_links<scribo_support(F)> object_links<scribo_support(F)>
compute(Link_Functor<F>& functor); compute(Link_Functor<F>& functor, anchor::Type anchor);
/// \overload
/// The default anchor is set to 0, the mass center.
template <typename F>
object_links<scribo_support(F)>
compute(Link_Functor<F>& functor);
# ifndef MLN_INCLUDE_ONLY # ifndef MLN_INCLUDE_ONLY
template <typename F> template <typename F>
object_links<scribo_support(F)> object_links<scribo_support(F)>
compute(Link_Functor<F>& functor_) compute(Link_Functor<F>& functor_, anchor::Type anchor)
{ {
trace::entering("scribo::primitive::link::compute"); trace::entering("scribo::primitive::link::compute");
...@@ -96,7 +101,7 @@ namespace scribo ...@@ -96,7 +101,7 @@ namespace scribo
for_all_ncomponents(current_object, functor.objects().nlabels()) for_all_ncomponents(current_object, functor.objects().nlabels())
{ {
functor.start_processing_object(current_object); //<-- start_processing_object functor.start_processing_object(current_object); //<-- start_processing_object
primitive::internal::find_link(functor, current_object); primitive::internal::find_link(functor, current_object, anchor);
} }
trace::exiting("scribo::primitive::link::compute"); trace::exiting("scribo::primitive::link::compute");
...@@ -104,6 +109,14 @@ namespace scribo ...@@ -104,6 +109,14 @@ namespace scribo
} }
template <typename F>
object_links<scribo_support(F)>
compute(Link_Functor<F>& functor)
{
return compute(functor, anchor::MassCenter);
}
# endif // ! MLN_INCLUDE_ONLY # endif // ! MLN_INCLUDE_ONLY
} // end of namespace scribo::primitive::link } // end of namespace scribo::primitive::link
......
...@@ -98,7 +98,7 @@ namespace scribo ...@@ -98,7 +98,7 @@ namespace scribo
for_all_ncomponents(current_object, functor.objects().nlabels()) for_all_ncomponents(current_object, functor.objects().nlabels())
{ {
functor.start_processing_object(current_object); //<-- start_processing_object functor.start_processing_object(current_object); //<-- start_processing_object
primitive::internal::find_several_links(functor, current_object); internal::find_several_links(functor, current_object);
} }
trace::exiting("scribo::primitive::link::compute_several"); trace::exiting("scribo::primitive::link::compute_several");
......
...@@ -23,14 +23,15 @@ ...@@ -23,14 +23,15 @@
// exception does not however invalidate any other reasons why the // exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License. // executable file might be covered by the GNU General Public License.
#ifndef SCRIBO_PRIMITIVE_LINK_INTERNAL_ANCHORS_3_HH #ifndef SCRIBO_PRIMITIVE_LINK_INTERNAL_COMPUTE_ANCHOR_HH
# define SCRIBO_PRIMITIVE_LINK_INTERNAL_ANCHORS_3_HH # define SCRIBO_PRIMITIVE_LINK_INTERNAL_COMPUTE_ANCHOR_HH
/// \file /// \file
/// ///
/// Routine providing 3 anchors for neighbor seeking. /// Routine providing anchors for neighbor seeking.
# include <mln/math/min.hh> # include <mln/math/min.hh>
# include <mln/util/array.hh>
# include <scribo/core/object_image.hh> # include <scribo/core/object_image.hh>
...@@ -46,20 +47,20 @@ namespace scribo ...@@ -46,20 +47,20 @@ namespace scribo
namespace internal namespace internal
{ {
using namespace mln;
/*! \brief Return the proper anchor used to find a neighbor. /*! \brief Return the proper anchor used to find a neighbor.
This routine provides up to 3 different anchors.
\param[in] objects An object image. \param[in] objects An object image.
\param[in] mass_centers Object mass centers. \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 following values:
- 0, top anchor. - anchor::MassCenter, mass center anchor.
- 1, center anchor. It is the mass center. - anchor::Top, top anchor.
- 2, bottom 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
...@@ -77,53 +78,56 @@ namespace scribo ...@@ -77,53 +78,56 @@ namespace scribo
*/ */
template <typename L, typename P> template <typename L, typename P>
mln_site(L) mln_site(L)
anchors_3(const object_image(L)& objects, compute_anchor(const object_image(L)& objects,
const mln::util::array<P>& mass_centers, const mln::util::array<P>& mass_centers,
unsigned current_object, unsigned anchor); unsigned current_object, anchor::Type anchor);
# ifndef MLN_INCLUDE_ONLY # ifndef MLN_INCLUDE_ONLY
template <typename L, typename P> template <typename L, typename P>
mln_site(L) mln_site(L)
anchors_3(const object_image(L)& objects, compute_anchor(const object_image(L)& objects,
const mln::util::array<P>& mass_centers, const mln::util::array<P>& mass_centers,
unsigned current_object, unsigned anchor) unsigned current_object, anchor::Type anchor)
{ {
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();
mln_site(L) sp = objects.bbox(current_object).center(); mln_site(L) sp = objects.bbox(current_object).center();
def::coord r; def::coord r = 0;
switch (anchor) switch (anchor)
{ {
// Masss Center
case anchor::MassCenter:
return mass_centers(current_object);
// Top // Top
case 0: case anchor::Top:
if (h < 30) if (h < 30)
r = objects.bbox(current_object).pmin().row() r = 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() r = objects.bbox(current_object).pmin().row()
- math::min(10u, h /10); + math::min(10u, h /10);
break; break;
// Center // Bottom
case 1: case anchor::Bottom:
return mass_centers(current_object);
// Bottom
case 2:
if (h < 30) if (h < 30)
r = objects.bbox(current_object).pmax().row() r = 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() r = objects.bbox(current_object).pmax().row()
- math::min(10u, h /10); - math::min(10u, h /10);
break; break;
case anchor::Center:
return objects.bbox(current_object).center();
default: default:
trace::warning("Non handled anchor"); trace::warning("Non handled anchor");
mln_assertion(anchor > 2); mln_assertion(anchor > 2);
...@@ -143,4 +147,4 @@ namespace scribo ...@@ -143,4 +147,4 @@ namespace scribo
} // end of namespace scribo } // end of namespace scribo
#endif // ! SCRIBO_PRIMITIVE_LINK_INTERNAL_ANCHORS_3_HH #endif // ! SCRIBO_PRIMITIVE_LINK_INTERNAL_COMPUTE_ANCHOR_HH
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
# include <mln/util/couple.hh> # include <mln/util/couple.hh>
# include <scribo/core/concept/link_functor.hh> # include <scribo/core/concept/link_functor.hh>
# include <scribo/core/anchors.hh>
# include <scribo/core/object_image.hh> # include <scribo/core/object_image.hh>
# include <scribo/core/object_links.hh> # include <scribo/core/object_links.hh>
# include <scribo/primitive/internal/update_link_array.hh> # include <scribo/primitive/internal/update_link_array.hh>
...@@ -59,27 +60,30 @@ namespace scribo ...@@ -59,27 +60,30 @@ namespace scribo
\param[in,out] functor Functor used to compute the \param[in,out] functor Functor used to compute the
links. Stores the results. links. Stores the results.
\param[in] current_object Current object id. \param[in] current_object Current object id.
\param[in] anchor The lookup anchor.
\return A couple. The first argument tells whether a valid \return A couple. The first argument tells whether a valid
link has been found, the second one is link anchor if exists. link has been found, the second one is link anchor if exists.
*/ */
template <typename F> template <typename F>
mln::util::couple<bool, mln_site(scribo_support_(F))> mln::util::couple<bool, mln_site(scribo_support_(F))>
find_link(Link_Functor<F>& functor, unsigned current_object); find_link(Link_Functor<F>& functor, unsigned current_object,
anchor::Type anchor);
# ifndef MLN_INCLUDE_ONLY # ifndef MLN_INCLUDE_ONLY
template <typename F> template <typename F>
mln::util::couple<bool, mln_site(scribo_support_(F))> mln::util::couple<bool, mln_site(scribo_support_(F))>
find_link(Link_Functor<F>& functor_, unsigned current_object) find_link(Link_Functor<F>& functor_, unsigned current_object,
anchor::Type anchor)
{ {
F& functor = exact(functor_); F& functor = exact(functor_);
functor.initialize_link(current_object); // <-- initialize_link functor.initialize_link(current_object); // <-- initialize_link
mln_site(scribo_support_(F)) mln_site(scribo_support_(F))
start_point = functor.start_point(current_object), start_point = functor.start_point(current_object, anchor), // <-- start_point
p = start_point; p = start_point;
mln_postcondition(p == start_point); mln_postcondition(p == start_point);
...@@ -93,9 +97,9 @@ namespace scribo ...@@ -93,9 +97,9 @@ namespace scribo
functor.compute_next_site(p); // <-- compute_next_site functor.compute_next_site(p); // <-- compute_next_site
if (functor.valid_link(current_object, start_point, p)) // <-- valid_link if (functor.valid_link(current_object, start_point, p)) // <-- valid_link
functor.validate_link(current_object, start_point, p); // <-- validate_link functor.validate_link(current_object, start_point, p, anchor); // <-- validate_link
else else
functor.invalidate_link(current_object, start_point, p); // <-- invalidate_link functor.invalidate_link(current_object, start_point, p, anchor); // <-- invalidate_link
functor.finalize_link(current_object); // <-- finalize_link functor.finalize_link(current_object); // <-- finalize_link
......
...@@ -29,6 +29,9 @@ ...@@ -29,6 +29,9 @@
/// \file /// \file
/// ///
/// Find the neighbor of a line of text if exists. /// Find the neighbor of a line of text if exists.
///
/// \fixme do not iterate over the number of anchor types but use a
/// set of anchors specified in the functor.
# include <mln/core/concept/image.hh> # include <mln/core/concept/image.hh>
...@@ -38,6 +41,7 @@ ...@@ -38,6 +41,7 @@
# include <mln/util/couple.hh> # include <mln/util/couple.hh>
# include <scribo/core/concept/link_functor.hh> # include <scribo/core/concept/link_functor.hh>
# include <scribo/core/anchors.hh>
# include <scribo/core/object_image.hh> # include <scribo/core/object_image.hh>
# include <scribo/core/object_links.hh> # include <scribo/core/object_links.hh>
# include <scribo/primitive/internal/update_link_array.hh> # include <scribo/primitive/internal/update_link_array.hh>
...@@ -51,70 +55,82 @@ namespace scribo ...@@ -51,70 +55,82 @@ namespace scribo
namespace primitive namespace primitive
{ {
namespace internal namespace link
{ {
/*! Find the neighbor of a line of text if exists. namespace internal
{
/*! Find the neighbor of a line of text if exists.
\param[in,out] functor Functor used to compute the \param[in,out] functor Functor used to compute the
links. Stores the results. links. Stores the results.
\param current_object Current object id. \param current_object Current object id.
\return A couple. The first argument tells whether a valid \return A couple. The first argument tells whether a valid
link has been found, the second one is link anchor if exists. link has been found, the second one is link anchor if exists.
*/ */
template <typename F> template <typename F>
mln::util::couple<bool, mln_site(scribo_support_(F))> mln::util::couple<bool,
find_several_links(Link_Functor<F>& functor, mln::util::couple<anchor::Type,
unsigned current_object); mln_site(scribo_support_(F))> >
find_several_links(Link_Functor<F>& functor,
unsigned current_object);
# ifndef MLN_INCLUDE_ONLY # ifndef MLN_INCLUDE_ONLY
template <typename F> template <typename F>
mln::util::couple<bool, mln_site(scribo_support_(F))> mln::util::couple<bool,
find_several_links(Link_Functor<F>& functor_, mln::util::couple<anchor::Type,
unsigned current_object) mln_site(scribo_support_(F))> >
{ find_several_links(Link_Functor<F>& functor_,
F& functor = exact(functor_); unsigned current_object)
{
F& functor = exact(functor_);
typedef mln_site(scribo_support_(F)) P; typedef mln_site(scribo_support_(F)) P;
typedef mln::util::couple<unsigned, P> link_t; typedef mln::util::couple<anchor::Type, P> link_t;
P lp = functor.initialize_link(current_object); // <-- initialize_link functor.initialize_link(current_object); // <-- initialize_link