1、前言
最近项目需要使用到手机本地OCR识别,找了一圈,最后测试下来还是PaddleOCR最稳定,因为官方PaddleOCR Android版本的Demo集成的是V1.0版本的模型比较老,英语分词也不是很准确,识别率也不如V1.1版本,所以就计划升级到V1.1,但是升级到V1.1不是简单的替换模型,所以记录一下过程,希望帮到有同样需要的朋友。同时我也将我自己已经升级到V1.1版本的Android Demo上传至Github,需要直接使用的朋友,点这个:Android PaddleOCR V1.1。如果你需要了解一下过程,请往下看。
2、准备工作
2.1 Linux/Mac一台
因为直接替换模型运行后会报错,我们需要使用百度开源的PaddleOCR的toots工具进行一次模型转换,所以需要Linux/unix环境下进行编译,没有mac的同学建议安装虚拟机跑,有mac的我也建议虚拟机(Windows PC CPU还行的话),因为我在自己的MacBook Pro上面跑特别特别慢,mac风扇原地起飞,可能因为我的mac是19款,用虚拟机的话,速度就比较能接受了(我的CPU 3900X 虚拟机分配了12个CPU)。Ubuntu版本建议16.04(官方建议),下载地址:Ubuntu16.04.7 根据自己的CPU架构选择对应的版本即可。
2.2 Android Studio、NDK
我自己使用的Android Studio是4.1.1版本的。下载地址:Android Studio
需要安装20b版本及以上的DNK,自己测试22版本的编译时会出一下问题,建议下载20b版本的。下载地址:NDK,NDK需要配置环境变量,请自行百度。
2.3 模型文件
开源V1.1模型文件下载地址:V1.1
2.4 下载官方开源的V1.0版本Demo。
下载地址:V1.0版本Demo,需要注意的是,develop分支才会有demo,release分支是没有Demo的。
3、编译集成
注意:首先先确保你在2.4下载的V1.0版本的Demo能在本地编译运行,只要保证Android studio版本和NDK版本,应该是不会有什么问题的。
3.1 准备Android交叉编译环境
在虚拟机中安装上面下载的Ubuntu16.04,如没有特殊说明,以下所有操作均在Ubuntu16.04环境下进行,虚拟机的安装请自行百度,推荐VirtualBox,开源免费。
环境要求:
- gcc、g++、git、make、wget、python、adb
- Java environment
- cmake(建议使用3.10或以上版本)
- Android NDK (支持ndk-r17c及之后的所有ndk版本, 注意从ndk-r18开始,ndk交叉编译工具只支持clang, 不支持gcc)
# 1. Install basic software
apt update
apt-get install -y --no-install-recommends \
gcc g++ git make wget python unzip adb curl
# 2. Prepare Java env.
apt-get install -y default-jdk
# 3. Install cmake 3.10 or above
wget -c https://mms-res.cdn.bcebos.com/cmake-3.10.3-Linux-x86_64.tar.gz && \
tar xzf cmake-3.10.3-Linux-x86_64.tar.gz && \
mv cmake-3.10.3-Linux-x86_64 /opt/cmake-3.10 && \
ln -s /opt/cmake-3.10/bin/cmake /usr/bin/cmake && \
ln -s /opt/cmake-3.10/bin/ccmake /usr/bin/ccmake
# 4. Download Android NDK for linux-x86_64
# Note: Skip this step if NDK installed
# support android-ndk-r17c-linux-x86_64 and other later version such as ndk-r18b or ndk-r20b
# ref: https://developer.android.com/ndk/downloads
cd /tmp && curl -O https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip
cd /opt && unzip /tmp/android-ndk-r17c-linux-x86_64.zip
# 5. Add environment ${NDK_ROOT} to `~/.bashrc`
echo "export NDK_ROOT=/opt/android-ndk-r17c" >> ~/.bashrc
source ~/.bashrc
# Note: To other ndk version, the step is similar to the above.
# Take android-ndk-r20b-linux-x86_64 as example:
cd /tmp && curl -O https://dl.google.com/android/repository/android-ndk-r20b-linux-x86_64.zip
cd /opt && unzip /tmp/android-ndk-r20b-linux-x86_64.zip
echo "export NDK_ROOT=/opt/android-ndk-r20b" >> ~/.bashrc
source ~/.bashrc
3.2 下载PaddleLite源码
# 1. 下载Paddle-Lite源码 并切换到release分支
git clone https://github.com/PaddlePaddle/Paddle-Lite.git
cd Paddle-Lite && git checkout 2.7
# (可选) 删除此目录,编译脚本会自动从国内CDN下载第三方库文件
# rm -rf third-party
注意: 编译过程中,如出现源码编译耗时过长,通常是第三方库下载过慢或失败导致。请在git clone完Paddle-Lite仓库代码后,手动删除本地仓库根目录下的third-party目录。编译脚本会自动下载存储于国内 CDN 的第三方依赖的压缩包,节省从git repo同步第三方库代码的时间。官方完整文档:点我
确保处于V2.7分支
3.3 编译预测库
接下来就可以编译推测库了,命令如下:
./lite/tools/build_android.sh --arch=armv8 --with_cv=ON --with_extra=ON --toolchain=gcc --android_stl=c++_shared
因为我的项目需要的是arm64的库,所以编译命令如上,具体的编译参数解释如下(也可以使用 ./lite/tools/build_android.sh help 查看):
--arch: (armv8|armv7) arm版本,默认为armv8
--toolchain: (gcc|clang) 编译器类型,默认为gcc
--android_stl: (c++_static|c++_shared) NDK stl库链接方法,默认为静态链接c++_static
--with_java: (OFF|ON) 是否编译Java预测库, 默认为 ON
--with_cv: (OFF|ON) 是否编译CV相关预处理库, 默认为 OFF
--with_log: (OFF|ON) 是否输出日志信息, 默认为 ON
--with_exception: (OFF|ON) 是否在错误发生时抛出异常,默认为 OFF
--with_extra: (OFF|ON) 是否编译OCR/NLP模型相关kernel&OP,默认为OFF,只编译CV模型相关kernel&OP
--android_api_level: (num) 指定编译时支持的最低Android API Level,默认为Default
编译成功后如下(我的虚拟机环境大概需要10分钟):
编译完成后,会在此目录(PaddleLite/build.lite.android.armv8.gcc/inference_lite_lib.android.armv8)生成相应版本的预测库文件 ,文件目录结构如下:
红框框选的部分需要我们复制到Android Studio替换掉之前的预测库文件,需要注意arm架构版本,因为我只需要armv8的库,所以编译的是armv8的版本,所以这里只需要替换arm64-v8a的库即可,需要其他版本的库只需要修改上面的脚本来编译生成新的库文件即可。
3.4 模型优化与转换
上面已经准备好了Android端的预测库文件,现在我们只需要对模型进行优化和处理后,再导入Android Studio即可。
3.4.1 首先需要准备模型文件
下载2.3 (V1.1) 的原始模型文件,一共需要下载三个模型 1、文本检测模型 2、文本识别模型 3、文本方向分类模型
这里以文本检测模型为例,因为超轻的slim识别效果略微逊色,所以我选择的是2.6MB的版本,下载推理模型文件。
解压后目录结构如下:
上面的文件就是我们需要的原始未转换之前的模型文件,按照同样的方法下载识别模型和分类模型,并将这三个压缩包拷贝到虚拟机,(或者直接在虚拟机下载)并将他们分别解压到对应的文件夹,我的建议是创建一个新的文件夹来保存原始的模型文件,下面是我的目录结构。
3.4.2 接下来就是模型优化与转换
在Ubuntu上进入我们在3.2下载的PaddleLite项目的根目录下,执行以下命名生成opt工具
./lite/tools/build.sh build_optimize_tool
编译过程大概需要5分钟,编译成功后如下所示:
编译完成后,opt文件位于 build.opt/lite/api/
下,可通过如下方式查看opt的运行选项和使用方式;
cd build.opt/lite/api/
./opt
opt工具参数说明:
接下来,我们使用上面编译生成的opt工具对我们在3.4.1下载的模型进行转换和优化
./build.opt/lite/api/opt --model_file=../origin-model/v1.1/det/model --param_file=../origin-model/v1.1/det/params --optimize_out=model/det --valid_targets=arm --optimize_out_type=naive_buffer
./build.opt/lite/api/opt --model_file=../origin-model/v1.1/rec/model --param_file=../origin-model/v1.1/rec/params --optimize_out=model/rec --valid_targets=arm --optimize_out_type=naive_buffer
./build.opt/lite/api/opt --model_file=../origin-model/v1.1/cls/model --param_file=../origin-model/v1.1/cls/params --optimize_out=model/cls --valid_targets=arm --optimize_out_type=naive_buffer
注意:我的脚本执行路径是项目的根目录,模型文件存放路径为PaddleLite的同级目录下的 origin-model/v1.1/det/model 目录,大家在转化时请注意修改模型的路径;
下面是我的PaddleLite文件夹与origin-model的目录结构
上面的脚本执行完后,会在PaddleLite/model/文件夹下面生成对应的.nb后缀的优化后的模型文件
如果碰到如下错误:
请检查存放输出模型的文件夹是否已经创建,创建文件夹即可。
模型转换成功后,会在我们指定的输出路径生成下面的文件:
3.4.3 替换项目中的模型文件
将生成的模型文件,拷贝到V1.0的官方Demo中,文件位置如下:
修改代码中模型引用的位置:
路径:src\main\java\com\baidu\paddle\lite\demo\ocr\Predictor.java
// config.detModelFilename = realPath + File.separator + "ch_det_mv3_db_opt.nb";
// config.recModelFilename = realPath + File.separator + "ch_rec_mv3_crnn_opt.nb";
// config.clsModelFilename = realPath + File.separator + "cls_opt_arm.nb";
config.detModelFilename = realPath + File.separator + "det.nb";
config.recModelFilename = realPath + File.separator + "rec.nb";
config.clsModelFilename = realPath + File.separator + "cls.nb";
最后一步,更新字典库文件 点我下载
将下载的字典库文件替换Demo中的字典库文件即可。
注意:最好将官方1.0版本的Demo中build.gradle中配置的自动下载在第一次下载后注释掉,以免覆盖我们的文件
4、总结
以上就是升级V1.1模型的全部过程,如果在集成过程中遇到问题,可以给我留言,也可以直接Clone我升级后的Demo Android PaddleOCR V1.1。