* scribo/core/tag/anchor.hh: Add new anchors.
* scribo/filter/internal/alignment_angle.hh,
* scribo/primitive/link/internal/compute_anchor.hh: Support new
anchors.
* scribo/primitive/extract/separators_nonvisible.hh: Remove dead
code and comment debug code.
* scribo/toolchain/internal/content_in_doc_functor.hh: Detect
horizontal whitespace.
---
scribo/ChangeLog | 16 +
scribo/scribo/core/tag/anchor.hh | 5 +-
scribo/scribo/filter/internal/alignment_angle.hh | 144 +++--
.../primitive/extract/separators_nonvisible.hh | 673 +++++++++-----------
.../primitive/link/internal/compute_anchor.hh | 26 +-
.../toolchain/internal/content_in_doc_functor.hh | 13 +-
6 files changed, 447 insertions(+), 430 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index ab498cc..d783c5c 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,21 @@
2011-02-17 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Improve and cleanup whitespace separator detection.
+
+ * scribo/core/tag/anchor.hh: Add new anchors.
+
+ * scribo/filter/internal/alignment_angle.hh,
+ * scribo/primitive/link/internal/compute_anchor.hh: Support new
+ anchors.
+
+ * scribo/primitive/extract/separators_nonvisible.hh: Remove dead
+ code and comment debug code.
+
+ * scribo/toolchain/internal/content_in_doc_functor.hh: Detect
+ horizontal whitespace.
+
+2011-02-17 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Add new conversion routines from string to tag.
* scribo/core/tag/component.hh,
diff --git a/scribo/scribo/core/tag/anchor.hh b/scribo/scribo/core/tag/anchor.hh
index 262a32d..bb6780c 100644
--- a/scribo/scribo/core/tag/anchor.hh
+++ b/scribo/scribo/core/tag/anchor.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009, 2011 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of Olena.
//
@@ -43,9 +44,11 @@ namespace scribo
ActualRight,
Right,
TopLeft,
+ TopStrictLeft,
TopRight,
BottomLeft,
BottomRight,
+ BottomStrictRight,
Invalid
};
diff --git a/scribo/scribo/filter/internal/alignment_angle.hh
b/scribo/scribo/filter/internal/alignment_angle.hh
index 5b88012..33855a8 100644
--- a/scribo/scribo/filter/internal/alignment_angle.hh
+++ b/scribo/scribo/filter/internal/alignment_angle.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2010 EPITA Research and Development Laboratory
+// Copyright (C) 2010, 2011 EPITA Research and Development Laboratory
// (LRDE)
//
// This file is part of Olena.
@@ -73,76 +73,98 @@ namespace scribo
unsigned current_object, unsigned nbh_object,
anchor::Type anchor)
{
- trace::entering("scribo::filter::internal::alignment_angle_rad");
+ trace::entering("scribo::filter::internal::alignment_angle");
mln_precondition(comps.is_valid());
- float dr, dc;
+ float dr, dc, result = 0;
if (nbh_object == current_object)
return 0;
- // Center
- if (anchor == anchor::Center)
+ switch(anchor)
{
- dr = math::abs(comps(current_object).bbox().pcenter().row()
- - comps(nbh_object).bbox().pcenter().row());
- dc = math::abs(comps(current_object).bbox().pcenter().col()
- - comps(nbh_object).bbox().pcenter().col());
-
- return std::atan(dr / dc);
- }
-
- // Top
- else if (anchor == anchor::Top)
- {
- dr = math::abs(comps(current_object).bbox().pmin().row()
- - comps(nbh_object).bbox().pmin().row());
- dc = math::abs(comps(current_object).bbox().pcenter().col()
- - comps(nbh_object).bbox().pcenter().col());
-
- return std::atan(dr / dc);
+ // Center
+ case anchor::Center:
+ {
+ dr = math::abs(comps(current_object).bbox().pcenter().row()
+ - comps(nbh_object).bbox().pcenter().row());
+ dc = math::abs(comps(current_object).bbox().pcenter().col()
+ - comps(nbh_object).bbox().pcenter().col());
+
+ result = std::atan(dr / dc);
+ }
+ break;
+
+ // Mass Center
+ case anchor::MassCenter:
+ {
+ dr = math::abs(comps(current_object).mass_center().row()
+ - comps(nbh_object).mass_center().row());
+ dc = math::abs(comps(current_object).mass_center().col()
+ - comps(nbh_object).mass_center().col());
+
+ result = std::atan(dr / dc);
+ }
+ break;
+
+ // Top
+ case anchor::TopStrictLeft:
+ case anchor::Top:
+ {
+ dr = math::abs(comps(current_object).bbox().pmin().row()
+ - comps(nbh_object).bbox().pmin().row());
+ dc = math::abs(comps(current_object).bbox().pcenter().col()
+ - comps(nbh_object).bbox().pcenter().col());
+
+ result = std::atan(dr / dc);
+ }
+ break;
+
+ // Bottom
+ case anchor::BottomStrictRight:
+ case anchor::Bottom:
+ {
+ dr = math::abs(comps(current_object).bbox().pmax().row()
+ - comps(nbh_object).bbox().pmax().row());
+ dc = math::abs(comps(current_object).bbox().pcenter().col()
+ - comps(nbh_object).bbox().pcenter().col());
+
+ result = std::atan(dr / dc);
+ }
+ break;
+
+ // Left
+ case anchor::Left:
+ {
+ dr = math::abs(comps(current_object).bbox().pcenter().row()
+ - comps(nbh_object).bbox().pcenter().row());
+ dc = math::abs(comps(current_object).bbox().pmin().col()
+ - comps(nbh_object).bbox().pmin().col());
+
+ result = std::atan(dc / dr);
+ }
+ break;
+
+ // Right
+ case anchor::Right:
+ {
+ dr = math::abs(comps(current_object).bbox().pcenter().row()
+ - comps(nbh_object).bbox().pcenter().row());
+ dc = math::abs(comps(current_object).bbox().pmax().col()
+ - comps(nbh_object).bbox().pmax().col());
+
+ result = std::atan(dc / dr);
+ }
+ break;
+
+ default:
+ trace::warning("scribo::filter::internal::alignment_angle,"
+ " Invalid anchor value... Aborting computation.");
}
- // Bottom
- else if (anchor == anchor::Bottom)
- {
- dr = math::abs(comps(current_object).bbox().pmax().row()
- - comps(nbh_object).bbox().pmax().row());
- dc = math::abs(comps(current_object).bbox().pcenter().col()
- - comps(nbh_object).bbox().pcenter().col());
-
- return std::atan(dr / dc);
- }
-
- // Left
- else if (anchor == anchor::Left)
- {
- dr = math::abs(comps(current_object).bbox().pcenter().row()
- - comps(nbh_object).bbox().pcenter().row());
- dc = math::abs(comps(current_object).bbox().pmin().col()
- - comps(nbh_object).bbox().pmin().col());
-
- return std::atan(dc / dr);
- }
-
- // Right
- else if (anchor == anchor::Right)
- {
- dr = math::abs(comps(current_object).bbox().pcenter().row()
- - comps(nbh_object).bbox().pcenter().row());
- dc = math::abs(comps(current_object).bbox().pmax().col()
- - comps(nbh_object).bbox().pmax().col());
-
- return std::atan(dc / dr);
- }
-
- else
- trace::warning("Invalid anchor value... Aborting computation.");
-
- trace::exiting("scribo::filter::internal::alignment_angle_rad");
- return 0;
-
+ trace::exiting("scribo::filter::internal::alignment_angle");
+ return result;
}
# endif // ! MLN_INCLUDE_ONLY
diff --git a/scribo/scribo/primitive/extract/separators_nonvisible.hh
b/scribo/scribo/primitive/extract/separators_nonvisible.hh
index 81ebd64..4e31650 100644
--- a/scribo/scribo/primitive/extract/separators_nonvisible.hh
+++ b/scribo/scribo/primitive/extract/separators_nonvisible.hh
@@ -86,6 +86,8 @@
#include <scribo/preprocessing/denoise_fg.hh>
#include <scribo/preprocessing/rotate_90.hh>
+#include <scribo/primitive/link/internal/compute_anchor.hh>
+
#include <scribo/primitive/link/internal/dmax_default.hh>
#include <scribo/primitive/link/with_single_right_link_dmax_ratio.hh>
@@ -128,80 +130,6 @@ namespace scribo
namespace internal
{
- template <typename L>
- void filter_bad_groups(object_groups<L>& top_groups,
- object_groups<L>& bot_groups)
- {
- const component_set<L>& comps = top_groups.components();
- const L& lbl = comps.labeled_image();
-
- for_all_groups(c, top_groups)
- {
- box2d b = comps(c).bbox();
- b.enlarge(0, comps(c).bbox().height());
- b.crop_wrt(lbl.domain());
-
- typedef mln_value(L) V;
-
- const V* top_ptr = & lbl(b.pmin());
- const V* bot_ptr = & lbl(point2d(b.pmax().row(), b.pmin().col()));
-
- unsigned ntop = 0, nbot = 0;
- for (unsigned n = 0; n < b.width(); ++n)
- {
- if (*top_ptr)
- ++ntop;
- if (*bot_ptr)
- ++nbot;
- }
-
- if (ntop / b.width() > 0.50f)
- top_groups(c) = c;
-
- if (nbot / b.width() > 0.50f)
- bot_groups(c) = c;
- }
-
- }
-
-
- template <typename L>
- mln_site(L)
- my_anchors(const component_set<L>& comps,
- unsigned current_object,
- anchor::Type anchor)
- {
- mln_site(L) sp;// = comps(current_object).bbox().pcenter();
-
- unsigned h = comps(current_object).bbox().height();
-
- switch (anchor)
- {
- default:
- return sp;
-
-
- // Bounding box top center
- case anchor::Top: // FIXME: rename as TopLeft
- sp.col() = comps(current_object).bbox().pmin().col();
- sp.row() = comps(current_object).bbox().pmin().row()
- + math::min(2u, (h + 1) / 2 - 1);
- break;
-
-
- // Bounding box bottom center
- case anchor::Bottom: // FIXME: rename as BottomLeft
- sp.col() = comps(current_object).bbox().pmax().col();
- sp.row() = comps(current_object).bbox().pmax().row()
- - math::min(2u, (h + 1) / 2 - 1);
- break;
- }
-
- return sp;
- }
-
-
-
using namespace primitive::link::internal;
template <typename L, typename E>
@@ -225,12 +153,17 @@ namespace scribo
anchor::Horizontal,
dmax_default(dmax)),
anchor(anchor_),
- debug_(data::convert(value::rgb8(), input)),
- debug_angle_(data::convert(value::rgb8(), input)),
_debug_(debug)
{
+ (void) input; // FIXME : remove this argument
min_alpha_rad = (min_angle / 180.0f) * math::pi;
max_alpha_rad = (max_angle / 180.0f) * math::pi;
+
+ // if (_debug_)
+ // {
+ // debug_ = data::convert(value::rgb8(), input);
+ // debug_angle_ = data::convert(value::rgb8(), input);
+ // }
}
void compute_next_site_(P& p)
@@ -247,7 +180,8 @@ namespace scribo
mln_site(L)
start_point_(unsigned current_object, anchor::Type anchor)
{
- return my_anchors(this->components_, current_object, anchor);
+ return link::internal::compute_anchor(this->components_,
+ current_object, anchor);
}
@@ -303,27 +237,29 @@ namespace scribo
{
super_::validate_link_(current_object, start_point, p, anchor);
- if (_debug_)
- {
- mln_site(L)
- p1 = my_anchors(this->components_, current_object, anchor),
- p2 = my_anchors(this->components_, this->labeled_image_(p),
- anchor);
- mln::draw::line(debug_, p1, p2, literal::green);
-
-
- float
- angle = filter::internal::alignment_angle(this->components_,
- current_object,
- this->labeled_image_(p),
- anchor);
- angle = (angle * 180.0f) / math::pi;
- angle = angle * 20.0f + 1.0f;
- mln::draw::line(debug_angle_, p1, p2,
- value::rgb8(unsigned(angle),
- unsigned(angle),
- unsigned(angle)));
- }
+ // if (_debug_)
+ // {
+ // mln_site(L)
+ // p1 = link::internal::compute_anchor(this->components_,
+ // current_object, anchor),
+ // p2 = link::internal::compute_anchor(this->components_,
+ // this->labeled_image_(p),
+ // anchor);
+ // mln::draw::line(debug_, p1, p2, literal::green);
+
+
+ // float
+ // angle = filter::internal::alignment_angle(this->components_,
+ // current_object,
+ // this->labeled_image_(p),
+ // anchor);
+ // angle = (angle * 180.0f) / math::pi;
+ // angle = angle * 20.0f + 1.0f;
+ // mln::draw::line(debug_angle_, p1, p2,
+ // value::rgb8(unsigned(angle),
+ // unsigned(angle),
+ // unsigned(angle)));
+ // }
}
void invalidate_link_(unsigned current_object,
@@ -333,33 +269,36 @@ namespace scribo
{
super_::invalidate_link_(current_object, start_point, p, anchor);
- if (_debug_)
- {
- if (this->labeled_image_.domain().has(p) && this->labeled_image_(p)
!= 0)
- {
- mln_site(L)
- p1 = my_anchors(this->components_, current_object, anchor),
- p2 = my_anchors(this->components_, this->labeled_image_(p),
- anchor);
- if (this->labeled_image_.domain().has(p2) && norm::l1_distance(p1.to_vec(),
p2.to_vec()) < 300)
- {
- mln::draw::line(debug_, p1, p2, literal::red);
- }
-
-
- float
- angle = filter::internal::alignment_angle(this->components_,
- current_object,
- this->labeled_image_(p),
- anchor);
- angle = (angle * 180.0f) / math::pi;
- angle = angle * 20.0f + 1.0f;
- mln::draw::line(debug_angle_, p1, p2,
- value::rgb8(unsigned(angle),
- unsigned(angle),
- unsigned(angle)));
- }
- }
+ // if (_debug_)
+ // {
+ // if (this->labeled_image_.domain().has(p) &&
this->labeled_image_(p) != 0)
+ // {
+ // mln_site(L)
+ // p1 = link::internal::compute_anchor(this->components_,
+ // current_object, anchor),
+ // p2 = link::internal::compute_anchor(this->components_,
+ // this->labeled_image_(p),
+ // anchor);
+ // if (this->labeled_image_.domain().has(p2)
+ // && norm::l1_distance(p1.to_vec(), p2.to_vec()) < 300)
+ // {
+ // mln::draw::line(debug_, p1, p2, literal::red);
+ // }
+
+
+ // float
+ // angle = filter::internal::alignment_angle(this->components_,
+ // current_object,
+ // this->labeled_image_(p),
+ // anchor);
+ // angle = (angle * 180.0f) / math::pi;
+ // angle = angle * 20.0f + 1.0f;
+ // mln::draw::line(debug_angle_, p1, p2,
+ // value::rgb8(unsigned(angle),
+ // unsigned(angle),
+ // unsigned(angle)));
+ // }
+ // }
}
@@ -368,8 +307,8 @@ namespace scribo
anchor::Type anchor;
- mln_ch_value(L, value::rgb8) debug_;
- mln_ch_value(L, value::rgb8) debug_angle_;
+ // mln_ch_value(L, value::rgb8) debug_;
+ // mln_ch_value(L, value::rgb8) debug_angle_;
bool _debug_;
};
@@ -392,7 +331,8 @@ namespace scribo
float max_angle,
anchor::Type anchor,
bool debug)
- : super_(input, components, dmax, min_angle, max_angle, anchor, debug)
+ : super_(input, components, dmax, min_angle,
+ max_angle, anchor, debug)
{
}
@@ -427,7 +367,8 @@ namespace scribo
float max_angle,
anchor::Type anchor,
bool debug)
- : super_(input, components, dmax, min_angle, max_angle, anchor, debug)
+ : super_(input, components, dmax, min_angle,
+ max_angle, anchor, debug)
{
}
@@ -455,6 +396,8 @@ namespace scribo
mln_concrete(I)
separators_nonvisible(const Image<I>& in_)
{
+ trace::entering("scribo::primitive::extract::separators_nonvisible");
+
const I& in = exact(in_);
mln_precondition(in.is_valid());
typedef mln_value(I) Vi;
@@ -469,42 +412,35 @@ namespace scribo
util::timer t;
util::timer gt;
- // Load (OK)
- t.start();
- float t_ = t;
- std::cout << "Image loaded - " << t_ << std::endl;
-
gt.start();
- // Remove horizontal lines.
- t.restart();
+ // // Remove horizontal lines.
+ // t.restart();
- mln_concrete(I) hlines = primitive::extract::lines_h_pattern(in, 50, 3);
- mln_concrete(I) input = primitive::remove::separators(in, hlines);
+ // mln_concrete(I) hlines = primitive::extract::lines_h_pattern(in, 50, 3);
+ // mln_concrete(I) input = primitive::remove::separators(in, hlines);
- t_ = t;
- std::cout << "Horizontal lines removed - " << t_ <<
std::endl;
+ // t_ = t;
+ // std::cout << "Horizontal lines removed - " << t_ <<
std::endl;
// Closing structural - Connect characters.
- t.restart();
+ t.start();
win::hline2d vl(17);
- mln_concrete(I) input_clo = morpho::closing::structural(input, vl);
+ mln_concrete(I) input_clo = morpho::closing::structural(in, vl);
-// input_clo = scribo::preprocessing::rotate_90(input_clo, true);
-
- t_ = t;
+ float t_ = t;
std::cout << "closing_structural - " << t_ << std::endl;
- if (_debug_)
- {
- // Restore input orientation.
- input = scribo::preprocessing::rotate_90(input, false);
+ // if (_debug_)
+ // {
+ // // Restore input orientation.
+ // input = scribo::preprocessing::rotate_90(input, false);
- io::pbm::save(input_clo, "input_clo.pbm");
- }
+ // io::pbm::save(input_clo, "input_clo.pbm");
+ // }
// Rotate (OK)
t.restart();
@@ -526,9 +462,9 @@ namespace scribo
t_ = t;
std::cout << "extract::components - " << t_ << std::endl;
- if (_debug_)
- io::pgm::save(data::convert(value::int_u8(), components.labeled_image()),
- "lbl.pgm");
+ // if (_debug_)
+ // io::pgm::save(data::convert(value::int_u8(), components.labeled_image()),
+ // "lbl.pgm");
unsigned dmax = 5;
@@ -543,39 +479,42 @@ namespace scribo
{
// Right
internal::single_right_dmax_ratio_aligned_functor<L>
- functor(input_clo, components, dmax, min_angle, max_angle, anchor::Top, _debug_);
-// top_right = primitive::link::impl::compute_fastest(functor, anchor::Top);
- top_right = primitive::link::compute(functor, anchor::Top);
+ functor(input_clo, components, dmax, min_angle, max_angle,
+ anchor::TopStrictLeft, _debug_);
+// top_right = primitive::link::impl::compute_fastest(functor,
anchor::TopStrictLeft);
+ top_right = primitive::link::compute(functor, anchor::TopStrictLeft);
t.stop();
- if (_debug_)
- {
- io::ppm::save(functor.debug_, "right_top.ppm");
- io::ppm::save(functor.debug_angle_, "right_top_angle.ppm");
- }
+ // if (_debug_)
+ // {
+ // io::ppm::save(functor.debug_, "right_top.ppm");
+ // io::ppm::save(functor.debug_angle_, "right_top_angle.ppm");
+ // }
t.resume();
// Left
internal::single_left_dmax_ratio_aligned_functor<L>
- lfunctor(input_clo, components, dmax, min_angle, max_angle, anchor::Top, _debug_);
- top_left = primitive::link::compute(lfunctor, anchor::Top);
+ lfunctor(input_clo, components, dmax, min_angle, max_angle,
+ anchor::TopStrictLeft, _debug_);
+ top_left = primitive::link::compute(lfunctor, anchor::TopStrictLeft);
t.stop();
- if (_debug_)
- {
- io::ppm::save(lfunctor.debug_, "left_top.ppm");
- io::ppm::save(lfunctor.debug_angle_, "left_top_angle.ppm");
+ // if (_debug_)
+ // {
+ // io::ppm::save(lfunctor.debug_, "left_top.ppm");
+ // io::ppm::save(lfunctor.debug_angle_, "left_top_angle.ppm");
- mln_ch_value(I, value::rgb8) output = duplicate(functor.debug_);
- data::paste((lfunctor.debug_ | (pw::value(lfunctor.debug_) !=
pw::cst(literal::black))) | (pw::value(lfunctor.debug_) != pw::cst(literal::white)),
output);
+ // mln_ch_value(I, value::rgb8) output = duplicate(functor.debug_);
+ // data::paste((lfunctor.debug_ | (pw::value(lfunctor.debug_) !=
pw::cst(literal::black)))
+ // | (pw::value(lfunctor.debug_) != pw::cst(literal::white)), output);
- io::ppm::save(output, "left_right_top.ppm");
- }
+ // io::ppm::save(output, "left_right_top.ppm");
+ // }
t.resume();
}
@@ -585,105 +524,53 @@ namespace scribo
{
// Right
internal::single_right_dmax_ratio_aligned_functor<L>
- functor(input_clo, components, dmax, min_angle, max_angle, anchor::Bottom,
_debug_);
- bot_right = primitive::link::compute(functor, anchor::Bottom);
+ functor(input_clo, components, dmax, min_angle, max_angle,
+ anchor::BottomStrictRight, _debug_);
+ bot_right = primitive::link::compute(functor, anchor::BottomStrictRight);
t.stop();
- if (_debug_)
- {
- io::ppm::save(functor.debug_, "right_bot.ppm");
- io::ppm::save(functor.debug_angle_, "right_bot_angle.ppm");
- }
+ // if (_debug_)
+ // {
+ // io::ppm::save(functor.debug_, "right_bot.ppm");
+ // io::ppm::save(functor.debug_angle_, "right_bot_angle.ppm");
+ // }
t.resume();
// Left
internal::single_left_dmax_ratio_aligned_functor<L>
- lfunctor(input_clo, components, dmax, min_angle, max_angle, anchor::Bottom,
_debug_);
- bot_left = primitive::link::compute(lfunctor, anchor::Bottom);
+ lfunctor(input_clo, components, dmax, min_angle, max_angle,
+ anchor::BottomStrictRight, _debug_);
+ bot_left = primitive::link::compute(lfunctor, anchor::BottomStrictRight);
t.stop();
- if (_debug_)
- {
- io::ppm::save(lfunctor.debug_, "left_bot.ppm");
- io::ppm::save(lfunctor.debug_angle_, "left_bot_angle.ppm");
- }
+ // if (_debug_)
+ // {
+ // io::ppm::save(lfunctor.debug_, "left_bot.ppm");
+ // io::ppm::save(lfunctor.debug_angle_, "left_bot_angle.ppm");
- if (_debug_)
- {
- mln_ch_value(I, value::rgb8) output = duplicate(functor.debug_);
- data::paste((lfunctor.debug_ | (pw::value(lfunctor.debug_) !=
pw::cst(literal::black))) | (pw::value(lfunctor.debug_) != pw::cst(literal::white)),
output);
+ // mln_ch_value(I, value::rgb8) output = duplicate(functor.debug_);
+ // data::paste((lfunctor.debug_ | (pw::value(lfunctor.debug_) !=
pw::cst(literal::black)))
+ // | (pw::value(lfunctor.debug_) != pw::cst(literal::white)), output);
- io::ppm::save(output, "left_right_bot.ppm");
- }
+ // io::ppm::save(output, "left_right_bot.ppm");
+ // }
}
t_ = t;
std::cout << "links - " << t_ << std::endl;
-
+ // Merge links and build CC groups
t.restart();
- std::cout << "group - top" << std::endl;
object_groups<L>
top_groups = primitive::group::from_double_link_any(top_left, top_right);
- std::cout << "group - bot" << std::endl;
object_groups<L>
bot_groups = primitive::group::from_double_link_any(bot_left, bot_right);
t_ = t;
std::cout << "group - " << t_ << std::endl;
- t.restart();
- util::array<accu::shape::bbox<point2d> >
- btop_accu(top_groups.nelements()),
- bbot_accu(bot_groups.nelements());
-
-
- for_all_groups(c, top_groups)
- {
- btop_accu(top_groups(c)).take(components(c).bbox());
- bbot_accu(bot_groups(c)).take(components(c).bbox());
- }
- t_ = t;
- std::cout << "groups to group bboxes - " << t_ <<
std::endl;
-
-
-
- if (_debug_)
- {
-
- mln_ch_value(I, value::rgb8)
- wo_filtering = data::convert(value::rgb8(), input);
-
- for_all_comp_data(d, btop_accu)
- {
- if (btop_accu(d).is_valid())
- {
- mln::draw::line(wo_filtering,
- btop_accu(d).to_result().pmin(),
- point2d(btop_accu(d).to_result().pmin().row(),
- btop_accu(d).to_result().pmax().col()),
- literal::green);
-
- }
- }
-
- for_all_comp_data(d, bbot_accu)
- {
- if (bbot_accu(d).is_valid())
- {
- mln::draw::line(wo_filtering,
- point2d(bbot_accu(d).to_result().pmax().row(),
- bbot_accu(d).to_result().pmin().col()),
- bbot_accu(d).to_result().pmax(),
- literal::green);
- }
-
- }
- io::ppm::save(wo_filtering, "wo_filtering.ppm");
- }
-
-
+ // Filter CC groups
t.restart();
top_groups = filter::object_groups_small(top_groups, min_card);
bot_groups = filter::object_groups_small(bot_groups, min_card);
@@ -691,7 +578,7 @@ namespace scribo
std::cout << "small groups - " << t_ << std::endl;
-
+ // Compute group bboxes
t.restart();
util::array<accu::shape::bbox<point2d> >
top_accu(top_groups.nelements()),
@@ -708,78 +595,35 @@ namespace scribo
-
-
-
-
-
t.restart();
mln_concrete(I) separators;
initialize(separators, input_clo);
+
+ // FIXME: any way to fill border AND data at the same time?
data::fill(separators, false);
+ extension::fill(separators, false);
+
t_ = t;
std::cout << "Initialize separators image - " << t_ <<
std::endl;
- mln_ch_value(I, value::rgb8) both;
-
- if (_debug_)
- both = data::convert(value::rgb8(), input);
-
-
-
t.restart();
for_all_comp_data(d, top_accu)
{
- if (top_accu(d).is_valid() || btop_accu(d).is_valid())
+ if (top_accu(d).is_valid())
{
- if (top_accu(d).is_valid())
- {
- if (_debug_)
- mln::draw::line(both,
- top_accu(d).to_result().pmin(),
- point2d(top_accu(d).to_result().pmin().row(),
- top_accu(d).to_result().pmax().col()),
- literal::green);
-
- mln::draw::line(separators,
- top_accu(d).to_result().pmin(),
- point2d(top_accu(d).to_result().pmin().row(),
- top_accu(d).to_result().pmax().col()),
- true);
- }
- else
- if (_debug_ && btop_accu(d).is_valid())
- mln::draw::line(both,
- btop_accu(d).to_result().pmin(),
- point2d(btop_accu(d).to_result().pmin().row(),
- btop_accu(d).to_result().pmax().col()),
- literal::yellow);
-
+ mln::draw::line(separators,
+ top_accu(d).to_result().pmin(),
+ point2d(top_accu(d).to_result().pmin().row(),
+ top_accu(d).to_result().pmax().col()),
+ true);
}
- if (bot_accu(d).is_valid() || bbot_accu(d).is_valid())
+ if (bot_accu(d).is_valid())
{
- if (bot_accu(d).is_valid())
- {
- if (_debug_)
- mln::draw::line(both,
- point2d(bot_accu(d).to_result().pmax().row(),
- bot_accu(d).to_result().pmin().col()),
- bot_accu(d).to_result().pmax(),
- literal::green);
-
- mln::draw::line(separators,
- point2d(bot_accu(d).to_result().pmax().row(),
- bot_accu(d).to_result().pmin().col()),
- bot_accu(d).to_result().pmax(),
- true);
- }
- else
- if (_debug_ && bbot_accu(d).is_valid())
- mln::draw::line(both,
- point2d(bbot_accu(d).to_result().pmax().row(),
- bbot_accu(d).to_result().pmin().col()),
- bbot_accu(d).to_result().pmax(),
- literal::yellow);
+ mln::draw::line(separators,
+ point2d(bot_accu(d).to_result().pmax().row(),
+ bot_accu(d).to_result().pmin().col()),
+ bot_accu(d).to_result().pmax(),
+ true);
}
}
@@ -787,22 +631,112 @@ namespace scribo
std::cout << "Drawing output image - " << t_ << std::endl;
- if (_debug_)
- {
- io::ppm::save(both, "both.ppm");
- io::pbm::save(separators, "separators.pbm");
- }
+ // if (_debug_)
+ // {
+ // // Restore input orientation.
+ // mln_concrete(I) input = scribo::preprocessing::rotate_90(in, false);
+
+
+ // // Debug group bboxes (includes all bboxes before filtering)
+ // util::array<accu::shape::bbox<point2d> >
+ // btop_accu(top_groups.nelements()),
+ // bbot_accu(bot_groups.nelements());
+
+
+ // for_all_groups(c, top_groups)
+ // {
+ // btop_accu(top_groups(c)).take(components(c).bbox());
+ // bbot_accu(bot_groups(c)).take(components(c).bbox());
+ // }
+
+ // mln_ch_value(I, value::rgb8)
+ // wo_filtering = data::convert(value::rgb8(), input);
+
+ // for_all_comp_data(d, btop_accu)
+ // {
+ // if (btop_accu(d).is_valid())
+ // {
+ // mln::draw::line(wo_filtering,
+ // btop_accu(d).to_result().pmin(),
+ // point2d(btop_accu(d).to_result().pmin().row(),
+ // btop_accu(d).to_result().pmax().col()),
+ // literal::green);
+
+ // }
+ // }
+
+ // for_all_comp_data(d, bbot_accu)
+ // {
+ // if (bbot_accu(d).is_valid())
+ // {
+ // mln::draw::line(wo_filtering,
+ // point2d(bbot_accu(d).to_result().pmax().row(),
+ // bbot_accu(d).to_result().pmin().col()),
+ // bbot_accu(d).to_result().pmax(),
+ // literal::green);
+ // }
+
+ // }
+ // io::ppm::save(wo_filtering, "wo_filtering.ppm");
+
+ // mln_ch_value(I, value::rgb8) both = data::convert(value::rgb8(), input);
+
+ // for_all_comp_data(d, top_accu)
+ // {
+ // if (top_accu(d).is_valid() || btop_accu(d).is_valid())
+ // {
+ // if (top_accu(d).is_valid())
+ // {
+ // mln::draw::line(both,
+ // top_accu(d).to_result().pmin(),
+ // point2d(top_accu(d).to_result().pmin().row(),
+ // top_accu(d).to_result().pmax().col()),
+ // literal::green);
+ // }
+ // else
+ // if (btop_accu(d).is_valid())
+ // mln::draw::line(both,
+ // btop_accu(d).to_result().pmin(),
+ // point2d(btop_accu(d).to_result().pmin().row(),
+ // btop_accu(d).to_result().pmax().col()),
+ // literal::yellow);
+
+ // }
+ // if (bot_accu(d).is_valid() || bbot_accu(d).is_valid())
+ // {
+ // if (bot_accu(d).is_valid())
+ // {
+ // mln::draw::line(both,
+ // point2d(bot_accu(d).to_result().pmax().row(),
+ // bot_accu(d).to_result().pmin().col()),
+ // bot_accu(d).to_result().pmax(),
+ // literal::green);
+ // }
+ // else
+ // if (bbot_accu(d).is_valid())
+ // mln::draw::line(both,
+ // point2d(bbot_accu(d).to_result().pmax().row(),
+ // bbot_accu(d).to_result().pmin().col()),
+ // bbot_accu(d).to_result().pmax(),
+ // literal::yellow);
+ // }
+
+ // }
+
+ // io::ppm::save(both, "both.ppm");
+ // io::pbm::save(separators, "separators.pbm");
+ // }
// Hit or miss
{
- if (_debug_)
- {
- mln_concrete(I) input_with_seps = duplicate(input_clo);
- data::paste(separators | pw::value(separators), input_with_seps);
+ // if (_debug_)
+ // {
+ // mln_concrete(I) input_with_seps = duplicate(input_clo);
+ // data::paste(separators | pw::value(separators), input_with_seps);
- io::pbm::save(input_with_seps, "input_with_seps.pbm");
- }
+ // io::pbm::save(input_with_seps, "input_with_seps.pbm");
+ // }
t.restart();
unsigned length = 25;
@@ -819,11 +753,12 @@ namespace scribo
typedef mln_ch_value(I,unsigned) J;
J tmp = accu::transform_line(accu, input_clo, length, 1);
+
t_ = t;
std::cout << "* accu::transform_line - " << t_ <<
std::endl;
- if (_debug_)
- io::pgm::save(data::convert(value::int_u8(), tmp), "tmp.pgm");
+ // if (_debug_)
+ // io::pgm::save(data::convert(value::int_u8(), tmp), "tmp.pgm");
t.restart();
@@ -841,25 +776,53 @@ namespace scribo
unsigned invalid_ratio = unsigned(length * 0.30f);
- mln_piter(I) p(separators.domain());
- for_all(p)
- if (separators(p))
- {
- unsigned lbl = sep_lbl(p);
+ extension::adjust_fill(tmp, 21, 0);
+
+ value::int_u8 *sep_lbl_ptr = sep_lbl.buffer() +
sep_lbl.index_of_point(sep_lbl.domain().pmin());
+ bool *separators_ptr = separators.buffer() +
separators.index_of_point(separators.domain().pmin());
+ unsigned *tmp_ptr = tmp.buffer() + tmp.index_of_point(tmp.domain().pmin());;
+ int idx1 = tmp.delta_index(dp1);
+ int idx2 = tmp.delta_index(dp2);
+
+ unsigned nrows = separators.nrows();
+ unsigned ncols = separators.ncols();
- unsigned
- top_count = tmp(p + dp1),
- bot_count = tmp(p + dp2);
+ unsigned row_idx_sep_lbl = sep_lbl.delta_index(dpoint2d(+1, - ncols));
+ unsigned row_idx_separators = separators.delta_index(dpoint2d(+1, - ncols));
+ unsigned row_idx_tmp = tmp.delta_index(dpoint2d(+1, - ncols));
- // This site is wrapped between two lines of text so we don't
- // want it.
- if (top_count >= invalid_ratio + 1
- && bot_count >= invalid_ratio + 1)
+ for (unsigned row = 0; row < nrows; ++row)
+ {
+ for (unsigned col = 0; col < ncols; ++col)
+ {
+ if (*separators_ptr)
{
- relbl(lbl) = false;
+ unsigned lbl = *sep_lbl_ptr;
+
+ unsigned
+ top_count = *(tmp_ptr + idx1),
+ bot_count = *(tmp_ptr + idx2);
+
+ // This site is wrapped between two lines of text so we don't
+ // want it.
+ if (top_count >= invalid_ratio + 1
+ && bot_count >= invalid_ratio + 1)
+ {
+ relbl(lbl) = false;
+ }
}
+
+ ++tmp_ptr;
+ ++sep_lbl_ptr;
+ ++separators_ptr;
}
+ tmp_ptr += row_idx_tmp;
+ sep_lbl_ptr += row_idx_sep_lbl;
+ separators_ptr += row_idx_separators;
+ }
+
+
t_ = t;
std::cout << "* reading data - " << t_ << std::endl;
@@ -870,37 +833,35 @@ namespace scribo
mln_concrete(I) output = data::convert(bool(), sep_lbl);
- if (_debug_)
- {
- io::pbm::save(output, "separators_hom.pbm");
- io::pbm::save(separators, "separators_filtered.pbm");
- }
+ // if (_debug_)
+ // {
+ // io::pbm::save(output, "separators_hom.pbm");
+ // io::pbm::save(separators, "separators_filtered.pbm");
- t.restart();
- value::int_u16 ncomps;
- component_set<L> comps = primitive::extract::components(output, c8(), ncomps);
- mln_ch_value(I, value::rgb8) both;
+ // // value::int_u16 ncomps;
+ // // component_set<L> comps = primitive::extract::components(output, c8(),
ncomps);
+ // // mln_ch_value(I, value::rgb8) both;
- both = data::convert(value::rgb8(), input);
+ // // both = data::convert(value::rgb8(), input);
- // Needed since the rotated image origin is (0,0). Rotation does
- // not preserve rotated coordinates.
- dpoint2d dp(input.domain().pcenter() - input_clo.domain().pcenter());
+ // // // Needed since the rotated image origin is (0,0).
+ // // dpoint2d dp(input.domain().pcenter() - input_clo.domain().pcenter());
+
+ // // for_all_comps(c, comps)
+ // // {
+ // // box2d b = geom::rotate(comps(c).bbox(), -90, input_clo.domain().pcenter());
+ // // mln::draw::line(both,
+ // // b.pmin() + dp,
+ // // b.pmax() + dp,
+ // // literal::green);
+ // // }
+ // }
- for_all_comps(c, comps)
- {
- box2d b = geom::rotate(comps(c).bbox(), -90, input_clo.domain().pcenter());
- mln::draw::line(both,
- b.pmin() + dp,
- b.pmax() + dp,
- literal::green);
- }
- t_ = t;
- std::cout << "Output image - " << t_ << std::endl;
gt.stop();
t_ = gt;
- std::cout << "Total time: " << t_ << std::endl;
+ std::cout << "Non visible separators: " << t_ <<
std::endl;
+ trace::exiting("scribo::primitive::extract::separators_nonvisible");
return scribo::preprocessing::rotate_90(output, true);
}
}
diff --git a/scribo/scribo/primitive/link/internal/compute_anchor.hh
b/scribo/scribo/primitive/link/internal/compute_anchor.hh
index 1c52b91..c1a9106 100644
--- a/scribo/scribo/primitive/link/internal/compute_anchor.hh
+++ b/scribo/scribo/primitive/link/internal/compute_anchor.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.
//
@@ -88,10 +88,8 @@ namespace scribo
{
typedef mln_site(L) P;
- unsigned h = components(current_object).bbox().pmax().row()
- - components(current_object).bbox().pmin().row();
- unsigned w = components(current_object).bbox().pmax().col()
- - components(current_object).bbox().pmin().col();
+ unsigned h = components(current_object).bbox().height();
+ unsigned w = components(current_object).bbox().width();
mln_site(L) sp = components(current_object).bbox().pcenter();
@@ -113,6 +111,22 @@ namespace scribo
break;
+ // Bounding box top left
+ case anchor::TopStrictLeft:
+ sp.col() = components(current_object).bbox().pmin().col();
+ sp.row() = components(current_object).bbox().pmin().row()
+ + math::min(2u, (h + 1) / 2 - 1);
+ break;
+
+
+ // Bounding box bottom right
+ case anchor::BottomStrictRight:
+ sp.col() = components(current_object).bbox().pmax().col();
+ sp.row() = components(current_object).bbox().pmax().row()
+ - math::min(2u, (h + 1) / 2 - 1);
+ break;
+
+
// Bounding box bottom center
case anchor::Bottom:
if (h < 30)
diff --git a/scribo/scribo/toolchain/internal/content_in_doc_functor.hh
b/scribo/scribo/toolchain/internal/content_in_doc_functor.hh
index ed691e8..48098ba 100644
--- a/scribo/scribo/toolchain/internal/content_in_doc_functor.hh
+++ b/scribo/scribo/toolchain/internal/content_in_doc_functor.hh
@@ -34,11 +34,11 @@
# include <scribo/core/line_set.hh>
# include <scribo/core/paragraph_set.hh>
-# include <scribo/primitive/extract/elements.hh>
+# include <scribo/primitive/extract/non_text.hh>
# include <scribo/primitive/extract/components.hh>
-# include <scribo/primitive/extract/vertical_separators.hh>
+//# include <scribo/primitive/extract/vertical_separators.hh>
+# include <scribo/primitive/extract/separators.hh>
# include <scribo/primitive/extract/separators_nonvisible.hh>
-# include <scribo/primitive/extract/elements.hh>
# include <scribo/primitive/identify.hh>
@@ -168,16 +168,17 @@ namespace scribo
input_cleaned = exact(processed_image);
if (enable_line_seps)
{
- on_new_progress_label("Find vertical separators...");
+ on_new_progress_label("Find vertical and horizontal separators...");
- // Vertical separators
- separators = primitive::extract::vertical_separators(processed_image, 81);
+ // Vertical and horizontal separators
+ separators = primitive::extract::separators(processed_image, 81);
on_progress();
on_new_progress_label("Remove separators...");
input_cleaned = primitive::remove::separators(processed_image, separators);
+ doc.set_line_separators(separators);
on_progress();
}
--
1.5.6.5