我正在尝试找出在Android上培训和部署Tensorflow模型的工作流程。我知道在StackOverflow上有类似于这个的其他问题,但它们似乎都没有解决我遇到的问题。
在研究了Tensorflow存储库中的Android示例之后,我认为这应该是工作流程:
使用adb部署APK。
第6步是问题所在。 Bazel很乐意编译一个本机(到OSX).dylib,我可以通过JNI从Java调用它。同样,Android Studio将生成一大堆XML代码,这些代码构成了我想要的GUI。但是,Bazel希望所有java应用程序代码都在'WORKSPACE'顶级目录(在Tensorflow repo中)中,并且Android Studio会立即链接到SDK中的各种外部库以生成GUI(我知道因为我的Bazel编译运行失败,因为它找不到这些资源)。我可以找到迫使Bazel交叉编译.so文件的唯一方法是使其成为Android规则的依赖规则。直接交叉编译本机库是我更喜欢移植我的A.S.代码到Bazel项目。
我该怎样对待这个?据说Bazel会编译Android代码,但Android Studio会生成Bazel无法编译的代码。来自Google的所有示例都只是从回购中提供代码,而不知道它是如何生成的。据我所知,属于Android Studio应用程序的XML应该是生成的,而不是手工制作的。如果可以手工制作,我如何避免需要所有这些外部库?
也许我的工作流程出错了,或者Bazel / Android Studio的某些方面我不理解。任何帮助赞赏。
谢谢!
修改
我最终做了几件事可能有助于图书馆建设成功:
我在下面实现了推荐的Bazel BUILD文件,添加了一些内容(取自Android示例):
cc_binary(
name = "libName.so",
srcs = ["org_tensorflowtest_MyActivity.cc",
"org_tensorflowtest_MyActivity.h",
"jni.h",
"jni_md.h",
":libpthread.so"],
deps = ["//tensorflow/core:android_tensorflow_lib",
],
copts = [
"-std=c++11",
"-mfpu=neon",
"-O2",
],
linkopts = ["-llog -landroid -lm"],
linkstatic = 1,
linkshared = 1,
)
cc_binary(
name = "libpthread.so",
srcs = [],
linkopts = ["-shared"],
tags = [
"manual",
"notap",
],
)
我还没有确认此库可以在Android中加载和使用; Android Studio 1.5在承认本机库的存在方面似乎非常挑剔。
答案 0 :(得分:10)
在您的WORKSPACE文件中设置Android NDK之后,Bazel可以交叉编译Android的.so,如下所示:
cc_binary(
name = "libfoo.so",
srcs = ["foo.cc"],
deps = [":bar"],
linkstatic = 1,
linkshared = 1,
)
$ bazel build foo:libfoo.so \
--crosstool_top=//external:android/crosstool --cpu=armeabi-v7a \
--host_crosstool_top=@bazel_tools//tools/cpp:toolchain
$ file bazel-bin/foo/libfoo.so
bazel-bin/foo/libfoo.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), not stripped
Bazel希望所有的Java应用程序代码都在' WORKSPACE' 顶级目录(在Tensorflow仓库中)
当0.1.4发布时(现在推送它)并且我们已经将一些修复推送到TensorFlow和Protobuf,您可以开始使用TensorFlow仓库作为远程存储库。在WORKSPACE文件中进行设置后,您可以使用@tensorflow//foo/bar
标签引用TensorFlow规则。
答案 1 :(得分:1)
git clone --recurse-submodules https://github.com/tensorflow/tensorflow.git
注意: - recurse-submodules对于拉取子模块非常重要。
从这里安装Bazel。 Bazel是TensorFlow的主要构建系统。 现在,编辑WORKSPACE,我们可以在之前克隆的TensorFlow的根目录中找到WORKSPACE文件。
# Uncomment and update the paths in these entries to build the Android demo.
#android_sdk_repository(
# name = "androidsdk",
# api_level = 23,
# build_tools_version = "25.0.1",
# # Replace with path to Android SDK on your system
# path = "<PATH_TO_SDK>",
#)
#
#android_ndk_repository(
# name="androidndk",
# path="<PATH_TO_NDK>",
# api_level=14)
如下所示我们的sdk和ndk路径:
android_sdk_repository(
name = "androidsdk",
api_level = 23,
build_tools_version = "25.0.1",
# Replace with path to Android SDK on your system
path = "/Users/amitshekhar/Library/Android/sdk/",
)
android_ndk_repository(
name="androidndk",
path="/Users/amitshekhar/Downloads/android-ndk-r13/",
api_level=14)
然后构建.so文件。
bazel build -c opt //tensorflow/contrib/android:libtensorflow_inference.so \
--crosstool_top=//external:android/crosstool \
--host_crosstool_top=@bazel_tools//tools/cpp:toolchain \
--cpu=armeabi-v7a
用我们想要的目标架构替换armeabi-v7a。 该图书馆位于:
bazel-bin/tensorflow/contrib/android/libtensorflow_inference.so
构建Java版本:
bazel build //tensorflow/contrib/android:android_tensorflow_inference_java
我们可以在以下位置找到JAR文件:
bazel-bin/tensorflow/contrib/android/libandroid_tensorflow_inference_java.jar
现在我们有jar和.so文件。我已经构建了.so文件和jar,你可以直接使用project。
将libandroid_tensorflow_inference_java.jar放入libs文件夹并右键单击并添加为库。
compile files('libs/libandroid_tensorflow_inference_java.jar')
在主目录中创建jniLibs文件夹,并将libtensorflow_inference.so放在jniLibs / armeabi-v7a /文件夹中。
现在,我们将能够调用TensorFlow Java API。
TensorFlow Java API通过类TensorFlowInferenceInterface公开了所有必需的方法。
现在,我们必须使用模型路径调用TensorFlow Java API并加载它。
我写了一篇完整的博客here。