Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- 9625 discussions
last-svn-commit-649-g15f9077 scribo/primitive/extract/elements.hh: New routine.
by Guillaume Lazzara 15 Nov '10
by Guillaume Lazzara 15 Nov '10
15 Nov '10
---
scribo/ChangeLog | 4 +
scribo/scribo/primitive/extract/elements.hh | 227 +++++++++++++++++++++++++++
2 files changed, 231 insertions(+), 0 deletions(-)
create mode 100644 scribo/scribo/primitive/extract/elements.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 9c65829..e738a8a 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+ * scribo/primitive/extract/elements.hh: New routine.
+
+2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+
* scribo/primitive/extract/separators_nonvisible.hh: New routine.
2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
diff --git a/scribo/scribo/primitive/extract/elements.hh b/scribo/scribo/primitive/extract/elements.hh
new file mode 100644
index 0000000..c083988
--- /dev/null
+++ b/scribo/scribo/primitive/extract/elements.hh
@@ -0,0 +1,227 @@
+// Copyright (C) 2010 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.
+
+/// \file
+///
+/// \brief Find in a document elements which are not text.
+///
+/// \fixme To be optimized!
+
+#ifndef SCRIBO_PRIMITIVE_EXTRACT_ELEMENTS_HH
+# define SCRIBO_PRIMITIVE_EXTRACT_ELEMENTS_HH
+
+# include <mln/core/image/image2d.hh>
+# include <mln/data/fill.hh>
+# include <mln/util/array.hh>
+# include <mln/labeling/compute.hh>
+# include <mln/labeling/relabel.hh>
+# include <mln/accu/math/count.hh>
+# include <mln/pw/all.hh>
+
+# include <mln/value/label_8.hh>
+# include <mln/value/rgb8.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/component_set.hh>
+# include <scribo/core/line_set.hh>
+# include <scribo/filter/objects_small.hh>
+
+#include <mln/clustering/kmean_rgb.hh>
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace extract
+ {
+
+
+ template <typename L, typename I>
+ component_set<L>
+ elements(const document<L>& doc, const Image<I>& input);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace internal
+ {
+
+ template <typename L>
+ struct order_bbox
+ {
+ order_bbox(const scribo::component_set<L>& comps)
+ : comps_(comps)
+ {
+ }
+
+ bool operator()(const unsigned& c1, const unsigned& c2) const
+ {
+ if (comps_(c1).bbox().nsites() == comps_(c2).bbox().nsites())
+ return c1 > c2;
+ return comps_(c1).bbox().nsites() > comps_(c2).bbox().nsites();
+ }
+
+ scribo::component_set<L> comps_;
+ };
+
+ } // end of namespace scribo::primitive::extract::internal
+
+
+
+ // FACADE
+
+ template <typename L, typename I>
+ component_set<L>
+ elements(const document<L>& doc, const Image<I>& input_)
+ {
+ trace::entering("scribo::primitive::extract::elements");
+
+ const I& input = exact(input_);
+ mln_precondition(doc.is_valid());
+ mln_precondition(input.is_valid());
+
+ const line_set<L>& lines = doc.text();
+
+ // Element extraction
+
+ image2d<value::label_8> img_lbl8;
+ {
+ image2d<bool> content;
+ initialize(content, input);
+ data::fill(content, true);
+
+ for_all_lines(l, lines)
+ if (lines(l).type() == line::Text)
+ data::fill((content | lines(l).bbox()).rw(), false);
+
+ typedef mln::value::rgb<5> t_rgb5;
+ typedef mln::fun::v2v::rgb8_to_rgbn<5> t_rgb8_to_rgb5;
+
+ image2d<t_rgb5>
+ img_rgb5 = mln::data::transform(doc.image(), t_rgb8_to_rgb5());
+
+ img_lbl8 =
+ mln::clustering::kmean_rgb<double,5>((img_rgb5 | pw::value(content)), 3, 10, 10).unmorph_();
+ data::fill((img_lbl8 | !pw::value(content)).rw(), 0u);
+
+ mln::util::array<unsigned>
+ card = mln::labeling::compute(accu::math::count<value::label_8>(),
+ img_lbl8, img_lbl8, 3);
+
+ unsigned max = 0, bg_id = 0;
+ for_all_ncomponents(c, 3)
+ if (card(c) > max)
+ {
+ max = card(c);
+ bg_id = c;
+ }
+
+ mln::fun::i2v::array<bool> f(4, true);
+ f(0) = false;
+ f(bg_id) = false;
+ labeling::relabel_inplace(img_lbl8, 4, f);
+ }
+
+
+ component_set<L> output;
+
+ std::cout << "Removing small elements" << std::endl;
+ {
+ image2d<bool> elts;
+ initialize(elts, img_lbl8);
+ data::fill(elts, false);
+ data::fill((elts | (pw::value(img_lbl8) != pw::cst(0))).rw(), true);
+
+ scribo::def::lbl_type nlabels;
+ elts = filter::components_small(elts, c8(), nlabels, 40);
+
+ output = primitive::extract::components(elts, c8(), nlabels);
+ }
+
+
+ std::cout << "Ignoring inner elements" << std::endl;
+
+ {
+ // FIXME: We would like to use the convex hull instead of the bbox.
+ internal::order_bbox<L> func(output);
+ util::array<unsigned> box_ordered_comps;
+ for (unsigned i = 1; i < output.nelements(); ++i)
+ box_ordered_comps.append(i);
+ std::sort(box_ordered_comps.hook_std_vector_().begin(),
+ box_ordered_comps.hook_std_vector_().end(), func);
+
+ image2d<bool> merged_elts;
+ initialize(merged_elts, img_lbl8);
+ data::fill(merged_elts, false);
+ for (unsigned i = 0; i < box_ordered_comps.nelements(); ++i)
+ {
+ unsigned c = box_ordered_comps(i);
+ point2d
+ pminright = output(c).bbox().pmin(),
+ pmaxleft = output(c).bbox().pmax();
+ pminright.col() = output(c).bbox().pmax().col();
+ pmaxleft.col() = output(c).bbox().pmin().col();
+
+ if (merged_elts(output(c).bbox().pmin())
+ && merged_elts(output(c).bbox().pmax())
+ && merged_elts(pminright)
+ && merged_elts(pmaxleft))
+ output(c).update_tag(component::Ignored);
+ else
+ mln::draw::box_plain(merged_elts, output(c).bbox(), true);
+ }
+ }
+
+// mln::io::pbm::save(merged_elts, "merged_elts.pbm");
+
+// mln::util::array<image2d<value::rgb8> > elt_ima;
+// unsigned i = 0;
+// for_all_comps(c, elt_comp)
+// if (elt_comp(c).is_valid())
+// {
+// elt_ima.append(preprocessing::crop(doc.image(), elt_comp(c).bbox()));
+// mln::io::ppm::save(elt_ima(i), mln::debug::filename("elt.ppm", i));
+// ++i;
+// }
+
+
+ trace::exiting("scribo::primitive::extract::elements");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::primitive::extract
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_EXTRACT_ELEMENTS_HH
--
1.5.6.5
1
0
last-svn-commit-648-g222955a scribo/primitive/extract/elements.hh: New routine.
by Guillaume Lazzara 15 Nov '10
by Guillaume Lazzara 15 Nov '10
15 Nov '10
---
scribo/ChangeLog | 4 +
scribo/scribo/primitive/extract/elements.hh | 227 +++++++++++++++++++++++++++
2 files changed, 231 insertions(+), 0 deletions(-)
create mode 100644 scribo/scribo/primitive/extract/elements.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index be9d85d..828f9b8 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+ * scribo/primitive/extract/elements.hh: New routine.
+
+2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+
* scribo/primitive/extract/separators_nonvisible.hh: New routine.
2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
diff --git a/scribo/scribo/primitive/extract/elements.hh b/scribo/scribo/primitive/extract/elements.hh
new file mode 100644
index 0000000..c083988
--- /dev/null
+++ b/scribo/scribo/primitive/extract/elements.hh
@@ -0,0 +1,227 @@
+// Copyright (C) 2010 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.
+
+/// \file
+///
+/// \brief Find in a document elements which are not text.
+///
+/// \fixme To be optimized!
+
+#ifndef SCRIBO_PRIMITIVE_EXTRACT_ELEMENTS_HH
+# define SCRIBO_PRIMITIVE_EXTRACT_ELEMENTS_HH
+
+# include <mln/core/image/image2d.hh>
+# include <mln/data/fill.hh>
+# include <mln/util/array.hh>
+# include <mln/labeling/compute.hh>
+# include <mln/labeling/relabel.hh>
+# include <mln/accu/math/count.hh>
+# include <mln/pw/all.hh>
+
+# include <mln/value/label_8.hh>
+# include <mln/value/rgb8.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/component_set.hh>
+# include <scribo/core/line_set.hh>
+# include <scribo/filter/objects_small.hh>
+
+#include <mln/clustering/kmean_rgb.hh>
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace extract
+ {
+
+
+ template <typename L, typename I>
+ component_set<L>
+ elements(const document<L>& doc, const Image<I>& input);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace internal
+ {
+
+ template <typename L>
+ struct order_bbox
+ {
+ order_bbox(const scribo::component_set<L>& comps)
+ : comps_(comps)
+ {
+ }
+
+ bool operator()(const unsigned& c1, const unsigned& c2) const
+ {
+ if (comps_(c1).bbox().nsites() == comps_(c2).bbox().nsites())
+ return c1 > c2;
+ return comps_(c1).bbox().nsites() > comps_(c2).bbox().nsites();
+ }
+
+ scribo::component_set<L> comps_;
+ };
+
+ } // end of namespace scribo::primitive::extract::internal
+
+
+
+ // FACADE
+
+ template <typename L, typename I>
+ component_set<L>
+ elements(const document<L>& doc, const Image<I>& input_)
+ {
+ trace::entering("scribo::primitive::extract::elements");
+
+ const I& input = exact(input_);
+ mln_precondition(doc.is_valid());
+ mln_precondition(input.is_valid());
+
+ const line_set<L>& lines = doc.text();
+
+ // Element extraction
+
+ image2d<value::label_8> img_lbl8;
+ {
+ image2d<bool> content;
+ initialize(content, input);
+ data::fill(content, true);
+
+ for_all_lines(l, lines)
+ if (lines(l).type() == line::Text)
+ data::fill((content | lines(l).bbox()).rw(), false);
+
+ typedef mln::value::rgb<5> t_rgb5;
+ typedef mln::fun::v2v::rgb8_to_rgbn<5> t_rgb8_to_rgb5;
+
+ image2d<t_rgb5>
+ img_rgb5 = mln::data::transform(doc.image(), t_rgb8_to_rgb5());
+
+ img_lbl8 =
+ mln::clustering::kmean_rgb<double,5>((img_rgb5 | pw::value(content)), 3, 10, 10).unmorph_();
+ data::fill((img_lbl8 | !pw::value(content)).rw(), 0u);
+
+ mln::util::array<unsigned>
+ card = mln::labeling::compute(accu::math::count<value::label_8>(),
+ img_lbl8, img_lbl8, 3);
+
+ unsigned max = 0, bg_id = 0;
+ for_all_ncomponents(c, 3)
+ if (card(c) > max)
+ {
+ max = card(c);
+ bg_id = c;
+ }
+
+ mln::fun::i2v::array<bool> f(4, true);
+ f(0) = false;
+ f(bg_id) = false;
+ labeling::relabel_inplace(img_lbl8, 4, f);
+ }
+
+
+ component_set<L> output;
+
+ std::cout << "Removing small elements" << std::endl;
+ {
+ image2d<bool> elts;
+ initialize(elts, img_lbl8);
+ data::fill(elts, false);
+ data::fill((elts | (pw::value(img_lbl8) != pw::cst(0))).rw(), true);
+
+ scribo::def::lbl_type nlabels;
+ elts = filter::components_small(elts, c8(), nlabels, 40);
+
+ output = primitive::extract::components(elts, c8(), nlabels);
+ }
+
+
+ std::cout << "Ignoring inner elements" << std::endl;
+
+ {
+ // FIXME: We would like to use the convex hull instead of the bbox.
+ internal::order_bbox<L> func(output);
+ util::array<unsigned> box_ordered_comps;
+ for (unsigned i = 1; i < output.nelements(); ++i)
+ box_ordered_comps.append(i);
+ std::sort(box_ordered_comps.hook_std_vector_().begin(),
+ box_ordered_comps.hook_std_vector_().end(), func);
+
+ image2d<bool> merged_elts;
+ initialize(merged_elts, img_lbl8);
+ data::fill(merged_elts, false);
+ for (unsigned i = 0; i < box_ordered_comps.nelements(); ++i)
+ {
+ unsigned c = box_ordered_comps(i);
+ point2d
+ pminright = output(c).bbox().pmin(),
+ pmaxleft = output(c).bbox().pmax();
+ pminright.col() = output(c).bbox().pmax().col();
+ pmaxleft.col() = output(c).bbox().pmin().col();
+
+ if (merged_elts(output(c).bbox().pmin())
+ && merged_elts(output(c).bbox().pmax())
+ && merged_elts(pminright)
+ && merged_elts(pmaxleft))
+ output(c).update_tag(component::Ignored);
+ else
+ mln::draw::box_plain(merged_elts, output(c).bbox(), true);
+ }
+ }
+
+// mln::io::pbm::save(merged_elts, "merged_elts.pbm");
+
+// mln::util::array<image2d<value::rgb8> > elt_ima;
+// unsigned i = 0;
+// for_all_comps(c, elt_comp)
+// if (elt_comp(c).is_valid())
+// {
+// elt_ima.append(preprocessing::crop(doc.image(), elt_comp(c).bbox()));
+// mln::io::ppm::save(elt_ima(i), mln::debug::filename("elt.ppm", i));
+// ++i;
+// }
+
+
+ trace::exiting("scribo::primitive::extract::elements");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::primitive::extract
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_EXTRACT_ELEMENTS_HH
--
1.5.6.5
1
0
last-svn-commit-648-g929109d scribo/primitive/extract/separators_nonvisible.hh: New routine.
by Guillaume Lazzara 15 Nov '10
by Guillaume Lazzara 15 Nov '10
15 Nov '10
---
scribo/ChangeLog | 4 +
.../primitive/extract/separators_nonvisible.hh | 912 ++++++++++++++++++++
2 files changed, 916 insertions(+), 0 deletions(-)
create mode 100644 scribo/scribo/primitive/extract/separators_nonvisible.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index dd11567..9c65829 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+ * scribo/primitive/extract/separators_nonvisible.hh: New routine.
+
+2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Import rgb8 to rgbn conversion function from Yann's sandbox.
* mln/fun/v2v/rgb8_to_rgbn.hh: New.
diff --git a/scribo/scribo/primitive/extract/separators_nonvisible.hh b/scribo/scribo/primitive/extract/separators_nonvisible.hh
new file mode 100644
index 0000000..460d10e
--- /dev/null
+++ b/scribo/scribo/primitive/extract/separators_nonvisible.hh
@@ -0,0 +1,912 @@
+// Copyright (C) 2010 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.
+
+/// \file
+///
+/// \brief Find non visible separators (whitespaces)
+///
+/// \fixme To be cleaned up
+
+#ifndef SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
+# define SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
+
+#include <mln/core/concept/image.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/pw/all.hh>
+
+#include <mln/draw/line.hh>
+
+#include <mln/data/wrap.hh>
+#include <mln/data/fill.hh>
+#include <mln/data/convert.hh>
+
+
+#include <mln/labeling/colorize.hh>
+#include <mln/labeling/relabel.hh>
+#include <mln/labeling/blobs.hh>
+
+#include <mln/morpho/closing/structural.hh>
+#include <mln/morpho/closing/area.hh>
+#include <mln/morpho/opening/structural.hh>
+#include <mln/win/rectangle2d.hh>
+#include <mln/win/vline2d.hh>
+
+#include <mln/logical/not.hh>
+#include <mln/io/pbm/all.hh>
+#include <mln/io/pgm/all.hh>
+#include <mln/io/ppm/save.hh>
+
+#include <mln/literal/colors.hh>
+
+#include <mln/value/label_16.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/int_u16.hh>
+#include <mln/value/rgb8.hh>
+
+#include <mln/draw/box_plain.hh>
+
+#include <mln/transform/influence_zone_geodesic.hh>
+
+#include <mln/data/stretch.hh>
+
+#include <mln/util/timer.hh>
+
+#include <mln/norm/l1.hh>
+
+#include <scribo/core/object_groups.hh>
+#include <scribo/core/component_set.hh>
+#include <scribo/primitive/extract/components.hh>
+
+#include <scribo/primitive/extract/lines_h_pattern.hh>
+#include <scribo/primitive/remove/separators.hh>
+
+#include <scribo/preprocessing/denoise_fg.hh>
+#include <scribo/preprocessing/rotate_90.hh>
+
+#include <scribo/primitive/link/internal/dmax_default.hh>
+
+#include <scribo/primitive/link/with_single_right_link_dmax_ratio.hh>
+#include <scribo/primitive/link/with_single_right_link_dmax_ratio_aligned.hh>
+
+#include <scribo/primitive/group/from_double_link_any.hh>
+
+#include <scribo/filter/object_links_top_aligned.hh>
+#include <scribo/filter/object_groups_small.hh>
+#include <scribo/filter/object_links_bottom_aligned.hh>
+#include <scribo/debug/save_linked_bboxes_image.hh>
+#include <scribo/debug/decision_image.hh>
+
+
+
+
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace extract
+ {
+
+ using namespace mln;
+
+
+ /// \brief Find non visible separators (whitespaces)
+ //
+ template <typename I>
+ mln_concrete(I)
+ separators_nonvisible(const Image<I>& in_);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ // Enable debug.
+ bool _debug_;
+
+
+ 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>
+ class single_dmax_ratio_aligned_functor_base
+ : public link_single_dmax_ratio_base<L, dmax_default, E>
+ {
+ typedef link_single_dmax_ratio_base<L, dmax_default, E> super_;
+
+ public:
+ typedef mln_site(L) P;
+
+ single_dmax_ratio_aligned_functor_base(
+ const mln_ch_value(L,bool)& input,
+ const component_set<L>& components,
+ unsigned dmax,
+ float min_angle,
+ float max_angle,
+ anchor::Type anchor_)
+ : super_(components,
+ anchor::Horizontal,
+ dmax_default(dmax)),
+ anchor(anchor_),
+ debug_(data::convert(value::rgb8(), input)),
+ debug_angle_(data::convert(value::rgb8(), input))
+ {
+ min_alpha_rad = (min_angle / 180.0f) * math::pi;
+ max_alpha_rad = (max_angle / 180.0f) * math::pi;
+ }
+
+ void compute_next_site_(P& p)
+ {
+ ++p.col();
+ }
+
+ void compute_next_site_f_(unsigned& p)
+ {
+ ++p;
+ }
+
+
+ mln_site(L)
+ start_point_(unsigned current_object, anchor::Type anchor)
+ {
+ return my_anchors(this->components_, current_object, anchor);
+ }
+
+
+ inline
+ bool
+ valid_link_(unsigned current_object,
+ const P& start_point,
+ const P& p)
+ {
+ if (!super_::valid_link_(current_object, start_point, p))
+ return false;
+
+ box<P> b = this->components_(current_object).bbox();
+
+ // Distance between the two components.
+ float dist;
+
+ // current object is on the left.
+ if (p[this->direction_] > b.pmax()[this->direction_])
+ dist = math::abs(p[this->direction_] - b.pmax()[this->direction_]);
+ // current object is on the right.
+ else
+ dist = math::abs(p[this->direction_] - b.pmin()[this->direction_]);
+
+
+ int ldist = this->components_(current_object).bbox().width();
+
+ // Components are really close, so the angle is more permissive.
+ if (dist < 3 * ldist)
+ {
+ return
+ filter::internal::component_aligned_rad(this->components_,
+ current_object,
+ this->labeled_image_(p),
+ anchor,
+ max_alpha_rad);
+ }
+
+
+ // Components are really far, so the angle is less permissive.
+ return
+ filter::internal::component_aligned_rad(this->components_,
+ current_object,
+ this->labeled_image_(p),
+ anchor,
+ min_alpha_rad);
+ }
+
+ void validate_link_(unsigned current_object,
+ const P& start_point,
+ const P& p,
+ anchor::Type anchor)
+ {
+ 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(angle, angle, angle));
+ }
+ }
+
+ void invalidate_link_(unsigned current_object,
+ const P& start_point,
+ const P& p,
+ anchor::Type anchor)
+ {
+ 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(angle, angle, angle));
+ }
+ }
+ }
+
+
+ float min_alpha_rad;
+ float max_alpha_rad;
+ anchor::Type anchor;
+
+
+ mln_ch_value(L, value::rgb8) debug_;
+ mln_ch_value(L, value::rgb8) debug_angle_;
+ };
+
+
+ template <typename L>
+ class single_right_dmax_ratio_aligned_functor
+ : public single_dmax_ratio_aligned_functor_base<L, single_right_dmax_ratio_aligned_functor<L> >
+ {
+ typedef single_right_dmax_ratio_aligned_functor<L> self_t;
+ typedef single_dmax_ratio_aligned_functor_base<L, self_t> super_;
+
+ public:
+ typedef mln_site(L) P;
+
+ single_right_dmax_ratio_aligned_functor(
+ const mln_ch_value(L, bool)& input,
+ const component_set<L>& components,
+ unsigned dmax,
+ float min_angle,
+ float max_angle,
+ anchor::Type anchor)
+ : super_(input, components, dmax, min_angle, max_angle, anchor)
+ {
+ }
+
+ void compute_next_site_(P& p)
+ {
+ ++p.col();
+ }
+
+ void compute_next_site_f_(unsigned& p)
+ {
+ ++p;
+ }
+
+ };
+
+
+ template <typename L>
+ class single_left_dmax_ratio_aligned_functor
+ : public single_dmax_ratio_aligned_functor_base<L, single_left_dmax_ratio_aligned_functor<L> >
+ {
+ typedef single_left_dmax_ratio_aligned_functor<L> self_t;
+ typedef single_dmax_ratio_aligned_functor_base<L, self_t> super_;
+
+ public:
+ typedef mln_site(L) P;
+
+ single_left_dmax_ratio_aligned_functor(
+ const mln_ch_value(L, bool)& input,
+ const component_set<L>& components,
+ unsigned dmax,
+ float min_angle,
+ float max_angle,
+ anchor::Type anchor)
+ : super_(input, components, dmax, min_angle, max_angle, anchor)
+ {
+ }
+
+ void compute_next_site_(P& p)
+ {
+ --p.col();
+ }
+
+ void compute_next_site_f_(unsigned& p)
+ {
+ --p;
+ }
+
+
+ };
+
+ } // end of namespace scribo::primitive::extract::internal
+
+
+
+
+ // FACADE
+
+ template <typename I>
+ mln_concrete(I)
+ separators_nonvisible(const Image<I>& in_)
+ {
+ const I& in = exact(in_);
+ mln_precondition(in.is_valid());
+ typedef mln_value(I) Vi;
+ mlc_is(Vi,bool)::check();
+
+ internal::_debug_ = false;
+ unsigned
+ min_angle = 3,
+ max_angle = 5,
+ min_card = 3;
+
+ 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();
+
+ 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;
+
+
+ // Closing structural - Connect characters.
+ t.restart();
+
+ win::hline2d vl(17);
+ mln_concrete(I) input_clo = morpho::closing::structural(input, vl);
+
+// input_clo = scribo::preprocessing::rotate_90(input_clo, true);
+
+ t_ = t;
+ std::cout << "closing_structural - " << t_ << std::endl;
+
+ if (internal::_debug_)
+ {
+ // Restore input orientation.
+ input = scribo::preprocessing::rotate_90(input, false);
+
+ io::pbm::save(input_clo, "input_clo.pbm");
+ }
+
+ // Rotate (OK)
+ t.restart();
+ input_clo = scribo::preprocessing::rotate_90(input_clo, false);
+ t_ = t;
+ std::cout << "rotate_90 - " << t_ << std::endl;
+
+
+
+ /// Finding components.
+ typedef value::int_u16 V;
+ typedef mln_ch_value(I,V) L;
+
+ t.restart();
+ V ncomponents;
+ component_set<L>
+ components = scribo::primitive::extract::components(input_clo, c8(),
+ ncomponents);
+ t_ = t;
+ std::cout << "extract::components - " << t_ << std::endl;
+
+ if (internal::_debug_)
+ io::pgm::save(data::convert(value::int_u8(), components.labeled_image()),
+ "lbl.pgm");
+
+
+ unsigned dmax = 5;
+
+ t.restart();
+ object_links<L> top_right, bot_right;
+
+ object_links<L> top_left, bot_left;
+
+
+ // Top
+ {
+ // Right
+ internal::single_right_dmax_ratio_aligned_functor<L>
+ functor(input_clo, components, dmax, min_angle, max_angle, anchor::Top);
+// top_right = primitive::link::impl::compute_fastest(functor, anchor::Top);
+ top_right = primitive::link::compute(functor, anchor::Top);
+
+ t.stop();
+
+
+ if (internal::_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);
+ top_left = primitive::link::compute(lfunctor, anchor::Top);
+
+
+ t.stop();
+
+ if (internal::_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);
+
+ io::ppm::save(output, "left_right_top.ppm");
+ }
+
+ t.resume();
+ }
+
+
+ // Bottom
+ {
+ // Right
+ internal::single_right_dmax_ratio_aligned_functor<L>
+ functor(input_clo, components, dmax, min_angle, max_angle, anchor::Bottom);
+ bot_right = primitive::link::compute(functor, anchor::Bottom);
+ t.stop();
+
+ if (internal::_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);
+ bot_left = primitive::link::compute(lfunctor, anchor::Bottom);
+ t.stop();
+
+ if (internal::_debug_)
+ {
+ io::ppm::save(lfunctor.debug_, "left_bot.ppm");
+ io::ppm::save(lfunctor.debug_angle_, "left_bot_angle.ppm");
+ }
+
+ if (internal::_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);
+
+ io::ppm::save(output, "left_right_bot.ppm");
+ }
+ }
+
+
+ t_ = t;
+ std::cout << "links - " << t_ << std::endl;
+
+
+ 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 (internal::_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");
+ }
+
+
+ t.restart();
+ top_groups = filter::object_groups_small(top_groups, min_card);
+ bot_groups = filter::object_groups_small(bot_groups, min_card);
+ t_ = t;
+ std::cout << "small groups - " << t_ << std::endl;
+
+
+
+ t.restart();
+ util::array<accu::shape::bbox<point2d> >
+ top_accu(top_groups.nelements()),
+ bot_accu(bot_groups.nelements());
+
+
+ for_all_groups(c, top_groups)
+ {
+ top_accu(top_groups(c)).take(components(c).bbox());
+ bot_accu(bot_groups(c)).take(components(c).bbox());
+ }
+ t_ = t;
+ std::cout << "groups to group bboxes - " << t_ << std::endl;
+
+
+
+
+
+
+
+
+ t.restart();
+ mln_concrete(I) separators;
+ initialize(separators, input_clo);
+ data::fill(separators, false);
+ t_ = t;
+ std::cout << "Initialize separators image - " << t_ << std::endl;
+
+ mln_ch_value(I, value::rgb8) both;
+
+ if (internal::_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 (internal::_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 (internal::_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);
+
+ }
+ if (bot_accu(d).is_valid() || bbot_accu(d).is_valid())
+ {
+ if (bot_accu(d).is_valid())
+ {
+ if (internal::_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 (internal::_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);
+ }
+
+ }
+ t_ = t;
+ std::cout << "Drawing output image - " << t_ << std::endl;
+
+
+ if (internal::_debug_)
+ {
+ io::ppm::save(both, "both.ppm");
+ io::pbm::save(separators, "separators.pbm");
+ }
+
+
+ // Hit or miss
+ {
+ if (internal::_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");
+ }
+
+ t.restart();
+ unsigned length = 25;
+
+ dpoint2d
+ dp1(-21, 0),
+ dp2( 21, 0);
+
+ // Adjusting extension.
+ t.restart();
+ extension::adjust_fill(input_clo, length / 2, 0);
+
+ accu::count_value<bool> accu(true);
+ 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 (internal::_debug_)
+ io::pgm::save(data::convert(value::int_u8(), tmp), "tmp.pgm");
+
+
+ t.restart();
+ value::int_u8 nlabels;
+ mln_ch_value(I,value::int_u8)
+ sep_lbl = labeling::value(separators, true, c8(), nlabels);
+ t_ = t;
+ std::cout << "* labeling seps - " << t_ << std::endl;
+
+
+ t.restart();
+
+ util::array<bool> relbl(unsigned(nlabels) + 1, true);
+ relbl(0) = false;
+
+ unsigned invalid_ratio = unsigned(length * 0.30f);
+
+ mln_piter(I) p(separators.domain());
+ for_all(p)
+ if (separators(p))
+ {
+ unsigned lbl = sep_lbl(p);
+
+ unsigned
+ top_count = tmp(p + dp1),
+ bot_count = tmp(p + dp2);
+
+ // 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;
+ }
+ }
+
+ t_ = t;
+ std::cout << "* reading data - " << t_ << std::endl;
+
+ t.restart();
+ labeling::relabel_inplace(sep_lbl, nlabels, relbl);
+ t_ = t;
+ std::cout << "* relabel_inplace - " << t_ << std::endl;
+
+ mln_concrete(I) output = data::convert(bool(), sep_lbl);
+
+ if (internal::_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;
+
+ 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());
+
+ 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;
+
+ return scribo::preprocessing::rotate_90(output, true);
+ }
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::primitive::extract
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
--
1.5.6.5
1
0
last-svn-commit-647-geec4ffe scribo/primitive/extract/separators_nonvisible.hh: New routine.
by Guillaume Lazzara 15 Nov '10
by Guillaume Lazzara 15 Nov '10
15 Nov '10
---
scribo/ChangeLog | 4 +
.../primitive/extract/separators_nonvisible.hh | 912 ++++++++++++++++++++
2 files changed, 916 insertions(+), 0 deletions(-)
create mode 100644 scribo/scribo/primitive/extract/separators_nonvisible.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index cd8db5d..be9d85d 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+ * scribo/primitive/extract/separators_nonvisible.hh: New routine.
+
+2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Import rgb8 to rgbn conversion function from Yann's sandbox.
* mln/fun/v2v/rgb8_to_rgbn.hh: New.
diff --git a/scribo/scribo/primitive/extract/separators_nonvisible.hh b/scribo/scribo/primitive/extract/separators_nonvisible.hh
new file mode 100644
index 0000000..460d10e
--- /dev/null
+++ b/scribo/scribo/primitive/extract/separators_nonvisible.hh
@@ -0,0 +1,912 @@
+// Copyright (C) 2010 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.
+
+/// \file
+///
+/// \brief Find non visible separators (whitespaces)
+///
+/// \fixme To be cleaned up
+
+#ifndef SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
+# define SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
+
+#include <mln/core/concept/image.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/pw/all.hh>
+
+#include <mln/draw/line.hh>
+
+#include <mln/data/wrap.hh>
+#include <mln/data/fill.hh>
+#include <mln/data/convert.hh>
+
+
+#include <mln/labeling/colorize.hh>
+#include <mln/labeling/relabel.hh>
+#include <mln/labeling/blobs.hh>
+
+#include <mln/morpho/closing/structural.hh>
+#include <mln/morpho/closing/area.hh>
+#include <mln/morpho/opening/structural.hh>
+#include <mln/win/rectangle2d.hh>
+#include <mln/win/vline2d.hh>
+
+#include <mln/logical/not.hh>
+#include <mln/io/pbm/all.hh>
+#include <mln/io/pgm/all.hh>
+#include <mln/io/ppm/save.hh>
+
+#include <mln/literal/colors.hh>
+
+#include <mln/value/label_16.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/int_u16.hh>
+#include <mln/value/rgb8.hh>
+
+#include <mln/draw/box_plain.hh>
+
+#include <mln/transform/influence_zone_geodesic.hh>
+
+#include <mln/data/stretch.hh>
+
+#include <mln/util/timer.hh>
+
+#include <mln/norm/l1.hh>
+
+#include <scribo/core/object_groups.hh>
+#include <scribo/core/component_set.hh>
+#include <scribo/primitive/extract/components.hh>
+
+#include <scribo/primitive/extract/lines_h_pattern.hh>
+#include <scribo/primitive/remove/separators.hh>
+
+#include <scribo/preprocessing/denoise_fg.hh>
+#include <scribo/preprocessing/rotate_90.hh>
+
+#include <scribo/primitive/link/internal/dmax_default.hh>
+
+#include <scribo/primitive/link/with_single_right_link_dmax_ratio.hh>
+#include <scribo/primitive/link/with_single_right_link_dmax_ratio_aligned.hh>
+
+#include <scribo/primitive/group/from_double_link_any.hh>
+
+#include <scribo/filter/object_links_top_aligned.hh>
+#include <scribo/filter/object_groups_small.hh>
+#include <scribo/filter/object_links_bottom_aligned.hh>
+#include <scribo/debug/save_linked_bboxes_image.hh>
+#include <scribo/debug/decision_image.hh>
+
+
+
+
+
+namespace scribo
+{
+
+ namespace primitive
+ {
+
+ namespace extract
+ {
+
+ using namespace mln;
+
+
+ /// \brief Find non visible separators (whitespaces)
+ //
+ template <typename I>
+ mln_concrete(I)
+ separators_nonvisible(const Image<I>& in_);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ // Enable debug.
+ bool _debug_;
+
+
+ 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>
+ class single_dmax_ratio_aligned_functor_base
+ : public link_single_dmax_ratio_base<L, dmax_default, E>
+ {
+ typedef link_single_dmax_ratio_base<L, dmax_default, E> super_;
+
+ public:
+ typedef mln_site(L) P;
+
+ single_dmax_ratio_aligned_functor_base(
+ const mln_ch_value(L,bool)& input,
+ const component_set<L>& components,
+ unsigned dmax,
+ float min_angle,
+ float max_angle,
+ anchor::Type anchor_)
+ : super_(components,
+ anchor::Horizontal,
+ dmax_default(dmax)),
+ anchor(anchor_),
+ debug_(data::convert(value::rgb8(), input)),
+ debug_angle_(data::convert(value::rgb8(), input))
+ {
+ min_alpha_rad = (min_angle / 180.0f) * math::pi;
+ max_alpha_rad = (max_angle / 180.0f) * math::pi;
+ }
+
+ void compute_next_site_(P& p)
+ {
+ ++p.col();
+ }
+
+ void compute_next_site_f_(unsigned& p)
+ {
+ ++p;
+ }
+
+
+ mln_site(L)
+ start_point_(unsigned current_object, anchor::Type anchor)
+ {
+ return my_anchors(this->components_, current_object, anchor);
+ }
+
+
+ inline
+ bool
+ valid_link_(unsigned current_object,
+ const P& start_point,
+ const P& p)
+ {
+ if (!super_::valid_link_(current_object, start_point, p))
+ return false;
+
+ box<P> b = this->components_(current_object).bbox();
+
+ // Distance between the two components.
+ float dist;
+
+ // current object is on the left.
+ if (p[this->direction_] > b.pmax()[this->direction_])
+ dist = math::abs(p[this->direction_] - b.pmax()[this->direction_]);
+ // current object is on the right.
+ else
+ dist = math::abs(p[this->direction_] - b.pmin()[this->direction_]);
+
+
+ int ldist = this->components_(current_object).bbox().width();
+
+ // Components are really close, so the angle is more permissive.
+ if (dist < 3 * ldist)
+ {
+ return
+ filter::internal::component_aligned_rad(this->components_,
+ current_object,
+ this->labeled_image_(p),
+ anchor,
+ max_alpha_rad);
+ }
+
+
+ // Components are really far, so the angle is less permissive.
+ return
+ filter::internal::component_aligned_rad(this->components_,
+ current_object,
+ this->labeled_image_(p),
+ anchor,
+ min_alpha_rad);
+ }
+
+ void validate_link_(unsigned current_object,
+ const P& start_point,
+ const P& p,
+ anchor::Type anchor)
+ {
+ 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(angle, angle, angle));
+ }
+ }
+
+ void invalidate_link_(unsigned current_object,
+ const P& start_point,
+ const P& p,
+ anchor::Type anchor)
+ {
+ 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(angle, angle, angle));
+ }
+ }
+ }
+
+
+ float min_alpha_rad;
+ float max_alpha_rad;
+ anchor::Type anchor;
+
+
+ mln_ch_value(L, value::rgb8) debug_;
+ mln_ch_value(L, value::rgb8) debug_angle_;
+ };
+
+
+ template <typename L>
+ class single_right_dmax_ratio_aligned_functor
+ : public single_dmax_ratio_aligned_functor_base<L, single_right_dmax_ratio_aligned_functor<L> >
+ {
+ typedef single_right_dmax_ratio_aligned_functor<L> self_t;
+ typedef single_dmax_ratio_aligned_functor_base<L, self_t> super_;
+
+ public:
+ typedef mln_site(L) P;
+
+ single_right_dmax_ratio_aligned_functor(
+ const mln_ch_value(L, bool)& input,
+ const component_set<L>& components,
+ unsigned dmax,
+ float min_angle,
+ float max_angle,
+ anchor::Type anchor)
+ : super_(input, components, dmax, min_angle, max_angle, anchor)
+ {
+ }
+
+ void compute_next_site_(P& p)
+ {
+ ++p.col();
+ }
+
+ void compute_next_site_f_(unsigned& p)
+ {
+ ++p;
+ }
+
+ };
+
+
+ template <typename L>
+ class single_left_dmax_ratio_aligned_functor
+ : public single_dmax_ratio_aligned_functor_base<L, single_left_dmax_ratio_aligned_functor<L> >
+ {
+ typedef single_left_dmax_ratio_aligned_functor<L> self_t;
+ typedef single_dmax_ratio_aligned_functor_base<L, self_t> super_;
+
+ public:
+ typedef mln_site(L) P;
+
+ single_left_dmax_ratio_aligned_functor(
+ const mln_ch_value(L, bool)& input,
+ const component_set<L>& components,
+ unsigned dmax,
+ float min_angle,
+ float max_angle,
+ anchor::Type anchor)
+ : super_(input, components, dmax, min_angle, max_angle, anchor)
+ {
+ }
+
+ void compute_next_site_(P& p)
+ {
+ --p.col();
+ }
+
+ void compute_next_site_f_(unsigned& p)
+ {
+ --p;
+ }
+
+
+ };
+
+ } // end of namespace scribo::primitive::extract::internal
+
+
+
+
+ // FACADE
+
+ template <typename I>
+ mln_concrete(I)
+ separators_nonvisible(const Image<I>& in_)
+ {
+ const I& in = exact(in_);
+ mln_precondition(in.is_valid());
+ typedef mln_value(I) Vi;
+ mlc_is(Vi,bool)::check();
+
+ internal::_debug_ = false;
+ unsigned
+ min_angle = 3,
+ max_angle = 5,
+ min_card = 3;
+
+ 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();
+
+ 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;
+
+
+ // Closing structural - Connect characters.
+ t.restart();
+
+ win::hline2d vl(17);
+ mln_concrete(I) input_clo = morpho::closing::structural(input, vl);
+
+// input_clo = scribo::preprocessing::rotate_90(input_clo, true);
+
+ t_ = t;
+ std::cout << "closing_structural - " << t_ << std::endl;
+
+ if (internal::_debug_)
+ {
+ // Restore input orientation.
+ input = scribo::preprocessing::rotate_90(input, false);
+
+ io::pbm::save(input_clo, "input_clo.pbm");
+ }
+
+ // Rotate (OK)
+ t.restart();
+ input_clo = scribo::preprocessing::rotate_90(input_clo, false);
+ t_ = t;
+ std::cout << "rotate_90 - " << t_ << std::endl;
+
+
+
+ /// Finding components.
+ typedef value::int_u16 V;
+ typedef mln_ch_value(I,V) L;
+
+ t.restart();
+ V ncomponents;
+ component_set<L>
+ components = scribo::primitive::extract::components(input_clo, c8(),
+ ncomponents);
+ t_ = t;
+ std::cout << "extract::components - " << t_ << std::endl;
+
+ if (internal::_debug_)
+ io::pgm::save(data::convert(value::int_u8(), components.labeled_image()),
+ "lbl.pgm");
+
+
+ unsigned dmax = 5;
+
+ t.restart();
+ object_links<L> top_right, bot_right;
+
+ object_links<L> top_left, bot_left;
+
+
+ // Top
+ {
+ // Right
+ internal::single_right_dmax_ratio_aligned_functor<L>
+ functor(input_clo, components, dmax, min_angle, max_angle, anchor::Top);
+// top_right = primitive::link::impl::compute_fastest(functor, anchor::Top);
+ top_right = primitive::link::compute(functor, anchor::Top);
+
+ t.stop();
+
+
+ if (internal::_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);
+ top_left = primitive::link::compute(lfunctor, anchor::Top);
+
+
+ t.stop();
+
+ if (internal::_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);
+
+ io::ppm::save(output, "left_right_top.ppm");
+ }
+
+ t.resume();
+ }
+
+
+ // Bottom
+ {
+ // Right
+ internal::single_right_dmax_ratio_aligned_functor<L>
+ functor(input_clo, components, dmax, min_angle, max_angle, anchor::Bottom);
+ bot_right = primitive::link::compute(functor, anchor::Bottom);
+ t.stop();
+
+ if (internal::_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);
+ bot_left = primitive::link::compute(lfunctor, anchor::Bottom);
+ t.stop();
+
+ if (internal::_debug_)
+ {
+ io::ppm::save(lfunctor.debug_, "left_bot.ppm");
+ io::ppm::save(lfunctor.debug_angle_, "left_bot_angle.ppm");
+ }
+
+ if (internal::_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);
+
+ io::ppm::save(output, "left_right_bot.ppm");
+ }
+ }
+
+
+ t_ = t;
+ std::cout << "links - " << t_ << std::endl;
+
+
+ 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 (internal::_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");
+ }
+
+
+ t.restart();
+ top_groups = filter::object_groups_small(top_groups, min_card);
+ bot_groups = filter::object_groups_small(bot_groups, min_card);
+ t_ = t;
+ std::cout << "small groups - " << t_ << std::endl;
+
+
+
+ t.restart();
+ util::array<accu::shape::bbox<point2d> >
+ top_accu(top_groups.nelements()),
+ bot_accu(bot_groups.nelements());
+
+
+ for_all_groups(c, top_groups)
+ {
+ top_accu(top_groups(c)).take(components(c).bbox());
+ bot_accu(bot_groups(c)).take(components(c).bbox());
+ }
+ t_ = t;
+ std::cout << "groups to group bboxes - " << t_ << std::endl;
+
+
+
+
+
+
+
+
+ t.restart();
+ mln_concrete(I) separators;
+ initialize(separators, input_clo);
+ data::fill(separators, false);
+ t_ = t;
+ std::cout << "Initialize separators image - " << t_ << std::endl;
+
+ mln_ch_value(I, value::rgb8) both;
+
+ if (internal::_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 (internal::_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 (internal::_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);
+
+ }
+ if (bot_accu(d).is_valid() || bbot_accu(d).is_valid())
+ {
+ if (bot_accu(d).is_valid())
+ {
+ if (internal::_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 (internal::_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);
+ }
+
+ }
+ t_ = t;
+ std::cout << "Drawing output image - " << t_ << std::endl;
+
+
+ if (internal::_debug_)
+ {
+ io::ppm::save(both, "both.ppm");
+ io::pbm::save(separators, "separators.pbm");
+ }
+
+
+ // Hit or miss
+ {
+ if (internal::_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");
+ }
+
+ t.restart();
+ unsigned length = 25;
+
+ dpoint2d
+ dp1(-21, 0),
+ dp2( 21, 0);
+
+ // Adjusting extension.
+ t.restart();
+ extension::adjust_fill(input_clo, length / 2, 0);
+
+ accu::count_value<bool> accu(true);
+ 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 (internal::_debug_)
+ io::pgm::save(data::convert(value::int_u8(), tmp), "tmp.pgm");
+
+
+ t.restart();
+ value::int_u8 nlabels;
+ mln_ch_value(I,value::int_u8)
+ sep_lbl = labeling::value(separators, true, c8(), nlabels);
+ t_ = t;
+ std::cout << "* labeling seps - " << t_ << std::endl;
+
+
+ t.restart();
+
+ util::array<bool> relbl(unsigned(nlabels) + 1, true);
+ relbl(0) = false;
+
+ unsigned invalid_ratio = unsigned(length * 0.30f);
+
+ mln_piter(I) p(separators.domain());
+ for_all(p)
+ if (separators(p))
+ {
+ unsigned lbl = sep_lbl(p);
+
+ unsigned
+ top_count = tmp(p + dp1),
+ bot_count = tmp(p + dp2);
+
+ // 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;
+ }
+ }
+
+ t_ = t;
+ std::cout << "* reading data - " << t_ << std::endl;
+
+ t.restart();
+ labeling::relabel_inplace(sep_lbl, nlabels, relbl);
+ t_ = t;
+ std::cout << "* relabel_inplace - " << t_ << std::endl;
+
+ mln_concrete(I) output = data::convert(bool(), sep_lbl);
+
+ if (internal::_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;
+
+ 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());
+
+ 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;
+
+ return scribo::preprocessing::rotate_90(output, true);
+ }
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::primitive::extract
+
+ } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
--
1.5.6.5
1
0
last-svn-commit-647-gf6cd71c mln/clustering/kmean_rgb.hh: Import Kmean RGB from Yann's sandbox.
by Guillaume Lazzara 15 Nov '10
by Guillaume Lazzara 15 Nov '10
15 Nov '10
---
milena/ChangeLog | 5 +
.../green => milena}/mln/clustering/kmean_rgb.hh | 106 ++++++++++----------
2 files changed, 57 insertions(+), 54 deletions(-)
copy {scribo/sandbox/green => milena}/mln/clustering/kmean_rgb.hh (93%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index fee653d..66d79f3 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,8 @@
+2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ * mln/clustering/kmean_rgb.hh: Import Kmean RGB from Yann's
+ sandbox.
+
2010-06-21 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
Fix the way to convert unsigned to float.
diff --git a/scribo/sandbox/green/mln/clustering/kmean_rgb.hh b/milena/mln/clustering/kmean_rgb.hh
similarity index 93%
copy from scribo/sandbox/green/mln/clustering/kmean_rgb.hh
copy to milena/mln/clustering/kmean_rgb.hh
index 544066b..daf6499 100644
--- a/scribo/sandbox/green/mln/clustering/kmean_rgb.hh
+++ b/milena/mln/clustering/kmean_rgb.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
+// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -167,7 +167,7 @@ namespace mln
/// \return an image which represents the pixel classification.
template <typename T, unsigned n, typename I>
inline
- image2d<value::label_8>
+ mln_ch_value(I,value::label_8)
kmean_rgb(const Image<I>& point,
const unsigned k_center,
const unsigned watch_dog,
@@ -544,16 +544,22 @@ namespace mln
}
};
- template <typename T, unsigned n>
+ template <typename T, unsigned n, typename I>
inline
- image2d<value::label_8>
- kmean_image2d_rgb(const image2d< value::rgb<n> >& point,
- const unsigned k_center,
- const unsigned watch_dog = 10,
- const unsigned n_times = 10)
+ mln_ch_value(I,value::label_8)
+ kmean_image2d_rgb(const Image<I>& point__,
+ const unsigned k_center,
+ const unsigned watch_dog = 10,
+ const unsigned n_times = 10)
{
trace::entering("mln::clustering::impl::kmean_image2d_rgb");
- trace::quiet = true;
+
+ const I& point = exact(point__);
+ typedef mln_value(I) V;
+ mlc_is(V, value::rgb<n>)::check();
+ mlc_bool(mln_site_(I)::dim == 2u)::check();
+ mln_precondition(point.is_valid());
+
// BEGIN TYPEDEF
typedef value::rgb<8> t_rgb;
typedef value::label<8> t_label;
@@ -564,7 +570,7 @@ namespace mln
typedef T t_result1d;
typedef algebra::vec<3,T> t_result3d;
- typedef image2d<t_value> t_point_img;
+ typedef I t_point_img;
typedef image3d<unsigned> t_histo_img;
typedef util::array<t_result1d> t_number_img;
typedef util::array<t_result3d> t_mean_img;
@@ -574,7 +580,7 @@ namespace mln
typedef image3d<t_result1d> t_distance_val;
typedef util::array<t_distance_val> t_distance_img;
- typedef image2d<t_label> t_label_dbg;
+ typedef mln_ch_value(I,t_label) t_label_dbg;
typedef image2d<t_rgb> t_color_dbg;
typedef image2d<t_value> t_mean_dbg;
@@ -702,18 +708,14 @@ namespace mln
while (_current_launching < _n_times)
{
// BEGIN LAUNCH ONE TIME
- trace::quiet = false;
trace::entering("Launch one time");
- trace::quiet = true;
{
t_result1d old_variance = mln_max(t_result1d);
_within_variance = mln_max(t_result1d);
_current_step = 0;
// BEGIN INIT_MEAN
- trace::quiet = false;
trace::entering("init mean");
- trace::quiet = true;
{
t_value_comp0 min_comp0 = mln_min(t_value_comp0);
t_value_comp0 max_comp0 = mln_max(t_value_comp0);
@@ -730,16 +732,12 @@ namespace mln
_mean[l.index_()][2]=(rand()%(max_comp2-min_comp2))+min_comp2;
}
}
- trace::quiet = false;
trace::exiting("init mean");
- trace::quiet = true;
// END INIT MEAN
// UPDATE DISTANCE
- trace::quiet = false;
trace::entering("update distance");
- trace::quiet = true;
for (unsigned i = 0; i < _k_center; ++i)
{
@@ -760,9 +758,7 @@ namespace mln
}
}
- trace::quiet = false;
trace::exiting("update distance");
- trace::quiet = true;
// END UPDATE DISTANCE
do
@@ -770,9 +766,7 @@ namespace mln
old_variance = _within_variance;
// BEGIN UPDATE GROUP
- trace::quiet = false;
trace::entering("update group");
- trace::quiet = true;
{
mln_piter(t_group_img) rgb(_group.domain());
@@ -795,15 +789,11 @@ namespace mln
}
}
- trace::quiet = false;
trace::exiting("update group");
- trace::quiet = true;
// END UPDATE GROUP
// BEGIN UPDATE MEAN
- trace::quiet = false;
trace::entering("update mean");
- trace::quiet = true;
{
mln_eiter(t_number_img) en(_number);
mln_eiter(t_mean_img) em(_mean);
@@ -836,9 +826,7 @@ namespace mln
_mean[l.index_()] /= _number[l.index_()];
}
}
- trace::quiet = false;
trace::exiting("update mean");
- trace::quiet = true;
// END UPDATE MEAN
@@ -847,9 +835,7 @@ namespace mln
break;
// UPDATE DISTANCE
- trace::quiet = false;
trace::entering("update distance");
- trace::quiet = true;
for (unsigned i = 0; i < _k_center; ++i)
{
@@ -865,15 +851,11 @@ namespace mln
(diff2_row + diff2_col + diff2_sli);
}
}
- trace::quiet = false;
trace::exiting("update distance");
- trace::quiet = true;
// END UPDATE DISTANCE
// BEGIN UPDATE VARIANCE
- trace::quiet = false;
trace::entering("update variance");
- trace::quiet = true;
{
_within_variance = literal::zero;
mln_eiter(t_variance_img) l(_variance);
@@ -894,9 +876,7 @@ namespace mln
}
}
- trace::quiet = false;
trace::exiting("update variance");
- trace::quiet = true;
// END UPDATE VARIANCE
//update_cnv();
@@ -909,9 +889,7 @@ namespace mln
//finalize_cnv();
//build_all_dbg();
}
- trace::quiet = false;
trace::exiting("Launch one time");
- trace::quiet = true;
// END LAUNCH ONE TIME
if ((_is_number_valid && (_current_step < _watch_dog))||
@@ -962,7 +940,6 @@ namespace mln
// }
// END BUILD LABEL IMAGE
- trace::quiet = false;
trace::exiting("mln::clustering::impl::kmean_image2d_rgb");
return _label_dbg;
@@ -982,27 +959,49 @@ namespace mln
namespace internal
{
- template <typename T, unsigned n>
+ template <typename T, unsigned n, typename I>
inline
- image2d<value::label_8>
- kmean_rgb_dispatch(const image2d< value::rgb<n> >& img,
- const unsigned k_center,
- const unsigned watch_dog,
- const unsigned n_times)
+ mln_ch_value(I,value::label_8)
+ kmean_rgb_dispatch(const Image<I>& img,
+ const unsigned k_center,
+ const unsigned watch_dog,
+ const unsigned n_times,
+ const value::rgb<n>&,
+ const point2d&)
{
return impl::kmean_image2d_rgb<T,n>(img, k_center, watch_dog, n_times);
}
+ template <typename T, unsigned n, typename I, typename V, typename P>
+ inline
+ mln_ch_value(I,value::label_8)
+ kmean_rgb_dispatch(const Image<I>& img,
+ const unsigned k_center,
+ const unsigned watch_dog,
+ const unsigned n_times,
+ const V&,
+ const P&)
+ {
+ // No kmean implementation found.
+ mlc_abort(I)::check();
+
+ typedef mln_ch_value(I, value::label_8) output_t;
+ return output_t();
+ }
+
template <typename T, unsigned n, typename I>
inline
- image2d< value::label_8>
+ mln_ch_value(I,value::label_8)
kmean_rgb_dispatch(const Image<I>& img,
const unsigned k_center,
const unsigned watch_dog,
const unsigned n_times)
{
- return kmean_rgb_dispatch<T,n>(exact(img),k_center,watch_dog,n_times);
+ typedef mln_value(I) V;
+ typedef mln_site(I) P;
+ return kmean_rgb_dispatch<T,n>(img, k_center, watch_dog,
+ n_times, V(), P());
}
@@ -1015,7 +1014,7 @@ namespace mln
template <typename T, unsigned n, typename I>
inline
- image2d<value::label_8>
+ mln_ch_value(I,value::label_8)
kmean_rgb(const Image<I>& point,
const unsigned k_center,
const unsigned watch_dog,
@@ -1023,13 +1022,12 @@ namespace mln
{
trace::entering("mln::clustering::kmean_rgb");
- image2d<value::label_8> tmp = internal::kmean_rgb_dispatch<T,n>(point,
- k_center,
- watch_dog,
- n_times);
+ mln_ch_value(I, value::label_8)
+ output = internal::kmean_rgb_dispatch<T,n>(point, k_center,
+ watch_dog, n_times);
trace::exiting("mln::clustering::kmean_rgb");
- return tmp;
+ return output;
}
--
1.5.6.5
1
0
last-svn-commit-646-g964a8b8 mln/clustering/kmean_rgb.hh: Import Kmean RGB from Yann's sandbox.
by Guillaume Lazzara 15 Nov '10
by Guillaume Lazzara 15 Nov '10
15 Nov '10
---
milena/ChangeLog | 5 +
.../green => milena}/mln/clustering/kmean_rgb.hh | 106 ++++++++++----------
2 files changed, 57 insertions(+), 54 deletions(-)
copy {scribo/sandbox/green => milena}/mln/clustering/kmean_rgb.hh (93%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index fee653d..66d79f3 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,8 @@
+2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ * mln/clustering/kmean_rgb.hh: Import Kmean RGB from Yann's
+ sandbox.
+
2010-06-21 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
Fix the way to convert unsigned to float.
diff --git a/scribo/sandbox/green/mln/clustering/kmean_rgb.hh b/milena/mln/clustering/kmean_rgb.hh
similarity index 93%
copy from scribo/sandbox/green/mln/clustering/kmean_rgb.hh
copy to milena/mln/clustering/kmean_rgb.hh
index 544066b..daf6499 100644
--- a/scribo/sandbox/green/mln/clustering/kmean_rgb.hh
+++ b/milena/mln/clustering/kmean_rgb.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
+// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -167,7 +167,7 @@ namespace mln
/// \return an image which represents the pixel classification.
template <typename T, unsigned n, typename I>
inline
- image2d<value::label_8>
+ mln_ch_value(I,value::label_8)
kmean_rgb(const Image<I>& point,
const unsigned k_center,
const unsigned watch_dog,
@@ -544,16 +544,22 @@ namespace mln
}
};
- template <typename T, unsigned n>
+ template <typename T, unsigned n, typename I>
inline
- image2d<value::label_8>
- kmean_image2d_rgb(const image2d< value::rgb<n> >& point,
- const unsigned k_center,
- const unsigned watch_dog = 10,
- const unsigned n_times = 10)
+ mln_ch_value(I,value::label_8)
+ kmean_image2d_rgb(const Image<I>& point__,
+ const unsigned k_center,
+ const unsigned watch_dog = 10,
+ const unsigned n_times = 10)
{
trace::entering("mln::clustering::impl::kmean_image2d_rgb");
- trace::quiet = true;
+
+ const I& point = exact(point__);
+ typedef mln_value(I) V;
+ mlc_is(V, value::rgb<n>)::check();
+ mlc_bool(mln_site_(I)::dim == 2u)::check();
+ mln_precondition(point.is_valid());
+
// BEGIN TYPEDEF
typedef value::rgb<8> t_rgb;
typedef value::label<8> t_label;
@@ -564,7 +570,7 @@ namespace mln
typedef T t_result1d;
typedef algebra::vec<3,T> t_result3d;
- typedef image2d<t_value> t_point_img;
+ typedef I t_point_img;
typedef image3d<unsigned> t_histo_img;
typedef util::array<t_result1d> t_number_img;
typedef util::array<t_result3d> t_mean_img;
@@ -574,7 +580,7 @@ namespace mln
typedef image3d<t_result1d> t_distance_val;
typedef util::array<t_distance_val> t_distance_img;
- typedef image2d<t_label> t_label_dbg;
+ typedef mln_ch_value(I,t_label) t_label_dbg;
typedef image2d<t_rgb> t_color_dbg;
typedef image2d<t_value> t_mean_dbg;
@@ -702,18 +708,14 @@ namespace mln
while (_current_launching < _n_times)
{
// BEGIN LAUNCH ONE TIME
- trace::quiet = false;
trace::entering("Launch one time");
- trace::quiet = true;
{
t_result1d old_variance = mln_max(t_result1d);
_within_variance = mln_max(t_result1d);
_current_step = 0;
// BEGIN INIT_MEAN
- trace::quiet = false;
trace::entering("init mean");
- trace::quiet = true;
{
t_value_comp0 min_comp0 = mln_min(t_value_comp0);
t_value_comp0 max_comp0 = mln_max(t_value_comp0);
@@ -730,16 +732,12 @@ namespace mln
_mean[l.index_()][2]=(rand()%(max_comp2-min_comp2))+min_comp2;
}
}
- trace::quiet = false;
trace::exiting("init mean");
- trace::quiet = true;
// END INIT MEAN
// UPDATE DISTANCE
- trace::quiet = false;
trace::entering("update distance");
- trace::quiet = true;
for (unsigned i = 0; i < _k_center; ++i)
{
@@ -760,9 +758,7 @@ namespace mln
}
}
- trace::quiet = false;
trace::exiting("update distance");
- trace::quiet = true;
// END UPDATE DISTANCE
do
@@ -770,9 +766,7 @@ namespace mln
old_variance = _within_variance;
// BEGIN UPDATE GROUP
- trace::quiet = false;
trace::entering("update group");
- trace::quiet = true;
{
mln_piter(t_group_img) rgb(_group.domain());
@@ -795,15 +789,11 @@ namespace mln
}
}
- trace::quiet = false;
trace::exiting("update group");
- trace::quiet = true;
// END UPDATE GROUP
// BEGIN UPDATE MEAN
- trace::quiet = false;
trace::entering("update mean");
- trace::quiet = true;
{
mln_eiter(t_number_img) en(_number);
mln_eiter(t_mean_img) em(_mean);
@@ -836,9 +826,7 @@ namespace mln
_mean[l.index_()] /= _number[l.index_()];
}
}
- trace::quiet = false;
trace::exiting("update mean");
- trace::quiet = true;
// END UPDATE MEAN
@@ -847,9 +835,7 @@ namespace mln
break;
// UPDATE DISTANCE
- trace::quiet = false;
trace::entering("update distance");
- trace::quiet = true;
for (unsigned i = 0; i < _k_center; ++i)
{
@@ -865,15 +851,11 @@ namespace mln
(diff2_row + diff2_col + diff2_sli);
}
}
- trace::quiet = false;
trace::exiting("update distance");
- trace::quiet = true;
// END UPDATE DISTANCE
// BEGIN UPDATE VARIANCE
- trace::quiet = false;
trace::entering("update variance");
- trace::quiet = true;
{
_within_variance = literal::zero;
mln_eiter(t_variance_img) l(_variance);
@@ -894,9 +876,7 @@ namespace mln
}
}
- trace::quiet = false;
trace::exiting("update variance");
- trace::quiet = true;
// END UPDATE VARIANCE
//update_cnv();
@@ -909,9 +889,7 @@ namespace mln
//finalize_cnv();
//build_all_dbg();
}
- trace::quiet = false;
trace::exiting("Launch one time");
- trace::quiet = true;
// END LAUNCH ONE TIME
if ((_is_number_valid && (_current_step < _watch_dog))||
@@ -962,7 +940,6 @@ namespace mln
// }
// END BUILD LABEL IMAGE
- trace::quiet = false;
trace::exiting("mln::clustering::impl::kmean_image2d_rgb");
return _label_dbg;
@@ -982,27 +959,49 @@ namespace mln
namespace internal
{
- template <typename T, unsigned n>
+ template <typename T, unsigned n, typename I>
inline
- image2d<value::label_8>
- kmean_rgb_dispatch(const image2d< value::rgb<n> >& img,
- const unsigned k_center,
- const unsigned watch_dog,
- const unsigned n_times)
+ mln_ch_value(I,value::label_8)
+ kmean_rgb_dispatch(const Image<I>& img,
+ const unsigned k_center,
+ const unsigned watch_dog,
+ const unsigned n_times,
+ const value::rgb<n>&,
+ const point2d&)
{
return impl::kmean_image2d_rgb<T,n>(img, k_center, watch_dog, n_times);
}
+ template <typename T, unsigned n, typename I, typename V, typename P>
+ inline
+ mln_ch_value(I,value::label_8)
+ kmean_rgb_dispatch(const Image<I>& img,
+ const unsigned k_center,
+ const unsigned watch_dog,
+ const unsigned n_times,
+ const V&,
+ const P&)
+ {
+ // No kmean implementation found.
+ mlc_abort(I)::check();
+
+ typedef mln_ch_value(I, value::label_8) output_t;
+ return output_t();
+ }
+
template <typename T, unsigned n, typename I>
inline
- image2d< value::label_8>
+ mln_ch_value(I,value::label_8)
kmean_rgb_dispatch(const Image<I>& img,
const unsigned k_center,
const unsigned watch_dog,
const unsigned n_times)
{
- return kmean_rgb_dispatch<T,n>(exact(img),k_center,watch_dog,n_times);
+ typedef mln_value(I) V;
+ typedef mln_site(I) P;
+ return kmean_rgb_dispatch<T,n>(img, k_center, watch_dog,
+ n_times, V(), P());
}
@@ -1015,7 +1014,7 @@ namespace mln
template <typename T, unsigned n, typename I>
inline
- image2d<value::label_8>
+ mln_ch_value(I,value::label_8)
kmean_rgb(const Image<I>& point,
const unsigned k_center,
const unsigned watch_dog,
@@ -1023,13 +1022,12 @@ namespace mln
{
trace::entering("mln::clustering::kmean_rgb");
- image2d<value::label_8> tmp = internal::kmean_rgb_dispatch<T,n>(point,
- k_center,
- watch_dog,
- n_times);
+ mln_ch_value(I, value::label_8)
+ output = internal::kmean_rgb_dispatch<T,n>(point, k_center,
+ watch_dog, n_times);
trace::exiting("mln::clustering::kmean_rgb");
- return tmp;
+ return output;
}
--
1.5.6.5
1
0
last-svn-commit-646-gdc8a597 mln/fun/v2v/rgb8_to_rgbn.hh: Import rgb8 to rgbn conversion function from Yann's sandbox.
by Guillaume Lazzara 15 Nov '10
by Guillaume Lazzara 15 Nov '10
15 Nov '10
---
.../green => milena}/mln/fun/v2v/rgb8_to_rgbn.hh | 82 +++++++++-----------
scribo/ChangeLog | 6 ++
2 files changed, 42 insertions(+), 46 deletions(-)
copy {scribo/sandbox/green => milena}/mln/fun/v2v/rgb8_to_rgbn.hh (61%)
diff --git a/scribo/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh b/milena/mln/fun/v2v/rgb8_to_rgbn.hh
similarity index 61%
copy from scribo/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh
copy to milena/mln/fun/v2v/rgb8_to_rgbn.hh
index acf1b5e..f1f3611 100644
--- a/scribo/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh
+++ b/milena/mln/fun/v2v/rgb8_to_rgbn.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -23,9 +23,10 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef MLN_FUN_V2V_RGB8_TO_RGBN_HH
+#ifndef MLN_FUN_V2V_RGB8_TO_RGBN_HH
# define MLN_FUN_V2V_RGB8_TO_RGBN_HH
+# include <mln/core/concept/function.hh>
# include <mln/value/rgb8.hh>
# include <mln/value/rgb.hh>
# include <mln/core/contract.hh>
@@ -33,36 +34,6 @@
/// \file
///
/// \brief Convert rgb8 value to rgbn, n < 8.
-///
-/// The source implements the reduction of quantification for any size less 8.
-///
-/// The following sample is a typical use of the histogram.
-///
-/// #include <mln/accu/stat/histo3d_rgb.hh>
-/// #include <mln/core/image/image2d.hh>
-/// #include <mln/core/image/image3d.hh>
-/// #include <mln/data/compute.hh>
-/// #include <mln/data/transform.hh>
-/// #include <mln/fun/v2v/rgb8_to_rgbn.hh>
-/// #include <mln/img_path.hh>
-/// #include <mln/io/ppm/load.hh>
-/// #include <mln/value/rgb.hh>
-/// #include <mln/value/rgb8.hh>
-///
-/// int main()
-/// {
-/// typedef mln::value::rgb8 t_rgb8;
-/// typedef mln::value::rgb<7> t_rgb7;
-/// mln::image2d<t_rgb8> img_rgb8;
-/// mln::image2d<t_rgb7> img_rgb7;
-/// mln::image3d<unsigned> histo;
-///
-/// mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/lena.ppm");
-/// img_rgb7 =mln::data::transform(img_rgb8,mln::fun::v2v::rgb8_to_rgbn<7>());
-/// histo = mln::data::compute(mln::accu::meta::stat::histo3d_rgb(),img_rgb7);
-///
-/// return 0;
-/// }
namespace mln
@@ -74,11 +45,13 @@ namespace mln
namespace v2v
{
+
/// \brief Convert a rgb8 value to a rgn, n < 8.
///
- /// Param n defines the output quantification used for the transformation.
+ /// \param n defines the output quantification used for the transformation.
///
/// \ingroup modfunv2v
+ //
template <unsigned n>
struct rgb8_to_rgbn : Function_v2v< rgb8_to_rgbn<n> >
{
@@ -91,29 +64,46 @@ namespace mln
///
/// Conversion is done by computing the size by which we
/// divide each rgb component.
+ //
+ result operator()(const argument& c) const;
+
+ };
+
- result operator()(const argument& c) const
- {
- mln_precondition(8 > n);
+# ifndef MLN_INCLUDE_ONLY
- unsigned size = pow(2,(8-n));
- /*
+ /// \brief Convert a rgb8 value to a rgn, n < 8.
+ ///
+ /// \param n defines the output quantification used for the transformation.
+ ///
+ /// \ingroup modfunv2v
+ //
+ template <unsigned n>
+ typename rgb8_to_rgbn<n>::result
+ rgb8_to_rgbn<n>::operator()(const argument& c) const
+ {
+ mln_precondition(8 > n);
+
+ unsigned size = pow(2,(8-n));
+ /*
std::cout << "c : " << c << std::endl;
std::cout << "red : " << c.red() << std::endl;
std::cout << "size : " << size << std::endl;
std::cout << "res : " << (c.red() / size) << std::endl;
std::cout << "max : " << (mln_max(mln::value::int_u<n>))<< std::endl;
- */
- result res(c.red() / size, c.green() / size, c.blue() / size);
+ */
+ result res(c.red() / size, c.green() / size, c.blue() / size);
+
+ return res;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
- return res;
- }
- };
- }
+ } // end of namespace mln::fun::v2v
- }
+ } // end of namespace mln::fun
-}
+} // end of namespace mln
#endif // ! MLN_FUN_V2V_RGB8_TO_RGBN_HH
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 95fcab4..dd11567 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,11 @@
2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Import rgb8 to rgbn conversion function from Yann's sandbox.
+
+ * mln/fun/v2v/rgb8_to_rgbn.hh: New.
+
+2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+
* scribo/core/macros.hh: Remove deprecated macro.
2010-09-02 Guillaume Lazzara <z(a)lrde.epita.fr>
--
1.5.6.5
1
0
last-svn-commit-645-gbd9472a mln/fun/v2v/rgb8_to_rgbn.hh: Import rgb8 to rgbn conversion function from Yann's sandbox.
by Guillaume Lazzara 15 Nov '10
by Guillaume Lazzara 15 Nov '10
15 Nov '10
---
.../green => milena}/mln/fun/v2v/rgb8_to_rgbn.hh | 82 +++++++++-----------
scribo/ChangeLog | 6 ++
2 files changed, 42 insertions(+), 46 deletions(-)
copy {scribo/sandbox/green => milena}/mln/fun/v2v/rgb8_to_rgbn.hh (61%)
diff --git a/scribo/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh b/milena/mln/fun/v2v/rgb8_to_rgbn.hh
similarity index 61%
copy from scribo/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh
copy to milena/mln/fun/v2v/rgb8_to_rgbn.hh
index acf1b5e..f1f3611 100644
--- a/scribo/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh
+++ b/milena/mln/fun/v2v/rgb8_to_rgbn.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -23,9 +23,10 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef MLN_FUN_V2V_RGB8_TO_RGBN_HH
+#ifndef MLN_FUN_V2V_RGB8_TO_RGBN_HH
# define MLN_FUN_V2V_RGB8_TO_RGBN_HH
+# include <mln/core/concept/function.hh>
# include <mln/value/rgb8.hh>
# include <mln/value/rgb.hh>
# include <mln/core/contract.hh>
@@ -33,36 +34,6 @@
/// \file
///
/// \brief Convert rgb8 value to rgbn, n < 8.
-///
-/// The source implements the reduction of quantification for any size less 8.
-///
-/// The following sample is a typical use of the histogram.
-///
-/// #include <mln/accu/stat/histo3d_rgb.hh>
-/// #include <mln/core/image/image2d.hh>
-/// #include <mln/core/image/image3d.hh>
-/// #include <mln/data/compute.hh>
-/// #include <mln/data/transform.hh>
-/// #include <mln/fun/v2v/rgb8_to_rgbn.hh>
-/// #include <mln/img_path.hh>
-/// #include <mln/io/ppm/load.hh>
-/// #include <mln/value/rgb.hh>
-/// #include <mln/value/rgb8.hh>
-///
-/// int main()
-/// {
-/// typedef mln::value::rgb8 t_rgb8;
-/// typedef mln::value::rgb<7> t_rgb7;
-/// mln::image2d<t_rgb8> img_rgb8;
-/// mln::image2d<t_rgb7> img_rgb7;
-/// mln::image3d<unsigned> histo;
-///
-/// mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/lena.ppm");
-/// img_rgb7 =mln::data::transform(img_rgb8,mln::fun::v2v::rgb8_to_rgbn<7>());
-/// histo = mln::data::compute(mln::accu::meta::stat::histo3d_rgb(),img_rgb7);
-///
-/// return 0;
-/// }
namespace mln
@@ -74,11 +45,13 @@ namespace mln
namespace v2v
{
+
/// \brief Convert a rgb8 value to a rgn, n < 8.
///
- /// Param n defines the output quantification used for the transformation.
+ /// \param n defines the output quantification used for the transformation.
///
/// \ingroup modfunv2v
+ //
template <unsigned n>
struct rgb8_to_rgbn : Function_v2v< rgb8_to_rgbn<n> >
{
@@ -91,29 +64,46 @@ namespace mln
///
/// Conversion is done by computing the size by which we
/// divide each rgb component.
+ //
+ result operator()(const argument& c) const;
+
+ };
+
- result operator()(const argument& c) const
- {
- mln_precondition(8 > n);
+# ifndef MLN_INCLUDE_ONLY
- unsigned size = pow(2,(8-n));
- /*
+ /// \brief Convert a rgb8 value to a rgn, n < 8.
+ ///
+ /// \param n defines the output quantification used for the transformation.
+ ///
+ /// \ingroup modfunv2v
+ //
+ template <unsigned n>
+ typename rgb8_to_rgbn<n>::result
+ rgb8_to_rgbn<n>::operator()(const argument& c) const
+ {
+ mln_precondition(8 > n);
+
+ unsigned size = pow(2,(8-n));
+ /*
std::cout << "c : " << c << std::endl;
std::cout << "red : " << c.red() << std::endl;
std::cout << "size : " << size << std::endl;
std::cout << "res : " << (c.red() / size) << std::endl;
std::cout << "max : " << (mln_max(mln::value::int_u<n>))<< std::endl;
- */
- result res(c.red() / size, c.green() / size, c.blue() / size);
+ */
+ result res(c.red() / size, c.green() / size, c.blue() / size);
+
+ return res;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
- return res;
- }
- };
- }
+ } // end of namespace mln::fun::v2v
- }
+ } // end of namespace mln::fun
-}
+} // end of namespace mln
#endif // ! MLN_FUN_V2V_RGB8_TO_RGBN_HH
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index e0d155a..cd8db5d 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,11 @@
2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Import rgb8 to rgbn conversion function from Yann's sandbox.
+
+ * mln/fun/v2v/rgb8_to_rgbn.hh: New.
+
+2010-11-15 Guillaume Lazzara <z(a)lrde.epita.fr>
+
* scribo/core/macros.hh: Remove deprecated macro.
2010-09-02 Guillaume Lazzara <z(a)lrde.epita.fr>
--
1.5.6.5
1
0
last-svn-commit-656-gb7fe0b0 scribo/core/component_set.hh: Combine separator images.
by Guillaume Lazzara 15 Nov '10
by Guillaume Lazzara 15 Nov '10
15 Nov '10
---
scribo/scribo/core/component_set.hh | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/scribo/scribo/core/component_set.hh b/scribo/scribo/core/component_set.hh
index 77cbaa5..103826f 100644
--- a/scribo/scribo/core/component_set.hh
+++ b/scribo/scribo/core/component_set.hh
@@ -46,6 +46,8 @@
# include <mln/labeling/compute.hh>
# include <mln/labeling/relabel.hh>
+# include <mln/logical/or.hh>
+
# include <mln/convert/from_to.hh>
# include <mln/core/image/dmorph/image_if.hh>
@@ -541,7 +543,10 @@ namespace scribo
void
component_set<L>::add_separators(const mln_ch_value(L, bool)& ima)
{
- this->data_->separators_ = ima;
+ if (! has_separators())
+ this->data_->separators_ = ima;
+ else
+ mln::logical::or_inplace(this->data_->separators_, ima);
}
--
1.5.6.5
1
0
last-svn-commit-655-g52af6ec scribo/core/component_set.hh: Combine separator images.
by Guillaume Lazzara 15 Nov '10
by Guillaume Lazzara 15 Nov '10
15 Nov '10
---
scribo/scribo/core/component_set.hh | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/scribo/scribo/core/component_set.hh b/scribo/scribo/core/component_set.hh
index 77cbaa5..103826f 100644
--- a/scribo/scribo/core/component_set.hh
+++ b/scribo/scribo/core/component_set.hh
@@ -46,6 +46,8 @@
# include <mln/labeling/compute.hh>
# include <mln/labeling/relabel.hh>
+# include <mln/logical/or.hh>
+
# include <mln/convert/from_to.hh>
# include <mln/core/image/dmorph/image_if.hh>
@@ -541,7 +543,10 @@ namespace scribo
void
component_set<L>::add_separators(const mln_ch_value(L, bool)& ima)
{
- this->data_->separators_ = ima;
+ if (! has_separators())
+ this->data_->separators_ = ima;
+ else
+ mln::logical::or_inplace(this->data_->separators_, ima);
}
--
1.5.6.5
1
0