个人需求
SpaceX在发射猎鹰9号的时候,在画面左下角及右下角均会出现一二级火箭的实时速度与高度信息,同时画面中间底部还是时间:

前几天我发了一篇文章,讲的是猎鹰9号那超神的40秒,其中就大量引用了Transport-3任务中猎鹰9号一级火箭从点火到落地的实时速度与高度,美中不足的是,速度与高度的数据,我是看着视频每隔10秒,手工录入到Excel中的,这种事情做一次还可以,但要做第二次,简直受不了!而且!如果我想压缩一下时间间隔,那录入量将会成倍地增加,这种事情对一个程序员来讲是不可以接受了!

于是我就想玩点高端的,为什么不自动从视频中通过图片文字识别的方式来获取这些数据的?我的构想很简单,三步走:
其一、将视频按每秒切割成图片,对整体图片进行降噪处理,然后只聚焦有数字的图片区域,也就是对已降噪的图片的进行三次裁剪,生成三张关联的小图片。
其二、对生成的图片进行字符识别,由训练好的第三方模型库生成文本字符。
其三、将自动提取的数据写入数据库,然后搞个简单的可视化Web页面。
如此一来,每次SpaceX发射猎鹰9号,把视频下载下来之后,就可以自动获取此次任务中一级火箭与二级火箭的实时速度与高度数据了,这对进一步加深对猎鹰9号的了解绝对是有很大帮助的!
技术选型
本人Java系程序员,以快速实现个人需求,搜寻支持Java的开源库,开源库要实现两个功能,其一是能够对视频进行单帧画面捕获与裁剪,其二是能够识别图片上的文字,还好这两个需求已经是历史悠久了,视频帧画面捕获与裁剪选定使用开源的OpenCV,图片文字识别选定使用开源的Tesseract。

由于苹果M1系列芯片刚发布没两年,很多开源的功能库虽然支持通过JNA包装让Java来调用,但绝大多数都是X86平台的,所以如果基于Arm架构的M1系列芯片要使用,最好还是通过源码专门以Arm指令再编译一次,正好也可趁此机会了解一下高深莫测的C系编译与打包。
这里得稍微吐槽一下,像这种多数是由C或C++编写的图像类别类的开源基础库,在网络上找来找去,也只能用国外的了。
Tesseract简介
Tesseract是一款开源的光学字符识别(OCR)引擎,据说识别准确率位居前三,光学字符识别,简单来说就是从数字图片中基于训练的模型识别出各个语系的字符,支持世界主流语言。

据悉,Tesseract在Windows系统以及Ubuntu系统会经过了严格的测试,综合表现良好,不知在MacOS下会有怎样的识别表现,正好本期内容就可以专门试验一下。
OpenCV简介
情绪估计、面部识别、手势识别、人机交互、运动追踪、对象检测、立体视觉、增强现实等,当然就我个人而言,我可能只会用到它提供的二维或三维基础视觉工具包。

另外,OpenCV的合作伙伴阵容强大,Intel、微软、华为等科技巨头均在其列:

在商用方面,OpenCV给各位开发者吃了一个定心丸儿--免费:

安装前置:HomeBrew
具体HomeBrew是做什么的,不妨看一张官方图片:

如红色框框所示,HomeBrew是macOS或Linux系统中软件包的管理器,安装起来十分简单,官方也给出了兼下载跟运行于一体的命令:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
备注:如果在下载时出现了443端口拒绝连接的情况,网上有两种解决方式,其一是查找到该域名对应的IP地址,通过向hosts中添加映射解决,其二是让终端使用http代理。
安装成功之后,在终端输入brew能正确给出如下信息便算是安装成功:

安装HomeBrew是为了通过它来安装OpenCV以及Tesseract的各种依赖软件包。
编译安装Tesseract
Tesseract虽然在Maven仓库中有Java的JNA包装Tess4J,但是通过在Pom文件中直接引用这个Jar包是无法正常使用的:

究其原因,目前我个人的理解是,Tess4J只是一个JNA包装,也就是它只是相当于Java中的一个接口,而其定义方法的具体实现,则是依赖于适配于运行平台的本地运行库,在Windows平台中,多数以.dll的方式存在,在MacOS中,则是.dylib的后缀,大家不妨看看我在本地编译安装Tesseract之前的运行报错信息:

未找到/usr/lib/liblept.5.dylib。
首先从GitHub上下载Tesseract的最新源代码,很小的一个压缩包:

然后通过HomeBrew安装Tesseract的依赖包,依赖列表如下:
# 必备依赖brew install automake autoconf libtoolbrew install pkgconfigbrew install icu4cbrew install leptonica# 训练工具brew install pango# 扩展特性brew install libarchive# g++编译依赖brew install gcc
在安装的时候,建议先开个代理并给终端设置一下使用代理,比如我的配置下会在终端上输入,如此一来在下载速度上会有很大的效果,最重要的是如果遇到被污染的域名,代理可以正确避开它:
export https_proxy=http://127.0.0.1:7890 http_proxy=http://127.0.0.1:7890 all_proxy=socks5://127.0.0.1:7890
另外,在使用brew安装软件包的时候,最好也是每个软件包单独安装,就是采用
brew install xxx
而不是采用
brew install xxx yyy zzz
的方式,这样至少哪个安装成功了,哪个安装失败了,心里会有个数,另外,软件包安装失败,绝大多数情况下都是由网络原因引起了,问题不大,多尝试几次总会可以的,就上面的那9个依赖包,我实装大约用时一小时,依赖包成功安装之后,接下来就要进入编译环节了。
具体怎么编译,先后执行哪些命令,Tesseract官方网站给出了具体的说明,在macOS下基于HomeBrew的编译命令,官方的指导为:
cd tesseract./autogen.shmkdir build && cd build../configure PKG_CONFIG_PATH=/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libarchive/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfigmake -jsudo make installmake trainingsudo make training-install
第一行进入刚才下载的Tesseract的源码文件夹,第二行则是先执行一个脚本,具体做什么没有细看,第三行和第四行是在源码文件夹中创建一个build文件夹用于编译工作,然后在build文件夹里执行后续的命令。
第六行,这里要调整一下,要将以下三个依赖包的路径调整为通过HomeBrew安装的路径,
icu4c,libarchive,libffi
那具体这三个包被HomeBrew安装到哪里了呢?一般情况下都是在HomeBrew文件夹里,所以第六行命令调整完之后应该是:
PKG_CONFIG_PATH=/opt/homebrew/opt/icu4c/lib/pkgconfig:/opt/homebrew/opt/libarchive/lib/pkgconfig:/opt/homebrew/opt/libffi/lib/pkgconfig
这里有一点需要注意,官方的编译文档中还有一句话,说是在M1芯片系列下,可能需要再指定一个配置项:
../configure CXX="g++ --target=arm-apple-darwin64"
很明显,这个配置项的意思是专门为MacOS的Arm平台进行编译,但我在实际执行时,这个命令是无法执行成功的,我选择暂时跳过继续执行后面的命令,经实际验证,在macOS 12.1下,Tesseract的源码版本为5.01的情况下,即使这个命令执行不成功,也没有影响到后续的编译安装与调用。
剩余的四条命令就是编译并安装Tesseract以及训练的模型数据,整体而言,Tesseract 5.01在M1 Pro下执行上面的几条编译安装命令,用时在10分钟左右,执行完之后,就需要去看一下Tesseract的基础库有没有正确生成,前文提到了在编译安装前Intelli IDEA中报的一个错误:

提示
liblept.5.dylib
找不到,编译安装之后经实际验证,目录
/opt/homebrew/opt/leptonica/lib/
下存在目标文件,而目录
/usr/lib/
下没有该文件,但再次通过IDEA运行测试程序,无报错,能正常识别测试图片中的字符:

测试图片

识别结果
测试图片中,较大的字符串分别是猎鹰9号一级火箭的速度3203以及高度26.1,时间为00:01:45,识别结果图片中,出现了3203 26.1 400:01:45,由此可见,速度正确识别出来,高度也正常识别了出来,只是时间这块,将T+识别成了数字4,这是因为我对Tesseract指定了字符白名单,只让其在0123456789.:这12个字符中猜测结果。

到此为止,Tesseract算是正常跟Java集成在一起了,总结一下就是,先在Maven工程配置文件中引入Tess4J这个JNA包装,然后通过编译源码的方式安装部署Tesseract的实际本地实现,至于识别精度,那只能在后期慢慢去优化配置或者图片质量了。
编译安装OpenCV
为什么要编译呢?虽然OpenCV在Maven仓库中有由OpenPNP编译打包的可依赖功能包,但其没有添加对Arm64架构的MacOS的支持,故只能由代码进行编译。
OpenCV源代码的最新版本是4.5.5,经实测4.5.5版本在M1系列芯片进行进行编译不通过,个人选择4.5.4版本进行编译安装。
从GitHub上下载4.5.4版本的OpenCV源代码:

OpenCV的编译依赖两个构建工具,分别是cmake和ant,二者可以通过HomeBrew安装:
brew install cmakebrew install ant
如果网络正常,上面两条命令大概10分钟就可以完成,对了,此时如果想看一下通过HomeBrew已安装了哪些软件包,可以使用命令:
brew list
大家可以看一下我当前通过HomeBrew安装的软件包截图:

接下来,进入OpenCV 4.5.4的源码文件夹,创建并进入build子文件夹:
mkdir build && cd build

重头戏来了,编译配置命令如下所示:
cmake -DCMAKE_SYSTEM_PROCESSOR=arm64 \-DCMAKE_OSX_ARCHITECTURES=arm64 \-DWITH_OPENJPEG=OFF \-DWITH_IPP=OFF \-D CMAKE_BUILD_TYPE=RELEASE \-D CMAKE_INSTALL_PREFIX=/usr/local/opencv \-D JAVA_INCLUDE_PATH=$JAVA_HOME/include \-D JAVA_AWT_LIBRARY=$JAVA_HOME/jre/lib/amd64/libawt.so \-D JAVA_JVM_LIBRARY=$JAVA_HOME/jre/lib/arm/server/libjvm.so \-D BUILD_opencv_python2=OFF \-D BUILD_opencv_java=ON \-D INSTALL_PYTHON_EXAMPLES=OFF \-D INSTALL_C_EXAMPLES=OFF \-D OPENCV_ENABLE_NONFREE=OFF \-D BUILD_EXAMPLES=ON ..
上面的命令有几个注意事项:
第一行,处理器类型设置为arm64
第二行,平台架构类型设置为arm64
第七八九行,提供设置好JAVA_HOME环境变量
第二一行,为Java编译opencv设置为开启,也就是ON
这条命令执行起来还是很快的,大约两分钟就能完事儿:

然后使用make命令进行编译:
make -j8
其中-j后面的8表示使用8个CPU核心进行编译,整体速度还可以,大约用时三分钟左右:

最后进行编译后文件在本地的安装:
sudo make install
整体很快速,半分钟左右:
...-- Installing: /usr/local/opencv/share/opencv4/lbpcascades/lbpcascade_frontalface_improved.xml-- Installing: /usr/local/opencv/share/opencv4/lbpcascades/lbpcascade_profileface.xml-- Installing: /usr/local/opencv/share/opencv4/lbpcascades/lbpcascade_silverware.xml-- Installing: /usr/local/opencv/bin/opencv_annotation-- Installing: /usr/local/opencv/bin/opencv_visualisation-- Installing: /usr/local/opencv/bin/opencv_interactive-calibration-- Installing: /usr/local/opencv/bin/opencv_version-- Installing: /usr/local/opencv/bin/opencv_model_diagnostics
至此,OpenCV的编译与安装成功结果,可以去目录
/usr/local/opencv/share/java/opencv4
看一下生成的库文件,库文件有两个:
libopencv_java454.dylibopencv-454.jar

此时按理说OpenCV已经成功安装到本地了,去Intellij IDEA里配置一下对刚生成的本地jar文件的依赖,然后写个测试程序,看能不能提取视频里的图片:

很不幸,编译链接失败,提示找不到opencv的本地运行库:

此时,只需要在IDEA里为opencv-454这个本地jar包指定一下本地运行库的位置就可以了:

在重新运行一次,我本地找了一个约2.4G的SpaceX猎鹰9号的发射视频,时长大约25分钟,我让程序每隔1秒提取一张图片,看看性能如何:

到这里为止,OpenCV也算是正式开始服役了。
剪裁与识别
最后一步,让Tesseract与OpenCV协同工作,一个负责抽取与剪裁图片,一个负责文字识别,其中我对视频又进行了剪裁,只提取猎鹰9号一级火箭有实时高度与速度的那段时间,时长不到10分钟,另外,还需要使用图片编辑软件定位要剪裁了高度、速度与时间的点坐标与长宽,开始行动!

话不多说,直接运行看结果:

经实际测试,识别成功率还是蛮高的,速度这块极少数情况会识别不出来。
结束语
总体而言,这个方案是可行的,后续还有三件事要做:
尝试使用OpenCV在生成图片的同时进行降噪处理,以提高后期图片识别的准确率。
尝试给Tesseract配置字体、调整色差等优化性操作,提高识别成功率。
也是本期内容的核心目标,将猎鹰9号的实时数据写入数据库,以便进行统计与分析!

另外,这篇文章是边实践边写的,可能有点太长了,其中肯定也有一些理解错误或非最优配置方式,如果读者你是一位编程大神,还请不吝赐教!隽月照星辰期待您的关注!