* src/Makefile.am,
* src/binarization/Makefile.am,
* src/preprocessing/Makefile.am: Add new targets.
* src/preprocessing/denoising.cc: New.
* src/preprocessing/split_bg_fg.cc: Fix usage.
* src/text_in_article.cc,
* src/text_in_photo_ppm_fast.cc: Update code according last
changes in core classes.
* src/text_in_photo_ppm_fast_2.cc: New example.
---
scribo/ChangeLog | 18 +
scribo/src/Makefile.am | 26 ++
scribo/src/binarization/Makefile.am | 2 +
scribo/src/preprocessing/Makefile.am | 2 +
.../denoising.cc} | 71 +++-
scribo/src/preprocessing/split_bg_fg.cc | 2 +-
scribo/src/text_in_article.cc | 459 +++++++++++++-------
scribo/src/text_in_photo_ppm_fast.cc | 215 +++++-----
...oto_ppm_fast.cc => text_in_photo_ppm_fast_2.cc} | 259 +++--------
9 files changed, 589 insertions(+), 465 deletions(-)
copy scribo/src/{filter/objects_large.cc => preprocessing/denoising.cc} (55%)
copy scribo/src/{text_in_photo_ppm_fast.cc => text_in_photo_ppm_fast_2.cc} (71%)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 7af1c38..13deec7 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,23 @@
2010-02-19 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Add and update examples.
+
+ * src/Makefile.am,
+ * src/binarization/Makefile.am,
+ * src/preprocessing/Makefile.am: Add new targets.
+
+ * src/preprocessing/denoising.cc: New.
+
+ * src/preprocessing/split_bg_fg.cc: Fix usage.
+
+ * src/text_in_article.cc,
+ * src/text_in_photo_ppm_fast.cc: Update code according last
+ changes in core classes.
+
+ * src/text_in_photo_ppm_fast_2.cc: New example.
+
+2010-02-19 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Small fixes.
* binarization/sauvola_ms.hh: Remove a useless include.
diff --git a/scribo/src/Makefile.am b/scribo/src/Makefile.am
index 6cc4229..a206e04 100644
--- a/scribo/src/Makefile.am
+++ b/scribo/src/Makefile.am
@@ -31,13 +31,19 @@ SUBDIRS = \
text
bin_PROGRAMS = \
+ pbm_lines_in_doc \
text_in_photo \
text_in_photo_ppm \
+ text_in_photo_ppm_fast \
+ text_in_photo_ppm_fast_2 \
text_in_photo_invert
+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_ppm_fast_2_SOURCES = text_in_photo_ppm_fast_2.cc
text_in_photo_invert_SOURCES = text_in_photo_invert.cc
@@ -65,5 +71,25 @@ if HAVE_TIFF
$(TIFF_LDFLAGS) \
-lpthread -lhpdf
+ bin_PROGRAMS += text_in_article
+ text_in_article_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(TESSERACT_CPPFLAGS) \
+ $(TIFF_CPPFLAGS)
+ text_in_article_LDFLAGS = $(AM_LDFLAGS) \
+ $(TESSERACT_LDFLAGS) \
+ $(TIFF_LDFLAGS) \
+ -lpthread
+# -lhpdf
+ text_in_article_SOURCES = text_in_article.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
+
endif HAVE_TIFF
endif HAVE_TESSERACT
diff --git a/scribo/src/binarization/Makefile.am b/scribo/src/binarization/Makefile.am
index 531d4cf..2c47ea1 100644
--- a/scribo/src/binarization/Makefile.am
+++ b/scribo/src/binarization/Makefile.am
@@ -22,11 +22,13 @@ include $(top_srcdir)/scribo/scribo.mk
bin_PROGRAMS = \
sauvola \
sauvola_ms \
+ sauvola_ms_slow \
sauvola_pgm \
simple
sauvola_SOURCES = sauvola.cc
sauvola_ms_SOURCES = sauvola_ms.cc
+sauvola_ms_slow_SOURCES = sauvola_ms_slow.cc
sauvola_pgm_SOURCES = sauvola_pgm.cc
simple_SOURCES = simple.cc
diff --git a/scribo/src/preprocessing/Makefile.am b/scribo/src/preprocessing/Makefile.am
index 086a70f..2422d87 100644
--- a/scribo/src/preprocessing/Makefile.am
+++ b/scribo/src/preprocessing/Makefile.am
@@ -20,11 +20,13 @@
include $(top_srcdir)/scribo/scribo.mk
bin_PROGRAMS = \
+ denoising \
preprocess \
split_bg_fg \
split_bg_fg_ms \
unskew
+denoising_SOURCES = denoising.cc
preprocess_SOURCES = preprocess.cc
split_bg_fg_SOURCES = split_bg_fg.cc
split_bg_fg_ms_SOURCES = split_bg_fg_ms.cc
diff --git a/scribo/src/filter/objects_large.cc b/scribo/src/preprocessing/denoising.cc
similarity index 55%
copy from scribo/src/filter/objects_large.cc
copy to scribo/src/preprocessing/denoising.cc
index a665032..769f75b 100644
--- a/scribo/src/filter/objects_large.cc
+++ b/scribo/src/preprocessing/denoising.cc
@@ -27,18 +27,20 @@
#include <mln/core/alias/neighb2d.hh>
#include <mln/data/convert.hh>
#include <mln/io/pbm/all.hh>
+#include <mln/value/label.hh>
+#include <mln/accu/math/count.hh>
+#include <mln/labeling/relabel.hh>
+#include <mln/labeling/compute.hh>
+#include <mln/labeling/foreground.hh>
-#include <mln/value/label_16.hh>
-
-#include <scribo/filter/objects_large.hh>
#include <scribo/debug/usage.hh>
const char *args_desc[][2] =
{
{ "input.pbm", "A binary image. 'True' for objects,
'False'\
for the background." },
- { "max_area", "The maximum object area value. Objects with an area
greater\
-than this value are removed." },
+ { "nbh", "Select the neighborhood used for checking neighbors.
'4' will use C4, '8' will use C8." },
+ { "n_nbh", "The minimum neighbor count to be set to true." },
{0, 0}
};
@@ -46,10 +48,10 @@ int main(int argc, char *argv[])
{
using namespace mln;
- if (argc != 4)
+ if (argc != 5)
return scribo::debug::usage(argv,
- "Filter too large objects",
- "input.pbm max_area output.pbm",
+ "Remove noise.",
+ "input.pbm nbh min_nbh output.pbm",
args_desc,
"A binary image.");
@@ -59,13 +61,54 @@ int main(int argc, char *argv[])
I input;
io::pbm::load(input, argv[1]);
- value::label_16 nobjects;
- typedef object_image(mln_ch_value_(I,value::label_16)) obj_ima_t;
- obj_ima_t objects
- = scribo::primitive::extract::objects(input, c8(), nobjects);
+ typedef value::label<30> V;
+
+ neighb2d nbh;
+ if (atoi(argv[2]) == 4)
+ nbh = c4();
+ else if (atoi(argv[2]) == 8)
+ nbh = c8();
+ else
+ {
+ std::cout << "Error: nbh must be set to '4' or '8'!"
<< std::endl;
+ return 1;
+ }
+
+ unsigned min_nbh = atoi(argv[3]);
+
+
+ V nlabels;
+ image2d<V> lbl = labeling::foreground(input, nbh, nlabels);
+ std::cout << nlabels << std::endl;
+
+
+ util::array<unsigned> result = labeling::compute(accu::meta::math::count(), lbl,
nlabels);
+
+ fun::i2v::array<bool> f(static_cast<unsigned>(nlabels) + 1, true);
+ for (unsigned i = 1; i <= nlabels; ++i)
+ if (result(i) < min_nbh)
+ f(i) = false;
+
+ labeling::relabel_inplace(lbl, nlabels, f);
+ std::cout << nlabels << std::endl;
+
+
+// mln_piter_(I) p(input.domain());
+// mln_niter_(neighb2d) n(nbh, p);
+// unsigned n_nbh;
+// for_all(p)
+// if (input(p))
+// {
+// n_nbh = 0;
+// for_all(n)
+// if (input(n))
+// ++n_nbh;
+
+// if (n_nbh < min_nbh)
+// input(p) = false;
+// }
- obj_ima_t filtered = scribo::filter::objects_large(objects, atoi(argv[2]));
- io::pbm::save(data::convert(bool(), filtered), argv[3]);
+ io::pbm::save(data::convert(bool(), lbl), argv[4]);
trace::exiting("main");
diff --git a/scribo/src/preprocessing/split_bg_fg.cc
b/scribo/src/preprocessing/split_bg_fg.cc
index a1aab52..0d7ba8a 100644
--- a/scribo/src/preprocessing/split_bg_fg.cc
+++ b/scribo/src/preprocessing/split_bg_fg.cc
@@ -49,7 +49,7 @@ int main(int argc, char *argv[])
if (argc != 6)
return scribo::debug::usage(argv,
"Split background and foreground.",
- "input.pbm bg.ppm fg.ppm",
+ "input.pbm lambda delta bg.ppm fg.ppm",
args_desc, "The foreground image.");
typedef image2d<value::rgb8> I;
diff --git a/scribo/src/text_in_article.cc b/scribo/src/text_in_article.cc
index d140719..876eba5 100644
--- a/scribo/src/text_in_article.cc
+++ b/scribo/src/text_in_article.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,6 +26,7 @@
#include <libgen.h>
+#include <fstream>
#include <iostream>
#include <mln/core/image/image2d.hh>
@@ -32,6 +34,7 @@
#include <mln/io/pbm/all.hh>
#include <mln/io/ppm/save.hh>
+#include <mln/io/dump/save.hh>
#include <mln/math/min.hh>
@@ -43,43 +46,58 @@
#include <mln/draw/box.hh>
#include <mln/draw/line.hh>
+#include <mln/data/convert.hh>
+
#include <mln/extension/adjust.hh>
#include <mln/accu/stat/median_h.hh>
-#include <scribo/draw/bounding_boxes.hh>
+#include <mln/labeling/colorize.hh>
+#include <mln/labeling/relabel.hh>
+
+//#include <scribo/draw/bounding_boxes.hh>
+#include <scribo/draw/bounding_box_links.hh>
-#include <scribo/primitive/extract/objects.hh>
+#include <scribo/primitive/extract/components.hh>
#include <scribo/primitive/link/merge_double_link.hh>
#include <scribo/primitive/link/with_single_left_link_dmax_ratio.hh>
#include <scribo/primitive/link/with_single_right_link_dmax_ratio.hh>
#include <scribo/primitive/group/apply.hh>
-#include <scribo/primitive/group/from_double_link.hh>
+// #include <scribo/primitive/group/from_double_link.hh>
#include <scribo/primitive/group/from_single_link.hh>
#include <scribo/filter/object_links_bbox_h_ratio.hh>
#include <scribo/filter/objects_small.hh>
-#include <scribo/filter/objects_thin.hh>
-#include <scribo/filter/objects_thick.hh>
+// #include <scribo/filter/objects_thin.hh>
+// #include <scribo/filter/objects_thick.hh>
+
+// #include <scribo/filter/object_groups_small.hh>
-#include <scribo/filter/object_groups_small.hh>
+// #include <scribo/debug/decision_image.hh>
+// #include <scribo/debug/save_bboxes_image.hh>
+// #include <scribo/debug/save_bboxes_image.hh>
+// #include <scribo/debug/save_linked_bboxes_image.hh>
+
+#include <scribo/core/line_set.hh>
+#include <scribo/io/xml/save_text_lines.hh>
-#include <scribo/debug/decision_image.hh>
-#include <scribo/debug/save_bboxes_image.hh>
-#include <scribo/debug/save_bboxes_image.hh>
-#include <scribo/debug/save_linked_bboxes_image.hh>
#include <scribo/debug/usage.hh>
#include <scribo/make/debug_filename.hh>
+//#include <scribo/text/recognition.hh>
+
+#include <scribo/text/merging.hh>
+
+
const char *args_desc[][2] =
{
- { "input.pbm", "A binary image. 'False' for objects,
'True'\
+ { "input.pbm", "A binary image. 'False' for object,
'True'\
for the background." },
{ "debug_dir", "Output directory for debug image" },
{0, 0}
@@ -105,223 +123,340 @@ int main(int argc, char* argv[])
image2d<bool> input;
- io::pbm::load(input, argv[1]);
-
- typedef image2d<value::label_16> L;
+ mln::io::pbm::load(input, argv[1]);
- /// Finding objects.
- std::cout << "Finding objects..." << std::endl;
- value::label_16 nobjects;
- object_image(L)
- objects = scribo::primitive::extract::objects(input,
- c8(),
- nobjects);
+ typedef value::label_16 V;
+ typedef image2d<V> L;
+ /// Finding components.
+ std::cout << "Finding components..." << std::endl;
+ V ncomponents;
+ component_set<L>
+ components = scribo::primitive::extract::components(input,
+ c8(),
+ ncomponents);
/// First filtering.
- std::cout << "Filtering objects..." << std::endl;
- object_image(L) filtered_objects
- = scribo::filter::objects_small(objects, 6);
+ std::cout << "Filtering components..." << std::endl;
+ component_set<L> filtered_components
+ = scribo::filter::components_small(components, 6);
+
+ {
+ unsigned none = 0, ignored = 0;
+ for_all_comps(i, filtered_components)
+ {
+ if (filtered_components.info(i).tag() == component::Ignored)
+ ++ignored;
+ else
+ ++none;
+ }
+ std::cout << "stats - none = " << none << " -
ignored = " << ignored << std::endl;
+
+ }
/// Linking potential objects
std::cout << "Linking objects..." << std::endl;
object_links<L> left_link
- = primitive::link::with_single_left_link_dmax_ratio(filtered_objects);
+ = primitive::link::with_single_left_link_dmax_ratio(filtered_components, 2);
object_links<L> right_link
- = primitive::link::with_single_right_link_dmax_ratio(filtered_objects);
-
+ = primitive::link::with_single_right_link_dmax_ratio(filtered_components, 2);
// Validating left and right links.
object_links<L>
- merged_links = primitive::link::merge_double_link(filtered_objects,
+ merged_links = primitive::link::merge_double_link(filtered_components,
left_link,
right_link);
-#ifndef NOUT
- if (argc == 4)
- {
- image2d<value::rgb8> output = data::convert(value::rgb8(), input);
- scribo::draw::bounding_box_links(output,
- merged_links,
- literal::green);
-
- util::array<bool> drawn(objects.nlabels(), 0);
- for_all_components(i, objects.bboxes())
- if (merged_links[i] == i && ! drawn(i))
- {
- mln::draw::box(output, objects.bbox(i), literal::orange);
- drawn[i] = true;
- }
- else
- {
- mln::draw::box(output, objects.bbox(i), literal::blue);
- mln::draw::box(output, objects.bbox(merged_links[i]), literal::blue);
- drawn[i] = true;
- drawn[merged_links[i]] = true;
- }
-
- io::ppm::save(output, scribo::make::debug_filename("links.ppm"));
- }
-#endif
+// #ifndef NOUT
+// if (argc == 4)
+// {
+// image2d<value::rgb8> output = data::convert(value::rgb8(), input);
+// scribo::draw::bounding_box_links(output,
+// merged_links,
+// literal::green);
+// mln::util::array<bool>
drawn(static_cast<unsigned>(filtered_components.nelements()) + 1, 0);
+// for_all_comps(i, filtered_components)
+// if (filtered_components(i).tag() != component::Ignored)
+// {
+// if (merged_links[i] == i && ! drawn(i))
+// {
+// mln::draw::box(output, filtered_components(i).bbox(), literal::orange);
+// drawn[i] = true;
+// }
+// else
+// {
+// mln::draw::box(output, filtered_components(i).bbox(), literal::blue);
+// mln::draw::box(output, filtered_components(merged_links[i]).bbox(),
literal::blue);
+// drawn[i] = true;
+// drawn[merged_links[i]] = true;
+// }
+// }
+
+// mln::io::ppm::save(output, scribo::make::debug_filename("links.ppm"));
+// }
+// #endif
// Remove links if bboxes have too different sizes.
object_links<L> hratio_filtered_links
- = filter::object_links_bbox_h_ratio(filtered_objects,
+ = filter::object_links_bbox_h_ratio(filtered_components,
merged_links,
- 2.0f);
+ 2.5f);
-#ifndef NOUT
- if (argc == 4)
- {
- image2d<value::rgb8>
- hratio_decision_image = scribo::debug::decision_image(input,
- merged_links,
- hratio_filtered_links);
- io::ppm::save(hratio_decision_image,
- scribo::make::debug_filename("hratio_links_decision_image.ppm"));
- }
-#endif
+// #ifndef NOUT
+// if (argc == 4)
+// {
+// image2d<value::rgb8>
+// hratio_decision_image = scribo::debug::decision_image(input,
+// merged_links,
+// hratio_filtered_links);
+// io::ppm::save(hratio_decision_image,
+// scribo::make::debug_filename("hratio_links_decision_image.ppm"));
+// }
+// #endif
- // FIXME: from_single_link should return a packed object_groups?
- //
- //######
+// // FIXME: from_single_link should return a packed object_groups?
+// //
+// //######
object_groups<L>
- groups = primitive::group::from_single_link(filtered_objects,
+ groups = primitive::group::from_single_link(filtered_components,
hratio_filtered_links);
- value::label_16 n_groups;
- mln::fun::i2v::array<value::label_16>
- groups_packed = mln::make::relabelfun(groups,
- filtered_objects.nlabels(),
- n_groups);
- //######
+// value::label_16 n_groups;
+// mln::fun::i2v::array<value::label_16>
+// groups_packed = mln::make::relabelfun(groups,
+// filtered_objects.nlabels(),
+// n_groups);
+// //######
- std::cout << "Grouping objects..." << std::endl;
- object_image(L)
- grouped_objects = primitive::group::apply(filtered_objects, groups);
+// mln::util::array<line_stats_extra> line_stats;
+ line_set<L>
+ lines = scribo::make::line_set(hratio_filtered_links, groups);
- // Compute min_row/max_row median
- std::cout << "Preparing output" << std::endl;
+
+
+ // Bboxes image.
{
image2d<value::rgb8> output = data::convert(value::rgb8(), input);
-// scribo::draw::bounding_box_links(output,
-// filtered_objects.bboxes(),
-// hratio_filtered_links,
-// literal::green);
-
- typedef mln::value::int_u<10> median_t;
- typedef mln::accu::stat::median_h<median_t> accu_t;
- util::array<accu_t>
- med_min_row(static_cast<unsigned>(grouped_objects.nlabels()) + 1),
- med_max_row(static_cast<unsigned>(grouped_objects.nlabels()) + 1);
+ for_all_lines(l, lines)
+ if (lines(l).tag() != line::Ignored)
+ mln::draw::box(output, lines(l).bbox(), literal::red);
-// std::cout << "Find median min/max rows" << std::endl;
- for_all_components(i, filtered_objects.bboxes())
- {
- if (groups_packed(i) != 0)
- {
- med_min_row(groups_packed(i)).take(filtered_objects.bbox(i).pmin().row() -
grouped_objects.bbox(groups_packed(i)).pmin().row());
+ mln::io::ppm::save(output,
+ scribo::make::debug_filename("step1_bboxes.ppm"));
+ }
- med_max_row(groups_packed(i)).take(grouped_objects.bbox(groups_packed(i)).pmax().row() -
filtered_objects.bbox(i).pmax().row());
- }
- }
+ // Bboxes enlarged
+ {
+ image2d<value::rgb8> output = data::convert(value::rgb8(), input);
- // Output
- std::cout << "Drawing bboxes" << std::endl;
- util::array<bool> drawn(static_cast<unsigned>(filtered_objects.nlabels())
+ 1, 0);
- util::array<bool> single(static_cast<unsigned>(grouped_objects.nlabels())
+ 1);
- for_all_components(i, filtered_objects.bboxes())
- if (hratio_filtered_links[i] == i && ! drawn(i))
+ for_all_lines(l, lines)
+ if (lines(l).tag() != line::Ignored)
{
- mln::draw::box(output, filtered_objects.bbox(i), literal::orange);
- drawn[i] = true;
- single(groups_packed(i)) = true;
+ if (text::internal::looks_like_a_text_line(lines(l)))
+ {
+ box2d
+ b = text::internal::enlarge(lines(l).bbox(),
+ text::internal::delta_of_line(lines(l)));
+ b.crop_wrt(input.domain());
+ mln::draw::box(output, b, literal::green);
+ }
+ else
+ mln::draw::box(output, lines(l).bbox(), literal::red);
}
- else
+
+ mln::io::ppm::save(output,
+ scribo::make::debug_filename("step1_bboxes_enlarged.ppm"));
+ }
+
+ // Looks like a text line
+ {
+ image2d<value::rgb8> output = data::convert(value::rgb8(), input);
+
+ for_all_lines(l, lines)
+ if (lines(l).tag() != line::Ignored)
{
- mln::draw::box(output, filtered_objects.bbox(i), literal::blue);
- mln::draw::box(output, filtered_objects.bbox(hratio_filtered_links[i]),
- literal::blue);
- drawn[i] = true;
- drawn[hratio_filtered_links[i]] = true;
- single(groups_packed(i)) = false;
+ if (text::internal::looks_like_a_text_line(lines(l)))
+ mln::draw::box(output, lines(l).bbox(), literal::green);
+ else
+ mln::draw::box(output, lines(l).bbox(), literal::red);
}
-// std::cout << "Drawing median lines" << std::endl;
- for_all_components(i, grouped_objects.bboxes())
- {
- if (! single(i))
+ mln::io::ppm::save(output,
+ scribo::make::debug_filename("step1_looks_like_a_text_line.ppm"));
+ }
+
+
+ // Bboxes + line infos
+ {
+ std::ofstream
file(scribo::make::debug_filename("step1_bboxes_100p.txt").c_str());
+ std::ofstream
file_50p(scribo::make::debug_filename("step1_bboxes_50p.txt").c_str());
+
+ for_all_lines(l, lines)
+ if (lines(l).tag() != line::Merged
+ && lines(l).tag() != line::Ignored
+ && lines(l).tag() != line::Pathological)
{
- point2d
- b_top(grouped_objects.bbox(i).pmin().row() + med_min_row(i).to_result(),
grouped_objects.bbox(i).pmin().col()),
- e_top(grouped_objects.bbox(i).pmin().row() + med_min_row(i).to_result(),
grouped_objects.bbox(i).pmax().col()),
- b_bot(grouped_objects.bbox(i).pmax().row() - med_max_row(i).to_result(),
grouped_objects.bbox(i).pmin().col()),
- e_bot(grouped_objects.bbox(i).pmax().row() - med_max_row(i).to_result(),
grouped_objects.bbox(i).pmax().col());
-
- mln::draw::box(output, grouped_objects.bbox(i), literal::purple);
- mln::draw::line(output, b_top, e_top, literal::cyan);
- mln::draw::line(output, b_bot, e_bot, literal::cyan);
+ file << lines(l).bbox().pmin().row() << " "
+ << lines(l).bbox().pmin().col() << " "
+ << lines(l).bbox().pmax().row() << " "
+ << lines(l).bbox().pmax().col() << " "
+ << lines(l).card() << " "
+ << lines(l).baseline() << " "
+ << lines(l).x_height() << " "
+ << lines(l).median() << " "
+ << lines(l).d_height() << " "
+ << lines(l).a_height() << " "
+ << lines(l).char_space() << " "
+ << lines(l).char_width() << std::endl;
+
+ file_50p << lines(l).bbox().pmin().row() / 2 << " "
+ << lines(l).bbox().pmin().col() / 2 << " "
+ << lines(l).bbox().pmax().row() / 2 << " "
+ << lines(l).bbox().pmax().col() / 2 << std::endl;
}
- }
- io::ppm::save(output, argv[2]);
+ file.close();
+ file_50p.close();
}
+ std::cout << "Merging lines..." << std::endl;
+ lines = scribo::text::merging(input.domain(), lines);
- // Display median character space.
+ // Median and base lines.
{
image2d<value::rgb8> output = data::convert(value::rgb8(), input);
- typedef mln::value::int_u<8> median_t;
- typedef mln::accu::stat::median_h<median_t> accu_t;
- util::array<accu_t>
- lspace_med(static_cast<unsigned>(grouped_objects.nlabels()) + 1);
- for_all_components(i, filtered_objects.bboxes())
- if (groups_packed(i) != 0)
+ for_all_lines(l, lines)
+ {
+ if (lines(l).tag() == line::Pathological)
+ mln::draw::box(output, lines(l).bbox(), literal::orange);
+ else if (lines(l).tag() != line::Merged)
{
- if (hratio_filtered_links(i) != i)
+ if (lines(l).card() > 1)
{
- unsigned
- space = filtered_objects.bbox(i).pmin().col() -
filtered_objects.bbox(hratio_filtered_links(i)).pmax().col();
+ point2d
+ b_top(lines(l).baseline() - lines(l).median(), lines(l).bbox().pmin().col()),
+ e_top(lines(l).baseline() - lines(l).median(), lines(l).bbox().pmax().col()),
+ b_bot(lines(l).baseline(), lines(l).bbox().pmin().col()),
+ e_bot(lines(l).baseline(), lines(l).bbox().pmax().col());
- lspace_med(groups_packed(i)).take(space);
+ mln::draw::line(output, b_top, e_top, literal::blue);
+ mln::draw::line(output, b_bot, e_bot, literal::cyan);
+// std::cout << lines(l) << std::endl;
}
+ mln::draw::box(output, lines(l).bbox(), literal::purple);
}
+ }
- std::cout << "Drawing median character space" << std::endl;
- for_all_components(i, filtered_objects.bboxes())
- if (groups_packed(i) != 0 && lspace_med(groups_packed(i)).card() > 1)
- {
- unsigned med = lspace_med(groups_packed(i)).to_result();
+ mln::io::ppm::save(output,
scribo::make::debug_filename("step2_x_height.ppm"));
+ }
- mln::draw::box(output, grouped_objects.bbox(groups_packed(i)),
- literal::purple);
- point2d
- beg = filtered_objects.bbox(i).pmax(),
- end = beg;
- beg.row() = filtered_objects.bbox(i).pmin().row();
- mln::draw::line(output, beg, end, literal::cyan);
- beg.col() += med;
- end.col() += med;
- mln::draw::line(output, beg, end, literal::cyan);
+ // Bboxes image.
+ {
+ image2d<value::rgb8> output = data::convert(value::rgb8(), input);
+ for_all_lines(l, lines)
+ if (lines(l).tag() != line::Merged
+ && lines(l).tag() != line::Ignored
+ && lines(l).tag() != line::Pathological)
+ {
+ mln::draw::box(output, lines(l).bbox(), literal::red);
}
- io::ppm::save(output, "median_wspace.ppm");
-
+ mln::io::ppm::save(output, argv[2]);
}
- trace::exiting("main");
+
+// // line label image.
+// {
+// util::array<V>
+// f(static_cast<unsigned>(filtered_components.nelements()) + 1, 0);
+// for_all_lines(l, lines)
+// if (lines(l).tag() != line::Merged
+// && lines(l).tag() != line::Ignored
+// && lines(l).tag() != line::Pathological)
+// {
+// for_all_elements(c, lines(l).components())
+// f(lines(l).components()[c]) = l;
+// }
+// L line_label = duplicate(filtered_components.labeled_image());
+// V nlbl = filtered_components.nelements();
+// mln::labeling::relabel_inplace(line_label, nlbl, f);
+
+// mln::io::ppm::save(labeling::colorize(value::rgb8(), line_label),
+// scribo::make::debug_filename("labeled_lines.ppm"));
+// mln::io::dump::save(line_label,
scribo::make::debug_filename("labeled_lines.dump"));
+// }
+
+
+
+// scribo::io::xml::save_text_lines(argv[1], lines, "out.xml");
+
+
+
+
+
+
+
+// scribo::text::recognition(lines, "fra", "out.txt");
+
+
+// // Display median character space.
+// {
+// image2d<value::rgb8> output = data::convert(value::rgb8(), input);
+// typedef mln::value::int_u<8> median_t;
+// typedef mln::accu::stat::median_h<median_t> accu_t;
+// util::array<accu_t>
+// lspace_med(static_cast<unsigned>(grouped_objects.nlabels()) + 1);
+
+// for_all_components(i, filtered_objects.bboxes())
+// if (groups_packed(i) != 0)
+// {
+// if (hratio_filtered_links(i) != i)
+// {
+// unsigned
+// space = filtered_objects.bbox(i).pmin().col() -
filtered_objects.bbox(hratio_filtered_links(i)).pmax().col();
+
+// lspace_med(groups_packed(i)).take(space);
+
+// }
+// }
+
+// std::cout << "Drawing median character space" << std::endl;
+// for_all_components(i, filtered_objects.bboxes())
+// if (groups_packed(i) != 0 && lspace_med(groups_packed(i)).card() >
1)
+// {
+// unsigned med = lspace_med(groups_packed(i)).to_result();
+
+// mln::draw::box(output, grouped_objects.bbox(groups_packed(i)),
+// literal::purple);
+
+// point2d
+// beg = filtered_objects.bbox(i).pmax(),
+// end = beg;
+// beg.row() = filtered_objects.bbox(i).pmin().row();
+// mln::draw::line(output, beg, end, literal::cyan);
+// beg.col() += med;
+// end.col() += med;
+// mln::draw::line(output, beg, end, literal::cyan);
+
+// }
+
+// io::ppm::save(output, "median_wspace.ppm");
+
+// }
+
+// trace::exiting("main");
}
diff --git a/scribo/src/text_in_photo_ppm_fast.cc b/scribo/src/text_in_photo_ppm_fast.cc
index 4a7562f..e4ddd48 100644
--- a/scribo/src/text_in_photo_ppm_fast.cc
+++ b/scribo/src/text_in_photo_ppm_fast.cc
@@ -58,7 +58,7 @@
#include <scribo/binarization/sauvola_ms.hh>
#include <scribo/binarization/sauvola.hh>
-#include <scribo/primitive/extract/objects.hh>
+#include <scribo/primitive/extract/components.hh>
#include <scribo/primitive/link/merge_double_link.hh>
#include <scribo/primitive/link/with_single_left_link.hh>
@@ -95,6 +95,9 @@
#include <scribo/src/afp/link.hh>
#include <scribo/src/afp/regroup.hh>
+#include <scribo/core/line_set.hh>
+#include <scribo/text/recognition.hh>
+
const char *args_desc[][2] =
{
{ "input.ppm", "A color image." },
@@ -137,20 +140,22 @@ namespace mln
template <typename I, typename L>
mln_concrete(I)
compute_highlight_image(const I& input_rgb,
- const object_image<L>& objects)
+ const scribo::component_set<L>& components)
{
mln_ch_value(I, bool) mask;
initialize(mask, input_rgb);
data::fill(mask, false);
- for_all_components(i, objects.bboxes())
- data::fill((mask | objects.bbox(i)).rw(), true);
+ for_all_comps(i, components)
+ if (components(i).is_valid())
+ data::fill((mask | components(i).bbox()).rw(), true);
mask_non_text f(mask);
mln_concrete(I) output = data::transform(input_rgb, f);
- for_all_components(i, objects.bboxes())
- mln::draw::box(output, objects.bbox(i), literal::red);
+ for_all_components(i, components)
+ if (components(i).is_valid())
+ mln::draw::box(output, components(i).bbox(), literal::red);
return output;
}
@@ -158,17 +163,17 @@ namespace mln
template <typename I, typename L>
mln_concrete(I)
compute_text_image(const I& input_rgb,
- const object_image<L>& grouped_objects)
+ const scribo::component_set<L>& grouped_objects)
{
- const util::array<mln_domain(L)>& bboxes = grouped_objects.bboxes();
-
unsigned shift = 5;
float height = 1, width = 0;
- for_all_components(i, bboxes)
- {
- height += bboxes(i).nrows() + shift;
- width = math::max(static_cast<float>(bboxes(i).ncols()), width);
- }
+ for_all_comps(i, grouped_objects)
+ if (grouped_objects(i).is_valid())
+ {
+ height += grouped_objects(i).bbox().nrows() + shift;
+ width = math::max(static_cast<float>(grouped_objects(i).bbox().ncols()),
+ width);
+ }
if (width == 0)
width = 1;
@@ -178,21 +183,23 @@ namespace mln
algebra::vec<2, float> dv;
dv[0] = 0;
dv[1] = 0;
- for_all_ncomponents(i, grouped_objects.nlabels())
- {
- mln_VAR(tmp, duplicate(input_rgb | grouped_objects.bbox(i)));
+ for_all_comps(i, grouped_objects)
+ if (grouped_objects(i).is_valid())
+ {
+ mln_VAR(tmp, duplicate(input_rgb | grouped_objects(i).bbox()));
- typedef fun::x2x::translation<mln_site_(I)::dim, float> trans_t;
- trans_t trans(dv - grouped_objects.bbox(i).pmin().to_vec());
+ typedef fun::x2x::translation<mln_site_(I)::dim, float> trans_t;
+ trans_t trans(dv - grouped_objects(i).bbox().pmin().to_vec());
- mln_domain(I) tr_box(grouped_objects.bbox(i).pmin().to_vec() + trans.t(),
- grouped_objects.bbox(i).pmax().to_vec() + trans.t());
+ mln_domain(I)
+ tr_box(grouped_objects(i).bbox().pmin().to_vec() + trans.t(),
+ grouped_objects(i).bbox().pmax().to_vec() + trans.t());
- tr_image<mln_domain(I), tmp_t, trans_t> tr_ima(tr_box, tmp, trans);
+ tr_image<mln_domain(I), tmp_t, trans_t> tr_ima(tr_box, tmp, trans);
- data::paste(tr_ima, output);
- dv[0] += grouped_objects.bbox(i).nrows() + shift;
- }
+ data::paste(tr_ima, output);
+ dv[0] += grouped_objects(i).bbox().nrows() + shift;
+ }
return output;
}
@@ -237,7 +244,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
std::cout << "Using lambda = " << lambda << std::endl;
image2d<value::int_u8> intensity_ima;
- util::timer timer_, global_t_;
+ mln::util::timer timer_, global_t_;
float t_;
global_t_.start();
@@ -284,12 +291,12 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
if (argc > 4 && atoi(argv[4]) != 0)
{
std::cout << "** Using sauvola_ms with w_1 = " << w <<
std::endl;
- input = binarization::sauvola_ms(intensity_ima, w, 3, 67);
+ input = scribo::binarization::sauvola_ms(intensity_ima, w, 3, 67);
}
else
{
std::cout << "** Using sauvola with w_1 = " << w <<
std::endl;
- input = binarization::sauvola(intensity_ima, w);
+ input = scribo::binarization::sauvola(intensity_ima, w);
}
#ifndef NOUT
if (debug)
@@ -310,45 +317,44 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
typedef image2d<value::label_16> L;
- /// Finding objects.
+ /// Finding components.
timer_.restart();
- typedef object_image(L) Obj;
- Obj filtered_objects;
+ typedef component_set<L> Obj;
+ Obj filtered_components;
{
- util::array<box2d> bboxes;
- util::array<point2d> mass_centers;
+ mln::util::array<std::pair<box2d, std::pair<point2d, unsigned> > >
attribs;
- value::label_16 nobjects;
- L components = extract_components(input, nobjects, bboxes, mass_centers);
+ value::label_16 ncomponents;
+ L components = extract_components(input, ncomponents, attribs);
- filtered_objects = Obj(components, nobjects, bboxes, mass_centers);
+ filtered_components = Obj(components, ncomponents, attribs);
}
t_ = timer_;
- std::cout << "Object extracted " << t_ << " - "
<< filtered_objects.nlabels() << " objects" << std::endl;
+ std::cout << "Object extracted " << t_ << " - "
<< filtered_components.nelements() << " components" <<
std::endl;
// if (debug)
-// io::pgm::save(data::stretch(value::int_u8(), filtered_objects),
"ref_objects.pgm");
+// io::pgm::save(data::stretch(value::int_u8(), filtered_components),
"ref_components.pgm");
- /// linking potential objects
+ /// linking potential components
timer_.restart();
- util::couple<object_links<L>, object_links<L> >
- links = primitive::link::left_right(filtered_objects);
+ mln::util::couple<object_links<L>, object_links<L> >
+ links = primitive::link::left_right(filtered_components);
object_links<L>& left_link = links.first();
object_links<L>& right_link = links.second();
// object_links<L> left_link
-// = primitive::link::with_single_left_link(filtered_objects, 30);
+// = primitive::link::with_single_left_link(filtered_components, 30);
// t_ = timer_;
// std::cout << "Left Link done " << t_ << std::endl;
// timer_.restart();
// object_links<L> right_link
-// = primitive::link::with_single_right_link(filtered_objects, 30);
+// = primitive::link::with_single_right_link(filtered_components, 30);
t_ = timer_;
std::cout << "Link done " << t_ << std::endl;
@@ -357,9 +363,9 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
#ifndef NOUT
if (debug)
{
- std::cerr << "BEFORE - nobjects = " <<
filtered_objects.nlabels() << std::endl;
+ std::cerr << "BEFORE - ncomponents = " <<
filtered_components.nelements() << std::endl;
scribo::debug::save_linked_bboxes_image(input,
- filtered_objects,
+ filtered_components,
left_link, right_link,
literal::red, literal::cyan,
literal::yellow,
@@ -373,7 +379,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
// Validating left and right links.
timer_.restart();
object_links<L>
- merged_links = primitive::link::merge_double_link(filtered_objects,
+ merged_links = primitive::link::merge_double_link(filtered_components,
left_link,
right_link);
t_ = timer_;
@@ -383,7 +389,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
// Remove links if bboxes have too different sizes.
timer_.restart();
object_links<L>
- hratio_filtered_links = filter::object_links_bbox_h_ratio(filtered_objects,
+ hratio_filtered_links = filter::object_links_bbox_h_ratio(filtered_components,
merged_links,
1.50f);
@@ -407,7 +413,7 @@ 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(filtered_objects,
+ = filter::object_links_bbox_overlap(filtered_components,
hratio_filtered_links,
0.80f);
@@ -428,39 +434,43 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
t_ = timer_;
- std::cout << "Objects links filtered. " << t_ <<
std::endl;
+ std::cout << "Components links filtered. " << t_ <<
std::endl;
timer_.restart();
object_groups<L>
- groups = primitive::group::from_single_link(filtered_objects,
+ groups = primitive::group::from_single_link(filtered_components,
overlap_filtered_links);
// Apply grouping in a temporary image (for debug purpose).
#ifndef NOUT
- object_image(L)
- raw_group_image = primitive::group::apply(filtered_objects,
+ component_set<L>
+ raw_group_image = primitive::group::apply(filtered_components,
groups);
#endif // !NOUT
t_ = timer_;
- std::cout << "Objects grouped. " << t_ << std::endl;
+ std::cout << "Components grouped. " << t_ << std::endl;
#ifndef NOUT
if (debug)
{
- image2d<value::rgb8> decision_image = data::convert(value::rgb8(), input);
+ image2d<value::rgb8>
+ decision_image = data::convert(value::rgb8(), input);
- scribo::draw::bounding_boxes(decision_image, filtered_objects, literal::green);
- scribo::draw::bounding_boxes(decision_image, raw_group_image, literal::blue);
+ scribo::draw::bounding_boxes(decision_image,
+ filtered_components, literal::green);
+ scribo::draw::bounding_boxes(decision_image,
+ raw_group_image, literal::blue);
io::ppm::save(decision_image,
scribo::make::debug_filename("group_and_object_image.ppm"));
decision_image = data::convert(value::rgb8(), input);
- scribo::draw::bounding_boxes(decision_image, raw_group_image, literal::blue);
+ scribo::draw::bounding_boxes(decision_image,
+ raw_group_image, literal::blue);
io::ppm::save(decision_image,
scribo::make::debug_filename("group_image.ppm"));
}
@@ -469,10 +479,10 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
std::cout << "Filtering groups..." << std::endl;
- util::timer g_timer;
+ mln::util::timer g_timer;
timer_.restart();
- // Remove objects part of groups with strictly less than 3 objects.
+ // Remove components part of groups with strictly less than 3 components.
g_timer.start();
object_groups<L> filtered_small_groups;
@@ -489,18 +499,19 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
#ifndef NOUT
- object_image(L) debug_image;
+ component_set<L> debug_image;
image2d<value::rgb8> decision_image;
if (debug)
{
decision_image = data::convert(value::rgb8(), input);
- object_image(L)
- grouped_objects = primitive::group::apply(filtered_objects,
+ component_set<L>
+ grouped_objects = primitive::group::apply(filtered_components,
filtered_small_groups);
- for_all_components(i, filtered_objects.bboxes())
- if (filtered_small_groups(i) != 0)
- mln::draw::box(decision_image, filtered_objects.bbox(i), literal::green);
+ for_all_components(i, filtered_components)
+ if (filtered_components(i).is_valid()
+ && filtered_small_groups(i) != 0)
+ mln::draw::box(decision_image, filtered_components(i).bbox(), literal::green);
scribo::draw::bounding_boxes(decision_image, raw_group_image, literal::red);
scribo::draw::bounding_boxes(decision_image, grouped_objects, literal::blue);
@@ -512,7 +523,7 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
- // Remove objects part of groups having a mean thickness lower than 8.
+ // Remove components part of groups having a mean thickness lower than 8.
g_timer.restart();
object_groups<L> filtered_thin_groups;
if (argc > 7 && atoi(argv[7]) != 0)
@@ -532,22 +543,21 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
{
decision_image = data::convert(value::rgb8(), input);
- object_image(L)
- grouped_objects = primitive::group::apply(filtered_objects,
- filtered_thin_groups);
+ component_set<L>
+ grouped_components = primitive::group::apply(filtered_components,
+ filtered_thin_groups);
- for_all_components(i, filtered_objects.bboxes())
- {
- if (filtered_thin_groups(i) != 0)
- mln::draw::box(decision_image, filtered_objects.bbox(i), literal::green);
- }
+ for_all_components(i, filtered_components)
+ if (filtered_components(i).is_valid()
+ && filtered_thin_groups(i) != 0)
+ mln::draw::box(decision_image, filtered_components(i).bbox(), literal::green);
scribo::draw::bounding_boxes(decision_image, debug_image, literal::red);
- scribo::draw::bounding_boxes(decision_image, grouped_objects, literal::blue);
+ scribo::draw::bounding_boxes(decision_image, grouped_components, literal::blue);
io::ppm::save(decision_image,
scribo::make::debug_filename("thin_groups_filter.ppm"));
- debug_image = grouped_objects;
+ debug_image = grouped_components;
}
#endif
@@ -556,32 +566,32 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
/// Apply grouping in the object image.
g_timer.restart();
-// groups = primitive::group::regroup_left(filtered_objects,
+// groups = primitive::group::regroup_left(filtered_components,
// filtered_thin_groups,
// 30);
- object_image(L)
- grouped_objects = primitive::group::apply(filtered_objects,
- filtered_thin_groups);
+ component_set<L>
+ grouped_components = primitive::group::apply(filtered_components,
+ filtered_thin_groups);
t_ = g_timer;
std::cout << "Group applied to object image " << t_ <<
std::endl;
- /// Objects have been grouped. We try to link groups together.
- /// This time a single link is enough since non-wanted objects have
+ /// Components have been grouped. We try to link groups together.
+ /// This time a single link is enough since non-wanted components have
/// been removed.
g_timer.restart();
- left_link = primitive::link::left(grouped_objects, 30);
+ left_link = primitive::link::left(grouped_components, 30);
// left_link
-// = primitive::link::with_single_left_link(grouped_objects, 30);
+// = primitive::link::with_single_left_link(grouped_components, 30);
/// Grouping groups.
- groups = primitive::group::from_single_link(grouped_objects, left_link);
+ groups = primitive::group::from_single_link(grouped_components, left_link);
-// object_image(L)
- grouped_objects = primitive::group::apply(grouped_objects, groups);
+// component_set<L>
+ grouped_components = primitive::group::apply(grouped_components, groups);
t_ = g_timer;
std::cout << "Link and group again " << t_ << std::endl;
@@ -590,21 +600,21 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
// if (debug)
// io::ppm::save(mln::labeling::colorize(value::rgb8(),
-// grouped_objects,
-// grouped_objects.nlabels()),
+// grouped_components,
+// grouped_components.nelements()),
// scribo::make::debug_filename("out_raw.ppm"));
timer_.resume();
-// io::pgm::save(data::wrap(value::int_u8(), grouped_objects.labeled_image_()),
"lbl_to_be_filtered.pgm");
+// io::pgm::save(data::wrap(value::int_u8(), grouped_components.labeled_image_()),
"lbl_to_be_filtered.pgm");
g_timer.restart();
/// Filter grouped objects not having enough background components.
if (argc > 5 && atoi(argv[5]) != 0)
{
std::cout << "** Using objects_with_two_holes" << std::endl;
- grouped_objects = scribo::filter::objects_with_two_holes(grouped_objects, 5);
+ grouped_components = scribo::filter::components_with_two_holes(grouped_components,
5);
t_ = g_timer;
std::cout << "Objects_with_holes " << t_ << std::endl;
}
@@ -623,36 +633,41 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
decision_image = data::convert(value::rgb8(), input);
scribo::draw::bounding_boxes(decision_image, debug_image, literal::red);
- scribo::draw::bounding_boxes(decision_image, grouped_objects, literal::blue);
+ scribo::draw::bounding_boxes(decision_image, grouped_components, literal::blue);
io::ppm::save(decision_image,
scribo::make::debug_filename("group_with_holes_filter.ppm"));
- std::cerr << "AFTER - nobjects = " << grouped_objects.nlabels()
<< std::endl;
+ std::cerr << "AFTER - nobjects = " <<
grouped_components.nelements() << std::endl;
}
#endif
timer_.restart();
std::cout << "Saving result..." << std::endl;
io::ppm::save(mln::labeling::colorize(value::rgb8(),
- grouped_objects,
- grouped_objects.nlabels()),
+ grouped_components.labeled_image(),
+ grouped_components.nelements()),
argv[2]);
#ifndef NOUT
-// scribo::debug::save_bboxes_image(input_rgb, grouped_objects.bboxes(),
+// scribo::debug::save_bboxes_image(input_rgb, grouped_components.bboxes(),
// literal::red,
// scribo::make::debug_filename("orig_with_bboxes.ppm"));
#endif
- io::ppm::save(compute_highlight_image(input_rgb, grouped_objects),
+ io::ppm::save(compute_highlight_image(input_rgb, grouped_components),
out_base_dir + "_input_with_bboxes.ppm");
- io::ppm::save(compute_text_image(input_rgb, grouped_objects),
+ io::ppm::save(compute_text_image(input_rgb, grouped_components),
out_base_dir + "_out_text.ppm");
t_ = timer_;
std::cout << "Output saved " << t_ << std::endl;
- std::cout << "# objects = " << grouped_objects.nlabels() <<
std::endl;
+ std::cout << "# objects = " << grouped_components.nelements()
<< std::endl;
+
+
+ scribo::line_set<L>
+ lines = scribo::line_set<L>(filtered_components, filtered_thin_groups);
+ text::recognition(lines, "fra", "out.txt");
trace::exiting("main");
- return grouped_objects.nlabels() != 0;
+ return grouped_components.nelements() != 0;
}
diff --git a/scribo/src/text_in_photo_ppm_fast.cc
b/scribo/src/text_in_photo_ppm_fast_2.cc
similarity index 71%
copy from scribo/src/text_in_photo_ppm_fast.cc
copy to scribo/src/text_in_photo_ppm_fast_2.cc
index 4a7562f..bb24a11 100644
--- a/scribo/src/text_in_photo_ppm_fast.cc
+++ b/scribo/src/text_in_photo_ppm_fast_2.cc
@@ -207,19 +207,16 @@ 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",
- "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]",
+ "Find text in a photo.",
+ "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.");
- std::string out_base_dir;
bool debug = false;
if (argc > 8)
{
scribo::make::internal::debug_filename_prefix = argv[8];
debug = true;
- out_base_dir = argv[8];
}
trace::entering("main");
@@ -229,12 +226,11 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
unsigned lambda;
- if (argc == 10)
+ if (argc == 6)
lambda = atoi(argv[9]);
else
lambda = 1.2 * (input_rgb.nrows() + input_rgb.ncols());
- std::cout << "Using lambda = " << lambda << std::endl;
image2d<value::int_u8> intensity_ima;
util::timer timer_, global_t_;
@@ -254,14 +250,6 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
intensity_ima = data::transform(fg, mln::fun::v2v::rgb_to_int_u<8>());
t_ = timer_;
std::cout << "Foreground extracted. " << t_ <<
std::endl;
-
-#ifndef NOUT
- if (debug)
- {
- io::ppm::save(fg, scribo::make::debug_filename("foreground.ppm"));
- }
-
-#endif // !NOUT
}
else
{
@@ -291,14 +279,6 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
std::cout << "** Using sauvola with w_1 = " << w <<
std::endl;
input = binarization::sauvola(intensity_ima, w);
}
-#ifndef NOUT
- if (debug)
- {
- io::pbm::save(input,
- scribo::make::debug_filename("binarization.pbm"));
- }
-
-#endif // !NOUT
// if (debug)
@@ -354,19 +334,19 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
-#ifndef NOUT
- if (debug)
- {
- std::cerr << "BEFORE - nobjects = " <<
filtered_objects.nlabels() << std::endl;
- scribo::debug::save_linked_bboxes_image(input,
- filtered_objects,
- left_link, right_link,
- literal::red, literal::cyan,
- literal::yellow,
- literal::green,
- scribo::make::debug_filename("links.ppm"));
- }
-#endif
+// #ifndef NOUT
+// if (argc > 4)
+// {
+// std::cerr << "BEFORE - nobjects = " <<
filtered_objects.nlabels() << std::endl;
+// scribo::debug::save_linked_bboxes_image(input,
+// filtered_objects,
+// left_link, right_link,
+// literal::red, literal::cyan,
+// literal::yellow,
+// literal::green,
+// scribo::make::debug_filename("links.ppm"));
+// }
+// #endif
@@ -390,17 +370,17 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
-#ifndef NOUT
- if (debug)
- {
- image2d<value::rgb8>
- hratio_decision_image = scribo::debug::decision_image(input,
- merged_links,
- hratio_filtered_links);
- io::ppm::save(hratio_decision_image,
- scribo::make::debug_filename("hratio_links_decision_image.ppm"));
- }
-#endif
+// #ifndef NOUT
+// if (argc > 4)
+// {
+// image2d<value::rgb8>
+// hratio_decision_image = scribo::debug::decision_image(input,
+// merged_links,
+// hratio_filtered_links);
+// io::ppm::save(hratio_decision_image,
+// scribo::make::debug_filename("hratio_links_decision_image.ppm"));
+// }
+// #endif
@@ -414,17 +394,17 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
-#ifndef NOUT
- if (debug)
- {
- image2d<value::rgb8> overlap_decision_image
- = scribo::debug::decision_image(input,
- hratio_filtered_links,
- overlap_filtered_links);
- io::ppm::save(overlap_decision_image,
- scribo::make::debug_filename("overlap_links_decision_image.ppm"));
- }
-#endif
+// #ifndef NOUT
+// if (argc > 4)
+// {
+// image2d<value::rgb8> overlap_decision_image
+// = scribo::debug::decision_image(input,
+// hratio_filtered_links,
+// overlap_filtered_links);
+// io::ppm::save(overlap_decision_image,
+// scribo::make::debug_filename("overlap_links_decision_image.ppm"));
+// }
+// #endif
t_ = timer_;
@@ -437,39 +417,45 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
-// Apply grouping in a temporary image (for debug purpose).
-#ifndef NOUT
- object_image(L)
- raw_group_image = primitive::group::apply(filtered_objects,
- groups);
-#endif // !NOUT
+ /// Apply grouping in a temporary image (for debug purpose).
+// #ifndef NOUT
+// object_image(L)
+// raw_group_image = primitive::group::apply(filtered_objects,
+// filter::object_groups_small(groups, 2));
+// #endif // !NOUT
t_ = timer_;
std::cout << "Objects grouped. " << t_ << std::endl;
-#ifndef NOUT
- if (debug)
- {
- image2d<value::rgb8> decision_image = data::convert(value::rgb8(), input);
+ util::timer g_timer;
- scribo::draw::bounding_boxes(decision_image, filtered_objects, literal::green);
- scribo::draw::bounding_boxes(decision_image, raw_group_image, literal::blue);
+ object_image(L)
+ grouped_objects = primitive::group::apply(filtered_objects,
+ groups);
- io::ppm::save(decision_image,
- scribo::make::debug_filename("group_and_object_image.ppm"));
+ t_ = g_timer;
+ std::cout << "Group applied to object image " << t_ <<
std::endl;
- decision_image = data::convert(value::rgb8(), input);
- scribo::draw::bounding_boxes(decision_image, raw_group_image, literal::blue);
- io::ppm::save(decision_image,
- scribo::make::debug_filename("group_image.ppm"));
- }
-#endif // !NOUT
+ /// Objects have been grouped. We try to link groups together.
+ /// This time a single link is enough since non-wanted objects have
+ /// been removed.
+ g_timer.restart();
+ left_link = primitive::link::left(grouped_objects, 30);
+// left_link
+// = primitive::link::with_single_left_link(grouped_objects, 30);
- std::cout << "Filtering groups..." << std::endl;
- util::timer g_timer;
+ /// Grouping groups.
+ groups = primitive::group::from_single_link(grouped_objects, left_link);
+
+// object_image(L)
+ grouped_objects = primitive::group::apply(grouped_objects, groups);
+
+
+
+ std::cout << "Filtering groups..." << std::endl;
timer_.restart();
// Remove objects part of groups with strictly less than 3 objects.
@@ -488,30 +474,6 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
-#ifndef NOUT
- object_image(L) debug_image;
- image2d<value::rgb8> decision_image;
- if (debug)
- {
- decision_image = data::convert(value::rgb8(), input);
- object_image(L)
- grouped_objects = primitive::group::apply(filtered_objects,
- filtered_small_groups);
-
- for_all_components(i, filtered_objects.bboxes())
- if (filtered_small_groups(i) != 0)
- mln::draw::box(decision_image, filtered_objects.bbox(i), literal::green);
- scribo::draw::bounding_boxes(decision_image, raw_group_image, literal::red);
- scribo::draw::bounding_boxes(decision_image, grouped_objects, literal::blue);
-
- io::ppm::save(decision_image,
- scribo::make::debug_filename("small_groups_filter.ppm"));
- debug_image = grouped_objects;
- }
-#endif
-
-
-
// Remove objects part of groups having a mean thickness lower than 8.
g_timer.restart();
object_groups<L> filtered_thin_groups;
@@ -527,78 +489,15 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
std::cout << "Groups too thin " << t_ << std::endl;
-#ifndef NOUT
- if (debug)
- {
- decision_image = data::convert(value::rgb8(), input);
-
- object_image(L)
- grouped_objects = primitive::group::apply(filtered_objects,
- filtered_thin_groups);
-
- for_all_components(i, filtered_objects.bboxes())
- {
- if (filtered_thin_groups(i) != 0)
- mln::draw::box(decision_image, filtered_objects.bbox(i), literal::green);
- }
-
- scribo::draw::bounding_boxes(decision_image, debug_image, literal::red);
- scribo::draw::bounding_boxes(decision_image, grouped_objects, literal::blue);
-
- io::ppm::save(decision_image,
- scribo::make::debug_filename("thin_groups_filter.ppm"));
- debug_image = grouped_objects;
- }
-#endif
-
-
-
- /// Apply grouping in the object image.
- g_timer.restart();
-
-// groups = primitive::group::regroup_left(filtered_objects,
-// filtered_thin_groups,
-// 30);
-
- object_image(L)
- grouped_objects = primitive::group::apply(filtered_objects,
- filtered_thin_groups);
-
- t_ = g_timer;
- std::cout << "Group applied to object image " << t_ <<
std::endl;
-
- /// Objects have been grouped. We try to link groups together.
- /// This time a single link is enough since non-wanted objects have
- /// been removed.
- g_timer.restart();
-
- left_link = primitive::link::left(grouped_objects, 30);
-// left_link
-// = primitive::link::with_single_left_link(grouped_objects, 30);
-
-
- /// Grouping groups.
- groups = primitive::group::from_single_link(grouped_objects, left_link);
-
-// object_image(L)
- grouped_objects = primitive::group::apply(grouped_objects, groups);
t_ = g_timer;
std::cout << "Link and group again " << t_ << std::endl;
timer_.stop();
-// if (debug)
-// io::ppm::save(mln::labeling::colorize(value::rgb8(),
-// grouped_objects,
-// grouped_objects.nlabels()),
-// scribo::make::debug_filename("out_raw.ppm"));
-
timer_.resume();
-// io::pgm::save(data::wrap(value::int_u8(), grouped_objects.labeled_image_()),
"lbl_to_be_filtered.pgm");
-
g_timer.restart();
/// Filter grouped objects not having enough background components.
if (argc > 5 && atoi(argv[5]) != 0)
@@ -609,27 +508,16 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
std::cout << "Objects_with_holes " << t_ << std::endl;
}
-
t_ = timer_;
std::cout << "Objects groups filtered. " << t_ <<
std::endl;
+// object_image(L)
+ grouped_objects = primitive::group::apply(grouped_objects, groups);
+
t_ = global_t_;
std::cout << "*** Result computed " << t_ << std::endl;
-#ifndef NOUT
- if (debug)
- {
- decision_image = data::convert(value::rgb8(), input);
-
- scribo::draw::bounding_boxes(decision_image, debug_image, literal::red);
- scribo::draw::bounding_boxes(decision_image, grouped_objects, literal::blue);
- io::ppm::save(decision_image,
scribo::make::debug_filename("group_with_holes_filter.ppm"));
-
- std::cerr << "AFTER - nobjects = " << grouped_objects.nlabels()
<< std::endl;
- }
-#endif
-
timer_.restart();
std::cout << "Saving result..." << std::endl;
io::ppm::save(mln::labeling::colorize(value::rgb8(),
@@ -637,16 +525,11 @@ Common usage: ./ppm_text_in_photo input.ppm output.ppm 1 1 1 1
1",
grouped_objects.nlabels()),
argv[2]);
-#ifndef NOUT
-// scribo::debug::save_bboxes_image(input_rgb, grouped_objects.bboxes(),
-// literal::red,
-// scribo::make::debug_filename("orig_with_bboxes.ppm"));
-#endif
io::ppm::save(compute_highlight_image(input_rgb, grouped_objects),
- out_base_dir + "_input_with_bboxes.ppm");
+ scribo::make::debug_filename("orig_with_bboxes.ppm"));
io::ppm::save(compute_text_image(input_rgb, grouped_objects),
- out_base_dir + "_out_text.ppm");
+ scribo::make::debug_filename("out_text.ppm"));
t_ = timer_;
std::cout << "Output saved " << t_ << std::endl;
--
1.5.6.5