Tensorflow移植Android上的过程和坑 – 解决了我在eclipse上的问题

重要,我之前用的应该是jdk8版本的,在我这里报错,各种调试排错,始终不行,后来换了7,很轻松就搞定,看了这么多篇文章,只有本篇切中要点解决了困扰我几天的问题,特此收藏,也给后来者点经验,减少弯路。另外,我是用的eclipse,可是满互联网搜到的都是android studio环境的,即便是有eclipse的也会存在提供的源码不全,库不全之类的问题。

写一段我将tensorflow移植到Android上的历程,希望后者能够避免我的坑,能更多的发展这个东西。

过程中参考了其他一些博客,外加自己的修改,填坑,由于可能比较长,剩下的之后再补充吧。

采用的策略是tensorflow moblie

但是谷歌开发会议上提出了Tensorflow Lite相信不久这个将会是主流

本篇主要针对移植的方面说明,对Android和tf的细节并未做详细说明

本篇不恰当之处还请指正,欢迎评论区指出不足之处

大体的路线是:

  1.    试图在Ubuntu上使用Bazel编译jar文件和so文件(包含Git下载源码,源码安装)
  2.    在Ubuntu上安装Android Studio
  3.    安装NDK
  4.    放弃编译,直接下载jar和so文件(太难编译了)
  5.   tensorflow保存pb文件
  6.   Ubuntu上成功
  7.   windows上成功

我的环境

  • Windows10
  • Ubuntu 16虚拟机
  • tensorflow版本:win(1.8.0-gpu) Ubuntu(1.8.0-cpu)
  • Python版本 :均为3.6
  • Android Studio3.x
  • 真机测试环境:小米5X

     

一,先在Ubuntu虚拟机上操作

  1,按照以前的经验,需要在Ubuntu上用tensorflow源码安装,再用bazel编译出

  1. libandroid_tensorflow_inference_java.jar(以下简称jar文件)
  2. libtensorflow_inference.so(以下简称so文件)

这两个文件是tensorflow移植到Android的关键,外加Tensorflow训练保存的pb文件

3.model.pb(以下简称pb文件)

  2,安装Android Studio、NDK和Bazel

AS:直接在官网安装即可

NDK:可以再AS的manager里面直接下载安装,也可以在官网指定版本安装

Bazel:官网安装即可,我的下载 Bazel 0.13..0

  注意:Bazel和NDK版本有限制(比如bazel13.0只支持02,13,14,15的NDK版本)但是AS里面默认安装最新版本,这里要注意

我当时安装的bazel13.0,只能匹配15及之前的NDK,而我的AS默认装的18版本,所以又去官网下载了15版本的NDK重弄了一下

  3,Ubuntu安装tensorflow源码

  因为我想最后移植到windows,(windows上的tf版本是1.8.0)所以在Ubuntu虚拟机上也指定了1.8.0版本下载

这一步需要在Github上将分支从master选择到自己选择的版本,在git clone一下,将源码下载下来

/.configure安装 tf源码

 小插曲:升级pip后出现Python脚本程序出现:ImportError: cannot import name main

       解决方案:参考了这篇博客 升级pip后出现ImportError: cannot import name main

安装成功后就可以通过bazel来编译源码,产生jar和文件和so文件

 出现问题,编译不出来,所有环境都配好了但是出不来

 解决方案:准备跳过编译环节,直接下载jar文件和so文件,

  4,Jar文件和So文件的解决方案

主要参考:tf移植Android

Jar和so文件github官网上貌似已经不提供下载了

两个文件下载地址(为此我收集的两个版本jar和so文件)

jar+so(jdk7):jar+so文件jdk7版本

(重要,我之前用的应该是jdk8版本的,在我这里报错,各种调试排错,始终不行,后来换了7,很轻松就搞定,看了这么多篇文章,只有本篇切中要点解决了困扰我几天的问题,特此收藏,也给后来者点经验,减少弯路。采用的最新版Classifier和TensorFlowImageClassifier,发现下文所说的三个接口并没有什么改变,不知道为什么)

jar+so(jdk8):jar+so文件jdk8版本

需要注意的是:两个版本的jar和so文件提供的tensorflow接口有所不同

这个是jdk7版本的

<code class="language-java hljs"></code>
  1. //整个流程核心的三个接口
  2. TensorFlowInferenceInterface.fillNodeFloat(); //输入数据
  3. TensorFlowInferenceInterface.runInference(); //模型运行
  4. TensorFlowInferenceInterface.readNodeFloat(); //得到输出数据

 

而这个是jdk8版本的

<code class="language-java hljs"></code>
  1. //jdk8版本的
  2. TensorFlowInferenceInterface.feed()//输入
  3. TensorFlowInferenceInterface.run()//运行
  4. TensorFlowInferenceInterface.fetch()//输出

 

可以根据需要按照自己的方式选择

  5,tensorflow训练pb文件

自己随便写了一个模型,这里必须要保存为pb文件,使用到的模块

from tensorflow.python.framework import graph_util

<code class="language-python hljs"></code>
  1. # -*- coding: utf-8 -*-
  2. “””
  3. Created on Sat Sep 22 20:18:18 2018
  4. 保存模型
  5. @author: hhuaf
  6. “””
  7. import tensorflow as tf
  8. from tensorflow.python.framework import graph_util
  9. import os
  10. pb_file_path = os.getcwd()
  11. with tf.Session(graph=tf.Graph()) as sess:
  12. x = tf.placeholder(tf.float32, name=‘input’)
  13. w = tf.Variable(tf.random_normal([1]), name=‘weight’)
  14. b = tf.Variable(1.0, name=‘b’)
  15. xy = tf.multiply(x, w)
  16. # 这里的输出需要加上name属性
  17. op = tf.add(x, x, name=‘output’)
  18. sess.run(tf.global_variables_initializer())
  19. # convert_variables_to_constants 需要指定output_node_names,list(),可以多个
  20. constant_graph = graph_util.convert_variables_to_constants(sess, sess.graph_def, [‘output’])
  21. # 测试 OP
  22. feed_dict = {x: 5.0}
  23. print(sess.run(op, feed_dict))
  24. print(‘w’,w.eval(),‘b’,b.eval())
  25. # 写入序列化的 PB 文件
  26. with tf.gfile.FastGFile(pb_file_path+‘model.pb’, mode=‘wb’) as f:
  27. f.write(constant_graph.SerializeToString())
  28. # 输出
  29. # INFO:tensorflow:Froze 1 variables.
  30. # Converted 1 variables to const ops.
  31. # 31

 

注意保存的时候输出的名字一定要记住[output]

得到pb文件后就可以在Android上面开始移植了

6、在Android的移植

我是下载了18年编译的java8的so文件和jar文件,加上上面训练的简单模型

环境配置方面很大程度上借鉴了这篇博客:将TensorFlow训练好的模型迁移到Android APP上

具体来说就是在app/src/main/下创建assets文件夹,里面放置我们训练好的pb文件

在app目录下创建libs文件夹(若有了就不用创建)放置jar文件

再libs目录下再创建armeabi-v7a文件夹,里面放置so文件

在app下的gradle里添加配置如下。后面的dependencies会自动添加(AS的好处)

<code class="language-java hljs"></code>
  1. apply plugin: ‘com.android.application’
  2. android {
  3. compileSdkVersion 28
  4. defaultConfig {
  5. applicationId “com.example.hhuaf.tf_new1”
  6. minSdkVersion 15
  7. targetSdkVersion 28
  8. versionCode 1
  9. versionName “1.0”
  10. testInstrumentationRunner “android.support.test.runner.AndroidJUnitRunner”
  11. multiDexEnabled true//新加
  12. ndk {//新加
  13. abiFilters “armeabi-v7a”//新加
  14. }//新加
  15. }
  16. buildTypes {
  17. release {
  18. minifyEnabled false
  19. proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
  20. }
  21. }
  22. //新加
  23. sourceSets {//新加
  24. main {//新加
  25. jni.srcDirs = []//新加
  26. jniLibs.srcDirs = [‘libs’]//新加
  27. }//新加
  28. }//新加
  29. }
  30. dependencies {
  31. implementation fileTree(include: [‘*.jar’], dir: ‘libs’)
  32. implementation ‘com.android.support:appcompat-v7:28.0.0’
  33. implementation ‘com.android.support.constraint:constraint-layout:1.1.3’
  34. testImplementation ‘junit:junit:4.12’
  35. androidTestImplementation ‘com.android.support.test:runner:1.0.2’
  36. androidTestImplementation ‘com.android.support.test.espresso:espresso-core:3.0.2’
  37. implementation files(‘libs/libandroid_tensorflow_inference_java.jar’)
  38. }

 

跑了通第一个demo

整体来说流程是这样

二、从Ubuntu到windows

除开bazel编译so和jar文件外,其实Linux和windows的移植并无差别,在有so,jar文件情况下,可以无视环境不同,直接移植

在win环境的AS配置方法与ubuntu完全一样,能成功移植

后话

虽然移植成功了,但是并没有通过编译过程,其实有点取巧,希望有大佬来提供一个成功编译的方案,有修改的地方以后会修改,如果参考的几篇博客有侵权的地方,我会马上删除!

来源URL:https://blog.csdn.net/qq_36440163/article/details/83060160

《Tensorflow移植Android上的过程和坑 – 解决了我在eclipse上的问题》有一个想法

评论已关闭。