自然场景中的中文识别尝试
想做个考试作弊系统[捂脸]……
又想作弊了
最近想整个通过图像识别自然场景中的中文“试卷” -> 自然语言处理 -> 查找题库 -> 返回结果的小程序。目前考虑的是,图像通过树莓派的摄像头产生,将结果输出到柔性墨水屏上。
1 Connectionist Text Proposal Network
据说ctpn算法在长文本上也能够保持一个不错的效果,先试试吧
1.1 虚拟环境
一开始想用pipenv
,不过在安装Cython
的lock package
的时候就挂起不动了,搜了一下估计是跟跟网络和依赖有关系,因此就直接用Python自带的venv
做虚拟环境管理了。
虚拟环境主要需要安装tensorflow,所以新建一个tf
虚拟空间并激活:
1 | python3 -m venv tf |
包依赖有Cython
、numpy
、opencv
。安装numpy
之前记得安装sudo apt -y install libatlas-base-dev
,不然会报libf77blas.so.3
找不到的错误。
1 | pip install numpy |
测试import tensorflow
的时候会报一堆Future Warning
。
1.2 安装OpenCV
安装OpenCV很麻烦,单独拉出来写。
1.2.1 准备工作
- 打开摄像头:
sudo raspi-config
-> Enable camera。 - 扩展存储卡空间,以防不测:
sudo raspi-config
-> Advanced Options -> Expand filesystem。 - 重启:
sudo reboot -h now
,检查空间df -h
。 - 可选,清理不常用的程序:
1
2
3
4sudo apt-get purge wolfram-engine
sudo apt-get purge libreoffice*
sudo apt-get clean
sudo apt autoremove
1.2.2 安装OpenCV依赖
注意,我在使用lite系统的时候,会遇到关于NEON的cmake错误,在桌面版下一切正常。
更新系统:
1 | time sudo apt update && time sudo apt upgrade && time sudo apt dist-upgrade |
安装cmake
等开发工具:
1 | sudo apt install -y build-essential cmake unzip pkg-config |
安装图片和视频相关库:
1 | sudo apt install -y libjpeg-dev libpng-dev libtiff-dev |
可选,安装GUI库GTK以及能减少GTK警告的库[捂脸](名字中的*
号可以匹配到ARM版的库)
1 | sudo apt install -y libgtk-3-dev |
为OpenCV
安装数值优化库:
1 | sudo apt install -y libatlas-base-dev gfortran |
最后安装Python的头文件库:
1 | sudo apt-get install python3-dev |
1.2.3 下载OpenCV
下载opencv和附加的模块opencv_contrib,这些附加模块和函数可能会被经常用到:
1 | #proxychains4 wget -O opencv_4.1.1.zip https://github.com/opencv/opencv/archive/4.1.1.zip |
解压:
1 | unzip opencv_4.1.0.zip |
注意:我尝试编译4.1.1版,在编译到49%的时候总会出现:
1 | [ 49%] Linking CXX shared library ../../lib/libopencv_imgproc.so |
换4.1.0版就好了,耗时数小时。
1.2.4 CMake及编译
使用cmake
构建编译,再用make
进行编译,这一步非常耗时。先新建一个build
文件夹:
1 | cd opencv-4.1.0 |
运行cmake
,其中:
OPENCV_ENABLE_NONFREE=ON
标识可以让我们在OpenCV 4中使用SIFT/SURF等专利算法。OPENCV_GENERATE_PKGCONFIG=ON
生成opencv4.pc
用于后面darknet的编译。- 注意:保证
OPENCV_EXTRA_MODULES_PATH
的路径正确,不然会出现类似 sys/videoio.h: No such file or directory 的错误。1
2
3
4
5
6
7
8
9
10cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=~/ocr/opcv/opencv_contrib-4.1.0/modules \
-D ENABLE_NEON=ON \
-D ENABLE_VFPV3=ON \
-D BUILD_TESTS=OFF \
-D OPENCV_ENABLE_NONFREE=ON \
-D OPENCV_GENERATE_PKGCONFIG=ON \
-D INSTALL_PYTHON_EXAMPLES=OFF \
-D BUILD_EXAMPLES=OFF ..
接下来要为树莓派增加交换区空间,以便能够利用全部的四颗核心,否则可能会因为内存耗尽而挂起编译,打开/etc/dphys-swapfile
文件:
1 | sudo vim /etc/dphys-swapfile |
修改CONF_SWAPSIZE
标识,我们将交换区从100M增加到2048M:
1 | # set size to absolute value, leaving empty (default) then uses computed value |
重启交换服务:
1 | sudo /etc/init.d/dphys-swapfile stop |
注意:增加交换区空间有可能导致存储卡卡损坏,因为基于闪存的存储器的读写次数是有限的。我们这里仅在编译时增加交换区空间。
编译,用-j4
告诉make
使用四颗核心,这是最耗时的一步,大约用了4-5小时:
1 | make -j4 |
安装:
1 | sudo make install |
恢复交换区空间,打开/etc/dphys-swapfile
文件:
1 | sudo vim /etc/dphys-swapfile |
恢复CONF_SWAPSIZE=100
,并重启交换服务:
1 | sudo /etc/init.d/dphys-swapfile stop |
1.2.5 为Python虚拟环境建立OpenCV 4连接
在我们的tf
虚拟环境中建立OpenCV的软链接:
1 | ln -s /usr/local/lib/python3.7/site-packages/cv2/python-3.7/cv2.cpython-37m-arm-linux-gnueabihf.so /home/pi/cn_dect/tf/lib/python3.7/site-packages/cv2.so |
软链接的源和目的路径一定要写正确,其中源路径可以在安装时sudo make install
命令的输出中看到:
1 | -- Installing: /usr/local/lib/python3.7/site-packages/cv2/__init__.py |
1.2.6 测试OpenCV
测试虚拟环境中的OpenCV:
1 | Python 3.7.3 (default, Apr 3 2019, 05:39:12) |
成功。
1.3 测试text-detection-ctpn
无奈的是ctpn训练好的模型很大,一加载TensorFlow就报错,只好再把swap区改成2048[捂脸]。不知道这么玩下去存储卡能撑多久……
1 | python ./main/demo.py |
测试ctpn检测,还是比较慢的,第一张图在树莓派上就用了35秒。我准备再试试chineseocr这种端到端杂烩项目。
2 OCR
大概扫了一眼chineseocr这个项目,估计是用yolo3/darknet做的文本检测,再用基于pytorch的crnn做检测到的文本的ocr。
2.1 虚拟环境
还是用原来的虚拟环境
1 | cd ~/cn_dect/tf |
在虚拟环境中安装依赖(由于前面我们在本机上编译了OpenCV,所以不用再装opencv-contrib-python了):
1 | pip install scipy numpy easydict Cython h5py lmdb mahotas pandas requests bs4 matplotlib lxml pillow web.py keras |
2.2 编译 & 配置darknet
下载项目和darknet:
1 | proxychains4 git clone https://github.com/chineseocr/chineseocr.git |
修改darknet/Makefile
:
1 | GPU=0 |
直接make
时提示PKG_CONFIG_PAT
中找不到opencv.pc
,手动帮它找到:
1 | sudo cp /usr/local/lib/pkgconfig/opencv4.pc /usr/local/lib/pkgconfig/opencv.pc |
编译过程出现./src/image_opencv.cpp:12:1: error: ‘IplImage’ does not name a type
的错误,这是由于我们用的新版OpenCV导致的兼容性问题,此时需要pull
一个补丁:
1 | git fetch origin pull/1348/head:opencv4 |
把darknet/python/darknet.py
第48行改成刚编译好的libdarknet.so
的路径:
1 | lib = CDLL("/home/pi/cn_dect/chineseocr/darknet/libdarknet.so", RTLD_GLOBAL) |
2.3 下载OCR模型
因为是百度网盘上的东西,我用bnd2加了个速。
将下载的所有文件放在models
文件夹下。(如果是用python -m http.server 8000
做临时中转,wget -r http://192.168.1.100:8000
可以递归下载下所有目录和文件)
2.4 安装PyTorch
安装系统依赖:
1 | sudo apt install -y libopenblas-dev libblas-dev m4 cmake cython python3-dev python3-yaml python3-setuptools libatomic-ops-dev |
下载并安装:
1 | mkdir pytorch_install && cd pytorch_install |
貌似protobuf
这个库有个bug,会导致在编译近半时出现:
1 | [ 43%] Linking CXX executable ../../../bin/protoc |
需要更新一下protobuf
修复bug:
1 | proxychains4 git submodule update --remote third_party/protobuf |
因为我试了好几次了,因此用export BUILD_TEST=0
跳过测试以缩短编译时间,设置环境并编译:
1 | export NO_CUDA=1 |
接下来正式安装,安装前需要注意的是,一定要记得带着上面的export
的环境变量安装(因为编译时间太长,有时候编译完了重启就忘了设置环境变量):
1 | python3 setup.py install |
小注意一下:如果安装完成后不切换工作目录直接试就会出现No module named 'torch._C'
的异常,因为编译目录下就有一个torch
目录,切换工作目录再启动Python即可。
2.5 安装CTC模型
1 | pip install wget |
其中--recursive
指将引用的第三方git repo一并克隆。安装会持续个把小时,可以追几集番了。
2.6 下载语言模型
不到3个G,挂梯子下载了:
1 | cd chineseocr/models/ |
2.7 运行
按自己的情况修改config.py
文件,运行python app.py 8080
即可。在树莓派3B+上的结果是,内存耗尽[捂脸]总共不到1G的内存,连一个CTC模型都读不进去[捂脸]
更新到最新的app
分支
1 | git pull origin app |
这下炸出了一个貌似是bug的问题……这个分支(git版本daabebc93a8b4436a3653f83668429ab99eefaea
)跟以前最大的不同就是一开始就在用keras
和tensorflow
创建yolo3的darknet
,结果在text/keras_yolo3.py
的第285行boxes = concatenate(boxes, axis=0)
报错:
1 | 0) boxes = concatenate(boxes, axis= |
我目前的环境是:
1 | Python 3.7.3 (default, Apr 3 2019, 05:39:12) |
一步一步的在REPL中调试,只要一concatenate
,Placeholder_367
就报错,这个Placeholder就是text/keras_detect.py
中第23行就初始化了的那个input_shape
。不知道为什么,我在我自己的电脑上试了,同样的代码,完全没有问题,咱也不懂不知道,咱也懒得在github上问[捂脸]
其中,环境上的不同在于,电脑用的Python 3.6,TensorFlow 1.14.0,Keras 2.2.4。打算重新写张存储卡用Python 3.6的整套环境在树莓派上试一下,毕竟这张卡上还有波达方向定位的程序呢(用了Python 3.7的协程新特性)。之所以没有用chineseocr
项目要求的版本是因为树莓派上安装软件真的不容易[捂脸]
调试代码:
1 | import sys |
2.8 更换环境再试一遍
由于新的buster系统都是自带Python3.7,于是打算用pipenv
创建Python3.6版本的环境:
- 首先,pipenv在系统只有3.7版本的时候并不能直接创建3.6,所以我手动
sudo apt install python3.6
; - 结果发现并不是那么回事,这时候再次
pipenv --python 3.6
会报错,大概是说python3.6
的distutils
找不到模块; - 网上说可能是Linux自带的Python损坏,
sudo apt install python3-distutils
就好了,我试了一下,3.7确实是好了,3.6依然不行; - 我打算用系统级Python多版本切换: 重新设3.6为系统默认Python,再执行
1
2
3
4
5
6sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.7 2
配置版本
sudo update-alternatives --config python3
或切换设置
sudo update-alternatives --set python3 /usr/bin/python3.6apt
或者dpkg
安装说不定就安装到3.6下面去了,结果发现还是太天真了。
试完了想把系统Python切换到Python3.6上,再运行apt install python3-distutils
,结果并不可以。dist这个库安装完成后使用dpkg -L python3-distutils
查看发现它已经在/usr/lib/python3.7/distutils
文件夹下了,没法再装给Python3.6。被逼无奈只好强行把dpkg
列出来的文件拷过去了,反正都是纯Python代码且发布无所谓小版本:1
sudo cp -r /usr/lib/python3.7/distutils/* /usr/lib/python3.6/distutils/
- 这下终于好了,运行
pipenv --python 3.6
报环境变量的错,按提示重新配置即可:在运行1
2export LC_ALL=C.UTF-8
export LANG=C.UTF-8pipenv
终于成功安装了Python 3.6的环境。
装TensorFlow和Pytorch这两个大家伙,发现piwheel上没有现成的numpy[捂脸]
wget https://github.com/lhelontra/tensorflow-on-arm/releases/download/v1.14.0-buster/tensorflow-1.14.0-cp37-none-linux_armv7l.whl
2.9 在macOS上再试一遍
安装Xcode自不必说,然后同意许可,安装Apple Command Line Tools:
1 | sudo xcodebuild -license |
接下来我用macports安装系统依赖:
1 | sudo port install cmake pkgconfig |
下载OpenCV源码:
1 | proxychains4 wget -O opencv.zip https://github.com/opencv/opencv/archive/4.1.1.zip |
下面关于Python虚拟环境的路径,我都是用conda
做的管理,所以跟venv
、virtualenv
、pipenv
有所不同。准备执行cmake
:
1 | cd opencv |
编译并安装:
1 | make -j4 |
完成安装后注意看安装日志,我们需要的文件位于/usr/local/lib/python3.6/site-packages/cv2/python-3.6/cv2.cpython-36m-darwin.so
,为当前环境创造连接即可:
1 | ln -s /usr/local/lib/python3.6/site-packages/cv2/python-3.6/cv2.cpython-36m-darwin.so /Users/<user-name>/anaconda3/envs/py36/lib/python3.6/site-packages/cv2.so |