URL:
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox
ChangeLog:
2008-10-24 Jimmy Ma <jimmy.ma(a)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