⚠⚠⚠警告
Tensorflow官方在2021年8月份废弃了通过Makefile构建tflite的方式。从Tensorflow 2.7.0开始,官方只提供使用CMake或者Bazel构建tflite的支持。
本教程正是基于Makefile对tflite进行交叉编译的,这意味着本教程仅支持2.6以及之前的版本。博主会找时间对博文进行更新。
1. 编译完成的效果
本文需要的交叉编译工具、tensorflow-lite依赖库、修改过的makefile文件以及编译好的文件都已上传至csdn:
树莓派zero交叉编译tensorflow-lite所需依赖,工具链及编译好的库文件_tensorflow交叉编译-机器学习文档类资源-CSDN下载
编译完成后,主要可以得到两个库和三个可执行文件:
如果你已经有了现成的tflite模型文件,但需要编写一个使用该模型的C++应用程序在树莓派zero上运行,博主已经打包好了开发环境,可以在树莓派上直接编译出可执行文件,也可交叉编译:
https://github.com/NewComer00/tflite4zero_envhttps://github.com/NewComer00/tflite4zero_env
也可以参考此项目:
GitHub - cloudwiser/ObjectDetectionRPiZero: TensorFlow Lite object detection example for Raspberry Pi Zerohttps://github.com/cloudwiser/ObjectDetectionRPiZero
2. 在github仓库下载tf最新版本
仓库地址:
GitHub - tensorflow/tensorflow: An Open Source Machine Learning Framework for Everyone
下载、解压源码,tensorflow源码组织如下:
打开目录后:
3. 下载arm的交叉编译工具链
tf官网为我们推荐了rpi zero(即树莓派zero)交叉编译用的g++工具链:
https://github.com/rvagg/rpi-newer-crosstools/archive/eb68350c5c8ec1663b7fe52c742ac4271e3217c5.tar.gz
我们把它下载下来,并改一个比较短的名字:
我们需要用到的是其中6.5.0版本的交叉编译工具:
观察6.5.0版本工具中gcc/g++/ar的地址:
/your/path/to/rpi-newer-crosstools/x64-gcc-6.5.0/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-gcc
/your/path/to/rpi-newer-crosstools/x64-gcc-6.5.0/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-g++
/your/path/to/rpi-newer-crosstools/x64-gcc-6.5.0/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-ar
我们把上述地址中的公共部分(也就是所谓的“编译器前缀”)临时赋值给环境变量CC_PREFIX,之后直接引用变量值即可:
export CC_PREFIX=/your/path/to/rpi-newer-crosstools/x64-gcc-6.5.0/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-
4. 下载编译需要的依赖库
https://www.tensorflow.org/lite/guide/build_rpi
根据官方教程的"构建"一步,我们需要执行下载脚本,来下载编译需要的依赖库:
/your/path/to/tensorflow-2.4.1/tensorflow/lite/tools/make/download_dependencies.sh
但直接下载速度太慢,有好心人为我们提供了下载好的依赖包(需要消耗CSDN点数。如果点数不够,可以直接下载“1. 编译完成的效果”中的文件,里面有我调教好的依赖包):
tensorflow-lite依赖包_tflite依赖-深度学习文档类资源-CSDN下载
下载好依赖包后,将其中的downloads文件夹放在如下路径:
/your/path/to/tensorflow-2.4.1/tensorflow/lite/tools/make/
对于tf2.4来说,downloads文件夹中的ruy版本太低,需要从官方仓库下载新版的ruy替换.
通过查询download_dependencies.sh可以知道下载地址:
https://github.com/google/ruy/archive/54774a7a2cf85963777289193629d4bd42de4a59.zip
5. 修改Makefile文件
依赖准备好后,我们就要准备编译tflite了.由于rpi zero的硬件架构为armv6,tensorflow官方并没有专门对其进行适配,因此我们需要对Makefile文件进行修改.参考此链接的描述:
Can't cross-compile TFLite "Minimal" for Raspberry Pi Zero (armv6 target) · Issue #30181 · tensorflow/tensorflow · GitHub
首先在下面的目录中找到Makefile文件,对其进行一个备份(如复制一份文件,将其重命名为Makefile.origin),然后修改原文件.
/your/path/to/tensorflow-2.4.1/tensorflow/lite/tools/make/
我们找到负责跨平台的代码部分,在其中插入一段代码,负责处理armv6平台的编译配置:
# for rpi zero
ifeq ($(TARGET_ARCH), armv6)
CXXFLAGS += \
-march=armv6 \
-mfpu=vfp \
-funsafe-math-optimizations \
-ftree-vectorize \
-fPIC \
-marm
CFLAGS += \
-march=armv6 \
-mfpu=vfp \
-funsafe-math-optimizations \
-ftree-vectorize \
-fPIC \
-marm
LDFLAGS := \
-Wl,--no-export-dynamic \
-Wl,--exclude-libs,ALL \
-Wl,--gc-sections \
-Wl,--as-needed \
-latomic
endif
插入位置如下图所示:
6. 开始编译
编译前的准备都已经做好,现在我们可以着手编译tflite库了.
首先将当前目录切换到项目的最外层文件夹:
cd /your/path/to/tensorflow-2.4.1
接下来输入以下命令,开始编译:
make -j 4 -f tensorflow/lite/tools/make/Makefile TARGET=rpi TARGET_ARCH=armv6 CC=${CC_PREFIX}gcc CXX=${CC_PREFIX}g++ AR=${CC_PREFIX}ar
其中,-j 后的数字代表多线程编译的线程数量;
-f 后为指定的Makefile文件;
TARGET为平台名称;
TARGET_ARCH为平台架构;
CC后接指定的gcc编译器;
CXX后接指定的g++编译器;
AR后接指定的gnu-ar归档工具.
编译完毕后,会在your/path/to/tensorflow-2.4.1/tensorflow/lite/tools/make/目录下生成一个gen文件夹,里面存放有编译好的文件.
7. 运行测试
将gen/rpi_armv6/bin目录下生成的minimal可执行文件拷贝到rpi zero机器上去.
不带参数直接执行,以及带参数(指定一个tflite模型)执行的输出如下:
8. 其它
-
官网还给出了一个使用cmake(版本至少为3.16,要求比较高)编译tflite的教程,我这里实验失败了,cmake会卡在检查编译器一步,不知道什么问题: https://www.tensorflow.org/lite/guide/build_cmake_arm#build_for_raspberry_pi_zero_armv6
-
如果最后在rpi zero上执行时出现了illegal instruction错误,请检查你的交叉编译工具.建议使用文章中提供的6.5.0版本的工具,如果用的是最新的arm-linux-gnueabihf工具,可能会报错.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)