
URL: https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox ChangeLog: 2008-10-24 Jimmy Ma <jimmy.ma@lrde.epita.fr> Update OCR using tesseract. * garrigues/ocr/enlarge.hh: New. New enlargement algorithm better than the naive resize. * garrigues/ocr/ocr.cc: Provide sample code to link milena against tesseract. --- enlarge.hh | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ocr.cc | 91 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 198 insertions(+), 14 deletions(-) Index: branches/cleanup-2008/milena/sandbox/garrigues/ocr/ocr.cc =================================================================== --- branches/cleanup-2008/milena/sandbox/garrigues/ocr/ocr.cc (revision 2668) +++ branches/cleanup-2008/milena/sandbox/garrigues/ocr/ocr.cc (revision 2669) @@ -36,40 +36,103 @@ #include <mln/value/int_u8.hh> #include "resize.hh" -#include <mln/linear/convolve.hh> +#include "enlarge.hh" +//#include "skeleton.hh" #include <mln/linear/gaussian.hh> #include <mln/trace/all.hh> -#include <mln/io/pbm/load.hh> +#include <mln/io/pgm/load.hh> #include <mln/io/pgm/save.hh> +#include <mln/io/pbm/load.hh> +#include <mln/io/pbm/save.hh> #include <mln/core/alias/w_window2d_float.hh> +#include <mln/debug/println.hh> +#include <mln/geom/chamfer.hh> +#include <mln/make/win_chamfer.hh> +#include <mln/labeling/regional_maxima.hh> +#include <mln/morpho/dilation.hh> + +#include <tesseract/baseapi.h> + +// _COMPILATION_ +// g++ -DNDEBUG -O3 -I../../.. ocr.cc -L/usr/lib -ltesseract_full -lpthread + + +// Call tesseract +// lang: expected language +template <typename T> +char* tesseract(const char* lang, const mln::image2d<T>& input) +{ + TessBaseAPI::InitWithLanguage(NULL, NULL, lang, NULL, false, 0, NULL); + char* s = TessBaseAPI::TesseractRect( + (unsigned char*) input.buffer(), + sizeof (T), + input.ncols() * sizeof (T), + 0, 0, + input.ncols(), + input.nrows()); + return s; +} int main(int argc, char** argv) { - mln::trace::quiet = false; - using namespace mln; using value::int_u8; image2d<bool> input; - image2d<int_u8> output; - image2d<int_u8> output2; - if (argc != 3) + if (argc < 2) return 1; - + mln::border::thickness = 0; io::pbm::load(input, argv[1]); + std::cout << "> without any preprocessing." << std::endl; + char* s = tesseract("fra", input); + std::cout << s; + free(s); + + // + // PREPROCESS !! + // + // Resize +// output2 = geom::resize(cast_image<int_u8>(input), 3); + image2d<int_u8> output = enlarge(input, 1); + + // TODO CLEANUP +#if 0 + // Blur. + image2d<int_u8> output; + initialize(output, output2); + linear::gaussian(output2, 1, output); +#endif + +#if 0 + // Threshold + mln_piter_(image2d<unsigned>) p(output.domain()); + for_all(p) + { + output(p) = output(p) > 127 ? 1 : 0; + } +#endif - // Step 1: Enlarge input. - output = geom::resize(cast_image<int_u8>(input), 4); +#if 0 + // Compute chamfer distance map. + const w_window2d_int& w_win = make::mk_chamfer_3x3_int<8, 0> (); + image2d<unsigned> out = geom::chamfer(output, w_win, 255); + + for_all(p) + { + out(p) = out(p) > 10 ? 255 : 0; + } +#endif - // Step 2: Blur. - initialize(output2, output); - linear::gaussian(output, 15, output2); + io::pgm::save(cast_image<int_u8>(output), argv[2]); - io::pgm::save(output2, argv[2]); + std::cout << "> with preprocessing." << std::endl; + s = tesseract("fra", output); + std::cout << s; + free(s); } Index: branches/cleanup-2008/milena/sandbox/garrigues/ocr/enlarge.hh =================================================================== --- branches/cleanup-2008/milena/sandbox/garrigues/ocr/enlarge.hh (revision 0) +++ branches/cleanup-2008/milena/sandbox/garrigues/ocr/enlarge.hh (revision 2669) @@ -0,0 +1,121 @@ +#ifndef ENLARGE_HH +# define ENLARGE_HH + +# include <iostream> + +# include <mln/core/image/image2d.hh> +# include <mln/value/int_u8.hh> + + +float val(bool b) { return b ? 1 : 0; } + +int do_threshold(float value) +{ + return 255.f * value; +} + + +mln::image2d<mln::value::int_u8> +enlargex2(mln::image2d<bool> input) +{ + using namespace mln; + using value::int_u8; + + unsigned nrows, ncols; + + nrows = input.nrows(); + ncols = input.ncols(); + + image2d<int_u8> output(2 * nrows, 2 * ncols); + float value; + + // row 0 + + output.at(0, 0) = do_threshold(input.at(0, 0)); + + for (int col = 2; col < output.ncols(); col += 2) + { + value = val(input.at(0, col / 2)); + value += val(input.at(0, col / 2 - 1)); + output.at(0, col) = do_threshold(value / 2); + } + + for (int col = 1; col < output.ncols(); col += 2) + output.at(0, col) = do_threshold(input.at(0, col / 2)); + + // col 0 + + for (int row = 2; row < output.nrows(); row += 2) + { + value = val(input.at(row / 2, 0)); + value += val(input.at(row / 2 - 1, 0)); + output.at(row, 0) = do_threshold(value / 2); + } + + for (int row = 1; row < output.nrows(); row += 2) + output.at(row, 0) = do_threshold(input.at(row / 2, 0)); + + // others + + for (int row = 2; row < output.nrows(); row += 2) + { + for (int col = 2; col < output.ncols(); col += 2) + { + value = val(input.at(row / 2, col / 2)); + value += val(input.at(row / 2 - 1, col / 2)); + value += val(input.at(row / 2, col / 2 - 1)); + value += val(input.at(row / 2 - 1, col / 2 - 1)); + output.at(row, col) = do_threshold(value / 4); + } + for (int col = 1; col < output.ncols(); col += 2) + { + value = val(input.at(row / 2, col / 2)); + value += val(input.at(row / 2 - 1, col / 2)); + output.at(row, col) = do_threshold(value / 2); + } + } + + for (int row = 1; row < output.nrows(); row += 2) + { + for (int col = 2; col < output.ncols(); col += 2) + { + value = val(input.at(row / 2, col / 2)); + value += val(input.at(row / 2, col / 2 - 1)); + output.at(row, col) = do_threshold(value / 2); + } + for (int col = 1; col < output.ncols(); col += 2) + output.at(row, col) = do_threshold(input.at(row / 2, col / 2)); + } + + return output; +} + + +// enlarge 2^n times +mln::image2d<mln::value::int_u8> +enlarge(mln::image2d<bool> input, unsigned int n) +{ + using namespace mln; + using value::int_u8; + + image2d<int_u8> output; + + do + { + output = enlargex2(input); + + if (--n > 0) + { + initialize(input, output); + mln_piter_(image2d<bool>) p(input.domain()); + for_all(p) + input(p) = output(p) > 0; + } + else + break; + } + while (1); + return output; +} + +#endif // ! ENLARGE_HH