交叉编译tesseract-ocr到iOS平台

Tesseract是一个开源的OCR(Optical Character Recognition,光学字符识别)引擎,可以识别多种格式的图像文件并将其转换成文本。Tesseract最初由HP公司开发,后来由Google维护,目前Google开源到Github上。

源码下载地址

如果想在ios开发中使用该引擎,就需要对源代码进行交叉编译。最近有该方向的需求,边查资料,边整理如下:

首先在Mac上编译需要安装一些依赖库和编译工具。

1.安装m4

curl -O http://mirrors.kernel.org/gnu/m4/m4-latest.tar.gz
tar -xzvf m4-latest.tar.gz
cd m4-1.4.17
./configure --prefix=/usr/local
make
sudo make install

m4 是一种宏处理器,它扫描用户输入的文本并将其输出,期间如果遇到宏就将其展开后输出。宏有两种,一种是内建的,另一种是用户定义的,它们能接受任意数量的参数。 除了做展开宏的工作之外,m4 内建的宏能够加载文件,执行 Shell 命令,做整数运算,操纵文本,形成递归等等。m4 可用作编译器的前端,或者单纯作为宏处理器来用 。貌似是个很古老,很牛逼的东西,暂时接触不到,不深研究。
验证是否安装成功的方法如下:
在任意文件夹[vi hello.m4] 创建文件 hello.m4。
内容如下:

divert(0)
define(say_hello_world, Hello World!)
say_hello_world

保存后,执行如下命令:

$ m4  hello.m4

Hello World!  //屏幕输出结果

安装成功!

2.安装autoconf

curl -O http://mirrors.kernel.org/gnu/autoconf/autoconf-latest.tar.gz
tar -xzvf autoconf-latest.tar.gz
cd autoconf-2.69
./configure --prefix=/usr/local
make
sudo make install

Autoconf是一个用于包,以适应多种Unix类系统的 shell脚本的工具。由Autoconf生成的配置脚本在运行的时候与Autoconf是无关的, 就是说配置脚本的用户并不需要拥有Autoconf。

使用下面的命令,如果能正常输入版本信息,则安装成功。

autoconf --version

3.安装automake

curl -O http://mirrors.kernel.org/gnu/automake/automake-1.15.tar.xz
tar -xzvf automake-1.15.tar.xz
cd automake-1.15
./configure --prefix=/usr/local
make
sudo make install

automake是一个从Makefile.am文件自动生成Makefile.in的工具。

使用下面的命令,如果能正常输入版本信息,则安装成功。

automake --version

4.安装libtool

curl -O http://mirrors.kernel.org/gnu/libtool/libtool-2.4.6.tar.gz
tar -xzvf libtool-2.4.6.tar.gz
cd libtool-2.4.6
./configure --prefix=/usr/local
make
sudo make install

libtool 是一个通用库支持脚本,将使用动态库的复杂性隐藏在统一、可移植的接口中,也就是说,你可以通过如下所示的标准方法,在不同平台上创建并调用动态库,我们 可以认为libtool是gcc的一个抽象,也就是说,它包装了gcc或者其他的任何编译器,用户无需知道细节,只要告诉libtool说我需要要编译哪 些库即可,并且,它只与libtool文件打交道,例如lo、la为后缀的文件。

使用下面的命令,如果能正常输入版本信息,则安装成功。

libtool --version

5.下载leptonica

curl -O http://www.leptonica.com/source/leptonica-1.73.tar.gz
tar -xzvf leptonica-1.73.tar.gz

leptonica是图形处理的基础类库,tesseract-ocr的依赖库。

6.安装gtk+(需要gtk中的pango模块)

brew install gtk+
brew link gtk+

brew 的安装方法请参考这里

7.安装pkg-config,这是m4的模块。

brew install pkg-config
brew link pkg-config

该模块没有安装或者没有加载,会提示PKG_CHECK_MODULES函数不存在的错误。

上面的安装是基于本人机器既有配置。如果安装不成功,请参照错误信息解决,例如提前需要安装gcc。
依赖库和工具安装完成。

开始编译 tesseract
创建编译用的文件夹

#!/bin/sh
# build.sh

GLOBAL_OUTDIR="`pwd`/dependencies"
LOCAL_OUTDIR="./outdir"
LEPTON_LIB="`pwd`/leptonica-1.73"
TESSERACT_LIB="`pwd`/tesseract"

IOS_BASE_SDK="9.3"
IOS_DEPLOY_TGT="7.0"

XCODE_DEVELOPER=/Applications/Xcode.app/Contents/Developer
XCODETOOLCHAIN=$XCODE_DEVELOPER/Toolchains/XcodeDefault.xctoolchain
SDK_IPHONEOS=$(xcrun --sdk iphoneos --show-sdk-path)
SDK_IPHONESIMULATOR=$(xcrun --sdk iphonesimulator --show-sdk-path)

setenv_all()
{
        # Add internal libs
        export CFLAGS="$CFLAGS -I$GLOBAL_OUTDIR/include -L$GLOBAL_OUTDIR/lib"

        export CXX=`xcrun -find c++`
        export CC=`xcrun -find cc`
        export PATH="$XCODETOOLCHAIN/usr/bin:$PATH"

        export LD=`xcrun -find ld`
        export AR=`xcrun -find ar`
        export AS=`xcrun -find as`
        export NM=`xcrun -find nm`
        export RANLIB=`xcrun -find ranlib`

        export LDFLAGS="-L$SDKROOT/usr/lib/"

        export CPPFLAGS=$CFLAGS
        export CXXFLAGS=$CFLAGS
}

setenv_arm7()
{
    unset SDKROOT CFLAGS CC LD CPP CXX AR AS NM CXXCPP RANLIB LDFLAGS CPPFLAGS CXXFLAGS
    export SDKROOT=$SDK_IPHONEOS
    export CFLAGS="-arch armv7 -pipe -no-cpp-precomp -isysroot $SDKROOT -miphoneos-version-min=$IOS_DEPLOY_TGT -I$SDKROOT/usr/include/"
    setenv_all
}

setenv_arm7s()
{
    unset DEVROOT SDKROOT CFLAGS CC LD CPP CXX AR AS NM CXXCPP RANLIB LDFLAGS CPPFLAGS CXXFLAGS
    export SDKROOT=$SDK_IPHONEOS
    export CFLAGS="-arch armv7s -pipe -no-cpp-precomp -isysroot $SDKROOT -miphoneos-version-min=$IOS_DEPLOY_TGT -I$SDKROOT/usr/include/"
    setenv_all
}

setenv_arm64()
{
unset DEVROOT SDKROOT CFLAGS CC LD CPP CXX AR AS NM CXXCPP RANLIB LDFLAGS CPPFLAGS CXXFLAGS
export SDKROOT=$SDK_IPHONEOS
export CFLAGS="-arch arm64 -pipe -no-cpp-precomp -isysroot $SDKROOT -miphoneos-version-min=$IOS_DEPLOY_TGT -I$SDKROOT/usr/include/"
setenv_all
}

setenv_i386()
{
    unset DEVROOT SDKROOT CFLAGS CC LD CPP CXX AR AS NM CXXCPP RANLIB LDFLAGS CPPFLAGS CXXFLAGS
    export SDKROOT=$SDK_IPHONESIMULATOR
    export CFLAGS="-arch i386 -pipe -no-cpp-precomp -isysroot $SDKROOT -miphoneos-version-min=$IOS_DEPLOY_TGT"
    setenv_all
}

setenv_x86_64()
{
    unset DEVROOT SDKROOT CFLAGS CC LD CPP CXX AR AS NM CXXCPP RANLIB LDFLAGS CPPFLAGS CXXFLAGS
    export SDKROOT=$SDK_IPHONESIMULATOR
    export CFLAGS="-arch x86_64 -pipe -no-cpp-precomp -isysroot $SDKROOT -miphoneos-version-min=$IOS_DEPLOY_TGT"
    setenv_all
}

create_outdir_lipo()
{

    for lib_i386 in `find $LOCAL_OUTDIR/i386 -name "lib*.a"`; do
        lib_arm7=`echo $lib_i386 | sed "s/i386/arm7/g"`
        lib_arm7s=`echo $lib_i386 | sed "s/i386/arm7s/g"`
        lib_arm64=`echo $lib_i386 | sed "s/i386/arm64/g"`
        lib=`echo $lib_i386 | sed "s/i386//g"`
        lib_x86_64=`echo $lib_i386 | sed "s/i386/x86_64/g"`
        xcrun -sdk iphoneos lipo -arch armv7 $lib_arm7 -arch armv7s $lib_arm7s -arch arm64 $lib_arm64 -arch x86_64 $lib_x86_64 -arch i386 $lib_i386 -create -output $lib
    done
}

merge_libfiles()
{
        DIR=$1
        LIBNAME=$2

        cd $DIR
        for i in `find . -name "lib*.a"`; do
                $AR -x $i
        done
        $AR -r $LIBNAME *.o
        rm -rf *.o __*
        cd -
}

build_leptonica()
{
    #######################
    # LEPTONLIB
    #######################
    cd $LEPTON_LIB
    rm -rf $LOCAL_OUTDIR
    mkdir -p $LOCAL_OUTDIR/arm7 $LOCAL_OUTDIR/arm7s $LOCAL_OUTDIR/arm64 $LOCAL_OUTDIR/i386 $LOCAL_OUTDIR/x86_64

    make clean 2> /dev/null
    make distclean 2> /dev/null
    setenv_arm7
    ./configure --host=arm-apple-darwin7 --enable-shared=no --disable-programs --without-zlib --without-libpng --without-jpeg --without-giflib --without-libtiff
    make -j12
    cp -rvf src/.libs/lib*.a $LOCAL_OUTDIR/arm7

    make clean 2> /dev/null
    make distclean 2> /dev/null
    setenv_arm7s
    ./configure --host=arm-apple-darwin7s --enable-shared=no --disable-programs --without-zlib --without-libpng --without-jpeg --without-giflib --without-libtiff
    make -j12
    cp -rvf src/.libs/lib*.a $LOCAL_OUTDIR/arm7s

    make clean 2> /dev/null
    make distclean 2> /dev/null
    setenv_arm64
    ./configure --host=arm-apple-darwin64 --enable-shared=no --disable-programs --without-zlib --without-libpng --without-jpeg --without-giflib --without-libtiff
    make -j12
    cp -rvf src/.libs/lib*.a $LOCAL_OUTDIR/arm64

    make clean 2> /dev/null
    make distclean 2> /dev/null
    setenv_i386
    ./configure --enable-shared=no --disable-programs --without-zlib --without-libpng --without-jpeg --without-giflib --without-libtiff
    make -j12
    cp -rvf src/.libs/lib*.a $LOCAL_OUTDIR/i386

    make clean 2> /dev/null
    make distclean 2> /dev/null
    setenv_x86_64
    ./configure --host=x86_64-apple-darwin --enable-shared=no --disable-programs --without-zlib --without-libpng --without-jpeg --without-giflib --without-libtiff
    make -j12
    cp -rvf src/.libs/lib*.a $LOCAL_OUTDIR/x86_64

    create_outdir_lipo
    mkdir -p $GLOBAL_OUTDIR/include/leptonica && cp -rvf src/*.h $GLOBAL_OUTDIR/include/leptonica
    mkdir -p $GLOBAL_OUTDIR/lib && cp -rvf $LOCAL_OUTDIR/lib*.a $GLOBAL_OUTDIR/lib
    cd ..
}

build_tesseract()
{
    #######################
    # TESSERACT-OCR
    #######################
    cd $TESSERACT_LIB
    rm -rf $LOCAL_OUTDIR
    mkdir -p $LOCAL_OUTDIR/arm7 $LOCAL_OUTDIR/arm7s $LOCAL_OUTDIR/arm64 $LOCAL_OUTDIR/i386 $LOCAL_OUTDIR/x86_64

    make clean 2> /dev/null
    make distclean 2> /dev/null
    setenv_arm7
    bash autogen.sh
    ./configure --host=arm-apple-darwin7 --enable-shared=no LIBLEPT_HEADERSDIR=$GLOBAL_OUTDIR/include/
    make -j12
    for i in `find . -name "lib*.a" | grep -v arm`; do cp -rvf $i $LOCAL_OUTDIR/arm7; done
    merge_libfiles $LOCAL_OUTDIR/arm7 libtesseract_all.a

    make clean 2> /dev/null
    make distclean 2> /dev/null
    setenv_arm7s
    bash autogen.sh
    ./configure --host=arm-apple-darwin7s --enable-shared=no LIBLEPT_HEADERSDIR=$GLOBAL_OUTDIR/include/
    make -j12
    for i in `find . -name "lib*.a" | grep -v arm`; do cp -rvf $i $LOCAL_OUTDIR/arm7s; done
    merge_libfiles $LOCAL_OUTDIR/arm7s libtesseract_all.a

    make clean 2> /dev/null
    make distclean 2> /dev/null
    setenv_arm64
    bash autogen.sh
    ./configure --host=arm-apple-darwin64 --enable-shared=no LIBLEPT_HEADERSDIR=$GLOBAL_OUTDIR/include/
    make -j12
    for i in `find . -name "lib*.a" | grep -v arm`; do cp -rvf $i $LOCAL_OUTDIR/arm64; done
    merge_libfiles $LOCAL_OUTDIR/arm64 libtesseract_all.a

    make clean 2> /dev/null
    make distclean 2> /dev/null
    setenv_i386
    bash autogen.sh
    ./configure --enable-shared=no LIBLEPT_HEADERSDIR=$GLOBAL_OUTDIR/include/
    make -j12
    for i in `find . -name "lib*.a" | grep -v arm`; do cp -rvf $i $LOCAL_OUTDIR/i386; done
    merge_libfiles $LOCAL_OUTDIR/i386 libtesseract_all.a

    make clean 2> /dev/null
    make distclean 2> /dev/null
    setenv_x86_64
    bash autogen.sh
    ./configure --host=x86_64-apple-darwin --enable-shared=no LIBLEPT_HEADERSDIR=$GLOBAL_OUTDIR/include/
    make -j12
    for i in `find . -name "lib*.a" | grep -v arm | grep -v i386`; do cp -rvf $i $LOCAL_OUTDIR/x86_64; done
    merge_libfiles $LOCAL_OUTDIR/x86_64 libtesseract_all.a


    create_outdir_lipo
    mkdir -p $GLOBAL_OUTDIR/include/tesseract
    tess_inc=( api/apitypes.h api/baseapi.h ccmain/thresholder.h ccmain/resultiterator.h ccmain/pageiterator.h ccmain/ltrresultiterator.h
               ccstruct/publictypes.h ccutil/errcode.h ccutil/genericvector.h ccutil/helpers.h ccutil/host.h ccutil/ndminx.h ccutil/ocrclass.h
               ccutil/platform.h ccutil/tesscallback.h ccutil/unichar.h ccutil/unicharset.h ccutil/strngs.h ccutil/memry.h ccutil/unicharmap.h ccutil/fileerr.h ccutil/fileerr.h ccutil/serialis.h)
    for i in "${tess_inc[@]}"; do
       cp -rvf $i $GLOBAL_OUTDIR/include/tesseract
    done


    mkdir -p $GLOBAL_OUTDIR/lib && cp -rvf $LOCAL_OUTDIR/lib*.a $GLOBAL_OUTDIR/lib
    make clean 2> /dev/null
    make distclean 2> /dev/null
#   rm -rf $LOCAL_OUTDIR
    cd ..
}

build_leptonica
build_tesseract

echo "Finished!"

给 build.sh 添加执行权限,并执行

chmod +x build.sh
./build.sh

-------------------------------------
编译成功会提示[Finished!], 并且在生成以下目录结构的文件。

dependencies/include/leptonica/*.h  (33个头文件)
dependencies/include/tesseract/*.h  (23个头文件)
dependencies/lib/liblept.a
dependencies/lib/libtesseract_all.a
dependencies/lib/libtesseract_api.a
dependencies/lib/libtesseract_ccstruct.a
dependencies/lib/libtesseract_ccutil.a
dependencies/lib/libtesseract_classify.a
dependencies/lib/libtesseract_cube.a
dependencies/lib/libtesseract_cutil.a
dependencies/lib/libtesseract_dict.a
dependencies/lib/libtesseract_main.a
dependencies/lib/libtesseract_neural.a
dependencies/lib/libtesseract_opencl.a
dependencies/lib/libtesseract_textord.a
dependencies/lib/libtesseract_viewer.a
dependencies/lib/libtesseract_wordrec.a
dependencies/lib/libtesseract.a

实际开发中只要将 include下的头文件,以及 [/lib/liblept.a],[libtesseract_all.a] 添加到工程中
就可以开发了。

编译过程到此结束, 如有问题可以留言。

除特别注明外,本站所有文章均为[果博]原创 » 转载请注明出处来自https://aiguor.com/notes/177.html

评论 抢沙发

表情 格式
  • 昵称 (必填)
  • 邮箱 (必填)

关注移动互联网,与科技共成长

联系我们