Tensorflow lite 编译Android JNI C++ 动态链接库(步骤详细生动,还怕搞不定吗)

目录

      • 1. 准备食材(荤菜)
      • 2. 准备食材(素菜)
      • 3. 磨刀(tensorflow编译依赖)
      • 4. 切菜
      • 5 热油(设置输出的内容)
      • 6. 炒菜了(编译)
      • 7 浇汤头,也叫勾芡(整理头文件)
      • 8. 上菜啦(整理进CMakeLists.txt中)
      • 9. 吃完了,别走,付钱呀

如果你想在Android上用JNI跑TensorFlow神经网络,就需要把TensorFlow Lite编译成C++的动态链接库。由于烹饪技法奇特,凡人非三五天难以编译出来。

本大厨历经艰辛,达到彼岸。今天把烹饪过程详述于此,以示后来者。(有问题留言共同讨论)

1. 准备食材(荤菜)

  • 准备一个ubuntu 16系统
  • 下载tensorflow源代码:https://github.com/tensorflow 解压
  • 安装bazel
sudo apt install curl gnupg

curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list

sudo apt update

sudo apt install bazel

  • 安装工具链
sudo apt-get update
sudo apt-get install crossbuild-essential-arm64
  • 还要安装 python(3以上版本)

2. 准备食材(素菜)

  • 下载Android NDK

https://developer.android.google.cn/ndk/downloads?hl=zh-cn

解压出来放在一个妥当的位置(路径不要有中文)。记下路径。

  • 下载Android SDK

https://developer.android.com/studio/

(想办法也要下载正版的哟)同样,解压出来放在一个妥当的位置(路径不要有中文)。记下路径。

3. 磨刀(tensorflow编译依赖)

进入到tensorflow解压出来的目录下,运行下载依赖的脚本

./tensorflow/lite/tools/make/download_dependencies.sh

4. 切菜

还是在tensorflow的根目录里面,运行配置文件

./configure

这是会让你配置很多东西,前两个是python的路径,他们给的一般是正确的,直接回车。

中间会让你配置很多杂七杂八的,咱们不需要,直接输入No:N

最重要的一步,就是当出现配置Android时,要输入yes:y

然后会让你配置Android NDK的路径,把你开始解压出来的路径复制进去。回车。然后他会识别到版本,让你确认。回车就行。

然后会让你配置Android SDK的路径,和上一步一样,把解压路径复制进去。

5 热油(设置输出的内容)

我们希望输出的是一个动态链接库,即.so文件,所以,要配置

打开tensorflow/lite/BUILD文件配置输出的选项,在末尾添加如下内容:

cc_binary(
    name = "libtensorflowLite.so",
    linkopts = ["-shared", "-Wl,-soname=libtensorflowLite.so"],
    visibility = ["//visibility:public"],
    linkshared = 1,
    copts = tflite_copts(),
    deps = [
        ":framework",
        "//tensorflow/lite/kernels:builtin_ops",
    ],
)

6. 炒菜了(编译)

目前Android的主流架构是armeabi-v7aarm64-v8a,所以只要交叉编译这两个就行了,过程也很简单,

先炒第一盘菜,在tensorflow根目录运行:

#  "armeabi-v7a"
bazel build -c opt //tensorflow/lite:libtensorflowLite.so  --config=android_arm --cxxopt="-std=c++11" 

会在tensorflow/bazel-bin/tensorflow/lite/目录下生成一个libtensorflowLite.so文件。

在桌面上新建一个文件夹 叫armeabi-v7a,把编译生成的libtensorflowLite.so文件拷贝进去。因为原来的位置马上就要删了。

洗锅(清理环境),准备炒下一盆菜

# 洗锅
bazel clean

再编译arm64-v8a的动态库

# arm64-v8a
bazel build -c opt //tensorflow/lite:libtensorflowLite.so  --config=android_arm64 --cxxopt="-std=c++11"

同样在桌面上新建一个文件夹,叫arm64-v8a,把新输出的在tensorflow/bazel-bin/tensorflow/lite/目录下的libtensorflowLite.so文件拷贝进去。

最后把文件夹整理成这样:

在这里插入图片描述

7 浇汤头,也叫勾芡(整理头文件)

只有一个动态链接库也是没法用的,我们还需要有头文件,只有靠头文件才能找到对应的库。

头文件从哪里来呢,很简单,把tensorflow/lite中所有的.h文件和他们的层级目录全部整理出来。

也有个简单的方法,用shell脚本,进入到tensorflow中,运行

# 找到所有的 .h文件,全压缩到一个headers.tar中
find ./lite -name "*.h" | tar -cf headers.tar -T -

还有一个重要的头文件faltbuffer,它是tf lite的一个依赖库,也需要整理头文件出来。这个库位于tensorflow/lite/tools/make/downloads/flatbuffers,把里面的include文件夹全部拷贝出来,放在一个flatbuffers文件夹里面。

include/flatbuffers/

最后整理成的文件目录如下
Tensorflow lite 编译Android JNI C++ 动态链接库(步骤详细生动,还怕搞不定吗)_第1张图片

8. 上菜啦(整理进CMakeLists.txt中)

最后把我们的库整理进去

# tf lite 的库名字
add_library(tflite
        STATIC
        IMPORTED
        )
# # tf lite库的位置
set_target_properties(tflite
        PROPERTIES
        IMPORTED_LOCATION
     ${CMAKE_SOURCE_DIR}/../nativeLibs/${CMAKE_ANDROID_ARCH_ABI}/libtensorflowLite.so
        )
# 头文件位置也要找到
include_directories(${CMAKE_SOURCE_DIR}/../include)
# 绑定到我们的主库上
target_link_libraries( 
                       native-lib # 这个是你自己的库名字
                        tflite )

9. 吃完了,别走,付钱呀

点赞免单,哈哈哈

明天继续炒怎么在android中用这个库。

你可能感兴趣的:(android,晋级之路)