Olena-patches
Threads by month
- ----- 2025 -----
- 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
June 2010
- 9 participants
- 276 discussions

last-svn-commit-106-g11701a0 io/xml/save_text_lines.hh: Fix XML output.
by Guillaume Lazzara 03 Jun '10
by Guillaume Lazzara 03 Jun '10
03 Jun '10
---
scribo/ChangeLog | 4 ++
scribo/io/xml/save_text_lines.hh | 98 ++++++++++++++++++++------------------
2 files changed, 55 insertions(+), 47 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 53358b7..5dc9919 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+ * io/xml/save_text_lines.hh: Fix XML output.
+
+2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+
* debug/decision_image.hh: Add the anchor::Type as argument.
2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
diff --git a/scribo/io/xml/save_text_lines.hh b/scribo/io/xml/save_text_lines.hh
index 22aa3d9..7f0fdf4 100644
--- a/scribo/io/xml/save_text_lines.hh
+++ b/scribo/io/xml/save_text_lines.hh
@@ -84,56 +84,60 @@ namespace scribo
file << "<PcGts xmlns=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16 http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16/pagecontent…" pcGtsId=\"" << input_name << "\">" << std::endl;
- file << " <Metadata>" << std::endl;
- file << " <Creator>LRDE</pcCreator>" << std::endl;
- file << " <Created/>" << std::endl;
- file << " <LastChange/>" << std::endl;
- file << " <Comments>Generated by Scribo from Olena.</pcComments>" << std::endl;
- file << " </Metadata>" << std::endl;
-
- file << " <Page image_filename=\"" << input_name
- << "\" image_width=\"" << lines.component_set_().labeled_image().ncols()
- << "\" image_height=\"" << lines.component_set_().labeled_image().nrows()
+ file << " <PcMetadata>" << std::endl;
+ file << " <PcCreator>LRDE</PcCreator>" << std::endl;
+ file << " <PcCreated/>" << std::endl;
+ file << " <PcLastChange/>" << std::endl;
+ file << " <PcComments>Generated by Scribo from Olena.</PcComments>" << std::endl;
+ file << " </PcMetadata>" << std::endl;
+
+ file << " <page image_filename=\"" << input_name
+ << "\" image_width=\"" << lines.components().labeled_image().ncols()
+ << "\" image_height=\"" << lines.components().labeled_image().nrows()
<< "\">" << std::endl;
for_all_lines(l, lines)
- {
- file << " <text_region id=\"" << lines(l).id()
- << "\" txt_orientation=\"" << lines(l).orientation()
- << "\" txt_reading_orientation=\"" << lines(l).reading_orientation()
- << "\" txt_reading_direction=\"" << lines(l).reading_direction()
- << "\" txt_reverse_video=\"" << (lines(l).reverse_video() ? "true" : "false")
- << "\" txt_indented=\"" << (lines(l).indented() ? "true" : "false")
- // EXTENSIONS - Not officially supported
- << "\" baseline=\"" << lines(l).baseline()
- << "\" median=\"" << lines(l).median()
- << "\" x_height=\"" << lines(l).x_height()
- << "\" d_height=\"" << lines(l).d_height()
- << "\" a_height=\"" << lines(l).a_height()
- << "\" char_space=\"" << lines(l).char_space()
- << "\" char_width=\"" << lines(l).char_width()
- // End of EXTENSIONS
- << "\">"
- << std::endl;
-
- file << " <coords>" << std::endl
- << " <point x=\"" << lines(l).bbox().pmin().row()
- << "\" y=\"" << lines(l).bbox().pmin().col() << "\"/>"
- << std::endl
- << " <point x=\"" << lines(l).bbox().pmin().row()
- << "\" y=\"" << lines(l).bbox().pmax().col() << "\"/>"
- << std::endl
- << " <point x=\"" << lines(l).bbox().pmax().row()
- << "\" y=\"" << lines(l).bbox().pmin().col() << "\"/>"
- << std::endl
- << " <point x=\"" << lines(l).bbox().pmax().row()
- << "\" y=\"" << lines(l).bbox().pmax().col() << "\"/>"
- << std::endl
- << " </coords>" << std::endl;
- }
-
- file << " </text_region>" << std::endl;
- file << " </Page>" << std::endl;
+ if (lines(l).tag() != line::Merged
+ && lines(l).tag() != line::Ignored)
+ {
+ file << " <text_region id=\"" << lines(l).id()
+ << "\" txt_orientation=\"" << lines(l).orientation()
+ << "\" txt_reading_orientation=\"" << lines(l).reading_orientation()
+ << "\" txt_reading_direction=\"" << lines(l).reading_direction()
+ << "\" txt_reverse_video=\"" << (lines(l).reverse_video() ? "true" : "false")
+ << "\" txt_indented=\"" << (lines(l).indented() ? "true" : "false")
+ << "\" kerning=\"" << lines(l).char_space()
+
+ // EXTENSIONS - Not officially supported
+ << "\" baseline=\"" << lines(l).baseline()
+ << "\" meanline=\"" << lines(l).meanline()
+ << "\" x_height=\"" << lines(l).x_height()
+ << "\" d_height=\"" << lines(l).d_height()
+ << "\" a_height=\"" << lines(l).a_height()
+ << "\" char_width=\"" << lines(l).char_width()
+ // End of EXTENSIONS
+ << "\">"
+ << std::endl;
+
+ file << " <coords>" << std::endl
+ << " <point x=\"" << lines(l).bbox().pmin().col()
+ << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
+ << std::endl
+ << " <point x=\"" << lines(l).bbox().pmax().col()
+ << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
+ << std::endl
+ << " <point x=\"" << lines(l).bbox().pmax().col()
+ << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
+ << std::endl
+ << " <point x=\"" << lines(l).bbox().pmin().col()
+ << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
+ << std::endl
+ << " </coords>" << std::endl;
+
+ file << " </text_region>" << std::endl;
+ }
+
+ file << " </page>" << std::endl;
file << "</PcGts>" << std::endl;
--
1.5.6.5
1
0

last-svn-commit-105-g53a9811 debug/decision_image.hh: Add the anchor::Type as argument.
by Guillaume Lazzara 03 Jun '10
by Guillaume Lazzara 03 Jun '10
03 Jun '10
---
scribo/ChangeLog | 4 ++++
scribo/debug/decision_image.hh | 24 ++++++++++++++----------
2 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index a9c13e3..53358b7 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+ * debug/decision_image.hh: Add the anchor::Type as argument.
+
+2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Use anchor::Type in alignment routines' dispatch.
* filter/object_links_bottom_aligned.hh,
diff --git a/scribo/debug/decision_image.hh b/scribo/debug/decision_image.hh
index cc3f0f0..7f881d3 100644
--- a/scribo/debug/decision_image.hh
+++ b/scribo/debug/decision_image.hh
@@ -66,7 +66,8 @@ namespace scribo
mln_ch_value(I,value::rgb8)
decision_image(const Image<I>& input_,
const object_groups<L>& groups,
- const object_groups<L>& filtered_groups);
+ const object_groups<L>& filtered_groups,
+ anchor::Type anchor);
/*! \brief Save a color image showing the difference between to
object links.
@@ -84,7 +85,8 @@ namespace scribo
mln_ch_value(I,value::rgb8)
decision_image(const Image<I>& input_,
const object_links<L>& links,
- const object_links<L>& filtered_links);
+ const object_links<L>& filtered_links,
+ anchor::Type anchor);
# ifndef MLN_INCLUDE_ONLY
@@ -125,12 +127,13 @@ namespace scribo
mln_ch_value(I,value::rgb8)
decision_image(const Image<I>& input_,
const object_links<L>& links,
- const object_links<L>& filtered_links)
+ const object_links<L>& filtered_links,
+ anchor::Type anchor)
{
trace::entering("scribo::debug::decision_image");
const I& input = exact(input_);
- const component_set<L>& components = links.components();
+ const component_set<L>& comps = links.components();
mln_precondition(input.is_valid());
mln_precondition(links.is_valid());
@@ -142,21 +145,22 @@ namespace scribo
image2d<value::rgb8>
decision_image = data::convert(value::rgb8(), input);
- for_all_comps(i, components)
- mln::draw::box(decision_image, components(i).bbox(), literal::blue);
+ for_all_comps(i, comps)
+ mln::draw::box(decision_image, comps(i).bbox(), literal::blue);
for (unsigned i = 1; i < links.nelements(); ++i)
{
if (links(i) != i)
{
+ mln_site(L)
+ p1 = primitive::link::internal::compute_anchor(comps, i, anchor),
+ p2 = primitive::link::internal::compute_anchor(comps, links(i), anchor);
+
value::rgb8 value = literal::green;
if (links(i) != filtered_links(i))
value = literal::red;
- mln::draw::line(decision_image,
- components(i).bbox().pcenter(),
- components(links(i)).bbox().pcenter(),
- value);
+ mln::draw::line(decision_image, p1, p2, value);
}
}
--
1.5.6.5
1
0

last-svn-commit-104-gb54300a Use anchor::Type in alignment routines' dispatch.
by Guillaume Lazzara 03 Jun '10
by Guillaume Lazzara 03 Jun '10
03 Jun '10
* filter/object_links_bottom_aligned.hh,
* filter/object_links_center_aligned.hh,
* filter/object_links_left_aligned.hh,
* filter/object_links_non_aligned_simple.hh,
* filter/object_links_right_aligned.hh,
* filter/object_links_top_aligned.hh: Use anchor::Type.
* filter/internal/alignment_angle.hh,
* filter/internal/component_aligned.hh: New.
---
scribo/ChangeLog | 14 ++
scribo/filter/internal/alignment_angle.hh | 156 ++++++++++++++++++++++
scribo/filter/internal/component_aligned.hh | 114 ++++++++++++++++
scribo/filter/object_links_bottom_aligned.hh | 2 +-
scribo/filter/object_links_center_aligned.hh | 2 +-
scribo/filter/object_links_left_aligned.hh | 2 +-
scribo/filter/object_links_non_aligned_simple.hh | 109 +--------------
scribo/filter/object_links_right_aligned.hh | 2 +-
scribo/filter/object_links_top_aligned.hh | 2 +-
9 files changed, 297 insertions(+), 106 deletions(-)
create mode 100644 scribo/filter/internal/alignment_angle.hh
create mode 100644 scribo/filter/internal/component_aligned.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index da11249..a9c13e3 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,19 @@
2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Use anchor::Type in alignment routines' dispatch.
+
+ * filter/object_links_bottom_aligned.hh,
+ * filter/object_links_center_aligned.hh,
+ * filter/object_links_left_aligned.hh,
+ * filter/object_links_non_aligned_simple.hh,
+ * filter/object_links_right_aligned.hh,
+ * filter/object_links_top_aligned.hh: Use anchor::Type.
+
+ * filter/internal/alignment_angle.hh,
+ * filter/internal/component_aligned.hh: New.
+
+2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Small fixes related to object_groups.
* core/object_groups.hh: Add more preconditions.
diff --git a/scribo/filter/internal/alignment_angle.hh b/scribo/filter/internal/alignment_angle.hh
new file mode 100644
index 0000000..5b88012
--- /dev/null
+++ b/scribo/filter/internal/alignment_angle.hh
@@ -0,0 +1,156 @@
+// 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.
+
+#ifndef SCRIBO_FILTER_INTERNAL_ALIGNMENT_ANGLE_HH
+# define SCRIBO_FILTER_INTERNAL_ALIGNMENT_ANGLE_HH
+
+/// \file
+///
+/// Return the alignment angle between two components according to an
+/// anchor.
+
+
+# include <mln/util/array.hh>
+# include <mln/math/abs.hh>
+# include <mln/math/pi.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/tag/anchor.hh>
+# include <scribo/core/component_set.hh>
+
+namespace scribo
+{
+
+ namespace filter
+ {
+
+ namespace internal
+ {
+
+ using namespace mln;
+
+
+ /// Return the alignment angle between two components according
+ /// to anchor.
+ ///
+ /// \return An angle in Radians.
+ template <typename L>
+ float
+ alignment_angle(const component_set<L>& comps,
+ unsigned current_object, unsigned nbh_object,
+ anchor::Type anchor);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename L>
+ float
+ alignment_angle(const component_set<L>& comps,
+ unsigned current_object, unsigned nbh_object,
+ anchor::Type anchor)
+ {
+ trace::entering("scribo::filter::internal::alignment_angle_rad");
+
+ mln_precondition(comps.is_valid());
+
+ float dr, dc;
+
+ if (nbh_object == current_object)
+ return 0;
+
+ // Center
+ if (anchor == 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());
+
+ 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);
+ }
+
+ // 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;
+
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::filter::internal
+
+ } // end of namespace scribo::filter
+
+} // end of namespace scribo
+
+#endif // SCRIBO_FILTER_INTERNAL_ALIGNMENT_ANGLE_HH
diff --git a/scribo/filter/internal/component_aligned.hh b/scribo/filter/internal/component_aligned.hh
new file mode 100644
index 0000000..7200d44
--- /dev/null
+++ b/scribo/filter/internal/component_aligned.hh
@@ -0,0 +1,114 @@
+// 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.
+
+#ifndef SCRIBO_FILTER_INTERNAL_COMPONENT_ALIGNED_HH
+# define SCRIBO_FILTER_INTERNAL_COMPONENT_ALIGNED_HH
+
+/// \file
+///
+/// Invalidate components between two non aligned components.
+
+
+# include <mln/util/array.hh>
+# include <mln/math/abs.hh>
+# include <mln/math/pi.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/tag/anchor.hh>
+# include <scribo/core/component_set.hh>
+# include <scribo/filter/internal/alignment_angle.hh>
+
+namespace scribo
+{
+
+ namespace filter
+ {
+
+ namespace internal
+ {
+
+ using namespace mln;
+
+
+ template <typename L>
+ bool
+ component_aligned(const component_set<L>& comps,
+ unsigned current_object, unsigned nbh_object,
+ anchor::Type anchor, float max_alpha);
+
+
+ template <typename L>
+ bool
+ component_aligned_rad(const component_set<L>& comps,
+ unsigned current_object, unsigned nbh_object,
+ anchor::Type anchor, float max_alpha_rad);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename L>
+ bool
+ component_aligned(const component_set<L>& comps,
+ unsigned current_object, unsigned nbh_object,
+ anchor::Type anchor, float max_alpha)
+ {
+ float max_alpha_rad = (max_alpha / 180.0f) * math::pi;
+
+ return component_aligned(comps, current_object, anchor, max_alpha_rad);
+ }
+
+
+
+ template <typename L>
+ bool
+ component_aligned_rad(const component_set<L>& comps,
+ unsigned current_object, unsigned nbh_object,
+ anchor::Type anchor, float max_alpha_rad)
+ {
+ trace::entering("scribo::filter::internal::component_aligned_rad");
+
+ mln_precondition(comps.is_valid());
+
+ float angle = alignment_angle(comps, current_object,
+ nbh_object, anchor);
+
+ bool output = (angle <= max_alpha_rad);
+
+ trace::exiting("scribo::filter::internal::component_aligned_rad");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::filter::internal
+
+ } // end of namespace scribo::filter
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_FILTER_INTERNAL_COMPONENT_ALIGNED_HH
diff --git a/scribo/filter/object_links_bottom_aligned.hh b/scribo/filter/object_links_bottom_aligned.hh
index f1816d4..ba8ff31 100644
--- a/scribo/filter/object_links_bottom_aligned.hh
+++ b/scribo/filter/object_links_bottom_aligned.hh
@@ -97,7 +97,7 @@ namespace scribo
mln_precondition(links.is_valid());
object_links<L>
- output = object_links_non_aligned_simple(links, 2, max_alpha);
+ output = object_links_non_aligned_simple(links, anchor::Bottom, max_alpha);
trace::exiting("scribo::filter::object_links_bottom_aligned");
return output;
diff --git a/scribo/filter/object_links_center_aligned.hh b/scribo/filter/object_links_center_aligned.hh
index abbac9e..8d89e73 100644
--- a/scribo/filter/object_links_center_aligned.hh
+++ b/scribo/filter/object_links_center_aligned.hh
@@ -95,7 +95,7 @@ namespace scribo
object_links<L>
output = object_links_non_aligned_simple(objects, links,
- 0, max_alpha);
+ anchor::Center, max_alpha);
trace::exiting("scribo::filter::object_links_center_aligned");
return output;
diff --git a/scribo/filter/object_links_left_aligned.hh b/scribo/filter/object_links_left_aligned.hh
index e69b110..a352d71 100644
--- a/scribo/filter/object_links_left_aligned.hh
+++ b/scribo/filter/object_links_left_aligned.hh
@@ -103,7 +103,7 @@ namespace scribo
object_links<L>
output = object_links_non_aligned_simple(objects, links,
- 3,
+ anchor::Left,
max_alpha);
trace::exiting("scribo::filter::object_links_left_aligned");
diff --git a/scribo/filter/object_links_non_aligned_simple.hh b/scribo/filter/object_links_non_aligned_simple.hh
index 5ecba0f..ae63527 100644
--- a/scribo/filter/object_links_non_aligned_simple.hh
+++ b/scribo/filter/object_links_non_aligned_simple.hh
@@ -38,6 +38,7 @@
# include <scribo/core/macros.hh>
# include <scribo/core/object_links.hh>
+# include <scribo/filter/internal/component_aligned.hh>
namespace scribo
{
@@ -48,13 +49,13 @@ namespace scribo
using namespace mln;
/*! \brief Invalidate links between two non aligned components.
- Alignment is based on a given edge of object bounding boxes.
+ Alignment is based on a given anchor of object bounding boxes.
\param[in] links Object links information.
\param[in] max_alpha Maximum angle value (degrees).
- Exemple with dim == 1 and edge == 1 (bottom
+ Exemple with dim == 1 and anchor == 1 (bottom
horizontal filter):
\verbatim
@@ -79,18 +80,11 @@ namespace scribo
The angle between the two bottoms must be lower than \p alpha.
- edge values :
- 0 = center
- 1 = top
- 2 = bottom
- 3 = left
- 4 = right
-
*/
template <typename L>
object_links<L>
object_links_non_aligned_simple(const object_links<L>& links,
- unsigned edge,
+ anchor::Type anchor,
float max_alpha);
@@ -100,7 +94,7 @@ namespace scribo
template <typename L>
object_links<L>
object_links_non_aligned_simple(const object_links<L>& links,
- unsigned edge,
+ anchor::Type anchor,
float max_alpha)
{
trace::entering("scribo::filter::object_links_non_aligned_simple");
@@ -111,100 +105,13 @@ namespace scribo
const component_set<L>& comps = links.components();
object_links<L> output(links);
- float dr, dc;
float max_alpha_rad = (max_alpha / 180.0f) * math::pi;
- // Center
- if (edge == 0)
- {
- for_all_comps(i, comps)
- {
- if (links(i) != i)
- {
- dr = math::abs(comps(i).bbox().pcenter().row()
- - comps(links(i)).bbox().pcenter().row());
- dc = math::abs(comps(i).bbox().pcenter().col()
- - comps(links(i)).bbox().pcenter().col());
-
- if (std::atan(dr / dc) > max_alpha_rad)
- output(i) = i;
- }
- }
- }
- // Top
- else if (edge == 1)
- {
- for_all_comps(i, comps)
- if (links(i) != i)
- {
- dr = math::abs(comps(i).bbox().pmin().row()
- - comps(links(i)).bbox().pmin().row());
- dc = math::abs(comps(i).bbox().pcenter().col()
- - comps(links(i)).bbox().pcenter().col());
-
- if (std::atan(dr / dc) > max_alpha_rad)
- output(i) = i;
- }
- }
- // Bottom
- else if (edge == 2)
- {
- for_all_comps(i, comps)
- {
- if (links(i) != i)
- {
- dr = math::abs(comps(i).bbox().pmax().row()
- - comps(links(i)).bbox().pmax().row());
- dc = math::abs(comps(i).bbox().pcenter().col()
- - comps(links(i)).bbox().pcenter().col());
-
- if (std::atan(dr / dc) > max_alpha_rad)
- output(i) = i;
- }
- }
- }
- // Left
- else if (edge == 3)
- {
- for_all_comps(i, comps)
- {
- if (links(i) != i)
- {
- dr = math::abs(comps(i).bbox().pcenter().row()
- - comps(links(i)).bbox().pcenter().row());
- dc = math::abs(comps(i).bbox().pmin().col()
- - comps(links(i)).bbox().pmin().col());
-
- if (std::atan(dc / dr) > max_alpha_rad)
- output(i) = i;
- }
- }
- }
- // Right
- else if (edge == 4)
- {
- for_all_comps(i, comps)
- {
- if (links(i) != i)
- {
- dr = math::abs(comps(i).bbox().pcenter().row()
- - comps(links(i)).bbox().pcenter().row());
- dc = math::abs(comps(i).bbox().pmax().col()
- - comps(links(i)).bbox().pmax().col());
-
- if (std::atan(dc / dr) > max_alpha_rad)
- output(i) = i;
- }
- }
- }
- else
- {
- trace::warning("Invalid edge value... Aborting computation.");
- trace::exiting("scribo::filter::object_links_non_aligned_simple");
- return output;
- }
+ for_all_comps(i, comps)
+ if (!internal::component_aligned_rad(comps, i, links(i), anchor, max_alpha_rad))
+ output(i) = i;
trace::exiting("scribo::filter::object_links_non_aligned_simple");
diff --git a/scribo/filter/object_links_right_aligned.hh b/scribo/filter/object_links_right_aligned.hh
index 2ee0280..ee964a3 100644
--- a/scribo/filter/object_links_right_aligned.hh
+++ b/scribo/filter/object_links_right_aligned.hh
@@ -102,7 +102,7 @@ namespace scribo
object_links<L>
output = object_links_non_aligned_simple(objects, links,
- 4,
+ anchor::Right,
max_alpha);
trace::exiting("scribo::filter::object_links_right_aligned");
diff --git a/scribo/filter/object_links_top_aligned.hh b/scribo/filter/object_links_top_aligned.hh
index de5ab3b..57e8d40 100644
--- a/scribo/filter/object_links_top_aligned.hh
+++ b/scribo/filter/object_links_top_aligned.hh
@@ -96,7 +96,7 @@ namespace scribo
mln_precondition(links.is_valid());
object_links<L>
- output = object_links_non_aligned_simple(links, 1, max_alpha);
+ output = object_links_non_aligned_simple(links, anchor::Top, max_alpha);
trace::exiting("scribo::filter::object_links_top_aligned");
return output;
--
1.5.6.5
1
0

03 Jun '10
* core/object_groups.hh: Add more preconditions.
* filter/object_groups_small.hh: Call duplicate().
---
scribo/ChangeLog | 8 ++++++++
scribo/core/object_groups.hh | 2 ++
scribo/filter/object_groups_small.hh | 5 +++--
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index a7134fa..da11249 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,13 @@
2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Small fixes related to object_groups.
+
+ * core/object_groups.hh: Add more preconditions.
+
+ * filter/object_groups_small.hh: Call duplicate().
+
+2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Add init() member to object_links structure.
* core/object_links.hh: New init() member.
diff --git a/scribo/core/object_groups.hh b/scribo/core/object_groups.hh
index be97c06..97334f2 100644
--- a/scribo/core/object_groups.hh
+++ b/scribo/core/object_groups.hh
@@ -165,6 +165,7 @@ namespace scribo
const object_links<L>&
object_groups<L>::links() const
{
+ mln_assertion(data_ != 0);
return data_->links_;
}
@@ -172,6 +173,7 @@ namespace scribo
void
object_groups<L>::init_(const object_links<L>& links)
{
+ mln_assertion(data_ != 0);
data_->comp_to_group_ = links.comp_to_link();
}
diff --git a/scribo/filter/object_groups_small.hh b/scribo/filter/object_groups_small.hh
index 60f8753..f736a50 100644
--- a/scribo/filter/object_groups_small.hh
+++ b/scribo/filter/object_groups_small.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of Olena.
//
@@ -77,7 +78,7 @@ namespace scribo
for_all_groups(i, group_size)
++group_size[groups(i)];
- object_groups<L> output(groups);
+ object_groups<L> output = groups.duplicate();
output(0) = 0;
for_all_groups(i, output)
if (group_size[groups(i)] < n_links
--
1.5.6.5
1
0

last-svn-commit-102-g2c6947d Add init() member to object_links structure.
by Guillaume Lazzara 03 Jun '10
by Guillaume Lazzara 03 Jun '10
03 Jun '10
* core/object_links.hh: New init() member.
* filter/object_groups_v_thickness.hh,
* filter/object_groups_with_holes.hh,
* primitive/group/from_double_link.hh,
* primitive/link/internal/link_functor_base.hh,
* primitive/link/merge_double_link.hh,
* src/afp/link.hh,
* src/afp/regroup.hh: Call init() on object_links instances.
* primitive/internal/init_link_array.hh: Remove.
---
scribo/ChangeLog | 78 ++++++++++++--------
scribo/core/object_links.hh | 35 +++++++++-
scribo/filter/object_groups_v_thickness.hh | 5 +-
scribo/filter/object_groups_with_holes.hh | 24 +-----
scribo/primitive/group/from_double_link.hh | 3 +-
scribo/primitive/internal/init_link_array.hh | 78 --------------------
.../primitive/link/internal/link_functor_base.hh | 5 +-
scribo/primitive/link/merge_double_link.hh | 1 -
scribo/src/afp/link.hh | 13 +--
scribo/src/afp/regroup.hh | 1 -
10 files changed, 95 insertions(+), 148 deletions(-)
delete mode 100644 scribo/primitive/internal/init_link_array.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index ffd4a39..a7134fa 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,41 +1,57 @@
2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
- * scribo/src/text_in_photo_fast.cc: Group routine parameters in a
- global structure.
+ Add init() member to object_links structure.
+
+ * core/object_links.hh: New init() member.
+
+ * filter/object_groups_v_thickness.hh,
+ * filter/object_groups_with_holes.hh,
+ * primitive/group/from_double_link.hh,
+ * primitive/link/internal/link_functor_base.hh,
+ * primitive/link/merge_double_link.hh,
+ * src/afp/link.hh,
+ * src/afp/regroup.hh: Call init() on object_links instances.
+
+ * primitive/internal/init_link_array.hh: Remove.
+
+2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ * src/text_in_photo_fast.cc: Group routine parameters in a global
+ structure.
2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
Add new Sauvola overloads and update examples.
- * scribo/binarization/internal/first_pass_functor.hh,
- * scribo/binarization/local_threshold.hh,
- * scribo/binarization/sauvola.hh,
- * scribo/binarization/sauvola_ms.hh,
- * scribo/binarization/sauvola_ms_split.hh,
- * scribo/binarization/sauvola_threshold_image.hh,
- * scribo/canvas/integral_browsing.hh: Add more parameters to
- Sauvola routines.
-
- * scribo/binarization/sauvola_threshold_image_debug.hh: New. New
- overload providing debug outputs.
-
- * scribo/debug/usage.hh: Remove a parameter.
-
- * scribo/src/binarization/Makefile.am,
- * scribo/src/binarization/pgm_global_threshold_auto.cc,
- * scribo/src/binarization/pgm_sauvola.cc,
- * scribo/src/binarization/pgm_sauvola_ms.cc,
- * scribo/src/binarization/ppm_fg_sauvola_ms.cc,
- * scribo/src/binarization/ppm_sauvola.cc,
- * scribo/src/binarization/ppm_sauvola_ms.cc,
- * scribo/src/binarization/ppm_sauvola_ms_split.cc: Add new
- program arguments.
-
- * scribo/src/binarization/fg_sauvola_ms.cc,
- * scribo/src/binarization/sauvola.cc,
- * scribo/src/binarization/sauvola_ms.cc,
- * scribo/src/binarization/sauvola_ms_split.cc,
- * scribo/src/binarization/sauvola_debug.cc: New.
+ * binarization/internal/first_pass_functor.hh,
+ * binarization/local_threshold.hh,
+ * binarization/sauvola.hh,
+ * binarization/sauvola_ms.hh,
+ * binarization/sauvola_ms_split.hh,
+ * binarization/sauvola_threshold_image.hh,
+ * canvas/integral_browsing.hh: Add more parameters to Sauvola
+ routines.
+
+ * binarization/sauvola_threshold_image_debug.hh: New. New overload
+ providing debug outputs.
+
+ * debug/usage.hh: Remove a parameter.
+
+ * src/binarization/Makefile.am,
+ * src/binarization/pgm_global_threshold_auto.cc,
+ * src/binarization/pgm_sauvola.cc,
+ * src/binarization/pgm_sauvola_ms.cc,
+ * src/binarization/ppm_fg_sauvola_ms.cc,
+ * src/binarization/ppm_sauvola.cc,
+ * src/binarization/ppm_sauvola_ms.cc,
+ * src/binarization/ppm_sauvola_ms_split.cc: Add new program
+ arguments.
+
+ * src/binarization/fg_sauvola_ms.cc,
+ * src/binarization/sauvola.cc,
+ * src/binarization/sauvola_ms.cc,
+ * src/binarization/sauvola_ms_split.cc,
+ * src/binarization/sauvola_debug.cc: New.
2010-03-29 Guillaume Lazzara <z(a)lrde.epita.fr>
diff --git a/scribo/core/object_links.hh b/scribo/core/object_links.hh
index 654cb75..c10cae6 100644
--- a/scribo/core/object_links.hh
+++ b/scribo/core/object_links.hh
@@ -90,12 +90,18 @@ namespace scribo
const mln::util::array<unsigned>& comp_to_link() const;
+ void init();
private:
mln::util::tracked_ptr<data_t> data_;
};
+ template <typename L>
+ std::ostream&
+ operator<<(std::ostream& ostr, const object_links<L>& links);
+
+
# ifndef MLN_INCLUDE_ONLY
@@ -174,7 +180,7 @@ namespace scribo
unsigned
object_links<L>::nelements() const
{
- return data_->comp_to_link_.nelements() ;
+ return data_->comp_to_link_.nelements();
}
@@ -202,6 +208,33 @@ namespace scribo
}
+ template <typename L>
+ void
+ object_links<L>::init()
+ {
+ for (unsigned i = 0; i < nelements(); ++i)
+ if (data_->components_(i).tag() == component::Ignored)
+ data_->comp_to_link_(i) = 0;
+ else
+ data_->comp_to_link_(i) = i;
+ }
+
+
+ template <typename L>
+ std::ostream&
+ operator<<(std::ostream& ostr, const object_links<L>& links)
+ {
+ ostr << "object_links[";
+
+ for_all_links(l, links)
+ ostr << l << "->" << links.comp_to_link()[l] << ", ";
+
+ ostr << "]";
+
+ return ostr;
+ }
+
+
# endif // ! MLN_INCLUDE_ONLY
diff --git a/scribo/filter/object_groups_v_thickness.hh b/scribo/filter/object_groups_v_thickness.hh
index caac765..717b372 100644
--- a/scribo/filter/object_groups_v_thickness.hh
+++ b/scribo/filter/object_groups_v_thickness.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of Olena.
//
@@ -75,7 +76,7 @@ namespace scribo
mln::util::array<float>
group_thickness = estim::object_groups_v_thickness(groups);
- object_groups<L> output(groups);
+ object_groups<L> output = groups.duplicate();
output(0) = 0;
for (unsigned i = 1; i < output.nelements(); ++i)
if (groups.components()(i).is_valid()
diff --git a/scribo/filter/object_groups_with_holes.hh b/scribo/filter/object_groups_with_holes.hh
index 1f31c01..570ae6a 100644
--- a/scribo/filter/object_groups_with_holes.hh
+++ b/scribo/filter/object_groups_with_holes.hh
@@ -42,33 +42,13 @@
# include <mln/draw/box_plain.hh>
# include <mln/util/array.hh>
-# include <mln/labeling/blobs_and_compute.hh>
-
# include <mln/accu/math/count.hh>
# include <mln/fun/i2v/array.hh>
-# include <mln/io/pbm/save.hh>
-# include <mln/io/pgm/save.hh>
-
-# include <mln/data/convert.hh>
-
-# include <mln/labeling/background.hh>
-
# include <scribo/core/macros.hh>
# include <scribo/core/component_set.hh>
-# include <scribo/filter/internal/compute.hh>
-
-# include <mln/data/fill.hh>
-# include <mln/data/paste.hh>
-
-# include <mln/util/timer.hh>
-
-# include <mln/value/label_16.hh>
-# include <mln/core/var.hh>
-
-#include <mln/debug/filename.hh>
namespace scribo
{
@@ -195,6 +175,9 @@ namespace scribo
data::fill(card, 1);
border::fill(card, 1);
+ // We want to label background components only in the
+ // group bounding boxes. Thus, this image is a labeling
+ // constraint.
bboxes_ima = internal::compute_bboxes_image(components);
to_keep(0) = true;
@@ -285,7 +268,6 @@ namespace scribo
if (! to_keep(groups(c)))
output(c) = 0;
-// output.update_tags(to_keep, component::Ignored);
trace::exiting("scribo::filter::impl::generic::object_groups_with_holes");
return output;
diff --git a/scribo/primitive/group/from_double_link.hh b/scribo/primitive/group/from_double_link.hh
index a1e8479..14c5972 100644
--- a/scribo/primitive/group/from_double_link.hh
+++ b/scribo/primitive/group/from_double_link.hh
@@ -46,7 +46,6 @@
# include <scribo/core/component_set.hh>
# include <scribo/primitive/internal/find_root.hh>
# include <scribo/primitive/internal/is_link_valid.hh>
-# include <scribo/primitive/internal/init_link_array.hh>
namespace scribo
@@ -94,7 +93,7 @@ namespace scribo
mln_precondition(right_link.components_id_() == components.id_());
object_groups<L> parent(components, left_link.nelements());
- internal::init_link_array(parent);
+ parent.init();
for_all_ncomponents(i, components.nlabels())
{
mln::util::couple<bool, unsigned>
diff --git a/scribo/primitive/internal/init_link_array.hh b/scribo/primitive/internal/init_link_array.hh
deleted file mode 100644
index 2b46ad5..0000000
--- a/scribo/primitive/internal/init_link_array.hh
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
-//
-// This file is part of Olena.
-//
-// Olena is free software: you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation, version 2 of the License.
-//
-// Olena is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Olena. If not, see <http://www.gnu.org/licenses/>.
-//
-// As a special exception, you may use this file as part of a free
-// software project without restriction. Specifically, if other files
-// instantiate templates or use macros or inline functions from this
-// file, or you compile this file and link it with other files to produce
-// an executable, this file does not by itself cause the resulting
-// executable to be covered by the GNU General Public License. This
-// exception does not however invalidate any other reasons why the
-// executable file might be covered by the GNU General Public License.
-
-#ifndef SCRIBO_PRIMITIVE_INTERNAL_INIT_LINK_ARRAY_HH
-# define SCRIBO_PRIMITIVE_INTERNAL_INIT_LINK_ARRAY_HH
-
-/// \file
-///
-/// Initialize a link array.
-
-
-# include <scribo/core/object_links.hh>
-# include <scribo/core/component_set.hh>
-
-
-namespace scribo
-{
-
- using namespace mln;
-
- namespace primitive
- {
-
- namespace internal
- {
-
- /// Initialize a link array.
- template <typename L>
- void
- init_link_array(object_links<L>& link_array);
-
-# ifndef MLN_INCLUDE_ONLY
-
- template <typename L>
- inline
- void
- init_link_array(object_links<L>& link_array)
- {
- const component_set<L>& comp_set = link_array.components();
- for (unsigned i = 0; i < link_array.nelements(); ++i)
- if (comp_set(i).tag() == component::Ignored)
- link_array(i) = 0;
- else
- link_array(i) = i;
- }
-
-# endif // ! MLN_INCLUDE_ONLY
-
- } // end of namespace scribo::primitive::internal
-
- } // end of namespace scribo::primitive
-
-} // end of namespace scribo
-
-
-#endif // ! SCRIBO_PRIMITIVE_INTERNAL_INIT_LINK_ARRAY_HH
diff --git a/scribo/primitive/link/internal/link_functor_base.hh b/scribo/primitive/link/internal/link_functor_base.hh
index 5e4af46..f2641ad 100644
--- a/scribo/primitive/link/internal/link_functor_base.hh
+++ b/scribo/primitive/link/internal/link_functor_base.hh
@@ -45,7 +45,6 @@
# include <scribo/core/object_links.hh>
# include <scribo/core/concept/link_functor.hh>
# include <scribo/primitive/link/internal/compute_anchor.hh>
-# include <scribo/primitive/internal/init_link_array.hh>
# define scribo_support(T) typename T::support
# define scribo_support_(T) T::support
@@ -194,7 +193,7 @@ namespace scribo
labeled_image_(this->components_.labeled_image()),
nanchors_(nanchors)
{
- primitive::internal::init_link_array(links_);
+ links_.init();
}
@@ -207,7 +206,7 @@ namespace scribo
labeled_image_(this->components_.labeled_image()),
nanchors_(1)
{
- primitive::internal::init_link_array(links_);
+ links_.init();
}
diff --git a/scribo/primitive/link/merge_double_link.hh b/scribo/primitive/link/merge_double_link.hh
index 704c103..94a44ef 100644
--- a/scribo/primitive/link/merge_double_link.hh
+++ b/scribo/primitive/link/merge_double_link.hh
@@ -48,7 +48,6 @@
# include <scribo/core/component_set.hh>
# include <scribo/primitive/internal/find_root.hh>
# include <scribo/primitive/internal/is_link_valid.hh>
-# include <scribo/primitive/internal/init_link_array.hh>
namespace scribo
diff --git a/scribo/src/afp/link.hh b/scribo/src/afp/link.hh
index b6ef1f9..fc23991 100644
--- a/scribo/src/afp/link.hh
+++ b/scribo/src/afp/link.hh
@@ -3,7 +3,6 @@
#include <mln/util/couple.hh>
#include <scribo/core/component_set.hh>
#include <scribo/core/macros.hh>
-#include <scribo/primitive/internal/init_link_array.hh>
namespace scribo
{
@@ -21,21 +20,19 @@ namespace scribo
{
object_links<L>
right(components, static_cast<unsigned>(components.nelements()) + 1);
- primitive::internal::init_link_array(right);
+ right.init();
object_links<L>
left(components, static_cast<unsigned>(components.nelements()) + 1);
- primitive::internal::init_link_array(left);
+ left.init();
const L& lbl_ima = components.labeled_image();
for_all_comps(i, components)
{
float
- w = (components(i).bbox().pmax().col()
- - components(i).bbox().pmin().col()),
- h = (components(i).bbox().pmax().row()
- - components(i).bbox().pmin().row());
+ w = components(i).bbox().width(),
+ h = components(i).bbox().height();
unsigned dmax = (w / 2.0f) + (3 * math::max(w, h));
@@ -98,7 +95,7 @@ namespace scribo
{
object_links<L>
left(components, static_cast<unsigned>(components.nelements()) + 1);
- primitive::internal::init_link_array(left);
+ left.init();
const L& lbl_ima = components.labeled_image();
diff --git a/scribo/src/afp/regroup.hh b/scribo/src/afp/regroup.hh
index 3fcfcaa..44b5438 100644
--- a/scribo/src/afp/regroup.hh
+++ b/scribo/src/afp/regroup.hh
@@ -3,7 +3,6 @@
#include <mln/util/couple.hh>
#include <scribo/core/component_set.hh>
#include <scribo/core/macros.hh>
-#include <scribo/primitive/internal/init_link_array.hh>
namespace scribo
{
--
1.5.6.5
1
0

last-svn-commit-101-g4dad6c9 scribo/src/text_in_photo_fast.cc: Group routine parameters in a global structure.
by Guillaume Lazzara 03 Jun '10
by Guillaume Lazzara 03 Jun '10
03 Jun '10
---
scribo/ChangeLog | 5 ++
scribo/src/text_in_photo_fast.cc | 79 ++++++++++++++++++++++++++++---------
2 files changed, 65 insertions(+), 19 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 34a258f..ffd4a39 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,10 @@
2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+ * scribo/src/text_in_photo_fast.cc: Group routine parameters in a
+ global structure.
+
+2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Add new Sauvola overloads and update examples.
* scribo/binarization/internal/first_pass_functor.hh,
diff --git a/scribo/src/text_in_photo_fast.cc b/scribo/src/text_in_photo_fast.cc
index 68b2014..d61cc6f 100644
--- a/scribo/src/text_in_photo_fast.cc
+++ b/scribo/src/text_in_photo_fast.cc
@@ -57,8 +57,6 @@
#include <mln/subsampling/antialiased.hh>
-#include <mln/subsampling/antialiased_rgb.hh>
-
#include <scribo/draw/bounding_boxes.hh>
#include <scribo/draw/groups_bboxes.hh>
@@ -112,6 +110,7 @@
const char *args_desc[][2] =
{
{ "input.ppm", "A color image." },
+ { "ouput.ppm", "A color image where the text is highlighted." },
{ "debug_output_dir", "Directory were debug images will be saved" },
{ "lambda", "Lambda value used for foreground extraction" },
{0, 0}
@@ -121,6 +120,38 @@ const char *args_desc[][2] =
namespace mln
{
+
+ struct config
+ {
+ config()
+ {
+ sauvola_s = 3u;
+ sauvola_min_w = 51u;
+
+ // Group Filtering
+ bbox_h_ratio = 1.50f;
+ bbox_overlap = 0.80f;
+ small_groups = 3;
+ v_thickness = 8;
+ regroup_dmax = 30;
+ group_min_holes = 3;
+ }
+
+
+ // Sauvola ms
+ unsigned sauvola_s;
+ unsigned sauvola_min_w;
+
+ // Group Filtering
+ float bbox_h_ratio;
+ float bbox_overlap;
+ unsigned small_groups;
+ unsigned v_thickness;
+ unsigned regroup_dmax;
+ unsigned group_min_holes;
+ };
+
+
struct mask_non_text : Function_v2v<mask_non_text>
{
typedef value::rgb8 result;
@@ -239,10 +270,9 @@ int main(int argc, char* argv[])
if (argc < 3 || argc > 10)
return scribo::debug::usage(argv,
"Find text in a photo.\n\n\
-Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
+Common usage: ./text_in_photo_fast input.ppm output.ppm 1 1 1 1 1",
"input.ppm output.ppm <bg/fg enabled> <sauvola_ms enabled> <Bg comp filter enabled> <small group filter enabled> <thin group filter enabled> [debug_output_dir] [lambda]",
- args_desc,
- "A color image where the text is highlighted.");
+ args_desc);
std::string out_base_dir;
bool debug = false;
@@ -255,6 +285,8 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
trace::entering("main");
+ config conf;
+
image2d<value::rgb8> input_rgb;
io::magick::load(input_rgb, argv[1]);
@@ -264,7 +296,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
std::cout << "Original domain: " << input_rgb.domain() << std::endl;
- input_rgb = mln::subsampling::impl::antialiased_2d_rgb(input_rgb, factor);
+ input_rgb = mln::subsampling::antialiased(input_rgb, factor);
std::cout << "Resized domain: " << input_rgb.domain() << std::endl;
@@ -318,11 +350,11 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
unsigned w = std::min(intensity_ima.nrows() / 3, intensity_ima.ncols() / 3);
if (! w % 2)
++w;
- w = std::min(w, 51u);
+ w = std::min(w, conf.sauvola_min_w);
if (argc > 4 && atoi(argv[4]) != 0)
{
std::cout << "** Using sauvola_ms with w_1 = " << w << std::endl;
- input = scribo::binarization::sauvola_ms(intensity_ima, w, 3, 67);
+ input = scribo::binarization::sauvola_ms(intensity_ima, w, conf.sauvola_s);
}
else
{
@@ -420,7 +452,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
timer_.restart();
object_links<L>
hratio_filtered_links = filter::object_links_bbox_h_ratio(merged_links,
- 1.50f);
+ conf.bbox_h_ratio);
@@ -431,7 +463,8 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
image2d<value::rgb8>
hratio_decision_image = scribo::debug::decision_image(input,
merged_links,
- hratio_filtered_links);
+ hratio_filtered_links,
+ anchor::MassCenter);
io::ppm::save(hratio_decision_image,
scribo::make::debug_filename("hratio_links_decision_image.ppm"));
}
@@ -442,7 +475,8 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
//Remove links if bboxes overlap too much.
object_links<L> overlap_filtered_links
- = filter::object_links_bbox_overlap(hratio_filtered_links, 0.80f);
+ = filter::object_links_bbox_overlap(hratio_filtered_links,
+ conf.bbox_overlap);
@@ -453,7 +487,8 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
image2d<value::rgb8> overlap_decision_image
= scribo::debug::decision_image(input,
hratio_filtered_links,
- overlap_filtered_links);
+ overlap_filtered_links,
+ anchor::MassCenter);
io::ppm::save(overlap_decision_image,
scribo::make::debug_filename("overlap_links_decision_image.ppm"));
}
@@ -514,7 +549,8 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
if (argc > 6 && atoi(argv[6]) != 0)
{
std::cout << "** Using group too small" << std::endl;
- filtered_small_groups = filter::object_groups_small(groups, 3);
+ filtered_small_groups = filter::object_groups_small(groups,
+ conf.small_groups);
}
else
filtered_small_groups = groups;
@@ -532,7 +568,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
scribo::draw::groups_bboxes(decision_image, groups, literal::red);
scribo::draw::groups_bboxes(decision_image, filtered_small_groups,
- literal::blue);
+ literal::green);
io::ppm::save(decision_image,
@@ -549,7 +585,8 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
{
std::cout << "** Using group too thin" << std::endl;
filtered_thin_groups
- = filter::object_groups_v_thickness(filtered_small_groups, 8);
+ = filter::object_groups_v_thickness(filtered_small_groups,
+ conf.v_thickness);
}
else
filtered_thin_groups = filtered_small_groups;
@@ -565,7 +602,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
scribo::draw::groups_bboxes(decision_image, filtered_small_groups,
literal::red);
scribo::draw::groups_bboxes(decision_image, filtered_thin_groups,
- literal::blue);
+ literal::green);
io::ppm::save(decision_image,
scribo::make::debug_filename("thin_groups_filter.ppm"));
@@ -578,7 +615,8 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
g_timer.restart();
// Grouping groups together if possible.
- groups = primitive::regroup::from_single_left_link(filtered_thin_groups, 30);
+ groups = primitive::regroup::from_single_left_link(filtered_thin_groups,
+ conf.regroup_dmax);
// component_set<L>
@@ -607,7 +645,8 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
{
std::cout << "** Using objects_with_two_holes" << std::endl;
- groups = scribo::filter::object_groups_with_holes(groups, 5);
+ groups = scribo::filter::object_groups_with_holes(groups,
+ conf.group_min_holes);
t_ = g_timer;
std::cout << "Objects_with_holes " << t_ << std::endl;
@@ -626,7 +665,9 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
{
decision_image = data::convert(value::rgb8(), input);
- scribo::draw::groups_bboxes(decision_image, groups, literal::blue);
+ scribo::draw::groups_bboxes(decision_image, filtered_thin_groups,
+ literal::red);
+ scribo::draw::groups_bboxes(decision_image, groups, literal::green);
io::ppm::save(decision_image, scribo::make::debug_filename("group_with_holes_filter.ppm"));
}
--
1.5.6.5
1
0

last-svn-commit-100-gd10f1a6 Add new Sauvola overloads and update examples.
by Guillaume Lazzara 03 Jun '10
by Guillaume Lazzara 03 Jun '10
03 Jun '10
* scribo/binarization/internal/first_pass_functor.hh,
* scribo/binarization/local_threshold.hh,
* scribo/binarization/sauvola.hh,
* scribo/binarization/sauvola_ms.hh,
* scribo/binarization/sauvola_ms_split.hh,
* scribo/binarization/sauvola_threshold_image.hh,
* scribo/canvas/integral_browsing.hh: Add more parameters to
Sauvola routines.
* scribo/binarization/sauvola_threshold_image_debug.hh: New. New
overload providing debug outputs.
* scribo/debug/usage.hh: Remove a parameter.
* scribo/src/binarization/Makefile.am,
* scribo/src/binarization/pgm_global_threshold_auto.cc,
* scribo/src/binarization/pgm_sauvola.cc,
* scribo/src/binarization/pgm_sauvola_ms.cc,
* scribo/src/binarization/ppm_fg_sauvola_ms.cc,
* scribo/src/binarization/ppm_sauvola.cc,
* scribo/src/binarization/ppm_sauvola_ms.cc,
* scribo/src/binarization/ppm_sauvola_ms_split.cc: Add new
program arguments.
* scribo/src/binarization/fg_sauvola_ms.cc,
* scribo/src/binarization/sauvola.cc,
* scribo/src/binarization/sauvola_ms.cc,
* scribo/src/binarization/sauvola_ms_split.cc,
* scribo/src/binarization/sauvola_debug.cc: New.
---
scribo/ChangeLog | 34 +++
scribo/binarization/internal/first_pass_functor.hh | 22 +-
scribo/binarization/local_threshold.hh | 3 -
scribo/binarization/sauvola.hh | 61 ++++-
scribo/binarization/sauvola_ms.hh | 132 +++++----
scribo/binarization/sauvola_ms_split.hh | 29 ++-
scribo/binarization/sauvola_threshold_image.hh | 128 +++++----
...d_image.hh => sauvola_threshold_image_debug.hh} | 309 ++++++++------------
scribo/canvas/integral_browsing.hh | 13 -
scribo/debug/usage.hh | 13 +-
.../{ppm_fg_sauvola_ms.cc => fg_sauvola_ms.cc} | 15 +-
.../src/binarization/pgm_global_threshold_auto.cc | 3 +-
scribo/src/binarization/pgm_sauvola.cc | 28 ++-
scribo/src/binarization/pgm_sauvola_ms.cc | 53 +++-
scribo/src/binarization/ppm_fg_sauvola_ms.cc | 58 +++--
scribo/src/binarization/ppm_sauvola.cc | 38 ++-
scribo/src/binarization/ppm_sauvola_ms.cc | 57 +++--
scribo/src/binarization/ppm_sauvola_ms_split.cc | 65 +++--
.../binarization/{pgm_sauvola.cc => sauvola.cc} | 39 ++-
scribo/src/binarization/sauvola_debug.cc | 105 +++++++
.../{ppm_sauvola_ms.cc => sauvola_ms.cc} | 64 +++--
...ppm_sauvola_ms_split.cc => sauvola_ms_split.cc} | 71 ++++--
scribo/src/preprocessing/to_pgm.cc | 46 +++
23 files changed, 863 insertions(+), 523 deletions(-)
copy scribo/binarization/{sauvola_threshold_image.hh => sauvola_threshold_image_debug.hh} (55%)
copy scribo/src/binarization/{ppm_fg_sauvola_ms.cc => fg_sauvola_ms.cc} (87%)
copy scribo/src/binarization/{pgm_sauvola.cc => sauvola.cc} (68%)
create mode 100644 scribo/src/binarization/sauvola_debug.cc
copy scribo/src/binarization/{ppm_sauvola_ms.cc => sauvola_ms.cc} (61%)
copy scribo/src/binarization/{ppm_sauvola_ms_split.cc => sauvola_ms_split.cc} (64%)
create mode 100644 scribo/src/preprocessing/to_pgm.cc
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 50f9d86..34a258f 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,3 +1,37 @@
+2010-04-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Add new Sauvola overloads and update examples.
+
+ * scribo/binarization/internal/first_pass_functor.hh,
+ * scribo/binarization/local_threshold.hh,
+ * scribo/binarization/sauvola.hh,
+ * scribo/binarization/sauvola_ms.hh,
+ * scribo/binarization/sauvola_ms_split.hh,
+ * scribo/binarization/sauvola_threshold_image.hh,
+ * scribo/canvas/integral_browsing.hh: Add more parameters to
+ Sauvola routines.
+
+ * scribo/binarization/sauvola_threshold_image_debug.hh: New. New
+ overload providing debug outputs.
+
+ * scribo/debug/usage.hh: Remove a parameter.
+
+ * scribo/src/binarization/Makefile.am,
+ * scribo/src/binarization/pgm_global_threshold_auto.cc,
+ * scribo/src/binarization/pgm_sauvola.cc,
+ * scribo/src/binarization/pgm_sauvola_ms.cc,
+ * scribo/src/binarization/ppm_fg_sauvola_ms.cc,
+ * scribo/src/binarization/ppm_sauvola.cc,
+ * scribo/src/binarization/ppm_sauvola_ms.cc,
+ * scribo/src/binarization/ppm_sauvola_ms_split.cc: Add new
+ program arguments.
+
+ * scribo/src/binarization/fg_sauvola_ms.cc,
+ * scribo/src/binarization/sauvola.cc,
+ * scribo/src/binarization/sauvola_ms.cc,
+ * scribo/src/binarization/sauvola_ms_split.cc,
+ * scribo/src/binarization/sauvola_debug.cc: New.
+
2010-03-29 Guillaume Lazzara <z(a)lrde.epita.fr>
Add support for various image types in text_in_photo_fast.
diff --git a/scribo/binarization/internal/first_pass_functor.hh b/scribo/binarization/internal/first_pass_functor.hh
index df4c025..3455060 100644
--- a/scribo/binarization/internal/first_pass_functor.hh
+++ b/scribo/binarization/internal/first_pass_functor.hh
@@ -68,12 +68,12 @@ namespace scribo
unsigned n_nbhs;
util::array<int> dp;
- static const double one_k = 1 - 0.34;
- static const double k_R = 0.34 / 128.0;
+ double K_;
- first_pass_functor(const I& input)
+ first_pass_functor(const I& input, double K)
: input(input),
- pxl(input)
+ pxl(input),
+ K_(K)
{
res = 0;
pxl.start();
@@ -96,17 +96,9 @@ namespace scribo
unsigned p = pxl.offset();
- // Use an inlined and developed version of sauvola's
- // threshold formula.
-// value::int_u8 t_p = mean * (one_k + k_R * stddev);
-
-// std::cout << t_p << ", ";
-
-// std::cout << input.element(p) << " - " << t_p << std::endl;
- value::int_u8 t_p = sauvola_threshold_formula(mean, stddev);
-
-// std::cout << input.point_at_index(p)
-// << " - " << sauvola_threshold_formula(mean, stddev);
+ value::int_u8 t_p = sauvola_threshold_formula(mean, stddev,
+ K_,
+ SCRIBO_DEFAULT_SAUVOLA_R);
msk.element(p) = input.element(p) < t_p;
diff --git a/scribo/binarization/local_threshold.hh b/scribo/binarization/local_threshold.hh
index ea5b34e..aa53664 100644
--- a/scribo/binarization/local_threshold.hh
+++ b/scribo/binarization/local_threshold.hh
@@ -200,9 +200,6 @@ namespace scribo
internal::local_threshold_tests(input, threshold);
-
-
-
mln_ch_value(I, bool)
output = internal::local_threshold_dispatch(input, threshold);
diff --git a/scribo/binarization/sauvola.hh b/scribo/binarization/sauvola.hh
index c3a0cce..6dd812b 100644
--- a/scribo/binarization/sauvola.hh
+++ b/scribo/binarization/sauvola.hh
@@ -55,6 +55,23 @@ namespace scribo
\input[in] input An image.
\input[in] window_size The window size.
+ \input[in] K Sauvola's formulae constant.
+
+ \return A binary image.
+
+ */
+ template <typename I>
+ mln_ch_value(I, bool)
+ sauvola(const Image<I>& input, unsigned window_size, double K);
+
+
+
+ /*! \brief Convert an image into a binary image.
+
+ Sauvola's formulae constant K is set to 0.34.
+
+ \input[in] input An image.
+ \input[in] window_size The window size.
\return A binary image.
@@ -84,7 +101,7 @@ namespace scribo
template <typename I>
mln_ch_value(I, bool)
- sauvola(const Image<I>& input, unsigned window_size)
+ sauvola(const Image<I>& input, unsigned window_size, double K)
{
trace::entering("scribo::binarization::impl::generic::sauvola");
mln_precondition(exact(input).is_valid());
@@ -92,7 +109,8 @@ namespace scribo
mln_ch_value(I, bool)
output = local_threshold(input,
binarization::sauvola_threshold_image(input,
- window_size));
+ window_size,
+ K));
trace::exiting("scribo::binarization::impl::generic::sauvola");
return output;
@@ -103,7 +121,7 @@ namespace scribo
template <typename I>
mln_ch_value(I, bool)
- sauvola_rgb8(const Image<I>& input, unsigned window_size)
+ sauvola_rgb8(const Image<I>& input, unsigned window_size, double K)
{
trace::entering("scribo::binarization::impl::generic::sauvola");
mln_precondition(exact(input).is_valid());
@@ -114,7 +132,8 @@ namespace scribo
mln_ch_value(I, bool)
output = local_threshold(gima,
binarization::sauvola_threshold_image(gima,
- window_size));
+ window_size,
+ K));
trace::exiting("scribo::binarization::impl::generic::sauvola");
return output;
@@ -132,26 +151,29 @@ namespace scribo
template <typename I>
mln_ch_value(I, bool)
sauvola_dispatch(const mln_value(I)&,
- const Image<I>& input, unsigned window_size)
+ const Image<I>& input, unsigned window_size,
+ double K)
{
- return impl::generic::sauvola(input, window_size);
+ return impl::generic::sauvola(input, window_size, K);
}
template <typename I>
mln_ch_value(I, bool)
sauvola_dispatch(const value::rgb8&,
- const Image<I>& input, unsigned window_size)
+ const Image<I>& input, unsigned window_size,
+ double K)
{
- return impl::sauvola_rgb8(input, window_size);
+ return impl::sauvola_rgb8(input, window_size, K);
}
template <typename I>
mln_ch_value(I, bool)
- sauvola_dispatch(const Image<I>& input, unsigned window_size)
+ sauvola_dispatch(const Image<I>& input, unsigned window_size,
+ double K)
{
typedef mln_value(I) V;
- return sauvola_dispatch(V(), input, window_size);
+ return sauvola_dispatch(V(), input, window_size, K);
}
} // end of namespace scribo::binarization::internal
@@ -162,6 +184,22 @@ namespace scribo
template <typename I>
mln_ch_value(I, bool)
+ sauvola(const Image<I>& input, unsigned window_size, double K)
+ {
+ trace::entering("scribo::binarization::sauvola");
+
+ mln_precondition(exact(input).is_valid());
+
+ mln_ch_value(I, bool)
+ output = internal::sauvola_dispatch(input, window_size, K);
+
+ trace::exiting("scribo::binarization::sauvola");
+ return output;
+ }
+
+
+ template <typename I>
+ mln_ch_value(I, bool)
sauvola(const Image<I>& input, unsigned window_size)
{
trace::entering("scribo::binarization::sauvola");
@@ -169,7 +207,8 @@ namespace scribo
mln_precondition(exact(input).is_valid());
mln_ch_value(I, bool)
- output = internal::sauvola_dispatch(input, window_size);
+ output = internal::sauvola_dispatch(input, window_size,
+ SCRIBO_DEFAULT_SAUVOLA_K);
trace::exiting("scribo::binarization::sauvola");
return output;
diff --git a/scribo/binarization/sauvola_ms.hh b/scribo/binarization/sauvola_ms.hh
index 2717770..6e70e04 100644
--- a/scribo/binarization/sauvola_ms.hh
+++ b/scribo/binarization/sauvola_ms.hh
@@ -54,6 +54,9 @@
# include <mln/extension/adjust.hh>
+// FIXME: to be removed later...
+# include <mln/io/pgm/save.hh>
+
# include <scribo/subsampling/integral_single_image.hh>
# include <scribo/core/macros.hh>
@@ -81,6 +84,7 @@ namespace scribo
\param[in] w_1 The window size used to compute stats.
\param[in] s The scale factor used for the first subscaling.
\param[in] lambda_min_1 Size of the objects kept at scale 1.
+ \param[in] K Sauvola's formulae parameter.
\p w_1 and \p lambda_min_1 are expressed according to the image
@@ -90,6 +94,14 @@ namespace scribo
*/
template <typename I>
mln_ch_value(I,bool)
+ sauvola_ms(const Image<I>& input_1_, unsigned w_1,
+ unsigned s, unsigned lambda_min_1, double K);
+
+ /// \overload
+ /// K is set to 0.34.
+ //
+ template <typename I>
+ mln_ch_value(I,bool)
sauvola_ms(const Image<I>& input_1, unsigned w_1,
unsigned s, unsigned lambda_min_1);
@@ -105,6 +117,11 @@ namespace scribo
using namespace mln;
+
+ // FIXME: to be removed later...
+ char* scale_image_output = 0;
+
+
template <typename V>
V my_find_root(image2d<V>& parent, const V& x)
{
@@ -120,7 +137,8 @@ namespace scribo
unsigned lambda_min, unsigned lambda_max,
unsigned s,
unsigned q, unsigned i, unsigned w,
- const image2d<util::couple<double,double> >& integral_sum_sum_2)
+ const image2d<util::couple<double,double> >& integral_sum_sum_2,
+ double K)
{
typedef image2d<int_u8> I;
typedef point2d P;
@@ -133,15 +151,30 @@ namespace scribo
w_local_h = w_local,
w_local_w = w_local;
+ // Make sure the window fits in the image domain.
+ if (w >= static_cast<const unsigned>(integral_sum_sum_2.ncols()))
+ {
+ w_local_w = std::min(integral_sum_sum_2.ncols(), integral_sum_sum_2.nrows()) - integral_sum_sum_2.border();
+ w_local_h = w_local_w;
+ trace::warning("integral_browsing - Adjusting window width since it was larger than image width.");
+ }
+ if (w_local_h >= static_cast<const unsigned>(integral_sum_sum_2.nrows()))
+ {
+ w_local_h = std::min(integral_sum_sum_2.nrows(), integral_sum_sum_2.ncols()) - integral_sum_sum_2.border();
+ w_local_w = w_local_h;
+ trace::warning("integral_browsing - Adjusting window height since it was larger than image height.");
+ }
+
if (! (w_local % 2))
{
--w_local_w;
++w_local_h;
}
+
// 1st pass
scribo::binarization::internal::first_pass_functor< image2d<int_u8> >
- f(sub);
+ f(sub, K);
scribo::canvas::integral_browsing(integral_sum_sum_2,
ratio,
w_local_w, w_local_h,
@@ -757,7 +790,7 @@ namespace scribo
template <typename I>
mln_ch_value(I,bool)
sauvola_ms(const Image<I>& input_1_, unsigned w_1,
- unsigned s, unsigned lambda_min_1)
+ unsigned s, double K)
{
trace::entering("scribo::binarization::sauvola_ms");
@@ -768,6 +801,8 @@ namespace scribo
dpoint2d none(0, 0);
+ unsigned lambda_min_1 = w_1 / 2;
+
// Number of subscales.
unsigned nb_subscale = 3;
@@ -820,7 +855,7 @@ namespace scribo
// Subsampling to scale 3 and 4.
for (unsigned i = 3; i <= nb_subscale + 1; ++i)
- sub_ima.append(mln::subsampling::antialiased(sub_ima[i - 1], q, none,
+ sub_ima.append(mln::subsampling::antialiased(sub_ima[i - 1], q,
sub_domains[i].first(),
sub_domains[i].second()));
@@ -840,7 +875,8 @@ namespace scribo
mln_max(unsigned),
s,
q, i, w_work,
- integral_sum_sum_2);
+ integral_sum_sum_2,
+ K);
}
// Other scales -> maximum and minimum component size.
@@ -854,7 +890,8 @@ namespace scribo
lambda_max_2 / ratio,
s,
q, i, w_work,
- integral_sum_sum_2);
+ integral_sum_sum_2,
+ K);
}
}
@@ -863,13 +900,17 @@ namespace scribo
t_ima[2] = internal::compute_t_n_and_e_2(sub_ima[2], e_2, 0,
lambda_max_2,
s, 1, 2, w_work,
- integral_sum_sum_2);
+ integral_sum_sum_2,
+ K);
}
// Propagate scale values.
e_2 = transform::influence_zone_geodesic(e_2, c8());
+ // FIXME: Remove or make it better...
+ if (internal::scale_image_output)
+ io::pgm::save(e_2, internal::scale_image_output);
// Binarize
image2d<bool>
@@ -885,7 +926,7 @@ namespace scribo
template <typename I>
mln_ch_value(I,bool)
sauvola_ms_rgb8(const Image<I>& input_1_, unsigned w_1,
- unsigned s, unsigned lambda_min_1)
+ unsigned s, double K)
{
const I& input_1 = exact(input_1_);
@@ -893,54 +934,7 @@ namespace scribo
gima = data::transform(input_1, mln::fun::v2v::rgb_to_int_u<8>());
mln_ch_value(I, bool)
- output = generic::sauvola_ms(gima, w_1, s, lambda_min_1);
-
-
-// typedef mln_ch_value(I,bool) bin_t;
-
-
-// mln_ch_value(I, value::int_u8) r_i, g_i, b_i;
-
-// // Split the rgb8 image into 3 intensity images.
-// mln::data::split(input_1, r_i, g_i, b_i);
-
-// bin_t r_b, g_b, b_b;
-
-// r_b = generic::sauvola_ms(r_i, w_1, s, lambda_min_1);
-// g_b = generic::sauvola_ms(g_i, w_1, s, lambda_min_1);
-// b_b = generic::sauvola_ms(b_i, w_1, s, lambda_min_1);
-
-// border::resize(r_b, input_1.border());
-// border::resize(g_b, input_1.border());
-// border::resize(b_b, input_1.border());
-
-// bin_t output;
-// initialize(output, input_1);
-
-// typedef bool * b_ptr_t;
-// b_ptr_t
-// out_ptr = output.buffer(),
-// r_ptr = r_b.buffer(),
-// g_ptr = g_b.buffer(),
-// b_ptr = b_b.buffer();
-
-// unsigned ntrue;
-// for (unsigned n = 0; n < output.nelements(); ++n)
-// {
-// ntrue = 0;
-// if (*r_ptr)
-// ++ntrue;
-// if (*g_ptr)
-// ++ntrue;
-// if (*b_ptr)
-// ++ntrue;
-
-// *out_ptr++ = ntrue > 1;;
-
-// ++r_ptr;
-// ++g_ptr;
-// ++b_ptr;
-// }
+ output = generic::sauvola_ms(gima, w_1, s, K);
return output;
}
@@ -959,9 +953,9 @@ namespace scribo
mln_ch_value(I,bool)
sauvola_ms_dispatch(const mln_value(I)&,
const Image<I>& input_1, unsigned w_1,
- unsigned s, unsigned lambda_min_1)
+ unsigned s, double K)
{
- return impl::generic::sauvola_ms(input_1, w_1, s, lambda_min_1);
+ return impl::generic::sauvola_ms(input_1, w_1, s, K);
}
@@ -970,19 +964,19 @@ namespace scribo
mln_ch_value(I,bool)
sauvola_ms_dispatch(const value::rgb8&,
const Image<I>& input_1, unsigned w_1,
- unsigned s, unsigned lambda_min_1)
+ unsigned s, double K)
{
- return impl::sauvola_ms_rgb8(input_1, w_1, s, lambda_min_1);
+ return impl::sauvola_ms_rgb8(input_1, w_1, s, K);
}
template <typename I>
mln_ch_value(I,bool)
sauvola_ms_dispatch(const Image<I>& input_1, unsigned w_1,
- unsigned s, unsigned lambda_min_1)
+ unsigned s, double K)
{
typedef mln_value(I) V;
- return sauvola_ms_dispatch(V(), input_1, w_1, s, lambda_min_1);
+ return sauvola_ms_dispatch(V(), input_1, w_1, s, K);
}
@@ -995,20 +989,28 @@ namespace scribo
template <typename I>
mln_ch_value(I,bool)
sauvola_ms(const Image<I>& input_1_, unsigned w_1,
- unsigned s, unsigned lambda_min_1)
+ unsigned s, double K)
{
trace::entering("scribo::binarization::sauvola_ms");
- mln_precondition(input_1.is_valid());
+ mln_precondition(exact(input_1_).is_valid());
mln_ch_value(I,bool)
- output = internal::sauvola_ms_dispatch(input_1_, w_1, s, lambda_min_1);
+ output = internal::sauvola_ms_dispatch(input_1_, w_1, s, K);
trace::exiting("scribo::binarization::sauvola_ms");
return output;
}
+ template <typename I>
+ mln_ch_value(I,bool)
+ sauvola_ms(const Image<I>& input_1, unsigned w_1, unsigned s)
+ {
+ return sauvola_ms(input_1, w_1, s, SCRIBO_DEFAULT_SAUVOLA_K);
+ }
+
+
# endif // ! MLN_INCLUDE_ONLY
diff --git a/scribo/binarization/sauvola_ms_split.hh b/scribo/binarization/sauvola_ms_split.hh
index cba5d94..de8517c 100644
--- a/scribo/binarization/sauvola_ms_split.hh
+++ b/scribo/binarization/sauvola_ms_split.hh
@@ -61,6 +61,7 @@ namespace scribo
\param[in] min_ntrue A site is set to 'True' in the output if it
is set to 'True' at least \p min_ntrue
components. Possible values: 1, 2, 3.
+ \param[in] K Sauvola's formula parameter.
\p w_1 and \p lambda_min_1 are expressed according to the image
at scale 0, i.e. the original size.
@@ -70,16 +71,27 @@ namespace scribo
template <typename I>
mln_ch_value(I, bool)
sauvola_ms_split(const Image<I>& input_1_, unsigned w_1,
+ unsigned s, unsigned lambda_min_1, unsigned min_ntrue,
+ double K);
+
+
+ /// \overload
+ /// K is set to 0.34.
+ template <typename I>
+ mln_ch_value(I, bool)
+ sauvola_ms_split(const Image<I>& input_1_, unsigned w_1,
unsigned s, unsigned lambda_min_1, unsigned min_ntrue);
+
# ifndef MLN_INCLUDE_ONLY
template <typename I>
mln_ch_value(I, bool)
sauvola_ms_split(const Image<I>& input_1_, unsigned w_1,
- unsigned s, unsigned lambda_min_1, unsigned min_ntrue)
+ unsigned s, unsigned lambda_min_1, unsigned min_ntrue,
+ double K)
{
trace::entering("scribo::binarization::sauvola_ms_split");
@@ -97,9 +109,9 @@ namespace scribo
bin_t r_b, g_b, b_b;
- r_b = impl::generic::sauvola_ms(r_i, w_1, s, lambda_min_1);
- g_b = impl::generic::sauvola_ms(g_i, w_1, s, lambda_min_1);
- b_b = impl::generic::sauvola_ms(b_i, w_1, s, lambda_min_1);
+ r_b = impl::generic::sauvola_ms(r_i, w_1, s, lambda_min_1, K);
+ g_b = impl::generic::sauvola_ms(g_i, w_1, s, lambda_min_1, K);
+ b_b = impl::generic::sauvola_ms(b_i, w_1, s, lambda_min_1, K);
border::resize(r_b, input_1.border());
border::resize(g_b, input_1.border());
@@ -138,6 +150,15 @@ namespace scribo
}
+ template <typename I>
+ mln_ch_value(I, bool)
+ sauvola_ms_split(const Image<I>& input_1, unsigned w_1,
+ unsigned s, unsigned lambda_min_1, unsigned min_ntrue)
+ {
+ return sauvola_ms_split(input_1, w_1, s, lambda_min_1, min_ntrue,
+ SCRIBO_DEFAULT_SAUVOLA_K);
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace scribo::binarization
diff --git a/scribo/binarization/sauvola_threshold_image.hh b/scribo/binarization/sauvola_threshold_image.hh
index b5bc72d..88b3842 100644
--- a/scribo/binarization/sauvola_threshold_image.hh
+++ b/scribo/binarization/sauvola_threshold_image.hh
@@ -47,10 +47,24 @@
# include <mln/fun/v2v/rgb_to_int_u.hh>
-# include <mln/debug/println.hh>
-
# include <scribo/core/init_integral_image.hh>
+
+
+// Setup default Sauvola's formulae parameters values.
+// These macros may be used in other variant of Sauvola's algorithm.
+//
+// Values are set according to the following reference: "Automatic
+// Evaluation of Document Binarization Results", Badekas and al, 2005
+//
+// Badekas et al. said 0.34 was best.
+# define SCRIBO_DEFAULT_SAUVOLA_K 0.34
+//
+// 128 is best for grayscale documents.
+# define SCRIBO_DEFAULT_SAUVOLA_R 128
+
+
+
namespace scribo
{
@@ -73,11 +87,18 @@ namespace scribo
template <typename I, typename J>
mln_ch_value(I, value::int_u8)
sauvola_threshold_image(const Image<I>& input, unsigned window_size,
+ double K,
Image<J>& simple,
Image<J>& squared);
+ /// \overload
+ template <typename I>
+ mln_ch_value(I, value::int_u8)
+ sauvola_threshold_image(const Image<I>& input, unsigned window_size,
+ double K);
/// \overload
+ /// K is set to 0.34
template <typename I>
mln_ch_value(I, value::int_u8)
sauvola_threshold_image(const Image<I>& input, unsigned window_size);
@@ -113,9 +134,9 @@ namespace scribo
inline
double
sauvola_threshold_formula(const double m_x_y, const double s_x_y,
- const double k, const double R)
+ const double K, const double R)
{
- return m_x_y * (1.0 + k * ((s_x_y / R) - 1.0));
+ return m_x_y * (1.0 + K * ((s_x_y / R) - 1.0));
}
@@ -125,13 +146,9 @@ namespace scribo
double
sauvola_threshold_formula(double m_x_y, double s_x_y)
{
- // Badekas et al. said 0.34 was best.
- const double k = 0.34;
-
- // 128 is best for grayscale documents.
- const double R = 128;
-
- return sauvola_threshold_formula(m_x_y, s_x_y, k, R);
+ return sauvola_threshold_formula(m_x_y, s_x_y,
+ SCRIBO_DEFAULT_SAUVOLA_K,
+ SCRIBO_DEFAULT_SAUVOLA_R);
}
@@ -155,7 +172,7 @@ namespace scribo
compute_sauvola_threshold(const P& p,
const J& simple,
const J& squared,
- int win_width, double k, double R)
+ int win_width, double K, double R)
{
mln_precondition(simple.nrows() == squared.nrows());
mln_precondition(simple.ncols() == squared.ncols());
@@ -191,7 +208,7 @@ namespace scribo
double s_x_y = std::sqrt((s_x_y_tmp - (m_x_y_tmp * m_x_y_tmp) / wh) / (wh - 1.f));
// Thresholding.
- double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, k, R);
+ double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, K, R);
return t_x_y;
}
@@ -201,7 +218,8 @@ namespace scribo
double
compute_sauvola_threshold_single_image(const P& p,
const J& integral,
- int win_width)
+ int win_width,
+ double K, double R)
{
// Window half width.
int w_2 = win_width >> 1;
@@ -234,7 +252,7 @@ namespace scribo
double s_x_y = std::sqrt((s_x_y_tmp - (m_x_y_tmp * m_x_y_tmp) / wh) / (wh - 1.f));
// Thresholding.
- double t_x_y = m_x_y * (1.0 + 0.34 * ((s_x_y / 128) - 1.0));
+ double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, K, R);
return t_x_y;
}
@@ -248,13 +266,9 @@ namespace scribo
const J& squared,
int win_width)
{
- // Badekas et al. said 0.34 was best.
- const double k = 0.34;
-
- // 128 is best for grayscale documents.
- const double R = 128;
-
- return compute_sauvola_threshold(p, simple, squared, win_width, k, R);
+ return compute_sauvola_threshold(p, simple, squared, win_width,
+ SCRIBO_DEFAULT_SAUVOLA_K,
+ SCRIBO_DEFAULT_SAUVOLA_R);
}
@@ -285,6 +299,7 @@ namespace scribo
inline
mln_concrete(I)
sauvola_threshold_image(const Image<I>& input_, unsigned window_size,
+ double K,
Image<J>& simple_,
Image<J>& squared_)
{
@@ -313,7 +328,9 @@ namespace scribo
for(def::coord col = 0; col < ncols; ++col)
output.at_(row, col)
= internal::compute_sauvola_threshold(P(row, col), simple,
- squared, window_size);
+ squared, window_size,
+ K,
+ SCRIBO_DEFAULT_SAUVOLA_R);
trace::exiting("scribo::binarization::impl::generic::sauvola_threshold");
return output;
@@ -327,10 +344,11 @@ namespace scribo
inline
mln_concrete(I)
sauvola_threshold_image_gl(const I& input, unsigned window_size,
- Image<J>& simple,
- Image<J>& squared)
+ double K,
+ Image<J>& simple,
+ Image<J>& squared)
{
- return impl::generic::sauvola_threshold_image(input, window_size,
+ return impl::generic::sauvola_threshold_image(input, window_size, K,
simple, squared);
}
@@ -339,6 +357,7 @@ namespace scribo
inline
mln_ch_value(I, value::int_u8)
sauvola_threshold_image_rgb8(const I& input, unsigned window_size,
+ double K,
Image<J>& simple,
Image<J>& squared)
{
@@ -350,6 +369,7 @@ namespace scribo
mln_ch_value(I, value::int_u8)
output = impl::generic::sauvola_threshold_image(gima, window_size,
+ K,
simple, squared);
trace::exiting("scribo::binarization::impl::sauvola_threshold_image_rgb8");
@@ -372,10 +392,12 @@ namespace scribo
mln_ch_value(I, value::int_u<n>)
sauvola_threshold_image_dispatch(const value::int_u<n>&, const I& input,
unsigned window_size,
+ double K,
J& simple,
J& squared)
{
- return impl::sauvola_threshold_image_gl(input, window_size, simple, squared);
+ return impl::sauvola_threshold_image_gl(input, window_size, K,
+ simple, squared);
}
template <typename I, typename J>
@@ -383,11 +405,12 @@ namespace scribo
mln_ch_value(I, value::int_u8)
sauvola_threshold_image_dispatch(const value::rgb8&, const I& input,
unsigned window_size,
+ double K,
J& simple,
J& squared)
{
return impl::sauvola_threshold_image_rgb8(input, window_size,
- simple, squared);
+ K, simple, squared);
}
template <typename I, typename J>
@@ -395,6 +418,7 @@ namespace scribo
mln_ch_value(I, value::int_u8)
sauvola_threshold_image_dispatch(const mln_value(I)&, const I& input,
unsigned window_size,
+ double K,
J& simple,
J& squared)
{
@@ -413,37 +437,21 @@ namespace scribo
template <typename I, typename J>
mln_ch_value(I, value::int_u8)
sauvola_threshold_image(const Image<I>& input, unsigned window_size,
- Image<J>& simple,
- Image<J>& squared)
+ double K,
+ Image<J>& simple,
+ Image<J>& squared)
{
trace::entering("scribo::binarization::sauvola_threshold_image");
mln_precondition(mln_site_(I)::dim == 2);
mln_precondition(exact(input).is_valid());
-
-// {
-// J& simple_ = exact(simple);
-// J& squared_ = exact(squared);
-// mln_piter(J) p(simple_.domain());
-// for_all(p)
-// {
-// std::cout << simple_(p) << ", ";
-// }
-// std::cout << std::endl << " ------- " << std::endl;
-// for_all(p)
-// {
-// std::cout << squared_(p) << ", ";
-// }
-// std::cout << std::endl << " ------- " << std::endl;
-// }
-
-
-
typedef mln_value(I) value_t;
mln_ch_value(I, value::int_u8)
- output = internal::sauvola_threshold_image_dispatch(value_t(), exact(input),
+ output = internal::sauvola_threshold_image_dispatch(value_t(),
+ exact(input),
window_size,
+ K,
exact(simple),
exact(squared));
@@ -455,19 +463,25 @@ namespace scribo
template <typename I>
inline
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input, unsigned window_size)
+ sauvola_threshold_image(const Image<I>& input, unsigned window_size,
+ double K)
{
mln_ch_value(I, double)
simple = init_integral_image(input, scribo::internal::identity_),
squared = init_integral_image(input, scribo::internal::square_);
-// debug::println(input);
-// std::cout << "============" << std::endl;
-// // debug::println(simple);
-// // std::cout << "============" << std::endl;
-// // debug::println(squared);
+ return sauvola_threshold_image(input, window_size,
+ K, simple, squared);
+ }
+
- return sauvola_threshold_image(input, window_size, simple, squared);
+ template <typename I>
+ inline
+ mln_ch_value(I, value::int_u8)
+ sauvola_threshold_image(const Image<I>& input, unsigned window_size)
+ {
+ return sauvola_threshold_image(input, window_size,
+ SCRIBO_DEFAULT_SAUVOLA_K);
}
diff --git a/scribo/binarization/sauvola_threshold_image.hh b/scribo/binarization/sauvola_threshold_image_debug.hh
similarity index 55%
copy from scribo/binarization/sauvola_threshold_image.hh
copy to scribo/binarization/sauvola_threshold_image_debug.hh
index b5bc72d..18216a6 100644
--- a/scribo/binarization/sauvola_threshold_image.hh
+++ b/scribo/binarization/sauvola_threshold_image_debug.hh
@@ -24,8 +24,8 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_HH
-# define SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_HH
+#ifndef SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_DEBUG_HH
+# define SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_DEBUG_HH
/// \file
///
@@ -47,9 +47,23 @@
# include <mln/fun/v2v/rgb_to_int_u.hh>
-# include <mln/debug/println.hh>
-
# include <scribo/core/init_integral_image.hh>
+# include <scribo/binarization/sauvola_threshold_image.hh>
+
+
+// Setup default Sauvola's formulae parameters values.
+// These macros may be used in other variant of Sauvola's algorithm.
+//
+// Values are set according to the following reference: "Automatic
+// Evaluation of Document Binarization Results", Badekas and al, 2005
+//
+// Badekas et al. said 0.34 was best.
+# define SCRIBO_DEFAULT_SAUVOLA_K 0.34
+//
+// 128 is best for grayscale documents.
+# define SCRIBO_DEFAULT_SAUVOLA_R 128
+
+
namespace scribo
{
@@ -72,23 +86,16 @@ namespace scribo
*/
template <typename I, typename J>
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input, unsigned window_size,
- Image<J>& simple,
- Image<J>& squared);
-
+ sauvola_threshold_image_debug(const Image<I>& input, unsigned window_size,
+ double K,
+ Image<J>& simple,
+ Image<J>& squared);
/// \overload
template <typename I>
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input, unsigned window_size);
-
-
- /// \overload
- /// The window size is set to 11.
- //
- template <typename I>
- mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input);
+ sauvola_threshold_image_debug(const Image<I>& input, unsigned window_size,
+ double K);
@@ -98,42 +105,8 @@ namespace scribo
namespace internal
{
- /*! \brief compute Sauvola's threshold applying directly the formula.
-
- \param[in] m_x_y Mean value.
- \param[in] s_x_y Standard deviation.
- \param[in] k Control the threshold value in the local
- window. The higher, the lower the threshold
- form the local mean m(x, y).
- \param[in] R Maximum value of the standard deviation (128
- for grayscale documents).
-
- \return A threshold.
- */
- inline
- double
- sauvola_threshold_formula(const double m_x_y, const double s_x_y,
- const double k, const double R)
- {
- return m_x_y * (1.0 + k * ((s_x_y / R) - 1.0));
- }
-
-
- /// \overload
- //
- inline
- double
- sauvola_threshold_formula(double m_x_y, double s_x_y)
- {
- // Badekas et al. said 0.34 was best.
- const double k = 0.34;
-
- // 128 is best for grayscale documents.
- const double R = 128;
-
- return sauvola_threshold_formula(m_x_y, s_x_y, k, R);
- }
-
+ unsigned mean_debug_factor = 1;
+ unsigned stddev_debug_factor = 10;
/*! \brief Compute a point wise threshold according Sauvola's
binarization.
@@ -150,12 +123,13 @@ namespace scribo
\return A threshold.
*/
- template <typename P, typename J>
+ template <typename P, typename I, typename J>
double
compute_sauvola_threshold(const P& p,
+ I& mean, I& stddev,
const J& simple,
const J& squared,
- int win_width, double k, double R)
+ int win_width, double K, double R)
{
mln_precondition(simple.nrows() == squared.nrows());
mln_precondition(simple.ncols() == squared.ncols());
@@ -182,6 +156,8 @@ namespace scribo
double m_x_y = m_x_y_tmp / wh;
+ mean(p) = m_x_y * mean_debug_factor;
+
// Standard deviation.
double s_x_y_tmp = (squared.at_(row_max, col_max)
+ squared.at_(row_min, col_min)
@@ -190,74 +166,15 @@ namespace scribo
double s_x_y = std::sqrt((s_x_y_tmp - (m_x_y_tmp * m_x_y_tmp) / wh) / (wh - 1.f));
- // Thresholding.
- double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, k, R);
-
- return t_x_y;
- }
-
-
- template <typename P, typename J>
- double
- compute_sauvola_threshold_single_image(const P& p,
- const J& integral,
- int win_width)
- {
- // Window half width.
- int w_2 = win_width >> 1;
-
- int row_min = std::max(0, p.row() - w_2);
- int col_min = std::max(0, p.col() - w_2);
-
- int row_max = std::min(static_cast<int>(integral.nrows()) - 1,
- p.row() + w_2);
- int col_max = std::min(static_cast<int>(integral.ncols()) - 1,
- p.col() + w_2);
-
-
- double wh = (row_max - row_min + 1) * (col_max - col_min + 1);
-
- // Mean.
- double m_x_y_tmp = (integral.at_(row_max, col_max).first()
- + integral.at_(row_min, col_min).first()
- - integral.at_(row_max, col_min).first()
- - integral.at_(row_min, col_max).first());
-
- double m_x_y = m_x_y_tmp / wh;
-
- // Standard deviation.
- double s_x_y_tmp = (integral.at_(row_max, col_max).second()
- + integral.at_(row_min, col_min).second()
- - integral.at_(row_max, col_min).second()
- - integral.at_(row_min, col_max).second());
-
- double s_x_y = std::sqrt((s_x_y_tmp - (m_x_y_tmp * m_x_y_tmp) / wh) / (wh - 1.f));
+ stddev(p) = s_x_y * stddev_debug_factor;
// Thresholding.
- double t_x_y = m_x_y * (1.0 + 0.34 * ((s_x_y / 128) - 1.0));
+ double t_x_y = sauvola_threshold_formula(m_x_y, s_x_y, K, R);
return t_x_y;
}
-
- template <typename P, typename J>
- double
- compute_sauvola_threshold(const P& p,
- const J& simple,
- const J& squared,
- int win_width)
- {
- // Badekas et al. said 0.34 was best.
- const double k = 0.34;
-
- // 128 is best for grayscale documents.
- const double R = 128;
-
- return compute_sauvola_threshold(p, simple, squared, win_width, k, R);
- }
-
-
} // end of namespace scribo::binarization::internal
} // end of namespace scribo::binarization
@@ -284,13 +201,18 @@ namespace scribo
template <typename I, typename J>
inline
mln_concrete(I)
- sauvola_threshold_image(const Image<I>& input_, unsigned window_size,
- Image<J>& simple_,
- Image<J>& squared_)
+ sauvola_threshold_image_debug(const Image<I>& input_,
+ unsigned window_size,
+ double K,
+ Image<I>& mean_, Image<I>& stddev_,
+ Image<J>& simple_,
+ Image<J>& squared_)
{
- trace::entering("scribo::binarization::impl::generic::sauvola_threshold_image");
+ trace::entering("scribo::binarization::impl::generic::sauvola_threshold_image_debug");
const I& input = exact(input_);
+ I& mean = exact(mean_);
+ I& stddev = exact(stddev_);
J& simple = exact(simple_);
J& squared = exact(squared_);
@@ -312,8 +234,11 @@ namespace scribo
for(def::coord row = 0; row < nrows; ++row)
for(def::coord col = 0; col < ncols; ++col)
output.at_(row, col)
- = internal::compute_sauvola_threshold(P(row, col), simple,
- squared, window_size);
+ = internal::compute_sauvola_threshold(P(row, col),
+ mean, stddev,
+ simple, squared,
+ window_size, K,
+ SCRIBO_DEFAULT_SAUVOLA_R);
trace::exiting("scribo::binarization::impl::generic::sauvola_threshold");
return output;
@@ -326,33 +251,43 @@ namespace scribo
template <typename I, typename J>
inline
mln_concrete(I)
- sauvola_threshold_image_gl(const I& input, unsigned window_size,
- Image<J>& simple,
- Image<J>& squared)
+ sauvola_threshold_image_debug_gl(const Image<I>& input,
+ unsigned window_size,
+ double K,
+ Image<I>& mean, Image<I>& stddev,
+ Image<J>& simple,
+ Image<J>& squared)
{
- return impl::generic::sauvola_threshold_image(input, window_size,
- simple, squared);
+ return impl::generic::sauvola_threshold_image_debug(input, window_size,
+ K,
+ mean, stddev,
+ simple, squared);
}
template <typename I, typename J>
inline
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image_rgb8(const I& input, unsigned window_size,
- Image<J>& simple,
- Image<J>& squared)
+ sauvola_threshold_image_debug_rgb8(const Image<I>& input,
+ unsigned window_size,
+ double K,
+ Image<I>& mean, Image<I>& stddev,
+ Image<J>& simple,
+ Image<J>& squared)
{
- trace::entering("scribo::binarization::impl::sauvola_threshold_image_rgb8");
+ trace::entering("scribo::binarization::impl::sauvola_threshold_image_debug_rgb8");
mln_ch_value(I, value::int_u8) gima;
gima = data::transform(input,
mln::fun::v2v::rgb_to_int_u<8>());
mln_ch_value(I, value::int_u8)
- output = impl::generic::sauvola_threshold_image(gima, window_size,
- simple, squared);
+ output = impl::generic::sauvola_threshold_image_debug(gima, window_size,
+ K,
+ mean, stddev,
+ simple, squared);
- trace::exiting("scribo::binarization::impl::sauvola_threshold_image_rgb8");
+ trace::exiting("scribo::binarization::impl::sauvola_threshold_image_debug_rgb8");
return output;
}
@@ -370,33 +305,43 @@ namespace scribo
template <unsigned n, typename I, typename J>
inline
mln_ch_value(I, value::int_u<n>)
- sauvola_threshold_image_dispatch(const value::int_u<n>&, const I& input,
- unsigned window_size,
- J& simple,
- J& squared)
+ sauvola_threshold_image_debug_dispatch(const value::int_u<n>&,
+ const I& input,
+ unsigned window_size,
+ double K,
+ I& mean, I& stddev,
+ J& simple,
+ J& squared)
{
- return impl::sauvola_threshold_image_gl(input, window_size, simple, squared);
+ return impl::sauvola_threshold_image_debug_gl(input, window_size, K,
+ mean, stddev,
+ simple, squared);
}
template <typename I, typename J>
inline
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image_dispatch(const value::rgb8&, const I& input,
- unsigned window_size,
- J& simple,
- J& squared)
+ sauvola_threshold_image_debug_dispatch(const value::rgb8&, const I& input,
+ unsigned window_size,
+ double K,
+ I& mean, I& stddev,
+ J& simple,
+ J& squared)
{
- return impl::sauvola_threshold_image_rgb8(input, window_size,
- simple, squared);
+ return impl::sauvola_threshold_image_debug_rgb8(input, window_size,
+ K, mean, stddev,
+ simple, squared);
}
template <typename I, typename J>
inline
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image_dispatch(const mln_value(I)&, const I& input,
- unsigned window_size,
- J& simple,
- J& squared)
+ sauvola_threshold_image_debug_dispatch(const mln_value(I)&, const I& input,
+ I& mean, I& stddev,
+ unsigned window_size,
+ double K,
+ J& simple,
+ J& squared)
{
// No dispatch for this kind of value type.
mlc_abort(I)::check();
@@ -412,40 +357,27 @@ namespace scribo
template <typename I, typename J>
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input, unsigned window_size,
- Image<J>& simple,
- Image<J>& squared)
+ sauvola_threshold_image_debug(const Image<I>& input, unsigned window_size,
+ double K,
+ Image<I>& mean, Image<I>& stddev,
+ Image<J>& simple,
+ Image<J>& squared)
{
- trace::entering("scribo::binarization::sauvola_threshold_image");
+ trace::entering("scribo::binarization::sauvola_threshold_image_debug");
mln_precondition(mln_site_(I)::dim == 2);
mln_precondition(exact(input).is_valid());
-
-// {
-// J& simple_ = exact(simple);
-// J& squared_ = exact(squared);
-// mln_piter(J) p(simple_.domain());
-// for_all(p)
-// {
-// std::cout << simple_(p) << ", ";
-// }
-// std::cout << std::endl << " ------- " << std::endl;
-// for_all(p)
-// {
-// std::cout << squared_(p) << ", ";
-// }
-// std::cout << std::endl << " ------- " << std::endl;
-// }
-
-
-
typedef mln_value(I) value_t;
mln_ch_value(I, value::int_u8)
- output = internal::sauvola_threshold_image_dispatch(value_t(), exact(input),
- window_size,
- exact(simple),
- exact(squared));
+ output = internal::sauvola_threshold_image_debug_dispatch(value_t(),
+ exact(input),
+ window_size,
+ K,
+ exact(mean),
+ exact(stddev),
+ exact(simple),
+ exact(squared));
trace::exiting("scribo::text::ppm2pbm");
return output;
@@ -455,28 +387,17 @@ namespace scribo
template <typename I>
inline
mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input, unsigned window_size)
+ sauvola_threshold_image_debug(const Image<I>& input, unsigned window_size,
+ double K,
+ Image<I>& mean, Image<I>& stddev)
{
mln_ch_value(I, double)
simple = init_integral_image(input, scribo::internal::identity_),
squared = init_integral_image(input, scribo::internal::square_);
-// debug::println(input);
-// std::cout << "============" << std::endl;
-// // debug::println(simple);
-// // std::cout << "============" << std::endl;
-// // debug::println(squared);
-
- return sauvola_threshold_image(input, window_size, simple, squared);
- }
-
-
- template <typename I>
- inline
- mln_ch_value(I, value::int_u8)
- sauvola_threshold_image(const Image<I>& input)
- {
- return sauvola_threshold_image(input, 11);
+ return sauvola_threshold_image_debug(input, window_size, K,
+ mean, stddev,
+ simple, squared);
}
@@ -487,4 +408,4 @@ namespace scribo
} // end of namespace scribo
-#endif // ! SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_HH
+#endif // ! SCRIBO_BINARIZATION_SAUVOLA_THRESHOLD_IMAGE_DEBUG_HH
diff --git a/scribo/canvas/integral_browsing.hh b/scribo/canvas/integral_browsing.hh
index 45ff38d..4e55109 100644
--- a/scribo/canvas/integral_browsing.hh
+++ b/scribo/canvas/integral_browsing.hh
@@ -127,19 +127,6 @@ namespace scribo
unsigned s_2 = s * s;
- // Make sure the window fits in the image domain.
- if (w >= static_cast<const unsigned>(ncols))
- {
- w = ncols - 1;
- trace::warning("integral_browsing - Adjusting window width since it was larger than image width.");
- }
- if (h >= static_cast<const unsigned>(nrows))
- {
- h = nrows - 1;
- trace::warning("integral_browsing - Adjusting window height since it was larger than image height.");
- }
-
-
// -------------------------------
// T (top)
// -------------------------------
diff --git a/scribo/debug/usage.hh b/scribo/debug/usage.hh
index 6b6c9b7..2c6fa48 100644
--- a/scribo/debug/usage.hh
+++ b/scribo/debug/usage.hh
@@ -26,6 +26,7 @@
#ifndef SCRIBO_DEBUG_USAGE_HH
# define SCRIBO_DEBUG_USAGE_HH
+#include <libgen.h>
#include <iostream>
namespace scribo
@@ -45,7 +46,7 @@ namespace scribo
/// \return Return 1.
//
int usage(char* argv[], const char *desc, const char* args,
- const char*args_desc[][2], const char *out_desc);
+ const char*args_desc[][2]);
# ifndef MLN_INCLUDE_ONLY
@@ -53,21 +54,21 @@ namespace scribo
inline
int
usage(char* argv[], const char *desc, const char* args,
- const char*args_desc[][2], const char *out_desc = 0)
+ const char*args_desc[][2])
{
- std::cout << "Usage: " << argv[0] << " " << args
+ std::cout << "Usage: " << basename(argv[0]) << " " << args
<< std::endl
<< std::endl;
std::cout << "-----------" << std::endl;
std::cout << desc << std::endl
- << std::endl;
+ << std::endl;
for (unsigned i = 0; args_desc[i][0] != 0; ++i)
std::cout << " " << args_desc[i][0] << ": " << args_desc[i][1]
<< std::endl;
- if (out_desc)
- std::cout << std::endl << "Output: " << out_desc << std::endl;
+// if (out_desc)
+// std::cout << std::endl << "Output: " << out_desc << std::endl;
std::cout << "-----------" << std::endl;
std::cout << "EPITA/LRDE - Scribo 2009" << std::endl;
diff --git a/scribo/src/binarization/ppm_fg_sauvola_ms.cc b/scribo/src/binarization/fg_sauvola_ms.cc
similarity index 87%
copy from scribo/src/binarization/ppm_fg_sauvola_ms.cc
copy to scribo/src/binarization/fg_sauvola_ms.cc
index 5f45470..9c606d6 100644
--- a/scribo/src/binarization/ppm_fg_sauvola_ms.cc
+++ b/scribo/src/binarization/fg_sauvola_ms.cc
@@ -26,7 +26,7 @@
#include <mln/core/image/image2d.hh>
#include <mln/value/rgb8.hh>
-#include <mln/io/ppm/load.hh>
+#include <mln/io/magick/load.hh>
#include <mln/io/pbm/save.hh>
#include <scribo/binarization/sauvola_ms.hh>
@@ -53,7 +53,8 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
- { "input.ppm", "A color image." },
+ { "input.*", "An image." },
+ { "output.pbm", "A binary image." },
{ "lambda", "Lambda used to split bg/fg." },
{ "w", "Window size at scale 1. (Common value: 101)" },
{ "s", "First subsampling ratio (Common value: 3)." },
@@ -71,9 +72,9 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
- "Multi-Scale Binarization of a color image based on Sauvola's algorithm. Performs a binarization on each component of the color image and merges the results.",
- "input.ppm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "Multi-Scale Binarization based on Sauvola's algorithm. Performs a binarization on each component of the color image and merges the results.",
+ "input.* output.pbm w s area_threshold",
+ args_desc);
trace::entering("main");
@@ -90,13 +91,13 @@ int main(int argc, char *argv[])
image2d<value::rgb8> input_1;
- io::ppm::load(input_1, argv[1]);
+ io::magick::load(input_1, argv[1]);
image2d<value::rgb8>
fg = scribo::preprocessing::split_bg_fg(input_1, lambda, 32).first();
image2d<bool>
- output = scribo::binarization::sauvola_ms(fg, w_1, s, lambda_min_1);
+ output = scribo::binarization::sauvola_ms(fg, w_1, s, lambda_min_1, SCRIBO_DEFAULT_SAUVOLA_K);
io::pbm::save(output, argv[6]);
}
diff --git a/scribo/src/binarization/pgm_global_threshold_auto.cc b/scribo/src/binarization/pgm_global_threshold_auto.cc
index 7f1dacf..568eba2 100644
--- a/scribo/src/binarization/pgm_global_threshold_auto.cc
+++ b/scribo/src/binarization/pgm_global_threshold_auto.cc
@@ -33,6 +33,7 @@
const char *args_desc[][2] =
{
{ "input.pgm", "A gray level image." },
+ { "output.pbm", "A binary image." },
{0, 0}
};
@@ -46,7 +47,7 @@ int main(int argc, char *argv[])
return scribo::debug::usage(argv,
"Binarization of a gray-level image using an automatic global threshold.",
"input.pgm output.pbm",
- args_desc, "A binary image.");
+ args_desc);
trace::entering("main");
diff --git a/scribo/src/binarization/pgm_sauvola.cc b/scribo/src/binarization/pgm_sauvola.cc
index 843c355..c6ba643 100644
--- a/scribo/src/binarization/pgm_sauvola.cc
+++ b/scribo/src/binarization/pgm_sauvola.cc
@@ -33,7 +33,9 @@
const char *args_desc[][2] =
{
{ "input.pgm", "A gray level image." },
- { "w", "Window size." },
+ { "output.pbm", "A binary image." },
+ { "w", "Window size (default 51)." },
+ { "k", "Sauvola's formulae parameter (default 0.34)." },
{0, 0}
};
@@ -43,23 +45,35 @@ int main(int argc, char *argv[])
using namespace mln;
using value::int_u8;
- if (argc != 4)
+ if (argc != 5 && argc != 4 && argc != 3)
return scribo::debug::usage(argv,
"Binarization of a gray level image based on Sauvola's algorithm.",
- "input.pgm w output.pbm",
- args_desc, "A binary image.");
+ "input.pgm output.pbm <w> <k>",
+ args_desc);
trace::entering("main");
- unsigned w = atoi(argv[2]);
+ unsigned w;
+ if (argc == 4)
+ w = atoi(argv[3]);
+ else
+ w = 51;
+
+ double k;
+ if (argc == 5)
+ k = atof(argv[4]);
+ else
+ k = 0.34f;
+
+ std::cout << "Using w=" << w << " and k=" << k << std::endl;
image2d<int_u8> input;
io::pgm::load(input, argv[1]);
- image2d<bool> out = scribo::binarization::sauvola(input, w);
+ image2d<bool> out = scribo::binarization::sauvola(input, w, k);
- io::pbm::save(out, argv[3]);
+ io::pbm::save(out, argv[2]);
trace::exiting("main");
diff --git a/scribo/src/binarization/pgm_sauvola_ms.cc b/scribo/src/binarization/pgm_sauvola_ms.cc
index d446c3e..fefdd6a 100644
--- a/scribo/src/binarization/pgm_sauvola_ms.cc
+++ b/scribo/src/binarization/pgm_sauvola_ms.cc
@@ -34,16 +34,19 @@
bool check_args(int argc, char * argv[])
{
- if (argc < 5 || argc > 6)
+ if (argc < 3 || argc > 6)
return false;
- int s = atoi(argv[3]);
-
- if (s < 1 || s > 3)
+ if (argc >= 5)
{
- std::cout << "s must be set to 2 or 3."
- << std::endl;
- return false;
+ int s = atoi(argv[4]);
+
+ if (s < 1 || s > 3)
+ {
+ std::cout << "s must be set to 2 or 3."
+ << std::endl;
+ return false;
+ }
}
return true;
@@ -53,9 +56,10 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
{ "input.pgm", "A graylevel image." },
- { "w", "Window size at scale 1. (Common value: 101)" },
- { "s", "First subsampling ratio (Common value: 3)." },
- { "min_area", "Minimum object area at scale 1 (Common value: 67)" },
+ { "out.pbm", "A binary image." },
+ { "w", "Window size at scale 1. (default: 101)" },
+ { "s", "First subsampling ratio (default: 3)." },
+ { "k", "Sauvola's formuale parameter (default: 0.34)" },
{0, 0}
};
@@ -70,28 +74,43 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
"Multi-Scale Binarization of a color image based on Sauvola's algorithm.",
- "input.pgm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "input.pgm output.pbm <w> <s> <k>",
+ args_desc);
trace::entering("main");
// Window size
- unsigned w_1 = atoi(argv[2]); // Scale 1
+ unsigned w_1;
+ if (argc >= 4)
+ w_1 = atoi(argv[3]); // Scale 1
+ else
+ w_1 = 101u;
// First subsampling scale.
- unsigned s = atoi(argv[3]);
+ unsigned s;
+ if (argc >= 5)
+ s = atoi(argv[4]);
+ else
+ s = 3u;
// Lambda value
- unsigned lambda_min_1 = atoi(argv[4]);
+ unsigned lambda_min_1 = 67; // FIXME: should be adapted to the
+ // window size.
+ double k;
+ if (argc >= 6)
+ k = atof(argv[5]);
+ else
+ k = 0.34f;
image2d<value::int_u8> input_1;
io::pgm::load(input_1, argv[1]);
image2d<bool>
- output = scribo::binarization::sauvola_ms(input_1, w_1, s, lambda_min_1);
+ output = scribo::binarization::sauvola_ms(input_1, w_1, s,
+ lambda_min_1, k);
- io::pbm::save(output, argv[5]);
+ io::pbm::save(output, argv[2]);
}
diff --git a/scribo/src/binarization/ppm_fg_sauvola_ms.cc b/scribo/src/binarization/ppm_fg_sauvola_ms.cc
index 5f45470..65e8621 100644
--- a/scribo/src/binarization/ppm_fg_sauvola_ms.cc
+++ b/scribo/src/binarization/ppm_fg_sauvola_ms.cc
@@ -35,16 +35,19 @@
bool check_args(int argc, char * argv[])
{
- if (argc != 7)
+ if (argc < 3 || argc > 7)
return false;
- int s = atoi(argv[4]);
-
- if (s < 2 || s > 3)
+ if (argc >= 6)
{
- std::cout << "s must be set to 2 or 3."
- << std::endl;
- return false;
+ int s = atoi(argv[5]);
+
+ if (s < 2 || s > 3)
+ {
+ std::cout << "s must be set to 2 or 3."
+ << std::endl;
+ return false;
+ }
}
return true;
@@ -54,10 +57,11 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
{ "input.ppm", "A color image." },
+ { "output.pbm", "A binary image." },
{ "lambda", "Lambda used to split bg/fg." },
- { "w", "Window size at scale 1. (Common value: 101)" },
- { "s", "First subsampling ratio (Common value: 3)." },
- { "min_area", "Minimum object area at scale 1 (Common value: 67)" },
+ { "w", "Window size at scale 1. (default: 101)" },
+ { "s", "First subsampling ratio. (default: 3)" },
+ { "k", "Sauvola's formula parameter. (default: 0.34)" },
{0, 0}
};
@@ -72,33 +76,49 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
"Multi-Scale Binarization of a color image based on Sauvola's algorithm. Performs a binarization on each component of the color image and merges the results.",
- "input.ppm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "input.ppm output.pbm lambda <w> <s> <k>",
+ args_desc);
trace::entering("main");
- unsigned lambda = atoi(argv[2]);
+ unsigned lambda = atoi(argv[3]);
// Window size
- unsigned w_1 = atoi(argv[3]); // Scale 1
+ unsigned w_1;
+ if (argc >= 5)
+ w_1 = atoi(argv[4]); // Scale 1
+ else
+ w_1 = 101u;
// First subsampling scale.
- unsigned s = atoi(argv[4]);
+ unsigned s;
+ if (argc >= 6)
+ s = atoi(argv[5]);
+ else
+ s = 3u;
// Lambda value
- unsigned lambda_min_1 = atoi(argv[5]);
+ unsigned lambda_min_1 = 67; // FIXME: should be adapted to the
+ // window size.
+
+ double k;
+ if (argc >= 7)
+ k = atof(argv[6]);
+ else
+ k = 0.34f;
+
image2d<value::rgb8> input_1;
io::ppm::load(input_1, argv[1]);
image2d<value::rgb8>
- fg = scribo::preprocessing::split_bg_fg(input_1, lambda, 32).first();
+ fg = scribo::preprocessing::split_bg_fg(input_1, lambda, 32).second();
image2d<bool>
- output = scribo::binarization::sauvola_ms(fg, w_1, s, lambda_min_1);
+ output = scribo::binarization::sauvola_ms(fg, w_1, s, lambda_min_1, k);
- io::pbm::save(output, argv[6]);
+ io::pbm::save(output, argv[2]);
}
diff --git a/scribo/src/binarization/ppm_sauvola.cc b/scribo/src/binarization/ppm_sauvola.cc
index c3ce28a..0b798ae 100644
--- a/scribo/src/binarization/ppm_sauvola.cc
+++ b/scribo/src/binarization/ppm_sauvola.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of Olena.
//
@@ -25,7 +26,6 @@
#include <mln/io/ppm/load.hh>
#include <mln/io/pbm/save.hh>
-#include <mln/value/rgb8.hh>
#include <scribo/binarization/sauvola.hh>
#include <scribo/debug/usage.hh>
@@ -33,7 +33,9 @@
const char *args_desc[][2] =
{
{ "input.ppm", "A color image." },
- { "wsize", "Window size (Common value: 51)." },
+ { "output.pbm", "A binary image." },
+ { "w", "Window size (default 51)." },
+ { "k", "Sauvola's formulae parameter (default 0.34)." },
{0, 0}
};
@@ -41,20 +43,36 @@ const char *args_desc[][2] =
int main(int argc, char *argv[])
{
using namespace mln;
- using value::rgb8;
- if (argc != 4)
+ if (argc != 5 && argc != 4 && argc != 3)
return scribo::debug::usage(argv,
- "Binarization of a color image based on Sauvola's algorithm. First convert the color image to an intensity image and then run Sauvola.",
- "input.ppm wsize output.pbm",
- args_desc, "A binary image.");
+ "Binarization of a gray level image based on Sauvola's algorithm.",
+ "input.ppm output.pbm <w> <k>",
+ args_desc);
trace::entering("main");
- image2d<rgb8> input;
+ unsigned w;
+ if (argc == 4)
+ w = atoi(argv[3]);
+ else
+ w = 51;
+
+ double k;
+ if (argc == 5)
+ k = atof(argv[4]);
+ else
+ k = 0.34f;
+
+ std::cout << "Using w=" << w << " and k=" << k << std::endl;
+
+ image2d<value::rgb8> input;
io::ppm::load(input, argv[1]);
- io::pbm::save(scribo::binarization::sauvola(input, atoi(argv[2])), argv[3]);
+ image2d<bool> out = scribo::binarization::sauvola(input, w, k);
+
+
+ io::pbm::save(out, argv[2]);
trace::exiting("main");
diff --git a/scribo/src/binarization/ppm_sauvola_ms.cc b/scribo/src/binarization/ppm_sauvola_ms.cc
index d8c1c9c..f2cbb6f 100644
--- a/scribo/src/binarization/ppm_sauvola_ms.cc
+++ b/scribo/src/binarization/ppm_sauvola_ms.cc
@@ -25,7 +25,7 @@
// executable file might be covered by the GNU General Public License.
#include <mln/core/image/image2d.hh>
-#include <mln/value/rgb8.hh>
+#include <mln/value/int_u8.hh>
#include <mln/io/ppm/load.hh>
#include <mln/io/pbm/save.hh>
@@ -34,16 +34,19 @@
bool check_args(int argc, char * argv[])
{
- if (argc < 5 || argc > 6)
+ if (argc < 3 || argc > 6)
return false;
- int s = atoi(argv[3]);
-
- if (s < 2 || s > 3)
+ if (argc >= 5)
{
- std::cout << "s must be set to 2 or 3."
- << std::endl;
- return false;
+ int s = atoi(argv[4]);
+
+ if (s < 1 || s > 3)
+ {
+ std::cout << "s must be set to 2 or 3."
+ << std::endl;
+ return false;
+ }
}
return true;
@@ -53,9 +56,10 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
{ "input.ppm", "A color image." },
- { "w", "Window size at scale 1. (Common value: 101)" },
- { "s", "First subsampling ratio (Common value: 3)." },
- { "min_area", "Minimum object area at scale 1 (Common value: 67)" },
+ { "out.pbm", "A binary image." },
+ { "w", "Window size at scale 1. (default: 101)" },
+ { "s", "First subsampling ratio (default: 3)." },
+ { "k", "Sauvola's formuale parameter (default: 0.34)" },
{0, 0}
};
@@ -69,29 +73,44 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
- "Multi-Scale Binarization of a color image based on Sauvola's algorithm. Performs a binarization on each component of the color image and merges the results.",
- "input.ppm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "Multi-Scale Binarization of a color image based on Sauvola's algorithm.",
+ "input.ppm output.pbm <w> <s> <k>",
+ args_desc);
trace::entering("main");
// Window size
- unsigned w_1 = atoi(argv[2]); // Scale 1
+ unsigned w_1;
+ if (argc >= 4)
+ w_1 = atoi(argv[3]); // Scale 1
+ else
+ w_1 = 101u;
// First subsampling scale.
- unsigned s = atoi(argv[3]);
+ unsigned s;
+ if (argc >= 5)
+ s = atoi(argv[4]);
+ else
+ s = 3u;
// Lambda value
- unsigned lambda_min_1 = atoi(argv[4]);
+ unsigned lambda_min_1 = 67; // FIXME: should be adapted to the
+ // window size.
+ double k;
+ if (argc >= 6)
+ k = atof(argv[5]);
+ else
+ k = 0.34f;
image2d<value::rgb8> input_1;
io::ppm::load(input_1, argv[1]);
image2d<bool>
- output = scribo::binarization::sauvola_ms(input_1, w_1, s, lambda_min_1);
+ output = scribo::binarization::sauvola_ms(input_1, w_1, s,
+ lambda_min_1, k);
- io::pbm::save(output, argv[5]);
+ io::pbm::save(output, argv[2]);
}
diff --git a/scribo/src/binarization/ppm_sauvola_ms_split.cc b/scribo/src/binarization/ppm_sauvola_ms_split.cc
index 3f721db..b1f10ea 100644
--- a/scribo/src/binarization/ppm_sauvola_ms_split.cc
+++ b/scribo/src/binarization/ppm_sauvola_ms_split.cc
@@ -34,16 +34,19 @@
bool check_args(int argc, char * argv[])
{
- if (argc != 7)
+ if (argc < 3 || argc > 7)
return false;
- int s = atoi(argv[3]);
-
- if (s < 1 || s > 3)
+ if (argc >= 5)
{
- std::cout << "s must be set to 2 or 3."
- << std::endl;
- return false;
+ int s = atoi(argv[4]);
+
+ if (s < 1 || s > 3)
+ {
+ std::cout << "s must be set to 2 or 3."
+ << std::endl;
+ return false;
+ }
}
return true;
@@ -53,10 +56,11 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
{ "input.ppm", "A color image." },
- { "w", "Window size at scale 1. (Common value: 101)" },
- { "s", "First subsampling ratio (Common value: 3)." },
- { "min_area", "Minimum object area at scale 1 (Common value: 67)" },
- { "min_ntrue", "The number of components in which a site must be set to 'True' in order to be set to 'True' in the output (Possible values: 1, 2, 3). (Common value: 2)" },
+ { "output.pbm", "A binary image." },
+ { "w", "Window size at scale 1. (default: 101)" },
+ { "s", "First subsampling ratio (default: 3)." },
+ { "min_ntrue", "The number of components in which a site must be set to 'True' in order to be set to 'True' in the output (Possible values: 1, 2, 3). (default: 2)" },
+ { "K", "Sauvola's formula parameter (default: 0.34)." },
{0, 0}
};
@@ -71,28 +75,53 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
"Multi-Scale Binarization of a color image based on Sauvola's algorithm. Performs a binarization on each component of the color image and merges the results.",
- "input.ppm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "input.ppm output.pbm <w> <s> <min_ntrue> <K>",
+ args_desc);
trace::entering("main");
// Window size
- unsigned w_1 = atoi(argv[2]); // Scale 1
+ unsigned w_1;
+ if (argc >= 4)
+ w_1 = atoi(argv[3]); // Scale 1
+ else
+ w_1 = 101u;
// First subsampling scale.
- unsigned s = atoi(argv[3]);
+ unsigned s;
+ if (argc >= 5)
+ s = atoi(argv[4]);
+ else
+ s = 3u;
+
+ // min_ntrue
+ unsigned min_ntrue;
+ if (argc >= 6)
+ min_ntrue = atoi(argv[5]);
+ else
+ min_ntrue = 2;
// Lambda value
- unsigned lambda_min_1 = atoi(argv[4]);
+ unsigned lambda_min_1 = 67; // FIXME: should be adapted to the
+ // window size.
+
+ double k;
+ if (argc >= 7)
+ k = atof(argv[6]);
+ else
+ k = 0.34f;
+
image2d<value::rgb8> input_1;
io::ppm::load(input_1, argv[1]);
+ std::cout << "Using w=" << w_1 << " - s=" << s << " - min_ntrue=" << min_ntrue << " - k=" << k << std::endl;
+
image2d<bool>
- output = scribo::binarization::sauvola_ms_split(input_1, w_1, s, lambda_min_1, atoi(argv[5]));
+ output = scribo::binarization::sauvola_ms_split(input_1, w_1, s, lambda_min_1, min_ntrue, k);
- io::pbm::save(output, argv[6]);
+ io::pbm::save(output, argv[2]);
}
diff --git a/scribo/src/binarization/pgm_sauvola.cc b/scribo/src/binarization/sauvola.cc
similarity index 68%
copy from scribo/src/binarization/pgm_sauvola.cc
copy to scribo/src/binarization/sauvola.cc
index 843c355..fb07b0d 100644
--- a/scribo/src/binarization/pgm_sauvola.cc
+++ b/scribo/src/binarization/sauvola.cc
@@ -24,7 +24,7 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#include <mln/io/pgm/load.hh>
+#include <mln/io/magick/load.hh>
#include <mln/io/pbm/save.hh>
#include <scribo/binarization/sauvola.hh>
@@ -32,8 +32,10 @@
const char *args_desc[][2] =
{
- { "input.pgm", "A gray level image." },
- { "w", "Window size." },
+ { "input.*", "An image." },
+ { "output.pbm", "A binary image." },
+ { "w", "Window size (default 51)." },
+ { "k", "Sauvola's formulae parameter (default 0.34)." },
{0, 0}
};
@@ -41,25 +43,36 @@ const char *args_desc[][2] =
int main(int argc, char *argv[])
{
using namespace mln;
- using value::int_u8;
- if (argc != 4)
+ if (argc != 5 && argc != 4 && argc != 3)
return scribo::debug::usage(argv,
- "Binarization of a gray level image based on Sauvola's algorithm.",
- "input.pgm w output.pbm",
- args_desc, "A binary image.");
+ "Binarization based on Sauvola's algorithm.",
+ "input.* output.pbm <w> <k>",
+ args_desc);
trace::entering("main");
- unsigned w = atoi(argv[2]);
+ unsigned w;
+ if (argc >= 4)
+ w = atoi(argv[3]);
+ else
+ w = 51;
- image2d<int_u8> input;
- io::pgm::load(input, argv[1]);
+ double k;
+ if (argc >= 5)
+ k = atof(argv[4]);
+ else
+ k = 0.34f;
- image2d<bool> out = scribo::binarization::sauvola(input, w);
+ std::cout << "Using w=" << w << " and k=" << k << std::endl;
+ image2d<value::rgb8> input;
+ io::magick::load(input, argv[1]);
- io::pbm::save(out, argv[3]);
+ image2d<bool> out = scribo::binarization::sauvola(input, w, k);
+
+
+ io::pbm::save(out, argv[2]);
trace::exiting("main");
diff --git a/scribo/src/binarization/sauvola_debug.cc b/scribo/src/binarization/sauvola_debug.cc
new file mode 100644
index 0000000..8bbc19c
--- /dev/null
+++ b/scribo/src/binarization/sauvola_debug.cc
@@ -0,0 +1,105 @@
+// Copyright (C) 2009, 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.
+
+#include <mln/io/magick/load.hh>
+#include <mln/io/pbm/save.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <scribo/binarization/local_threshold.hh>
+#include <scribo/binarization/sauvola_threshold_image_debug.hh>
+#include <scribo/debug/usage.hh>
+
+const char *args_desc[][2] =
+{
+ { "input.*", "An image." },
+ { "output.pbm", "A binary image." },
+ { "mean.pgm", "The local mean image." },
+ { "stddev.pgm", "The local standard deviation image." },
+ { "mean_factor", "Mean value factor (default 1)." },
+ { "stddev_factor", "Standard deviation value factor (default 10)." },
+ { "w", "Window size (default 51)." },
+ { "k", "Sauvola's formulae parameter (default 0.34)." },
+ {0, 0}
+};
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using namespace scribo::binarization;
+
+ if (argc < 5 || argc >= 9)
+ return scribo::debug::usage(argv,
+ "Binarization based on Sauvola's algorithm.",
+ "input.* output.pbm mean.pgm stddev.pgm <mean_factor> <stddev_factor> <w> <k>",
+ args_desc);
+
+ trace::entering("main");
+
+ unsigned w;
+ if (argc >= 8)
+ w = atoi(argv[7]);
+ else
+ w = 51;
+
+ double k;
+ if (argc >= 9)
+ k = atof(argv[8]);
+ else
+ k = 0.34f;
+
+ std::cout << "Using w=" << w << " and k=" << k << std::endl;
+
+ if (argc >= 6)
+ scribo::binarization::internal::mean_debug_factor = atoi(argv[5]);
+ if (argc >= 7)
+ scribo::binarization::internal::stddev_debug_factor = atoi(argv[6]);
+
+ image2d<value::rgb8> input;
+ io::magick::load(input, argv[1]);
+
+
+ image2d<value::int_u8> mean, stddev;
+ initialize(mean, input);
+ initialize(stddev, input);
+
+ image2d<value::int_u8>
+ gima = data::transform(input,
+ mln::fun::v2v::rgb_to_int_u<8>());
+
+
+ image2d<bool>
+ out = local_threshold(gima,
+ sauvola_threshold_image_debug(gima, w, k,
+ mean, stddev));
+
+
+ io::pbm::save(out, argv[2]);
+ io::pgm::save(mean, argv[3]);
+ io::pgm::save(stddev, argv[4]);
+
+ trace::exiting("main");
+}
diff --git a/scribo/src/binarization/ppm_sauvola_ms.cc b/scribo/src/binarization/sauvola_ms.cc
similarity index 61%
copy from scribo/src/binarization/ppm_sauvola_ms.cc
copy to scribo/src/binarization/sauvola_ms.cc
index d8c1c9c..3983793 100644
--- a/scribo/src/binarization/ppm_sauvola_ms.cc
+++ b/scribo/src/binarization/sauvola_ms.cc
@@ -25,8 +25,8 @@
// executable file might be covered by the GNU General Public License.
#include <mln/core/image/image2d.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/io/ppm/load.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/magick/load.hh>
#include <mln/io/pbm/save.hh>
#include <scribo/binarization/sauvola_ms.hh>
@@ -34,16 +34,19 @@
bool check_args(int argc, char * argv[])
{
- if (argc < 5 || argc > 6)
+ if (argc < 3 || argc > 7)
return false;
- int s = atoi(argv[3]);
-
- if (s < 2 || s > 3)
+ if (argc >= 5)
{
- std::cout << "s must be set to 2 or 3."
- << std::endl;
- return false;
+ int s = atoi(argv[4]);
+
+ if (s < 1 || s > 3)
+ {
+ std::cout << "s must be set to 2 or 3."
+ << std::endl;
+ return false;
+ }
}
return true;
@@ -52,10 +55,12 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
- { "input.ppm", "A color image." },
- { "w", "Window size at scale 1. (Common value: 101)" },
- { "s", "First subsampling ratio (Common value: 3)." },
- { "min_area", "Minimum object area at scale 1 (Common value: 67)" },
+ { "input.*", "An image." },
+ { "out.pbm", "A binary image." },
+ { "w", "Window size at scale 1. (default: 101)" },
+ { "s", "First subsampling ratio (default: 3)." },
+ { "k", "Sauvola's formuale parameter (default: 0.34)" },
+ { "scale.pgm", "Image of scales used for binarization." },
{0, 0}
};
@@ -69,29 +74,42 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
- "Multi-Scale Binarization of a color image based on Sauvola's algorithm. Performs a binarization on each component of the color image and merges the results.",
- "input.ppm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "Multi-Scale Binarization based on Sauvola's algorithm.",
+ "input.* output.pbm <w> <s> <k> <scale.pgm>",
+ args_desc);
trace::entering("main");
// Window size
- unsigned w_1 = atoi(argv[2]); // Scale 1
+ unsigned w_1;
+ if (argc >= 4)
+ w_1 = atoi(argv[3]); // Scale 1
+ else
+ w_1 = 101u;
// First subsampling scale.
- unsigned s = atoi(argv[3]);
+ unsigned s;
+ if (argc >= 5)
+ s = atoi(argv[4]);
+ else
+ s = 3u;
- // Lambda value
- unsigned lambda_min_1 = atoi(argv[4]);
+ double k;
+ if (argc >= 6)
+ k = atof(argv[5]);
+ else
+ k = 0.34f;
+ if (argc >= 7)
+ scribo::binarization::internal::scale_image_output = argv[6];
image2d<value::rgb8> input_1;
- io::ppm::load(input_1, argv[1]);
+ io::magick::load(input_1, argv[1]);
image2d<bool>
- output = scribo::binarization::sauvola_ms(input_1, w_1, s, lambda_min_1);
+ output = scribo::binarization::sauvola_ms(input_1, w_1, s, k);
- io::pbm::save(output, argv[5]);
+ io::pbm::save(output, argv[2]);
}
diff --git a/scribo/src/binarization/ppm_sauvola_ms_split.cc b/scribo/src/binarization/sauvola_ms_split.cc
similarity index 64%
copy from scribo/src/binarization/ppm_sauvola_ms_split.cc
copy to scribo/src/binarization/sauvola_ms_split.cc
index 3f721db..af8b604 100644
--- a/scribo/src/binarization/ppm_sauvola_ms_split.cc
+++ b/scribo/src/binarization/sauvola_ms_split.cc
@@ -26,7 +26,7 @@
#include <mln/core/image/image2d.hh>
#include <mln/value/rgb8.hh>
-#include <mln/io/ppm/load.hh>
+#include <mln/io/magick/load.hh>
#include <mln/io/pbm/save.hh>
#include <scribo/binarization/sauvola_ms_split.hh>
@@ -34,16 +34,19 @@
bool check_args(int argc, char * argv[])
{
- if (argc != 7)
+ if (argc < 3 || argc > 7)
return false;
- int s = atoi(argv[3]);
-
- if (s < 1 || s > 3)
+ if (argc >= 5)
{
- std::cout << "s must be set to 2 or 3."
- << std::endl;
- return false;
+ int s = atoi(argv[4]);
+
+ if (s < 1 || s > 3)
+ {
+ std::cout << "s must be set to 2 or 3."
+ << std::endl;
+ return false;
+ }
}
return true;
@@ -52,11 +55,12 @@ bool check_args(int argc, char * argv[])
const char *args_desc[][2] =
{
- { "input.ppm", "A color image." },
- { "w", "Window size at scale 1. (Common value: 101)" },
- { "s", "First subsampling ratio (Common value: 3)." },
- { "min_area", "Minimum object area at scale 1 (Common value: 67)" },
- { "min_ntrue", "The number of components in which a site must be set to 'True' in order to be set to 'True' in the output (Possible values: 1, 2, 3). (Common value: 2)" },
+ { "input.*", "An image." },
+ { "output.pbm", "A binary image." },
+ { "w", "Window size at scale 1. (default: 101)" },
+ { "s", "First subsampling ratio (default: 3)." },
+ { "min_ntrue", "The number of components in which a site must be set to 'True' in order to be set to 'True' in the output (Possible values: 1, 2, 3). (default: 2)" },
+ { "K", "Sauvola's formula parameter (default: 0.34)." },
{0, 0}
};
@@ -71,28 +75,53 @@ int main(int argc, char *argv[])
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
"Multi-Scale Binarization of a color image based on Sauvola's algorithm. Performs a binarization on each component of the color image and merges the results.",
- "input.ppm w s area_threshold output.pbm",
- args_desc, "A binary image.");
+ "input.* output.pbm <w> <s> <min_ntrue> <K>",
+ args_desc);
trace::entering("main");
// Window size
- unsigned w_1 = atoi(argv[2]); // Scale 1
+ unsigned w_1;
+ if (argc >= 4)
+ w_1 = atoi(argv[3]); // Scale 1
+ else
+ w_1 = 101u;
// First subsampling scale.
- unsigned s = atoi(argv[3]);
+ unsigned s;
+ if (argc >= 5)
+ s = atoi(argv[4]);
+ else
+ s = 3u;
+
+ // min_ntrue
+ unsigned min_ntrue;
+ if (argc >= 6)
+ min_ntrue = atoi(argv[5]);
+ else
+ min_ntrue = 2;
// Lambda value
- unsigned lambda_min_1 = atoi(argv[4]);
+ unsigned lambda_min_1 = 67; // FIXME: should be adapted to the
+ // window size.
+
+ double k;
+ if (argc >= 7)
+ k = atof(argv[6]);
+ else
+ k = 0.34f;
+
image2d<value::rgb8> input_1;
- io::ppm::load(input_1, argv[1]);
+ io::magick::load(input_1, argv[1]);
+
+ std::cout << "Using w=" << w_1 << " - s=" << s << " - min_ntrue=" << min_ntrue << " - k=" << k << std::endl;
image2d<bool>
- output = scribo::binarization::sauvola_ms_split(input_1, w_1, s, lambda_min_1, atoi(argv[5]));
+ output = scribo::binarization::sauvola_ms_split(input_1, w_1, s, lambda_min_1, min_ntrue, k);
- io::pbm::save(output, argv[6]);
+ io::pbm::save(output, argv[2]);
}
diff --git a/scribo/src/preprocessing/to_pgm.cc b/scribo/src/preprocessing/to_pgm.cc
new file mode 100644
index 0000000..974e03f
--- /dev/null
+++ b/scribo/src/preprocessing/to_pgm.cc
@@ -0,0 +1,46 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/io/magick/load.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <scribo/debug/usage.hh>
+
+
+const char *args_desc[][2] =
+{
+ { "input.*", "A color image." },
+ { "output.pgm", "A graylevel image." },
+ {0, 0}
+};
+
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+
+ if (argc != 3)
+ return scribo::debug::usage(argv,
+ "Convert a color image using the minimum RGB component value as intensity.",
+ "input.* output.pgm",
+ args_desc);
+
+
+ typedef image2d<value::rgb8> I;
+ I ima;
+ io::magick::load(ima, argv[1]);
+
+ image2d<value::int_u8> out;
+ initialize(out, ima);
+
+ value::rgb8 v;
+ mln_piter_(I) p(ima.domain());
+ for_all(p)
+ {
+ v = ima(p);
+ out(p) = std::min(v.red(), std::min(v.green(), v.blue()));
+ }
+
+ io::pgm::save(out, argv[2]);
+}
--
1.5.6.5
1
0

last-svn-commit-99-gb1a4d27 Add support for various image types in text_in_photo_fast.
by Guillaume Lazzara 03 Jun '10
by Guillaume Lazzara 03 Jun '10
03 Jun '10
* src/Makefile.am: Add ImageMagick CPPFLAGS and LDFLAGS.
* src/text_in_photo_ppm_fast.cc: Rename as...
* src/text_in_photo_fast.cc: ... this. Use ImageMagick to load images.
---
scribo/ChangeLog | 9 ++++
scribo/src/Makefile.am | 18 ++++----
..._in_photo_ppm_fast.cc => text_in_photo_fast.cc} | 42 ++++++++++++++++---
3 files changed, 53 insertions(+), 16 deletions(-)
rename scribo/src/{text_in_photo_ppm_fast.cc => text_in_photo_fast.cc} (94%)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index bc1c87a..50f9d86 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,3 +1,12 @@
+2010-03-29 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Add support for various image types in text_in_photo_fast.
+
+ * src/Makefile.am: Add ImageMagick CPPFLAGS and LDFLAGS.
+
+ * src/text_in_photo_ppm_fast.cc: Rename as...
+ * src/text_in_photo_fast.cc: ... this. Use ImageMagick to load images.
+
2010-03-19 Guillaume Lazzara <z(a)lrde.epita.fr>
Improve dematerialization wizard.
diff --git a/scribo/src/Makefile.am b/scribo/src/Makefile.am
index e254689..80dc782 100644
--- a/scribo/src/Makefile.am
+++ b/scribo/src/Makefile.am
@@ -34,7 +34,6 @@ bin_PROGRAMS = \
pbm_lines_in_doc \
text_in_photo \
text_in_photo_ppm \
- text_in_photo_ppm_fast \
text_in_photo_pbm_fast \
text_in_photo_invert
@@ -42,7 +41,6 @@ bin_PROGRAMS = \
pbm_lines_in_doc_SOURCES = pbm_lines_in_doc.cc
text_in_photo_SOURCES = text_in_photo.cc
text_in_photo_ppm_SOURCES = text_in_photo_ppm.cc
-text_in_photo_ppm_fast_SOURCES = text_in_photo_ppm_fast.cc
text_in_photo_pbm_fast_SOURCES = text_in_photo_pbm_fast.cc
text_in_photo_invert_SOURCES = text_in_photo_invert.cc
@@ -84,13 +82,15 @@ if HAVE_TIFF
text_in_article_pbm_SOURCES = text_in_article_pbm.cc
- text_in_photo_ppm_fast_CPPFLAGS = $(AM_CPPFLAGS) \
- $(TESSERACT_CPPFLAGS) \
- $(TIFF_CPPFLAGS)
- text_in_photo_ppm_fast_LDFLAGS = $(AM_LDFLAGS) \
- $(TESSERACT_LDFLAGS) \
- $(TIFF_LDFLAGS) \
- -lpthread
+ bin_PROGRAMS += text_in_photo_fast
+ text_in_photo_fast_SOURCES = text_in_photo_fast.cc
+ text_in_photo_fast_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(TESSERACT_CPPFLAGS) \
+ `Magick++-config --cppflags`
+
+ text_in_photo_fast_LDFLAGS = $(AM_LDFLAGS) \
+ $(TESSERACT_LDFLAGS) \
+ -lpthread `Magick++-config --libs`
endif HAVE_TIFF
endif HAVE_TESSERACT
diff --git a/scribo/src/text_in_photo_ppm_fast.cc b/scribo/src/text_in_photo_fast.cc
similarity index 94%
rename from scribo/src/text_in_photo_ppm_fast.cc
rename to scribo/src/text_in_photo_fast.cc
index d534161..68b2014 100644
--- a/scribo/src/text_in_photo_ppm_fast.cc
+++ b/scribo/src/text_in_photo_fast.cc
@@ -37,6 +37,7 @@
#include <mln/io/pbm/all.hh>
#include <mln/io/ppm/save.hh>
+#include <mln/io/magick/all.hh>
#include <mln/math/min.hh>
@@ -54,6 +55,10 @@
#include <mln/geom/translate.hh>
+#include <mln/subsampling/antialiased.hh>
+
+#include <mln/subsampling/antialiased_rgb.hh>
+
#include <scribo/draw/bounding_boxes.hh>
#include <scribo/draw/groups_bboxes.hh>
@@ -101,8 +106,8 @@
#include <scribo/src/afp/link.hh>
#include <scribo/src/afp/regroup.hh>
-#include <scribo/core/line_set.hh>
-#include <scribo/text/recognition.hh>
+// #include <scribo/core/line_set.hh>
+// #include <scribo/text/recognition.hh>
const char *args_desc[][2] =
{
@@ -210,6 +215,19 @@ namespace mln
return output;
}
+
+ template <typename I>
+ unsigned get_factor(const I& ima)
+ {
+ unsigned
+ nrows = ima.nrows(),
+ ncols = ima.ncols(),
+ max_dim = std::max(nrows, ncols),
+ factor = max_dim / 512;
+
+ return factor ? factor : 1;
+ }
+
} // end of namespace mln
@@ -238,8 +256,17 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
trace::entering("main");
image2d<value::rgb8> input_rgb;
- io::ppm::load(input_rgb, argv[1]);
+ io::magick::load(input_rgb, argv[1]);
+
+ unsigned factor = get_factor(input_rgb);
+
+ std::cout << "Reduction Factor : " << factor << std::endl;
+
+ std::cout << "Original domain: " << input_rgb.domain() << std::endl;
+
+ input_rgb = mln::subsampling::impl::antialiased_2d_rgb(input_rgb, factor);
+ std::cout << "Resized domain: " << input_rgb.domain() << std::endl;
unsigned lambda;
if (argc == 10)
@@ -291,7 +318,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
unsigned w = std::min(intensity_ima.nrows() / 3, intensity_ima.ncols() / 3);
if (! w % 2)
++w;
- w = std::min(w, 101u);
+ w = std::min(w, 51u);
if (argc > 4 && atoi(argv[4]) != 0)
{
std::cout << "** Using sauvola_ms with w_1 = " << w << std::endl;
@@ -311,6 +338,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
#endif // !NOUT
+ logical::not_inplace(input);
// if (debug)
// io::pbm::save(input, "input.pbm");
@@ -626,9 +654,9 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1 1",
- scribo::line_set<L>
- lines = scribo::make::line_set(groups);
- text::recognition(lines, "fra", "out.txt");
+// scribo::line_set<L>
+// lines = scribo::make::line_set(groups);
+// text::recognition(lines, "fra", "out.txt");
trace::exiting("main");
return comps.nelements() != 0;
--
1.5.6.5
1
0

03 Jun '10
* demo/wizard/src/crop_widget.cc,
* demo/wizard/src/main.cc,
* demo/wizard/src/main_window.cc,
* demo/wizard/src/main_window.hh,
* demo/wizard/src/preprocessing_widget.cc,
* demo/wizard/src/process_page.cc,
* demo/wizard/src/result_page.cc,
* demo/wizard/src/result_page.hh,
* demo/wizard/src/result_widget.cc,
* demo/wizard/src/result_widget.hh,
* demo/wizard/src/runner.cc,
* demo/wizard/ui/preprocessing_widget.ui,
* demo/wizard/wizard.pro: Add support for text recognition and
display results.
---
scribo/ChangeLog | 19 +++++++
scribo/demo/wizard/src/crop_widget.cc | 2 +-
scribo/demo/wizard/src/main.cc | 13 +++++
scribo/demo/wizard/src/main_window.cc | 23 ++++++--
scribo/demo/wizard/src/main_window.hh | 2 +
scribo/demo/wizard/src/preprocessing_widget.cc | 10 +++-
scribo/demo/wizard/src/process_page.cc | 5 --
scribo/demo/wizard/src/result_page.cc | 43 +++++++++++++++
.../wizard/src/{crop_page.hh => result_page.hh} | 18 +++---
scribo/demo/wizard/src/result_widget.cc | 43 +++++++++++++++
.../wizard/src/{crop_page.hh => result_widget.hh} | 18 +++----
scribo/demo/wizard/src/runner.cc | 55 +++++++++++++-------
scribo/demo/wizard/ui/preprocessing_widget.ui | 4 +-
scribo/demo/wizard/wizard.pro | 48 +++++++++--------
14 files changed, 228 insertions(+), 75 deletions(-)
create mode 100644 scribo/demo/wizard/src/result_page.cc
copy scribo/demo/wizard/src/{crop_page.hh => result_page.hh} (81%)
create mode 100644 scribo/demo/wizard/src/result_widget.cc
copy scribo/demo/wizard/src/{crop_page.hh => result_widget.hh} (79%)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 68ec602..bc1c87a 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,24 @@
2010-03-19 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Improve dematerialization wizard.
+
+ * demo/wizard/src/crop_widget.cc,
+ * demo/wizard/src/main.cc,
+ * demo/wizard/src/main_window.cc,
+ * demo/wizard/src/main_window.hh,
+ * demo/wizard/src/preprocessing_widget.cc,
+ * demo/wizard/src/process_page.cc,
+ * demo/wizard/src/result_page.cc,
+ * demo/wizard/src/result_page.hh,
+ * demo/wizard/src/result_widget.cc,
+ * demo/wizard/src/result_widget.hh,
+ * demo/wizard/src/runner.cc,
+ * demo/wizard/ui/preprocessing_widget.ui,
+ * demo/wizard/wizard.pro: Add support for text recognition and
+ display results.
+
+2010-03-19 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Add a new demo in Scribo.
* demo/demat/demat.pro,
diff --git a/scribo/demo/wizard/src/crop_widget.cc b/scribo/demo/wizard/src/crop_widget.cc
index 37a9e80..8067fda 100644
--- a/scribo/demo/wizard/src/crop_widget.cc
+++ b/scribo/demo/wizard/src/crop_widget.cc
@@ -29,7 +29,7 @@ namespace scribo
QPixmap crop_widget::image() const
{
- return viewer_->image().copy(crop_area().toRect());
+ return viewer_->image().copy(crop_area().toRect().intersected(viewer_->image().rect()));
}
} // end of namespace scribo::demo
diff --git a/scribo/demo/wizard/src/main.cc b/scribo/demo/wizard/src/main.cc
index 12f024a..5b771e2 100644
--- a/scribo/demo/wizard/src/main.cc
+++ b/scribo/demo/wizard/src/main.cc
@@ -2,12 +2,25 @@
#include <src/main_window.hh>
#include <src/preprocessing_task.hh>
+namespace scribo { namespace demo {extern QString basedir_; } }
+
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
qRegisterMetaType<preprocessing_task_set_t>("preprocessing_task_set_t");
+
+ if (argc == 2)
+ {
+ scribo::demo::basedir_ = argv[1];
+ }
+ else
+ {
+ qDebug() << "Usage: " << argv[0] << " <path_to_scribo/src>";
+ return 1;
+ }
+
scribo::demo::wizard::main_window win;
win.show();
diff --git a/scribo/demo/wizard/src/main_window.cc b/scribo/demo/wizard/src/main_window.cc
index 35aa8c7..7f44ec5 100644
--- a/scribo/demo/wizard/src/main_window.cc
+++ b/scribo/demo/wizard/src/main_window.cc
@@ -31,6 +31,7 @@
#include <src/preprocessing_page.hh>
#include <src/process_page.hh>
#include <src/rotate_page.hh>
+#include <src/result_page.hh>
namespace scribo
{
@@ -44,15 +45,15 @@ namespace scribo
main_window::main_window()
{
- setOptions(QWizard::NoBackButtonOnStartPage
- | QWizard::DisabledBackButtonOnLastPage
- | QWizard::NoCancelButton);
-
QPixmap bg_pixmap(":/images/images/dematerialization.png");
setPixmap(QWizard::WatermarkPixmap, bg_pixmap);
setPixmap(QWizard::BackgroundPixmap, bg_pixmap);
+ connect(this, SIGNAL(currentIdChanged(int)),
+ this, SLOT(showCustomButton_slot(int)));
+
+
// Page_Load
load_page* page_load = new load_page(this);
addPage(page_load);
@@ -78,7 +79,7 @@ namespace scribo
addPage(new process_page(this));
// Page_Result
- addPage(new QWizardPage(this));
+ addPage(new result_page(this));
}
@@ -122,6 +123,18 @@ namespace scribo
}
+ void main_window::showCustomButton_slot(int id)
+ {
+ if (id == Page_Result)
+ setOptions(options() | QWizard::HaveCustomButton1);
+ else
+ {
+ setOptions(QWizard::NoBackButtonOnStartPage
+// | QWizard::DisabledBackButtonOnLastPage
+ | QWizard::NoCancelButton);
+ }
+ }
+
} // end of namespace scribo::demo::wizard
} // end of namespace scribo::demo
diff --git a/scribo/demo/wizard/src/main_window.hh b/scribo/demo/wizard/src/main_window.hh
index af4c113..44e6d92 100644
--- a/scribo/demo/wizard/src/main_window.hh
+++ b/scribo/demo/wizard/src/main_window.hh
@@ -48,6 +48,8 @@ namespace scribo
virtual int nextId() const;
+ private slots:
+ void showCustomButton_slot(int id);
private:
enum { Page_Load,
diff --git a/scribo/demo/wizard/src/preprocessing_widget.cc b/scribo/demo/wizard/src/preprocessing_widget.cc
index 7a2c9fa..7c66719 100644
--- a/scribo/demo/wizard/src/preprocessing_widget.cc
+++ b/scribo/demo/wizard/src/preprocessing_widget.cc
@@ -35,8 +35,11 @@ namespace scribo
{
qDebug() << "setup text doc";
- removeBg->setChecked(true);
- unskew->setChecked(true);
+ // Disabled
+ removeBg->setChecked(false);
+ unskew->setChecked(false);
+
+ // Enabled
removeNoise->setChecked(true);
improveContrast->setChecked(true);
}
@@ -44,6 +47,9 @@ namespace scribo
void preprocessing_widget::clear_checked()
{
+ // Enabled
+
+ // Disabled
removeBg->setChecked(false);
unskew->setChecked(false);
removeNoise->setChecked(false);
diff --git a/scribo/demo/wizard/src/process_page.cc b/scribo/demo/wizard/src/process_page.cc
index bbba0e3..bff087a 100644
--- a/scribo/demo/wizard/src/process_page.cc
+++ b/scribo/demo/wizard/src/process_page.cc
@@ -21,11 +21,6 @@ namespace scribo
setSubTitle("Processing...");
setTitle("Please wait while computing results.");
-
- void progress(unsigned i);
-
- void progress(unsigned i);
-
connect(&runner_, SIGNAL(new_intermediate_result(const QImage&)),
widget_, SLOT(update_pixmap(const QImage&)));
diff --git a/scribo/demo/wizard/src/result_page.cc b/scribo/demo/wizard/src/result_page.cc
new file mode 100644
index 0000000..1bb08d8
--- /dev/null
+++ b/scribo/demo/wizard/src/result_page.cc
@@ -0,0 +1,43 @@
+#include <src/result_page.hh>
+#include <src/result_widget.hh>
+
+
+namespace scribo
+{
+
+ namespace demo
+ {
+
+
+ result_page::result_page(QWidget *parent)
+ : QWizardPage(parent)
+ {
+ widget_ = new result_widget(this);
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(widget_);
+ setLayout(layout);
+
+ setTitle("Result");
+ setSubTitle("Copy and paste the recognized text.");
+
+ connect(parent, SIGNAL(customButtonClicked(int)),
+ parent, SLOT(restart()));
+ }
+
+
+ void result_page::cleanupPage()
+ {
+ widget_->reset();
+ }
+
+
+ void result_page::initializePage()
+ {
+ setButtonText(QWizard::CustomButton1, "restart");
+ widget_->load("/tmp/out.txt");
+ }
+
+
+ } // end of namespace scribo::demo
+
+} // end of namespace scribo
diff --git a/scribo/demo/wizard/src/crop_page.hh b/scribo/demo/wizard/src/result_page.hh
similarity index 81%
copy from scribo/demo/wizard/src/crop_page.hh
copy to scribo/demo/wizard/src/result_page.hh
index 9891a7e..c6f02b9 100644
--- a/scribo/demo/wizard/src/crop_page.hh
+++ b/scribo/demo/wizard/src/result_page.hh
@@ -23,11 +23,12 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef SCRIBO_DEMO_SHARED_SRC_CROP_PAGE_HH
-# define SCRIBO_DEMO_SHARED_SRC_CROP_PAGE_HH
+#ifndef SCRIBO_DEMO_SHARED_SRC_RESULT_PAGE_HH
+# define SCRIBO_DEMO_SHARED_SRC_RESULT_PAGE_HH
# include <QtGui>
-# include <src/crop_widget.hh>
+# include <src/result_widget.hh>
+# include <src/runner.hh>
namespace scribo
{
@@ -36,19 +37,18 @@ namespace scribo
{
- class crop_page : public QWizardPage
+ class result_page : public QWizardPage
{
Q_OBJECT;
public:
- crop_page(QWidget *parent = 0);
+ result_page(QWidget *parent = 0);
virtual void cleanupPage();
virtual void initializePage();
- virtual bool validatePage();
- private:
- crop_widget *widget_;
+ private: // attributes
+ result_widget* widget_;
};
@@ -57,4 +57,4 @@ namespace scribo
} // end of namespace scribo
-#endif // ! SCRIBO_DEMO_SHARED_SRC_CROP_PAGE_HH
+#endif // ! SCRIBO_DEMO_SHARED_SRC_RESULT_PAGE_HH
diff --git a/scribo/demo/wizard/src/result_widget.cc b/scribo/demo/wizard/src/result_widget.cc
new file mode 100644
index 0000000..889ba4b
--- /dev/null
+++ b/scribo/demo/wizard/src/result_widget.cc
@@ -0,0 +1,43 @@
+#include <src/result_widget.hh>
+
+namespace scribo
+{
+
+ namespace demo
+ {
+
+
+ result_widget::result_widget(QWidget *parent)
+ : QWidget(parent)
+ {
+ text_ = new QTextEdit(this);
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(text_);
+ setLayout(layout);
+ }
+
+ void result_widget::load(const QString& filename)
+ {
+ QFile file(filename);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ return;
+
+ QTextStream in(&file);
+ in.setCodec("UTF-8");
+ while (!in.atEnd())
+ {
+ QString line = in.readLine();
+ text_->append(line);
+ }
+
+ }
+
+ void result_widget::reset()
+ {
+ text_->clear();
+ }
+
+
+ } // end of namespace scribo::demo
+
+} // end of namespace scribo
diff --git a/scribo/demo/wizard/src/crop_page.hh b/scribo/demo/wizard/src/result_widget.hh
similarity index 79%
copy from scribo/demo/wizard/src/crop_page.hh
copy to scribo/demo/wizard/src/result_widget.hh
index 9891a7e..4472238 100644
--- a/scribo/demo/wizard/src/crop_page.hh
+++ b/scribo/demo/wizard/src/result_widget.hh
@@ -23,11 +23,10 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef SCRIBO_DEMO_SHARED_SRC_CROP_PAGE_HH
-# define SCRIBO_DEMO_SHARED_SRC_CROP_PAGE_HH
+#ifndef SCRIBO_DEMO_SHARED_SRC_RESULT_WIDGET_HH
+# define SCRIBO_DEMO_SHARED_SRC_RESULT_WIDGET_HH
# include <QtGui>
-# include <src/crop_widget.hh>
namespace scribo
{
@@ -36,19 +35,18 @@ namespace scribo
{
- class crop_page : public QWizardPage
+ class result_widget : public QWidget
{
Q_OBJECT;
public:
- crop_page(QWidget *parent = 0);
+ result_widget(QWidget *parent = 0);
+ void reset();
- virtual void cleanupPage();
- virtual void initializePage();
- virtual bool validatePage();
+ void load(const QString& filename);
private:
- crop_widget *widget_;
+ QTextEdit *text_;
};
@@ -57,4 +55,4 @@ namespace scribo
} // end of namespace scribo
-#endif // ! SCRIBO_DEMO_SHARED_SRC_CROP_PAGE_HH
+#endif // ! SCRIBO_DEMO_SHARED_SRC_RESULT_WIDGET_HH
diff --git a/scribo/demo/wizard/src/runner.cc b/scribo/demo/wizard/src/runner.cc
index 162f1cb..dd9ad9c 100644
--- a/scribo/demo/wizard/src/runner.cc
+++ b/scribo/demo/wizard/src/runner.cc
@@ -27,7 +27,7 @@ namespace scribo
namespace demo
{
- QString basedir_ = "/home/lazzara/build/scribo/src";
+ QString basedir_ = "";
runner::runner(QObject *parent)
: QThread(parent)
@@ -53,6 +53,8 @@ namespace scribo
// Notification of the number of tasks.
emit new_progress_max_value(tasks_.size() + 2);
+ qDebug() << "progress steps : " << tasks_.size() + 2;
+
image2d<value::qt::rgb32> ima = load();
preprocess(ima);
@@ -131,10 +133,10 @@ namespace scribo
std::cout << "Improve contrast homogeneity" << std::endl;
emit new_progress_label("Improve contrast homogeneity");
- intensity_ima = preprocessing::homogeneous_contrast(intensity_ima, 75);
+ intensity_ima = arith::revert(preprocessing::homogeneous_contrast(intensity_ima, 75));
image2d<value::qt::rgb32>
- tmp_color32 = data::convert(value::qt::rgb32(), out_bool);
+ tmp_color32 = data::convert(value::qt::rgb32(), intensity_ima);
emit new_intermediate_result(convert::to_qimage(tmp_color32));
emit progress(1);
}
@@ -149,14 +151,13 @@ namespace scribo
{
// FIXME: sauvola should not negate the image.
std::cout << "Binarization Sauvola" << std::endl;
- out_bool = logical::not_(binarization::sauvola(intensity_ima));
+ out_bool = binarization::sauvola(intensity_ima);
}
else if (tasks_.contains(BinarizationSauvolaMs))
{
// FIXME: sauvola should not negate the image.
std::cout << "Binarization Sauvola_ms" << std::endl;
- out_bool = logical::not_(binarization::sauvola_ms(intensity_ima,
- 51, 2, 67));
+ out_bool = binarization::sauvola_ms(intensity_ima, 51, 2, 67);
}
else if (tasks_.contains(BinarizationSimple))
{
@@ -175,22 +176,24 @@ namespace scribo
emit progress(1);
+ // FIXME: remove!
+ logical::not_inplace(out_bool);
+
//========
// Denoise
//========
- if (tasks_.contains(RemoveNoise))
- {
- std::cout << "Remove noise" << std::endl;
- emit new_progress_label("Remove noise");
+// if (tasks_.contains(RemoveNoise))
+// {
+// std::cout << "Remove noise" << std::endl;
+// emit new_progress_label("Remove noise");
- out_bool = preprocessing::denoise(out_bool, c8(), 2, 2);
-
- image2d<value::qt::rgb32>
- tmp_color32 = data::convert(value::qt::rgb32(), out_bool);
- emit new_intermediate_result(convert::to_qimage(tmp_color32));
- emit progress(1);
- }
+// out_bool = preprocessing::denoise(out_bool, c8(), 2, 2);
+// image2d<value::qt::rgb32>
+// tmp_color32 = data::convert(value::qt::rgb32(), out_bool);
+// emit new_intermediate_result(convert::to_qimage(tmp_color32));
+// emit progress(1);
+// }
//=======
// Unskew
@@ -226,8 +229,21 @@ namespace scribo
switch(doc_type_)
{
case Text_Doc:
+ emit new_progress_label("Finding text in document...");
qDebug() << "Running text_in_article_pbm";
- args << "/tmp/tmp.pbm" << "/tmp/out.ppm";
+ args << "/tmp/tmp.pbm" << "/tmp/out.txt";
+
+ // Denoise.
+ if (! tasks_.contains(RemoveNoise))
+ args << "0";
+ else
+ {
+ args << "1";
+ emit progress(1); // Consider denoising as done even though it is performed later.
+ }
+
+ args << "/tmp/";
+
if (process_.execute(basedir_ + "/text_in_article_pbm", args))
{
qDebug() << "Error while running text_in_article_pbm.";
@@ -236,6 +252,7 @@ namespace scribo
break;
case Picture:
+ emit new_progress_label("Finding text in picture...");
qDebug() << "Running text_in_photo_pbm_fast";
args << "/tmp/tmp.pbm" << "/tmp/out.ppm" << "1" << "1" << "1";
if (process_.execute(basedir_ + "/text_in_photo_pbm_fast", args))
@@ -263,7 +280,7 @@ namespace scribo
process_.waitForFinished(-1);
emit progress(1);
- emit new_intermediate_result(QImage("/tmp/out.ppm"));
+ emit new_intermediate_result(QImage("/tmp/_09_step2_bboxes.ppm"));
qDebug() << "Done";
}
diff --git a/scribo/demo/wizard/ui/preprocessing_widget.ui b/scribo/demo/wizard/ui/preprocessing_widget.ui
index 17225a8..6b9c178 100644
--- a/scribo/demo/wizard/ui/preprocessing_widget.ui
+++ b/scribo/demo/wizard/ui/preprocessing_widget.ui
@@ -70,7 +70,7 @@
<item>
<widget class="QCheckBox" name="removeNoise" >
<property name="enabled" >
- <bool>false</bool>
+ <bool>true</bool>
</property>
<property name="text" >
<string>Remove noise</string>
@@ -83,7 +83,7 @@
<item>
<widget class="QCheckBox" name="improveContrast" >
<property name="enabled" >
- <bool>false</bool>
+ <bool>true</bool>
</property>
<property name="text" >
<string>Improve brightness/contrast</string>
diff --git a/scribo/demo/wizard/wizard.pro b/scribo/demo/wizard/wizard.pro
index c7ab290..9dd5296 100644
--- a/scribo/demo/wizard/wizard.pro
+++ b/scribo/demo/wizard/wizard.pro
@@ -11,27 +11,29 @@ INCLUDEPATH += . ../ ../shared $(OLN)/milena $(OLN)
DEFINES += NDEBUG MLN_INCLUDE_ONLY
# Input
-HEADERS += \
- ../shared/src/image_viewer.hh \
- ../shared/src/internal/interactive_scene.hh \
- ../shared/src/crop_item.hh \
+ HEADERS += \
+ ../shared/src/image_viewer.hh \
+ ../shared/src/internal/interactive_scene.hh \
+ ../shared/src/crop_item.hh \
../shared/src/browse_widget.hh \
- src/load_page.hh \
- src/load_widget.hh \
- src/doc_type_widget.hh \
- src/doc_type_page.hh \
- src/crop_widget.hh \
- src/crop_page.hh \
- src/rotate_widget.hh \
- src/rotate_page.hh \
- src/preprocessing_widget.hh \
- src/preprocessing_page.hh \
- src/process_page.hh \
- src/process_widget.hh \
- src/runner.hh \
- src/preprocessing_task.hh \
- src/doc_type.hh \
- src/main_window.hh
+ src/load_page.hh \
+ src/load_widget.hh \
+ src/doc_type_widget.hh \
+ src/doc_type_page.hh \
+ src/crop_widget.hh \
+ src/crop_page.hh \
+ src/rotate_widget.hh \
+ src/rotate_page.hh \
+ src/preprocessing_widget.hh \
+ src/preprocessing_page.hh \
+ src/process_page.hh \
+ src/process_widget.hh \
+ src/runner.hh \
+ src/preprocessing_task.hh \
+ src/doc_type.hh \
+ src/main_window.hh \
+ src/result_page.hh \
+ src/result_widget.hh
SOURCES += \
@@ -40,7 +42,7 @@ SOURCES += \
../shared/src/browse_widget.cc \
src/main.cc \
src/main_window.cc \
- src/doc_type_widget.cc \
+ src/doc_type_widget.cc \
src/doc_type_page.cc \
src/load_page.cc \
src/load_widget.cc \
@@ -52,7 +54,9 @@ SOURCES += \
src/preprocessing_page.cc \
src/process_page.cc \
src/process_widget.cc \
- src/mln_widgets.cc
+ src/mln_widgets.cc \
+ src/result_page.cc \
+ src/result_widget.cc
FORMS += \
../shared/ui/browse_widget.ui \
--
1.5.6.5
1
0
* demo/demat/demat.pro,
* demo/demat/demat.qrc,
* demo/demat/src/doc_type.hh,
* demo/demat/src/main.cc,
* demo/demat/src/main_window.cc,
* demo/demat/src/main_window.hh,
* demo/demat/src/mln_widgets.cc,
* demo/demat/src/preprocessing_task.hh,
* demo/demat/src/process_args.hh,
* demo/demat/src/runner.cc,
* demo/demat/src/runner.hh,
* demo/demat/ui/main_window.ui: New.
* demo/shared/src/crop_item.cc,
* demo/shared/src/crop_item.hh,
* demo/shared/src/image_viewer.cc,
* demo/shared/src/image_viewer.hh,
* demo/shared/ui/image_viewer.ui: Update according the needs of
this new demo.
---
scribo/ChangeLog | 24 ++
scribo/demo/demat/demat.pro | 37 ++
scribo/demo/demat/demat.qrc | 4 +
scribo/demo/{wizard => demat}/src/doc_type.hh | 0
scribo/demo/demat/src/main.cc | 27 ++
scribo/demo/demat/src/main_window.cc | 240 +++++++++++++
scribo/demo/demat/src/main_window.hh | 91 +++++
scribo/demo/demat/src/mln_widgets.cc | 11 +
.../{wizard => demat}/src/preprocessing_task.hh | 0
scribo/demo/demat/src/process_args.hh | 47 +++
scribo/demo/demat/src/runner.cc | 316 +++++++++++++++++
scribo/demo/demat/src/runner.hh | 93 +++++
scribo/demo/demat/ui/main_window.ui | 366 ++++++++++++++++++++
scribo/demo/shared/src/crop_item.cc | 45 ++-
scribo/demo/shared/src/crop_item.hh | 12 +-
scribo/demo/shared/src/image_viewer.cc | 65 +++-
scribo/demo/shared/src/image_viewer.hh | 14 +-
scribo/demo/shared/ui/image_viewer.ui | 34 ++-
18 files changed, 1398 insertions(+), 28 deletions(-)
create mode 100644 scribo/demo/demat/demat.pro
create mode 100644 scribo/demo/demat/demat.qrc
copy scribo/demo/{wizard => demat}/src/doc_type.hh (100%)
create mode 100644 scribo/demo/demat/src/main.cc
create mode 100644 scribo/demo/demat/src/main_window.cc
create mode 100644 scribo/demo/demat/src/main_window.hh
create mode 100644 scribo/demo/demat/src/mln_widgets.cc
copy scribo/demo/{wizard => demat}/src/preprocessing_task.hh (100%)
create mode 100644 scribo/demo/demat/src/process_args.hh
create mode 100644 scribo/demo/demat/src/runner.cc
create mode 100644 scribo/demo/demat/src/runner.hh
create mode 100644 scribo/demo/demat/ui/main_window.ui
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 40a5fb4..68ec602 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,29 @@
2010-03-19 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Add a new demo in Scribo.
+
+ * demo/demat/demat.pro,
+ * demo/demat/demat.qrc,
+ * demo/demat/src/doc_type.hh,
+ * demo/demat/src/main.cc,
+ * demo/demat/src/main_window.cc,
+ * demo/demat/src/main_window.hh,
+ * demo/demat/src/mln_widgets.cc,
+ * demo/demat/src/preprocessing_task.hh,
+ * demo/demat/src/process_args.hh,
+ * demo/demat/src/runner.cc,
+ * demo/demat/src/runner.hh,
+ * demo/demat/ui/main_window.ui: New.
+
+ * demo/shared/src/crop_item.cc,
+ * demo/shared/src/crop_item.hh,
+ * demo/shared/src/image_viewer.cc,
+ * demo/shared/src/image_viewer.hh,
+ * demo/shared/ui/image_viewer.ui: Update according the needs of
+ this new demo.
+
+2010-03-19 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Small fixes in Scribo.
* binarization/sauvola_ms.hh: Fix compilation issues on MacOS X.
diff --git a/scribo/demo/demat/demat.pro b/scribo/demo/demat/demat.pro
new file mode 100644
index 0000000..4f4af23
--- /dev/null
+++ b/scribo/demo/demat/demat.pro
@@ -0,0 +1,37 @@
+# -*- c++ -*-
+######################################################################
+# Automatically generated by qmake (2.01a) Tue Feb 9 12:02:10 2010
+######################################################################
+
+TEMPLATE = app
+TARGET =
+DEPENDPATH += . src
+INCLUDEPATH += . ../ ../shared $(OLN)/milena $(OLN)
+
+QMAKE_CXXFLAGS += -g
+
+LIBS += `Magick++-config --ldflags --libs`
+
+DEFINES += NDEBUG MLN_INCLUDE_ONLY
+
+# Input
+ HEADERS += \
+ ../shared/src/image_viewer.hh \
+ ../shared/src/internal/interactive_scene.hh \
+ ../shared/src/crop_item.hh \
+ ../shared/src/browse_widget.hh \
+ src/runner.hh \
+ src/main_window.hh
+
+SOURCES += \
+ ../shared/src/crop_item.cc \
+ ../shared/src/internal/interactive_scene.cc \
+ ../shared/src/browse_widget.cc \
+ src/mln_widgets.cc
+
+FORMS += \
+ ../shared/ui/image_viewer.ui \
+ ui/main_window.ui
+
+
+RESOURCES += ../shared/shared.qrc demat.qrc
diff --git a/scribo/demo/demat/demat.qrc b/scribo/demo/demat/demat.qrc
new file mode 100644
index 0000000..68031c7
--- /dev/null
+++ b/scribo/demo/demat/demat.qrc
@@ -0,0 +1,4 @@
+<RCC>
+ <qresource prefix="images" >
+ </qresource>
+</RCC>
diff --git a/scribo/demo/wizard/src/doc_type.hh b/scribo/demo/demat/src/doc_type.hh
similarity index 100%
copy from scribo/demo/wizard/src/doc_type.hh
copy to scribo/demo/demat/src/doc_type.hh
diff --git a/scribo/demo/demat/src/main.cc b/scribo/demo/demat/src/main.cc
new file mode 100644
index 0000000..ee35a48
--- /dev/null
+++ b/scribo/demo/demat/src/main.cc
@@ -0,0 +1,27 @@
+#include <QtGui>
+#include <src/main_window.hh>
+#include <src/preprocessing_task.hh>
+
+namespace scribo { namespace demo {extern QString basedir_; } }
+
+int main(int argc, char* argv[])
+{
+ QApplication app(argc, argv);
+
+ qRegisterMetaType<preprocessing_task_set_t>("preprocessing_task_set_t");
+
+ if (argc == 2)
+ {
+ scribo::demo::basedir_ = argv[1];
+ }
+ else
+ {
+ qDebug() << "Usage: " << argv[0] << " <path_to_scribo/src>";
+ return 1;
+ }
+
+ scribo::demo::demat::main_window win;
+ win.show();
+
+ return app.exec();
+}
diff --git a/scribo/demo/demat/src/main_window.cc b/scribo/demo/demat/src/main_window.cc
new file mode 100644
index 0000000..ee82ca1
--- /dev/null
+++ b/scribo/demo/demat/src/main_window.cc
@@ -0,0 +1,240 @@
+// 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.
+
+#include <src/main_window.hh>
+
+#include <src/doc_type.hh>
+#include <src/preprocessing_task.hh>
+#include <src/process_args.hh>
+
+#include <mln/data/convert.hh>
+#include <mln/convert/to_qimage_nocopy.hh>
+#include <mln/core/routine/duplicate.hh>
+#include <mln/make/box2d.hh>
+#include <mln/data/paste.hh>
+#include <mln/io/magick/load.hh>
+
+namespace scribo
+{
+
+ namespace demo
+ {
+
+ namespace demat
+ {
+
+ // FIXME: move it as attribute.
+ static mln::image2d<mln::value::rgb8> input_;
+
+
+ main_window::main_window()
+ {
+ setupUi(this);
+
+ text_->hide();
+
+ connect(action_Open, SIGNAL(activated()),
+ this, SLOT(open_file_slot()));
+
+ connect(run_btn, SIGNAL(clicked()), this, SLOT(run()));
+
+
+ // Connections to/from task runner.
+ connect(&runner_, SIGNAL(new_progress_label(const QString&)),
+ this, SLOT(update_progress_label_slot(const QString&)));
+
+ connect(&runner_, SIGNAL(progress(unsigned)),
+ this, SLOT(progress_slot(unsigned)));
+ connect(&runner_, SIGNAL(finished()),
+ this, SLOT(process_finished_slot()));
+
+ // Connections for dock windows.
+ connect(advanced_dock_, SIGNAL(visibilityChanged(bool)),
+ actionAdvanced_options, SLOT(setChecked(bool)));
+ connect(options_dock_, SIGNAL(visibilityChanged(bool)),
+ actionOptions, SLOT(setChecked(bool)));
+
+ connect(actionAdvanced_options, SIGNAL(triggered(bool)),
+ advanced_dock_, SLOT(setVisible(bool)));
+ connect(actionOptions, SIGNAL(triggered(bool)),
+ options_dock_, SLOT(setVisible(bool)));
+
+ progress_ = new QProgressDialog();
+ progress_->setLabelText("Processing...");
+ progress_->setCancelButton(0);
+ progress_->setAutoClose(true);
+
+ // Setup crop tool.
+ viewer_->set_selection_enabled(true);
+ connect(viewer_, SIGNAL(ready_for_crop()), this, SLOT(crop_slot()));
+ }
+
+
+ void main_window::open_file_slot()
+ {
+ QFileDialog dialog;
+ QStringList filters;
+ filters << tr("Image (*.ppm *.pbm *.pgm *.png *.jpg)");
+ dialog.setNameFilters(filters);
+
+ dialog.setFileMode(QFileDialog::ExistingFile);
+ dialog.setLabelText(QFileDialog::LookIn,
+ tr("Choose an existing file"));
+
+ if (dialog.exec() && current_image_ != dialog.selectedFiles().at(0))
+ {
+ current_image_ = dialog.selectedFiles().at(0);
+ load();
+ }
+
+ }
+
+
+ void main_window::load()
+ {
+ text_->hide();
+
+ mln::io::magick::load(input_, current_image_.toStdString());
+
+ input_dsp_ = QPixmap::fromImage(mln::convert::to_qimage_nocopy(input_));
+
+ viewer_->draw_image(input_dsp_);
+ }
+
+
+ void main_window::run()
+ {
+ preprocessing_task_set_t tasks = get_tasks();
+
+ prepare_progress_bar(tasks.size());
+
+ process_args args; // Nothing for now.
+
+ runner_.start(current_image_, input_, Text_Doc, tasks, args);
+ }
+
+
+ preprocessing_task_set_t main_window::get_tasks()
+ {
+ preprocessing_task_set_t tasks;
+
+ if (removeBg->isChecked())
+ tasks.insert(RemoveBg);
+
+ if (unskew->isChecked())
+ tasks.insert(Unskew);
+
+ if (removeNoise->isChecked())
+ tasks.insert(RemoveNoise);
+
+ if (improveContrast->isChecked())
+ tasks.insert(ImproveContrast);
+
+ if (reduceSize->isChecked())
+ tasks.insert(ReduceSize);
+
+ if (binarizationCBox->currentIndex() == 0)
+ tasks.insert(BinarizationSimple);
+ else if (binarizationCBox->currentIndex() == 1)
+ tasks.insert(BinarizationSauvola);
+ else if (binarizationCBox->currentIndex() == 2)
+ tasks.insert(BinarizationSauvolaMs);
+
+ return tasks;
+ }
+
+
+ void main_window::prepare_progress_bar(unsigned max)
+ {
+ progress_->show();
+ progress_->setValue(0);
+ progress_->setMaximum(max + 3);
+ }
+
+
+ void main_window::progress_slot(unsigned i)
+ {
+ progress_->setValue(progress_->value() + i);
+ }
+
+
+ void main_window::update_progress_label_slot(const QString& msg)
+ {
+ progress_->setLabelText(msg);
+ }
+
+
+ void main_window::process_finished_slot()
+ {
+ text_->clear();
+
+ QFile file("/tmp/out.txt");
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ return;
+
+ QTextStream in(&file);
+ in.setCodec("UTF-8");
+ while (!in.atEnd())
+ {
+ QString line = in.readLine();
+ text_->append(line);
+ }
+
+
+ text_->show();
+ }
+
+
+ void main_window::crop_slot()
+ {
+ mln::box2d b = input_.domain();
+ QRectF selection = viewer_->selection();
+
+ mln::box2d sbox = mln::make::box2d(selection.topLeft().y(),
+ selection.topLeft().x(),
+ selection.bottomRight().y(),
+ selection.bottomRight().x());
+
+ sbox.crop_wrt(b);
+
+ if (sbox.is_valid())
+ {
+ // Update underlying data.
+ mln::image2d<mln::value::rgb8> output(sbox);
+ mln::data::fill(output, input_);
+ input_ = output;
+
+ // Update display
+ viewer_->draw_image(input_);
+ }
+
+ viewer_->enable_crop_tool(false); // Disable crop tool
+ }
+
+ } // end of namespace scribo::demo::demat
+
+ } // end of namespace scribo::demo
+
+} // end of namespace scribo
diff --git a/scribo/demo/demat/src/main_window.hh b/scribo/demo/demat/src/main_window.hh
new file mode 100644
index 0000000..f52f171
--- /dev/null
+++ b/scribo/demo/demat/src/main_window.hh
@@ -0,0 +1,91 @@
+// 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.
+
+#ifndef SCRIBO_DEMO_DEMAT_SRC_MAIN_WINDOW_HH
+# define SCRIBO_DEMO_DEMAT_SRC_MAIN_WINDOW_HH
+
+# include <QtGui/QMainWindow>
+# include <ui_main_window.h>
+# include <src/doc_type.hh>
+# include <src/preprocessing_task.hh>
+# include <src/runner.hh>
+
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/dmorph/image_if.hh>
+# include <mln/pw/all.hh>
+# include <mln/value/rgb8.hh>
+
+
+namespace scribo
+{
+
+ namespace demo
+ {
+
+ namespace demat
+ {
+
+
+ class main_window : public QMainWindow, private Ui::MainWindow
+ {
+ Q_OBJECT;
+
+ public:
+ main_window();
+
+ private slots:
+ void run();
+ void open_file_slot();
+ void progress_slot(unsigned i);
+ void update_progress_label_slot(const QString&);
+ void process_finished_slot();
+
+ void crop_slot();
+
+ private: // members
+ void load();
+
+ void prepare_progress_bar(unsigned max);
+ Doc_Type get_doc_type();
+ preprocessing_task_set_t get_tasks();
+
+ private: // attributes
+ QPixmap input_dsp_;
+
+ QString current_image_;
+
+ QProgressDialog* progress_;
+ runner runner_;
+ };
+
+
+ } // end of namespace scribo::demo::demat
+
+ } // end of namespace scribo::demo
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_DEMO_DEMAT_SRC_MAIN_WINDOW_HH
diff --git a/scribo/demo/demat/src/mln_widgets.cc b/scribo/demo/demat/src/mln_widgets.cc
new file mode 100644
index 0000000..079fc7f
--- /dev/null
+++ b/scribo/demo/demat/src/mln_widgets.cc
@@ -0,0 +1,11 @@
+#undef MLN_INCLUDE_ONLY
+
+// Windows
+#include <src/main_window.cc>
+
+// Widgets
+#include <shared/src/image_viewer.cc>
+
+// Misc
+#include <src/main.cc>
+#include <src/runner.cc>
diff --git a/scribo/demo/wizard/src/preprocessing_task.hh b/scribo/demo/demat/src/preprocessing_task.hh
similarity index 100%
copy from scribo/demo/wizard/src/preprocessing_task.hh
copy to scribo/demo/demat/src/preprocessing_task.hh
diff --git a/scribo/demo/demat/src/process_args.hh b/scribo/demo/demat/src/process_args.hh
new file mode 100644
index 0000000..5ca72cf
--- /dev/null
+++ b/scribo/demo/demat/src/process_args.hh
@@ -0,0 +1,47 @@
+// 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.
+
+#ifndef SCRIBO_DEMO_SHARED_SRC_PROCESS_ARGS_HH
+# define SCRIBO_DEMO_SHARED_SRC_PROCESS_ARGS_HH
+
+
+namespace scribo
+{
+
+ namespace demo
+ {
+
+ struct process_args
+ {
+ unsigned scale;
+ };
+
+
+ } // end of namespace scribo::demo
+
+} // end of namespace scribo
+
+
+#endif // !SCRIBO_DEMO_SHARED_SRC_PROCESS_ARGS_HH
diff --git a/scribo/demo/demat/src/runner.cc b/scribo/demo/demat/src/runner.cc
new file mode 100644
index 0000000..6972902
--- /dev/null
+++ b/scribo/demo/demat/src/runner.cc
@@ -0,0 +1,316 @@
+#include <src/runner.hh>
+
+#include <shared/src/to_mln_image.hh>
+#include <src/preprocessing_task.hh>
+#include <src/doc_type.hh>
+
+#include <mln/convert/to_qimage.hh>
+#include <mln/convert/to_qimage_nocopy.hh>
+#include <mln/fun/v2v/rgb_to_int_u.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/data/convert.hh>
+#include <mln/data/paste_without_localization.hh>
+#include <mln/io/pbm/save.hh>
+#include <mln/io/magick/load.hh>
+#include <mln/subsampling/antialiased.hh>
+
+#include <scribo/preprocessing/split_bg_fg.hh>
+#include <scribo/preprocessing/denoise.hh>
+#include <scribo/preprocessing/homogeneous_contrast.hh>
+#include <scribo/preprocessing/unskew.hh>
+#include <scribo/binarization/sauvola.hh>
+#include <scribo/binarization/sauvola_ms.hh>
+#include <scribo/binarization/simple.hh>
+
+#include <mln/logical/not.hh>
+
+namespace scribo
+{
+
+ namespace demo
+ {
+
+ QString basedir_ = "";
+
+ // FIXME: move as attribute.
+ mln::image2d<mln::value::rgb8> input_;
+
+
+ runner::runner(QObject *parent)
+ : QThread(parent)
+ {
+ process_.moveToThread(this);
+ }
+
+
+ void runner::start(const QString& filename,
+ const mln::image2d<mln::value::rgb8>& input,
+ const Doc_Type& doc_type,
+ const preprocessing_task_set_t& tasks,
+ const process_args& args)
+ {
+ filename_ = filename;
+ doc_type_ = doc_type;
+ tasks_ = tasks;
+ args_ = args;
+ input_ = input;
+
+ QThread::start();
+ }
+
+
+ void runner::run()
+ {
+ // Notification of the number of tasks.
+ emit new_progress_max_value(tasks_.size() + 2);
+
+ qDebug() << "progress steps : " << tasks_.size() + 2;
+
+ image2d<value::rgb8> ima = load();
+
+ preprocess(ima);
+
+ process();
+ }
+
+
+ image2d<value::rgb8> runner::load()
+ {
+ emit new_progress_label("Loading image");
+
+ image2d<value::rgb8> output(input_.nrows(), input_.ncols(),
+ input_.border());
+ data::paste_without_localization(input_, output);
+
+// io::magick::load(output, filename_.toStdString());
+
+ emit progress(1);
+
+ return output;
+ }
+
+
+ void runner::preprocess(const image2d<value::rgb8>& ima)
+ {
+
+ image2d<value::rgb8> tmp_color = duplicate(ima);
+
+
+ //==================
+ // Remove background
+ //==================
+ if (tasks_.contains(RemoveBg))
+ {
+ std::cout << "Foreground extraction" << std::endl;
+ emit new_progress_label("Foreground Extraction");
+
+ tmp_color = scribo::preprocessing::split_bg_fg(tmp_color, 10000, 32).second();
+
+ emit progress(1);
+ }
+
+
+ //=============================================
+ // Convert to grayscale image (always happens).
+ //=============================================
+ emit new_progress_label("Convert to gray-scale image");
+ image2d<value::int_u8>
+ intensity_ima = data::transform(tmp_color,
+ mln::fun::v2v::rgb_to_int_u<8>());
+ emit progress(1);
+
+
+ // FIXME: SUbsampling should be done at the very beginning!!!!
+ //
+ //==========
+ // Subsample
+ //==========
+ if (tasks_.contains(ReduceSize))
+ {
+ emit new_progress_label("Subsampling input image");
+ intensity_ima = mln::subsampling::antialiased(intensity_ima,
+ find_best_scale(intensity_ima));
+ emit progress(1);
+ }
+
+
+ //=============================
+ // Improve contrast homogeneity
+ //=============================
+ if (tasks_.contains(ImproveContrast))
+ {
+ std::cout << "Improve contrast homogeneity" << std::endl;
+ emit new_progress_label("Improve contrast homogeneity");
+
+ intensity_ima = arith::revert(preprocessing::homogeneous_contrast(intensity_ima, 75));
+
+ emit progress(1);
+ }
+
+
+ std::cout << intensity_ima.domain() << std::endl;
+ io::pgm::save(intensity_ima, "intensity_ima.pgm");
+
+ //==============================
+ // Binarization (always happens)
+ //==============================
+ image2d<bool> out_bool;
+ emit new_progress_label("Binarization");
+
+ if (tasks_.contains(BinarizationSauvola))
+ {
+ // FIXME: sauvola should not negate the image.
+ std::cout << "Binarization Sauvola" << std::endl;
+ out_bool = binarization::sauvola(intensity_ima);
+ }
+ else if (tasks_.contains(BinarizationSauvolaMs))
+ {
+ // FIXME: sauvola should not negate the image.
+ std::cout << "Binarization Sauvola_ms" << std::endl;
+ out_bool = binarization::sauvola_ms(intensity_ima, 51, 2, 67);
+ }
+ else if (tasks_.contains(BinarizationSimple))
+ {
+ std::cout << "Binarization Simple" << std::endl;
+ out_bool = scribo::binarization::simple(intensity_ima);
+ }
+ else
+ {
+ std::cout << "Binary image conversion" << std::endl;
+ out_bool = data::convert(bool(), intensity_ima);
+ }
+
+ emit progress(1);
+
+
+ // FIXME: remove!
+// logical::not_inplace(out_bool);
+
+ //========
+ // Denoise
+ //========
+// if (tasks_.contains(RemoveNoise))
+// {
+// std::cout << "Remove noise" << std::endl;
+// emit new_progress_label("Remove noise");
+
+// out_bool = preprocessing::denoise(out_bool, c8(), 2, 2);
+
+// emit progress(1);
+// }
+
+ //=======
+ // Unskew
+ //=======
+ if (tasks_.contains(Unskew))
+ {
+ std::cout << "Unskew" << std::endl;
+ emit new_progress_label("Unskew");
+
+ out_bool = scribo::preprocessing::unskew(out_bool).first();
+
+ emit progress(1);
+ }
+
+
+ //=========================
+ // Save preprocessed image.
+ //=========================
+ io::pbm::save(out_bool, "/tmp/tmp.pbm");
+ }
+
+
+ void runner::process()
+ {
+ QStringList args;
+
+
+ // FIXME: require binaries to ask for a filename for bboxes
+ // output files.
+ switch(doc_type_)
+ {
+ case Text_Doc:
+ emit new_progress_label("Finding text in document...");
+ qDebug() << "Running text_in_article_pbm";
+ args << "/tmp/tmp.pbm" << "/tmp/out.txt";
+
+ // Denoise.
+ if (! tasks_.contains(RemoveNoise))
+ args << "0";
+ else
+ {
+ args << "1";
+ emit progress(1); // Consider denoising as done even though it is performed later.
+ }
+
+ args << "/tmp/";
+
+ if (process_.execute(basedir_ + "/text_in_article_pbm", args))
+ {
+ qDebug() << "Error while running text_in_article_pbm.";
+ return;
+ }
+ break;
+
+ case Picture:
+ emit new_progress_label("Finding text in picture...");
+ qDebug() << "Running text_in_photo_pbm_fast";
+ args << "/tmp/tmp.pbm" << "/tmp/out.ppm" << "1" << "1" << "1";
+ if (process_.execute(basedir_ + "/text_in_photo_pbm_fast", args))
+ {
+ qDebug() << "Error while running text_in_photo_pbm_fast.";
+ return;
+ }
+ break;
+
+ case Mixed_Doc:
+ qDebug() << "Running pbm_text_in_mixed_doc";
+ if (process_.execute(basedir_ + "/pbm_text_in_mixed_doc", args))
+ {
+ qDebug() << "Error while running pbm_text_in_mixed_doc.";
+ return;
+ }
+ break;
+
+ default:
+ case Invalid_Doc:
+ qDebug() << "runner - Invalid doc type...";
+ return;
+ }
+
+ process_.waitForFinished(-1);
+
+ emit progress(1);
+
+ emit finished();
+ qDebug() << "Done";
+ }
+
+
+ void runner::stop()
+ {
+ process_.kill();
+ terminate();
+ }
+
+
+ template <typename V>
+ unsigned runner::find_best_scale(const image2d<V>& ima)
+ {
+ if (ima.nrows() > 2500
+ && ima.nrows() < 5000
+ && ima.ncols() > 2500
+ && ima.ncols() < 5000)
+ return 2;
+
+ if (ima.nrows() > 5000
+ && ima.ncols() > 5000)
+ return 3;
+
+ return 1;
+ }
+
+ } // end of namespace scribo::demo
+
+} // end of namespace scribo
diff --git a/scribo/demo/demat/src/runner.hh b/scribo/demo/demat/src/runner.hh
new file mode 100644
index 0000000..93e91bc
--- /dev/null
+++ b/scribo/demo/demat/src/runner.hh
@@ -0,0 +1,93 @@
+// 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.
+
+#ifndef SCRIBO_DEMO_SHARED_SRC_RUNNER_HH
+# define SCRIBO_DEMO_SHARED_SRC_RUNNER_HH
+
+# include <QtGui>
+# include <QProcess>
+
+# include <src/preprocessing_task.hh>
+# include <src/doc_type.hh>
+
+# include <mln/core/image/image2d.hh>
+# include <mln/value/qt/rgb32.hh>
+
+#include <src/process_args.hh>
+
+namespace scribo
+{
+
+ namespace demo
+ {
+
+
+ class runner : public QThread
+ {
+ Q_OBJECT;
+
+ public:
+ runner(QObject *parent = 0);
+
+ void start(const QString& filename,
+ const mln::image2d<mln::value::rgb8>& input,
+ const Doc_Type& doc_type,
+ const preprocessing_task_set_t& tasks,
+ const process_args& args);
+
+ void stop();
+
+ signals:
+ void new_intermediate_result(const QImage& ima);
+ void new_progress_max_value(unsigned i);
+ void new_progress_label(const QString& msg);
+ void progress(unsigned i);
+ void finished();
+
+ private: // members
+ mln::image2d<mln::value::rgb8> load();
+ void preprocess(const mln::image2d<mln::value::rgb8>& ima);
+ void process();
+ virtual void run();
+
+ template <typename V>
+ unsigned find_best_scale(const mln::image2d<V>& ima);
+
+ private: // attributes
+ QProcess process_;
+ Doc_Type doc_type_;
+ QSet<Preprocessing_Task> tasks_;
+ QString filename_;
+ process_args args_;
+ };
+
+
+
+ } // end of namespace scribo::demo
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_DEMO_SHARED_SRC_RUNNER_HH
diff --git a/scribo/demo/demat/ui/main_window.ui b/scribo/demo/demat/ui/main_window.ui
new file mode 100644
index 0000000..a552500
--- /dev/null
+++ b/scribo/demo/demat/ui/main_window.ui
@@ -0,0 +1,366 @@
+<ui version="4.0" >
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>666</width>
+ <height>647</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>MainWindow</string>
+ </property>
+ <widget class="QWidget" name="centralwidget" >
+ <layout class="QVBoxLayout" name="verticalLayout" >
+ <item>
+ <widget class="QSplitter" name="splitter" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <widget class="scribo::demo::shared::image_viewer" name="viewer_" />
+ <widget class="QTextEdit" name="text_" />
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout" >
+ <item>
+ <spacer name="horizontalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="run_btn" >
+ <property name="text" >
+ <string>&Run</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>666</width>
+ <height>24</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menu_File" >
+ <property name="title" >
+ <string>&File</string>
+ </property>
+ <addaction name="action_Open" />
+ <addaction name="separator" />
+ <addaction name="action_Quit" />
+ </widget>
+ <widget class="QMenu" name="menuWindow" >
+ <property name="title" >
+ <string>&Dialogs</string>
+ </property>
+ <addaction name="actionOptions" />
+ <addaction name="actionAdvanced_options" />
+ </widget>
+ <addaction name="menu_File" />
+ <addaction name="menuWindow" />
+ </widget>
+ <widget class="QStatusBar" name="statusbar" />
+ <widget class="QDockWidget" name="options_dock_" >
+ <property name="font" >
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="floating" >
+ <bool>false</bool>
+ </property>
+ <property name="features" >
+ <set>QDockWidget::AllDockWidgetFeatures</set>
+ </property>
+ <property name="allowedAreas" >
+ <set>Qt::AllDockWidgetAreas</set>
+ </property>
+ <property name="windowTitle" >
+ <string>Options</string>
+ </property>
+ <attribute name="dockWidgetArea" >
+ <number>1</number>
+ </attribute>
+ <widget class="QWidget" name="dockWidgetContents" >
+ <layout class="QVBoxLayout" name="verticalLayout_7" >
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_4" >
+ <item>
+ <widget class="QCheckBox" name="removeBg" >
+ <property name="font" >
+ <font>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="text" >
+ <string>Remove background (slow)</string>
+ </property>
+ <property name="checked" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="unskew" >
+ <property name="font" >
+ <font>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="text" >
+ <string>Unskew</string>
+ </property>
+ <property name="checked" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="removeNoise" >
+ <property name="enabled" >
+ <bool>true</bool>
+ </property>
+ <property name="font" >
+ <font>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="text" >
+ <string>Remove noise</string>
+ </property>
+ <property name="checked" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="improveContrast" >
+ <property name="enabled" >
+ <bool>true</bool>
+ </property>
+ <property name="font" >
+ <font>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="text" >
+ <string>Improve brightness/contrast</string>
+ </property>
+ <property name="checked" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_3" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <widget class="QDockWidget" name="advanced_dock_" >
+ <property name="font" >
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="windowTitle" >
+ <string>Advanced options</string>
+ </property>
+ <attribute name="dockWidgetArea" >
+ <number>1</number>
+ </attribute>
+ <widget class="QWidget" name="dockWidgetContents_3" >
+ <layout class="QVBoxLayout" name="verticalLayout_8" >
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2" >
+ <item>
+ <widget class="QCheckBox" name="reduceSize" >
+ <property name="font" >
+ <font>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="text" >
+ <string>Run on subsampled image</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_6" >
+ <item>
+ <widget class="QLabel" name="binarizeLbl" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font" >
+ <font>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="text" >
+ <string>Binarization method:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="binarizationCBox" >
+ <property name="font" >
+ <font>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="currentIndex" >
+ <number>2</number>
+ </property>
+ <item>
+ <property name="text" >
+ <string>Global threshold</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Local threshold</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Local threshold multi-scale</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <action name="action_Open" >
+ <property name="text" >
+ <string>&Open</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+O</string>
+ </property>
+ </action>
+ <action name="action_Quit" >
+ <property name="text" >
+ <string>&Quit</string>
+ </property>
+ </action>
+ <action name="actionDocument_Type" >
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ <property name="text" >
+ <string>Document Type</string>
+ </property>
+ </action>
+ <action name="actionOptions" >
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ <property name="text" >
+ <string>Options</string>
+ </property>
+ </action>
+ <action name="actionAdvanced_options" >
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ <property name="text" >
+ <string>Advanced options</string>
+ </property>
+ </action>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>scribo::demo::shared::image_viewer</class>
+ <extends>QGraphicsView</extends>
+ <header location="global" >shared/src/image_viewer.hh</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>action_Quit</sender>
+ <signal>activated()</signal>
+ <receiver>MainWindow</receiver>
+ <slot>close()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>-1</x>
+ <y>-1</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>332</x>
+ <y>298</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/scribo/demo/shared/src/crop_item.cc b/scribo/demo/shared/src/crop_item.cc
index 100ac7d..70598fa 100644
--- a/scribo/demo/shared/src/crop_item.cc
+++ b/scribo/demo/shared/src/crop_item.cc
@@ -46,6 +46,11 @@ namespace scribo
grabMouse();
}
+ crop_item::~crop_item()
+ {
+
+ }
+
void crop_item::reset()
{
if (parentItem())
@@ -54,15 +59,15 @@ namespace scribo
cropRect_ = QRectF(20, 20, 100, 70);
}
- const QRectF& crop_item::cropRect() const
+ QRectF crop_item::cropRect() const
{
- return cropRect_;
+ return mapToScene(cropRect_).boundingRect();
}
QRectF crop_item::boundingRect() const
{
- return parentItem()->boundingRect();
+ return scene()->sceneRect();
}
void crop_item::paint(QPainter *painter,
@@ -84,15 +89,16 @@ namespace scribo
painter->fillPath(windowPath, QColor(0x33, 0x33, 0x33, 0xcc));
// Draw Crop Rect
- painter->setPen(QPen(QColor(0xdd, 0xdd, 0xdd), 1));
+ // QColor(0xdd, 0xdd, 0xdd)
+ painter->setPen(QPen(Qt::magenta, 3));
painter->drawPath(cropPath);
int topRightX = cropRect_.x() + cropRect_.width();
int bottomY = cropRect_.y() + cropRect_.height();
QPainterPath borderPath;
- int corner_width = cropRect_.width() / 6.f;
- int corner_height = cropRect_.height() / 6.f;
+ int corner_width = std::min(int(cropRect_.width() / 6.f), 80);
+ int corner_height = std::min(int(cropRect_.height() / 6.f), 80);
// Top-Left Corner
painter->drawRect(QRectF(cropRect_.x(), cropRect_.y(),
@@ -128,8 +134,8 @@ namespace scribo
cropResize_ = CropItemResizeNone;
if (event->buttons() & Qt::LeftButton)
{
- int wsize = cropRect_.width() / 6.f;
- int hsize = cropRect_.height() / 6.f;
+ int wsize = std::min(int(cropRect_.width() / 6.f), 80);
+ int hsize = std::min(int(cropRect_.height() / 6.f), 80);
int rightX = cropRect_.x() + cropRect_.width() - wsize;
int leftX = cropRect_.x();
@@ -305,6 +311,29 @@ namespace scribo
}
+ void crop_item::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * event)
+ {
+ QGraphicsItem::mouseDoubleClickEvent(event);
+
+ switch (cropResize_)
+ {
+ case CropItemResizeNone:
+ if (!cropRect_.contains(event->pos()))
+ return;
+
+ setCursor(Qt::SizeAllCursor);
+
+ if (!(event->buttons() & Qt::LeftButton))
+ return;
+
+ emit ready_for_crop();
+ break;
+
+ default:
+ break;
+ }
+ }
+
} // end of namespace scribo::demo::shared
} // end of namespace scribo::demo
diff --git a/scribo/demo/shared/src/crop_item.hh b/scribo/demo/shared/src/crop_item.hh
index c0b1394..d342f23 100644
--- a/scribo/demo/shared/src/crop_item.hh
+++ b/scribo/demo/shared/src/crop_item.hh
@@ -50,11 +50,15 @@ namespace scribo
namespace shared
{
- class crop_item : public QGraphicsItem
+ class crop_item : public QObject, public QGraphicsItem
{
+ Q_OBJECT;
+
public:
crop_item(QGraphicsItem *parent);
- const QRectF& cropRect() const;
+ virtual ~crop_item();
+
+ QRectF cropRect() const;
QRectF boundingRect() const;
void paint (QPainter *painter,
@@ -67,9 +71,13 @@ namespace scribo
void mousePressEvent (QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent (QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent * event);
// void updateCursor(QGraphicsSceneMouseEvent *event);
+ signals:
+ void ready_for_crop();
+
private:
enum CropItemResize
{
diff --git a/scribo/demo/shared/src/image_viewer.cc b/scribo/demo/shared/src/image_viewer.cc
index b61f86b..f9467dc 100644
--- a/scribo/demo/shared/src/image_viewer.cc
+++ b/scribo/demo/shared/src/image_viewer.cc
@@ -38,7 +38,8 @@ namespace scribo
{
image_viewer::image_viewer(QWidget *parent)
- : QWidget(parent), image_(0), selection_(0), angle_(0)
+ : QWidget(parent), image_(0), selection_(0), angle_(0),
+ zoom_fixed_(false)
{
setupUi(this);
@@ -87,7 +88,8 @@ namespace scribo
viewer_->show();
}
- void image_viewer::draw_image(const mln::image2d<dsp_data_t>& ima)
+ template <typename V>
+ void image_viewer::draw_image(const mln::image2d<V>& ima)
{
QImage
qima = mln::convert::to_qimage_nocopy(ima);
@@ -127,18 +129,15 @@ namespace scribo
if (pixmap.width() > viewer_->maximumViewportSize().width())
viewer_->fitInView(image_->boundingRect(), Qt::KeepAspectRatio);
- zoomLabel->setEnabled(true);
- zoomIn->setEnabled(true);
- zoomOut->setEnabled(true);
- zoomFixed->setEnabled(true);
- zoomOriginal->setEnabled(true);
+ enable_widgets(true);
image_->translate(origin.x(), origin.y());
+
viewer_->setSceneRect(image_->sceneBoundingRect());
// Restore selection mode if needed
- set_selection_enabled(restore_selection);
+ on_crop_btn_toggled(restore_selection);
}
@@ -150,8 +149,11 @@ namespace scribo
void image_viewer::resizeEvent(QResizeEvent * event)
{
- if (image_ != 0)
- resize_image(image_->boundingRect());
+ if (zoom_fixed_)
+ on_zoomFixed_clicked();
+ else
+ on_zoomOriginal_clicked();
+
event->ignore();
}
@@ -238,12 +240,14 @@ namespace scribo
void image_viewer::on_zoomFixed_clicked()
{
+ zoom_fixed_ = true;
if (image_ != 0)
resize_image(image_->boundingRect());
}
void image_viewer::on_zoomOriginal_clicked()
{
+ zoom_fixed_ = false;
if (image_ != 0)
resize_image(viewer_->viewport()->geometry());
}
@@ -259,12 +263,17 @@ namespace scribo
}
}
- void image_viewer::set_selection_enabled(bool b)
+ void image_viewer::on_crop_btn_toggled(bool b)
{
if (b)
{
if (selection_ == 0)
+ {
selection_ = new crop_item(image_);
+ connect(selection_, SIGNAL(ready_for_crop()),
+ this, SIGNAL(ready_for_crop()));
+
+ }
}
else
{
@@ -274,6 +283,18 @@ namespace scribo
}
+ void image_viewer::enable_crop_tool(bool b)
+ {
+ crop_btn->setChecked(b);
+ }
+
+
+ void image_viewer::set_selection_enabled(bool b)
+ {
+ crop_btn->setVisible(b);
+ }
+
+
void image_viewer::set_rotation_enabled(bool b)
{
angle_ = 0;
@@ -290,12 +311,11 @@ namespace scribo
}
- const QRectF& image_viewer::selection() const
+ QRectF image_viewer::selection() const
{
static QRectF invalid_selection;
- mln_assertion(has_selection());
- if (selection_)
+ if (has_selection())
return selection_->cropRect();
return invalid_selection;
@@ -337,6 +357,23 @@ namespace scribo
on_slider_valueChanged(sli);
}
+
+ void image_viewer::enable_widgets(bool b)
+ {
+ zoomLabel->setEnabled(b);
+ zoomIn->setEnabled(b);
+ zoomOut->setEnabled(b);
+ zoomFixed->setEnabled(b);
+ zoomOriginal->setEnabled(b);
+
+ rotate_ccw_btn->setEnabled(b);
+ rotate_cw_btn->setEnabled(b);
+ rotate_lbl->setEnabled(b);
+
+ crop_btn->setEnabled(b);
+ }
+
+
} // end of namespace scribo::demo::shared
} // end of namespace scribo::demo
diff --git a/scribo/demo/shared/src/image_viewer.hh b/scribo/demo/shared/src/image_viewer.hh
index 628f5d4..3fe23ab 100644
--- a/scribo/demo/shared/src/image_viewer.hh
+++ b/scribo/demo/shared/src/image_viewer.hh
@@ -60,7 +60,8 @@ namespace scribo
image_viewer(QWidget *parent = 0);
~image_viewer();
- void draw_image(const mln::image2d<dsp_data_t>& ima);
+ template <typename V>
+ void draw_image(const mln::image2d<V>& ima);
void draw_image(const QPixmap& pixmap);
void draw_image(const QPixmap& pixmap, const QPoint& origin);
@@ -76,7 +77,7 @@ namespace scribo
bool has_selection() const;
- const QRectF& selection() const;
+ QRectF selection() const;
bool has_rotation() const;
qreal rotation() const;
@@ -91,12 +92,16 @@ namespace scribo
void keyPressEvent(QKeyEvent *event);
void resizeEvent(QResizeEvent * event);
+ void enable_widgets(bool b);
+
private slots:
void visible_slider(bool b);
void move_vertical_sliders(int value);
void move_horizontal_sliders(int value);
+ void on_crop_btn_toggled(bool b);
+
void on_slider_valueChanged(int sli);
void on_rotate_cw_btn_clicked();
@@ -111,10 +116,11 @@ namespace scribo
public slots:
void set_image_layer_count(unsigned nslis);
void update_image(const mln::image2d<dsp_data_t>& ima);
-
+ void enable_crop_tool(bool b);
signals:
void slider_valueChanged(int sli);
+ void ready_for_crop();
private: // attributes
QGraphicsPixmapItem* image_;
@@ -122,6 +128,8 @@ namespace scribo
bool mouse_moving_;
QPoint p_start_;
qreal angle_;
+
+ bool zoom_fixed_;
};
diff --git a/scribo/demo/shared/ui/image_viewer.ui b/scribo/demo/shared/ui/image_viewer.ui
index d6f80cb..c129b97 100644
--- a/scribo/demo/shared/ui/image_viewer.ui
+++ b/scribo/demo/shared/ui/image_viewer.ui
@@ -5,7 +5,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>464</width>
+ <width>529</width>
<height>350</height>
</rect>
</property>
@@ -37,7 +37,33 @@
</spacer>
</item>
<item>
+ <widget class="QPushButton" name="crop_btn" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>16777215</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string>Crop</string>
+ </property>
+ <property name="icon" >
+ <iconset resource="../shared.qrc" >
+ <normaloff>:/icons/icons/crop-icon.png</normaloff>:/icons/icons/crop-icon.png</iconset>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QLabel" name="rotate_lbl" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
<property name="text" >
<string>Rotate:</string>
</property>
@@ -45,6 +71,9 @@
</item>
<item>
<widget class="QPushButton" name="rotate_cw_btn" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
<property name="toolTip" >
<string>Rotate clock-wise</string>
</property>
@@ -59,6 +88,9 @@
</item>
<item>
<widget class="QPushButton" name="rotate_ccw_btn" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
<property name="toolTip" >
<string>Rotate counter-clock-wise</string>
</property>
--
1.5.6.5
1
0