我的tesseract学习记录

前言:花了约三周看文档(打酱油),又花了两周搭环境,终于把tesseract用起来了,对简体中文的识别率还不错,在95%以上。现在简要记录一下安装、识别过程。

一、系统环境

  系统:windows7

  编译环境:VS2010

  依赖软件:leptonica、opencv2.4.10、tesseract3.02

  linux下的tesseract在这里

二、安装过程

  (1) leptonica

  1、leptonica是tesseract的依赖库,安装过程主要参考官网教程;

    vs2010的编译过程参考这里;

    建议直接使用leptonica提供的vs2008的工程,转换成vs2010以后,需要修改的地方如下:  

    Fix the liblept168 project by doing the following:

    1. Right-click on liblept168 and choose Properties.

    2. Then change liblept168 Property Pages | General | Target Name to one of the following values:

      For the LIB Debug Configuration:

      $(ProjectName)-static-mtdll-debug
      

      For the LIB Release Configuration:

      $(ProjectName)-static-mtdll
      

      For the DLL Debug Configuration:

      $(ProjectName)d

    编译即可得到:

    LIB_RELEASE和LIB_DEBUG:

    liblept168-static-mtdll.lib 和 liblept168-static-mtdll-debug.lib

    DLL_RELEASE和DLL_DEBUG:

    liblept168.lib、liblept168.dll和 liblept168d.lib、liblept168d.dll

 

    在调用生成的动态库liblept168d.dll,报错,找不到从属程序集 Microsoft.VC90.DebugCRT

    解决方法,参考这里

  2、如果想自己编译所有依赖库,超级麻烦,可以参考下面的步骤:

    一共需要安装5个依赖包,分别是:zlib、libpng、libjpeg、libtiff、giflib

    上述5个依赖库安装过程可参考这里;

    整个leptonica安装过程也可参考这里;

    注意:以下五个库的生成,应确保运行库都选择/MD或/MDd

       不使用全程序优化/GL编译

  1.zlib

    zlib的编译过程参考这里;

    首先cd to the BuildFolder\zlib\contrib\masmx86 directory. Then execute:bld_ml32.bat

    然后打开\BuildFolder\zlib\contrib\vstudio\vc10\zlibvc.sln

    修改运行时库为/MD或/MDd

    移除 ZLIB_WINAPI from Configuration Properties | C/C++ | Preprocessor | Preprocessor Definitions.

    If you don’t do this you’ll get undefined symbol error messages when trying to build libpng and libtiff.

    最后,Copy zlib\zlib.h and zconf.h to BuildFolder\include.

  2.libpng

    libpng的编译过程参考这里;

    (1)Open BuildFolder\lpng143\projects\visualc71\libpng

    (2)change the LIB Debug Configuration Properties | C/C++ | General | Debug Information Format 

    from Program Database for Edit & Continue (/ZI) to C7 Compatible (/Z7).

    (3)change run time library from /MT to /MD or from /MTd to /MDd

    (4)Build the libpng by right-clicking it and choosing Build

    

  3.libjpeg

    libjpeg的编译过程参考这里;

    如果编译的过程中,nmake有问题,参考这里;

    打开D:\libjpeg\jpeg-9a\install.txt 里面有vs2010编译的说明。

    编译jpeg时,官网上的只有release版本的lib,需要debug版本的lib的话,编译选项需要自己配置

    配置方法,就是拷贝release版本预处理器定义,并进行修改,将NDEBUG改为_DEBUG

    将运行库改为:/MDd

    基本运行时检查改为:两者

    将全程序优化(GL)选项关闭。

  4.libtiff

    libtiff源码的下载地址;

    编译过程参考这里

   libtiff depends on libjpeg and zlib.

    由于libtiff依赖了libjpeg和zlib,因此需要修改nmake.opt和tiffconf.vc.h文件。

 

    nmake.opt修改如下: 

    # Uncomment and edit following lines to enable JPEG support.
    #
    JPEG_SUPPORT = 1
    JPEGDIR = D:/zhuyan/leptlib/libtiff/jpeg
    JPEG_INCLUDE = -I$(JPEGDIR)
    JPEG_LIB = $(JPEGDIR)/libjpeg9a-static-mtdll.lib

    # Uncomment and edit following lines to enable ZIP support
    # (required for Deflate compression and Pixar log-format)
    #
    ZIP_SUPPORT = 1
    ZLIBDIR = D:/zhuyan/leptlib/libtiff/zlib
    ZLIB_INCLUDE = -I$(ZLIBDIR)
    ZLIB_LIB = $(ZLIBDIR)/zlib125-static-mtdll.lib

 

    tiffconf.vc.h(使用IDE,则直接在tiffconf.h中修改)修改如下:

    增加两条语句:

    #define JPEG_SUPPORT 1

    #define ZIP_SUPPORT 1

    

    使用nmake编译

    输入nmake /f makefile.vc clean

    输入nmake /f makefile.vc

  

    使用IDE编译:

    从nmake编译换成IDE编译,需要获取编译时宏定义参考这里;

    即在命令行中输入nmake /f makefile.vc clean all > vc.txt

    用于查看编译用到了哪些文件,定义了哪些宏。

    需要的源文件,tiff_* 共38个,port中3个源文件,snprintf.c,strcasecmp.c,getopt.c

  5.giflib

    giflib的官网地址;

    download giflib for windows : here

    按以下要求修改预处理器定义  

      WIN32
      WINDOWS32
      NDEBUG
      _LIB
      _OPEN_BINARY
      HAVE_IO_H
      HAVE_FCNTL_H
      HAVE_STDARG_H
      HAVE_BASETSD_H
      HAVE_STDINT_H
      HAVE_SYS_TYPES_H
      _MBCS

 

  3、 依赖库编译好了以后,直接使用leptonica的vs2008工程,将其转换为vs2010工程,

    由于使用的依赖库版本与工程中的设定不同,因此需要修改属性管理器中定义的用户宏。

    leptonica的vs2008工程中使用的宏:

          

    修改为自己使用的版本。

           

    修改方法参考这里;

   

  (2) tesseract3.02

    1.找到编译tesseract3.02的说明,由于这里没有vpn,可以直接参考下载的源码里自带的说明:

      D:\tesseract-3.02.02\vs2008\doc\setup.html

      也可以辅助参考一下官网说明;

      不想看英文的可以参考这里;

      官网中说,可以直接下载leptonica的leptonica-1.68-win32-lib-include-dirs.zip,包含了leptonica的所有头文件和静态库,这个是vs2008编译的。

      如果在vs2010工程中不能使用,只需使用vs2010重新编译leptonica的静态库和动态库。

    2.下载leptonica头文件和库文件;

     下载tesseract源码

    3.对D:\tesseract-3.02.02\vs2008\中的vs2008工程进行转换为vs2010,提出以下警告    

MSB8012: $(TargetName) ('libtesseract302') does not match the Librarian's OutputFile property value '..\LIB_Debug\libtesseract302-static-debug.lib' ('libtesseract302-static-debug') in project configuration 'LIB_Debug|Win32'. This may cause your project to build incorrectly. To correct this, please make sure that $(TargetName) property value matches the value specified in %(Lib.OutputFile).
MSB8012: $(TargetPath) ('D:\zhuyan\leptlib\tesseract-build\tesseract-3.02.02\vs2010\libtesseract\..\LIB_Debug\libtesseract302.lib') does not match the Librarian's OutputFile property value '..\LIB_Debug\libtesseract302-static-debug.lib' ('D:\zhuyan\leptlib\tesseract-build\tesseract-3.02.02\LIB_Debug\libtesseract302-static-debug.lib') in project configuration 'LIB_Debug|Win32'. This may cause your project to build incorrectly. To correct this, please make sure that $(TargetPath) property value matches the value specified in %(Lib.OutputFile).
MSB8012: $(TargetName) ('libtesseract302') does not match the Librarian's OutputFile property value '..\LIB_Release\libtesseract302-static.lib' ('libtesseract302-static') in project configuration 'LIB_Release|Win32'. This may cause your project to build incorrectly. To correct this, please make sure that $(TargetName) property value matches the value specified in %(Lib.OutputFile).
MSB8012: $(TargetPath) ('D:\zhuyan\leptlib\tesseract-build\tesseract-3.02.02\vs2010\libtesseract\..\LIB_Release\libtesseract302.lib') does not match the Librarian's OutputFile property value '..\LIB_Release\libtesseract302-static.lib' ('D:\zhuyan\leptlib\tesseract-build\tesseract-3.02.02\LIB_Release\libtesseract302-static.lib') in project configuration 'LIB_Release|Win32'. This may cause your project to build incorrectly. To correct this, please make sure that $(TargetPath) property value matches the value specified in %(Lib.OutputFile).
MSB8012: $(TargetPath) ('D:\zhuyan\leptlib\tesseract-build\tesseract-3.02.02\vs2010\libtesseract\..\DLL_Release\libtesseract302.dll') does not match the Linker's OutputFile property value '..\DLL_Release\libtesseract302.dll' ('D:\zhuyan\leptlib\tesseract-build\tesseract-3.02.02\DLL_Release\libtesseract302.dll') in project configuration 'DLL_Release|Win32'. This may cause your project to build incorrectly. To correct this, please make sure that $(TargetPath) property value matches the value specified in %(Link.OutputFile).
MSB8012: $(TargetName) ('libtesseract302') does not match the Linker's OutputFile property value '..\DLL_Debug\libtesseract302d.dll' ('libtesseract302d') in project configuration 'DLL_Debug|Win32'. This may cause your project to build incorrectly. To correct this, please make sure that $(TargetName) property value matches the value specified in %(Link.OutputFile).
MSB8012: $(TargetPath) ('D:\zhuyan\leptlib\tesseract-build\tesseract-3.02.02\vs2010\libtesseract\..\DLL_Debug\libtesseract302.dll') does not match the Linker's OutputFile property value '..\DLL_Debug\libtesseract302d.dll' ('D:\zhuyan\leptlib\tesseract-build\tesseract-3.02.02\DLL_Debug\libtesseract302d.dll') in project configuration 'DLL_Debug|Win32'. This may cause your project to build incorrectly. To correct this, please make sure that $(TargetPath) property value matches the value specified in %(Link.OutputFile).

    修改方法参考这里;

    错误描述为:

    warning MSB8012: TargetPath(D:\zhuyan\leptlib\tesseract-build\tesseract-3.02.02\vs2010\libtesseract\..\LIB_Debug\libtesseract302-static-mtdll-debug.lib)

    与 Library 的 OutputFile 属性值(D:\zhuyan\leptlib\tesseract-build\tesseract-3.02.02\vs2010\LIB_Debug\libtesseract302-static-debug.lib)不匹配。

    即:

    LIB_RELEASE:    

    将属性->配置属性->常规中目标文件名改为$(ProjectName)-static

    LIB_Debug:

    将属性->配置属性->常规中目标文件名改为$(ProjectName)-static-debug

    DLL_Debug:

    将属性->配置属性->常规中目标文件名改为$(ProjectName)d

    编译时,弹出如下错误:

    ..\..\ccmain\equationdetect.cpp : warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失

    这是因为该cpp文件的编码格式有问题,只需要在双击该文件,在右侧导航栏上点击该文件,在文件->高级保存选项中,在窗口中选择“简体中文(gb2312)-代码页936”,保存后重新编译。  

 

    4.编译过程主要参考有:

      http://www.jianshu.com/p/5446776095b8 

      http://blog.csdn.net/u012566751/article/details/54141109

      http://blog.csdn.net/rrrfff/article/details/8552946

      linux : http://blog.csdn.net/zhangping1987/article/details/51151050

 

      采用LIB_RELEASE和LIB_DEBUG模式,分别生成的文件是:libtesseract302-static.lib 和 libtesseract302-static-debug.lib

      采用DLL_RELEASE和DLL_DEBUG模式,分别生成的文件是:libtesseract302.dll、libtesseract302.lib 和 libtesseract302d.dll、libtesseract302d.lib

    5.api的使用,主要参考有:

      http://blog.csdn.net/u012566751/article/details/54136836

      http://www.tuicool.com/articles/aMZfMv

      https://wenku.baidu.com/view/46858352b7360b4c2e3f64b8.html

      主要参考:http://www.jianshu.com/p/a53c732d8da3

      工程配置如下:

      1、将tesseract中所有的.h文件搜索出来,放到文件夹include/tesseract,将静态库放到文件夹lib

      2、将leptonica中的所有.h文件,放到一个文件夹include/leptonica,将静态库放到文件夹lib

      3、属性->C/C++->附加包含目录,包含上述头文件的文件夹

      4、链接器->常规->附加库目录,包含上述静态库文件夹

      5、链接器->输入->附加依赖项,输入leptonica和tesseract的静态库

      6、如果使用的是动态库,则将动态库文件放到一个文件夹bin中,并修改计算机的环境变量,同时包含动态库的导入库lib

      7、注意,新建文件夹tessdata,存放训练过的语言文件,放的位置在xx/Tesseract-OCR/tessdata/

      8、需要将xx/Tesseract-OCR/添加到新建环境变量TESSDATA_PREFIX中,再将xx/Tesseract-OCR/添加到Path环境变量中。

 

      动态库的使用,网上例子很多(参考上面三个链接)。

      现在说下静态库的使用,必须包含所有上述的静态库,否则报错。

      参考D:\tesseract-3.02.02\vs2008\doc\programming.html

      LIB_Release Linker Additional Dependencies:

     ws2_32.lib
     user32.lib
     zlib$(ZLIB_VERSION)-static-mtdll.lib
     libpng$(LIBPNG_VERSION)-static-mtdll.lib
     libjpeg$(LIBJPEG_VERSION)-static-mtdll.lib
     giflib$(GIFLIB_VERSION)-static-mtdll.lib
     libtiff$(LIBTIFF_VERSION)-static-mtdll.lib
     liblept$(LIBLEPT_VERSION)-static-mtdll.lib
     libtesseract$(LIBTESS_VERSION)-static.lib

    6.opencv的使用
     opencv的静态库在工程中的debug和release模式中需要分别添加

       release:

        opencv_calib3d2410.lib
        opencv_contrib2410.lib
        opencv_core2410.lib
        opencv_features2d2410.lib
        opencv_flann2410.lib
        opencv_gpu2410.lib
        opencv_highgui2410.lib
        opencv_imgproc2410.lib
        opencv_legacy2410.lib
        opencv_ml2410.lib
        opencv_nonfree2410.lib
        opencv_objdetect2410.lib
        opencv_ocl2410.lib
        opencv_photo2410.lib
        opencv_stitching2410.lib
        opencv_superres2410.lib
        opencv_ts2410.lib
        opencv_video2410.lib
        opencv_videostab2410.lib

      debug模式就是在这些库的末尾加上d,比如opencv_videostab2410d.lib

三、识别过程

  (1)图像预处理

    图像预处理主要参考官网提出的对图像的处理,由于我主要用来识别扫描的文件,所以只做了简单的去噪,使用的是腐蚀和膨胀。由于只会opencv,所以用的opencv做图像预处理。

    如果扫描件的图片周围有黑框,可以参考Border removal中的算法去除。

    下面是做的一些图像处理时,参考的链接。

    1、 Border removal :

      a) http://answers.opencv.org/question/30082/detect-and-remove-borders-from-framed-photographs/

    2、 Binarization:

      a) threshold in opencv with parameter of OTSU

      b) other approach, ref: http://liris.cnrs.fr/christian.wolf/papers/icpr2002v.pdf

    3、 remove noise introduced by digitization:

      a) median filter for salt/pepper noise

      b) morphological operations : http://stackoverflow.com/questions/8654858/noise-removal-in-opencv

      c) mean filter for Gaussian noise

    4、 chunk segmentation :no images, horizontal or vertical separators

    5、 detect skew angle of text

      a) http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/

    

  (2)页面布局分析

    1、字体大小和分辨率

      在测试时发现,将一个文档的图片直接扔到tesseract中,识别效果不太理想,但是,将图片中字体和大小不同的文字截图成多个图片块,再扔给tesseract,识别率惊人的高。

      仔细看了一下官方网站,对待识别的图片中文字的要求是:

      Is there a Minimum Text Size? (It won't read screen text!)

      There is a minimum text size for reasonable accuracy. You have to consider resolution as well as point size. Accuracy drops off below 10pt x 300dpi,

      rapidly below 8pt x 300dpi. A quick check is to count the pixels of the x-height of your characters. (X-height is the height of the lower case x.)

      At 10pt x 300dpi x-heights are typically about 20 pixels,although this can vary dramatically from font to font. Below an x-height of 10 pixels,

      you have very little chance of accurate results, and below about 8 pixels, most of the text will be"noise removed".

      总的来说:最小5号字,扫描仪dpi不小于300,单个字符的高度不小于20个像素。

      由于使用的扫描仪,最后得到的是一个pdf格式的文档,得转成图片,转图片时,选择300dpi,使用的小工具转换的。

    2、页面分块

      既然将图片分块,可以提高识别率,那么就来分块吧。可是不知道用什么分块算法,不过幸好tesseract自带有页面布局分析模块,很强大,很好用(崇拜一下)。

      过程如下:

      1.初始化tesseract和设置参数

        api.Init()

        api.SetPageSegMode()  //这里要使用 tesseract::PSM_AUTO 自动页面布局分析模式

        api.SetImage((uchar*)src.data, src.cols, src.rows, src.channels(), src.cols * src.channels()); //我用的opencv的数据结构输入的

      2.获取图片分块

        Boxa *boxes = api.GetRegions(NULL);//获取粗分块

        BOX* box = boxaGetBox(boxes, i, L_CLONE);//获取分块方框的坐标,一共有boxes->n个方框

      3.获取文字行分块

        Boxa *lineboxes = api.GetTextlines(NULL,NULL);//获取每个粗分块中的文字行分块,这里会自动舍弃含有图片的分块。

 

      将分块后的图片,截取出来,直接扔到OCR里,结果啥也没识别出来,问题在哪里??

      原来是截取得文字行的高和宽将图片占满了,OCR没法识别,怎么办?我想的方法是在周围加空白。

      试了一些参数,在文字行四周增加空白的高宽比例为文字行高度的0.6倍,即垂直和水平方向上增加的空白的高度相加,为文字行高度的1.2倍。

      再扔到OCR里,效果还是不好啊(哭),觉得是不是文字的比例还是不合适,那么就进行缩放吧,将图片缩小了一倍,即缩放系数0.5,然后,surprise,识别率大增,非常满意。

      当然这里的两个参数,可以根据实际情况,来调整。

        int boxEdge = (int)r.height*1.2;//增加的空白比例

        Mat dst(box_img.rows+boxEdge,box_img.cols+boxEdge,box_img.type(), Scalar(255,255,255));//空白图片
        addWeighted(dst(Rect(boxEdge/2,boxEdge/2,r.width,r.height)),0,box_img,1,0.0,dst(Rect(boxEdge/2,boxEdge/2,r.width,r.height)));//文字与空白图片融合

        Mat resize_dst;
        double scale = 0.5;//缩放系数
        cv::resize(dst, resize_dst, cv::Size(dst.cols * scale, dst.rows * scale), (0,0), (0,0), cv::INTER_LINEAR);//缩放图片

      如果对tesseract页面布局分析的过程感兴趣的可参考:http://blog.csdn.net/kaelsass/article/details/46874627

 

    3、去除盖章

      由于我主要用来识别一些红头文件,所以,里面有些地方有盖的红章,tesseract在页面布局分析时,直接将含有叠加图片的整!行!文字都舍弃了(或者识别出来是乱码)。

      于是,我得想办法把红章去掉,然后识别红章下的文字。去掉的方法呢,首先想到的是颜色,检测红色,再去掉。然后发现红头文件啊,红色字也好多啊。

      灵机一动,可以将上一步页面布局分析中,将红章和文字划分为一块的那个分块图像单独拿出来,怎么找到呢,默认都是圆章,那么使用霍夫变换吧,检测圆。

      1.检测圆   

        cvtColor(box_img, gray_img, CV_BGR2GRAY);
        cv::GaussianBlur(gray_img,gray_img,cv::Size(7,7),1.5);
        std::vector<cv::Vec3f> circles;
        cv::HoughCircles(gray_img, circles, CV_HOUGH_GRADIENT,
                 2, // 累加器的分辨率(图像尺寸/2)
                 box_img.rows/2, // 两个圆之间的最小距离
                 200, // Canny中的高阈值
                 300, // 最小投票数
                 50, box_img.rows/2); // 有效半径的最小和最大值

      2.去除红色的像素点

        MatIterator_<Vec3b> it_in=box_img.begin<Vec3b>();

        if((*it_in)[2]>80)
        {
          (*it_in)[0]=255;//b
          (*it_in)[1]=255;//g
          (*it_in)[2]=255;//r
        }

 

      成功地去掉了红章以后,对文字造成了一些破坏,使用了膨胀+腐蚀来增强图像,最后识别率很高。

      前期的图像预处理很重要,最好丢进去的文字,没有噪声,没有倾斜,清晰,无底纹或者图片。

 

  (2)识别过程

     网上的例子很多,识别的过程,几乎做不了太多事情,除非去源码里进行改进,由于时间有限,加上tesseract的识别率还不错,所以,只需要对参数进行设置就可以了。

     这些参数,是用于识别日文时设置的,但官网上说,对中文也适用,主要是以下参数进行了设置:

      //SetVariable
      bool out;

      out = api.SetVariable("chop_enable","T");

      out = api.SetVariable("use_new_state_cost","F");
      out = api.SetVariable("segment_segcost_rating","F");

      out = api.SetVariable("enable_new_segsearch","0");

      out = api.SetVariable("language_model_ngram_on","0");

      out = api.SetVariable("textord_force_make_prop_words","F");
      out = api.SetVariable("edges_max_children_per_outline","40");

     设置这些参数后,确实对识别率有了一些提升。

     这些参数的说明,参考官网说明。

 

posted on 2017-03-16 12:08  Crysaty  阅读(1355)  评论(0)    收藏  举报

导航