
* text/clean.hh: Do not use the distance map anymore. * text/recognition.hh: Do not return an image of char anymore. Enlarge the temporary image domain. --- scribo/ChangeLog | 9 +++++ scribo/text/clean.hh | 73 ++++++++++++++++++++++++------------------- scribo/text/recognition.hh | 39 ++++++++++++++--------- 3 files changed, 74 insertions(+), 47 deletions(-) diff --git a/scribo/ChangeLog b/scribo/ChangeLog index 15ea49e..af2f788 100644 --- a/scribo/ChangeLog +++ b/scribo/ChangeLog @@ -1,5 +1,14 @@ 2009-09-15 Guillaume Lazzara <lazzara@lrde.epita.fr> + Make text cleaning work. + + * text/clean.hh: Do not use the distance map anymore. + + * text/recognition.hh: Do not return an image of char anymore. + Enlarge the temporary image domain. + +2009-09-15 Guillaume Lazzara <lazzara@lrde.epita.fr> + Add new filters in Scribo. * filter/common/objects_photo.hh, diff --git a/scribo/text/clean.hh b/scribo/text/clean.hh index 0f87139..e934241 100644 --- a/scribo/text/clean.hh +++ b/scribo/text/clean.hh @@ -41,7 +41,7 @@ # include <mln/logical/not.hh> -# include <mln/world/binary_2d/enlarge.hh> +//# include <mln/world/binary_2d/enlarge.hh> # include <mln/debug/filename.hh> # include <mln/io/pbm/save.hh> @@ -58,6 +58,15 @@ #include <mln/value/int_u8.hh> +#include <mln/fun/v2b/threshold.hh> +#include <mln/binarization/threshold.hh> +#include <mln/data/convert.hh> +#include <mln/value/rgb8.hh> +#include <mln/io/pgm/all.hh> + +#include <sandbox/inim/2009/ocr/resize.hh> +#include <sandbox/fabien/mln/upsampling/hq4x.hh> + namespace scribo { @@ -70,7 +79,8 @@ namespace scribo /// Improve quality of an image with text. /// - /// \param[in] input_ A binary image. + /// \param[in] input_ A binary image. Object are set to 'false' + /// and backgroud to 'true'. /// \param[in] dmap_win_ A weighted window. /// /// \return An image. The text have better quality. @@ -83,8 +93,6 @@ namespace scribo # ifndef MLN_INCLUDE_ONLY -// static int plop = 0; - template <typename I, typename W> mln_concrete(I) clean(const Image<I>& input_, const Weighted_Window<W>& dmap_win_) @@ -98,43 +106,44 @@ namespace scribo mln_precondition(input.is_valid()); mln_precondition(dmap_win.is_valid()); -// I input_large = world::binary_2d::enlarge(input, 2); -// image2d<bool> blur = linear::gaussian(input_large, 2); -// image2d<value::int_u8> blur = linear::gaussian(level::convert(value::int_u8(), input_large), 2); -// image2d<bool> blur = level::transform(linear::gaussian(level::convert(value::int_u8(), input_large), 2), fun::v2b::threshold<value::int_u8>(100)); + // Resize + typedef image2d<value::rgb8> J; + J tmp = data::convert(value::rgb8(), input); + J clarge = mln::upsampling::hq4x(tmp); + + //FIXME: not generic! + if (input.domain().pmax()[0] - input.domain().pmin()[0] <= 10) + clarge = mln::upsampling::hq4x(clarge); -// mln_ch_value(I,unsigned) -// dmap = transform::distance_front(logical::not_(input_large), c8(), -// dmap_win, -// mln_max(unsigned)); -// io::pgm::save(labeling::wrap(dmap), mln::debug::filename("dmap.pgm")); + I input_large = data::convert(bool(), clarge); -// I skeleton = topo::skeleton::crest(input_large, dmap, c8()); -// I constraint = topo::skeleton::crest(input_large, dmap, c8()); -// mln_postcondition(constraint.is_valid()); + // Blur + image2d<value::int_u8> + blur = linear::gaussian(data::convert(value::int_u8(), input_large), 2); -// io::pgm::save(labeling::wrap(constraint), mln::debug::filename("constraint.pgm")); + // Skeleton constraint + I K = topo::skeleton::crest(input_large, blur, c8()); -// I skeleton = -// morpho::skeleton_constrained(input_large, c8(), -// topo::skeleton::is_simple_point<I,neighb2d>, -// extend(constraint, false), arith::revert(dmap)); + // Skeleton + I skel_on_gaussian = + morpho::skeleton_constrained(input_large, c8(), + topo::skeleton::is_simple_point<I,neighb2d>, + extend(K, false), arith::revert(blur)); -// win::octagon2d disk(7); -// I output = morpho::dilation(skeleton, disk); + // Dilation + win::octagon2d oct(7); + I dilate_on_gaussian = morpho::dilation(skel_on_gaussian, oct); -// if (plop > 20 && plop < 50) - { -// io::pbm::save(input, mln::debug::filename("input.pbm")); -// io::pbm::save(input_large, mln::debug::filename("input_large_4x.pbm")); -// io::pbm::save(skeleton, mln::debug::filename("skeleton.pbm")); -// io::pbm::save(output, mln::debug::filename("dil_skel.pbm")); - } +// io::pgm::save(arith::revert(blur), "blur_revert.pgm"); +// io::pgm::save(blur, "gaussian.pgm"); +// io::pbm::save(input_large, mln::debug::filename("input_large_4x.pbm")); +// io::pbm::save(K, mln::debug::filename("K.pbm")); +// io::pbm::save(skel_on_gaussian, mln::debug::filename("skeleton_on_gaussian.pbm")); +// io::pbm::save(dilate_on_gaussian, mln::debug::filename("dilation_on_gaussian.pbm")); -// ++plop; trace::exiting("scribo::text::clean"); - return input; + return dilate_on_gaussian; } # endif // ! MLN_INCLUDE_ONLY diff --git a/scribo/text/recognition.hh b/scribo/text/recognition.hh index 6293e28..bd9f89b 100644 --- a/scribo/text/recognition.hh +++ b/scribo/text/recognition.hh @@ -68,6 +68,8 @@ # include <tesseract/baseapi.h> +#include <mln/labeling/colorize.hh> + namespace scribo { @@ -83,11 +85,9 @@ namespace scribo /// Tesseract. (fra, en, ...) /// \param[in] output_file If set, store the recognized text in /// this file. - /// - /// \return An image of characters. // template <typename L> - mln_ch_value(L,char) + void recognition(const object_image(L)& objects, const char *language, const char *output_file); @@ -98,7 +98,7 @@ namespace scribo template <typename L> - mln_ch_value(L,char) + void recognition(const object_image(L)& objects, const char *language, const char *output_file) @@ -110,9 +110,6 @@ namespace scribo // Initialize Tesseract. TessBaseAPI::InitWithLanguage(NULL, NULL, language, NULL, false, 0, NULL); - mln_ch_value(L,char) txt(objects.domain()); - data::fill(txt, ' '); - typedef mln_ch_value(L,bool) I; int vals[] = { 0, 9, 0, 9, 0, 9, 6, 4, 6, 9, @@ -128,17 +125,31 @@ namespace scribo /// Use text bboxes with Tesseract for_all_ncomponents(i, objects.nlabels()) { - I text_ima(objects.bbox(i)); - data::fill(text_ima, false); - data::fill((text_ima | (pw::value(objects) == pw::cst(i))).rw(), - true); + std::cout << "Text recognition... (" + << i << "/" << objects.nlabels() << ")" << std::endl; + + mln_domain(I) box = objects.bbox(i); + // Make sure characters are isolated from the borders. + // Help Tesseract. + box.enlarge(2); + I text_ima(box); + data::fill(text_ima, true); + + // Careful : background is set to 'False' + data::fill((text_ima | (pw::value(objects) == pw::cst(i))).rw(), + false); /// Improve text quality. /// text_ima_cleand domain is larger than text_ima's. I text_ima_cleaned = text::clean(text_ima, dmap_win); - border::resize(text_ima_cleaned, 0); // Make sure there is no border. + + // Setting objects to 'True' + logical::not_inplace(text_ima_cleaned); + + // Make sure there is no border. + border::resize(text_ima_cleaned, 0); // Recognize characters. char* s = TessBaseAPI::TesseractRect( @@ -157,10 +168,9 @@ namespace scribo - objects.bbox(i).pmin().col()) / 2; if (s != 0) { - std::cout << s << std::endl; + std::cerr << s << std::endl; if (output_file != 0) file << s << std::endl; - mln::debug::put_word(txt, p, s); } // The string has been allocated by Tesseract. We must free it. @@ -171,7 +181,6 @@ namespace scribo file.close(); trace::exiting("scribo::text::recognition"); - return txt; } -- 1.5.6.5