手写选择题识别-封装tensorflow模型-移植到android程序
来源:互联网 发布:男士内裤淘宝店铺名 编辑:程序博客网 时间:2024/05/17 23:49
第一部分:
现在遇到的问题:还是因为线下python训练好的模型,不能够直接无缝连接使用。
这个看起来是android中直接调用tensorflow模型,那就不用和c++模块进行对接了 。
说起来惭愧,虽然接触了一段时间的tensorflow,但是好多东西没有需要所以也没有接触到,比如一般使用的多的是tensorflow的模型保存与重载,现在又接触到了对tf的封装(还看了部署到线上的情况)。
所以知道需要看这些的资料,就顺便记录下来,万一使用这个方法了呢?
参考的教程:http://blog.csdn.net/masa_fish/article/details/56049710
在以前的模型中,需要注意 的几点
1.需要对输入层x,和输出层y,通过形参name进行命名。
###################### 1.对输入层x命名,注意x是以placehoder占位的,而输出层不是这个。x = tf.placeholder(tf.float32,shape=[None,n_input],name="x_input")y = tf.placeholder(tf.float32,shape=[None,n_output])########################################### 2.对输出层命名pred = tf.add(tf.matmul(dense, w2), b2, name="y_output")###################### 2.对输出层命名
2.需要将模型保存为.pb格式的文件(就在模型训练完后的位置添加一行代码就可以保存,)
需要导入graph_util包
from tensorflow.python.framework import graph_util##################模型封装 output_graph_def = graph_util.convert_variables_to_constants(sess, sess.graph_def, output_node_names=["output"]) # 形参output_node_names用于指定输出的节点名称(不是指的要输出的节点的名称) pb_file_path = " my_net/save_net.pb" with tf.gfile.FastGFile(pb_file_path, mode='wb') as f: f.write(output_graph_def.SerializeToString()) ##################模型封装
第二部分:
#################################下面入了个坑,果然是要首先有好教程才行
应该是需要从源码安装tensorflow,才能够移植到android应用,所以教程上 都是说下载源码后,然后再安装 Bazel 。(如果是已经通过pip 安装了tensorflow ,那么再来源码编译 会冲突吗?)
1.从github上下载源码(这个会下载最新的,应该不会因为代码是前面一点的版本,而这个是后面的版本就有问题吧)
sudo apt install gitgit clone https://github.com/tensorflow/tensorflow
这个会在当前文件夹下 克隆tensorflow源码到一个新的tensorflow文件夹中。
2.需要下载编译源码的工具
sudo apt-get install python-pip python-dev
先安装Bazel的依赖
sudo add-apt-repository ppa:webupd8team/javasudo apt-get install openjdk-8-jdk openjdk-8-sourcesudo apt-get install pkg-config zip g++ zlib1g-dev unzip
下载安装文件,然后再改变可执行权限
https://github.com/bazelbuild/bazel/releaseschmod +x bazel-0.5.3-installer-linux-x86_64.sh
https://github.com/bazelbuild/bazel/releases/download/0.5.3/bazel-0.5.3-installer-linux-x86_64.sh
下载速度好慢啊 ,是教育网的原因吗。(在这个地方等了会时间)
只能找网上其他的资源了
http://download.csdn.net/download/l1505624/9886656
从csdn下载的是:
bazel-0.5.2-installer-linux-x86_64.sh
开始:
1.复制到虚拟机中, 终端然后切换到.sh文件存放的路径,文件添加可执行权限:
$ chmod +x bazel-0.5.2-installer-linux-x86_64.sh
2.然后执行该文件:
$ ./bazel-0.5.2-installer-linux-x86_64.sh –user
3、 设置Bazel 环境变量
$ sudo gedit ~/.bashrc
在 ~/.bashrc文件的末尾添加
export PATH=’
在这个地方需要注意 修改完成后利用source使改变生效。我一开始就是忘记这个步骤,然后导致后面的情况出现(命令路径问题:比如我在这块不知道怎么就覆盖了一些路径,导致各种/usr/bin.找不到,所以需要添加到bashrc文件中进去 /bin,/usr/bin.)
source ~/.bashrc
4.在解压的tensorflow目录中运行,进行相关配置,尽量什么都不添加,因为还需要配置添加的路径,也就是需要安装那些。(在这个地方坑了很长时间,后面的安装会有报错信息)
./configure
前面准备的tensorflow地址中存在着中文,会报错,所以移动到其他 的目录下。
另外看教程学习的时候最好是同时看两篇,这样可以综合起来(毕竟环境不同,个人选择不同)
# pip3 uninstall -y tensorflow #若之前安装过则需要强制卸载,注意pip版本
bazel build -c opt tensorflow/tools/pip_package:build_pip_package、
这个与前面的config配置需要相对应。
执行的很长恨慢,而且报各种错。这个还是显示的是info,估计有error就失败了。
最后的
bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
然后进入/tmp/tensorflow_pkg 利用pip install 安装下载的版本。
但是,在import tensorflow时出错,明明还是挺简单的东西,却用了 这么久的时间,还出错。
第三部分:
。。。。感觉好失败。
本来还想放弃一个系统,来安装的
该放弃吧,得换个办法从tf模型移植到android,刚好又看到另外一个教程,最初开始的时候没有选择它,但是后面经过了上面的挫折后,才意识到他的好处,那就是如果你不想自己编译的话,提供了文件的地址下载。
虽然是要越错越勇,算了 主要的目的得先解决才好。嗯,是这样的越快决定了 ,饿死我了。
这样终于回归到了主线上来。该准备的准备的差不多了。
1.pb模型(没钱,只有一台破主机cpu的,跑了一段时间跑出来了):
可以先用一个简单点的模型来做测试:
# -*- coding:utf-8 -*-import tensorflow as tffrom tensorflow.python.framework import graph_utilsession = tf.Session()matrix1 = tf.constant([[3., 3.]], name='input')add2Mat = tf.add(matrix1, matrix1, name='output')session.run(add2Mat)output_graph_def = graph_util.convert_variables_to_constants(session, session.graph_def,output_node_names=['output'])with tf.gfile.FastGFile('model/cxq.pb', mode='wb') as f: f.write(output_graph_def.SerializeToString())session.close()
2.so和jar包:
3.创建android 项目:(我这个项目最后需要使用到c++,所以看到c++的就勾选中了,不知道后面的配置会有问题吗,先记录一下,方便以后对照)
这个下面的两个选择项不知道要不要选?
遇到的几个小问题:
直接下载ndk来解决;
直接点击error下载cmakedeng来解决;
4.把刚才的pb文件存放到assets文件夹下(默认没有这个文件夹,需要手动创建并配置)
按下面操作可以知道在哪以及为什么在main下面创建这个文件夹:
()
可以如下创建这个folder。(如果直接创建的是一个目录需要配置什么呢?)
下面就可以直接复制pb文件到这个文件夹下了:
5.将libandroid_tensorflow_inference_java.jar存放到/app/libs目录下,并且右键“add as Libary”
6.在/app/libs下新建armeabi文件夹,并将libtensorflow_inference.so放进去(这个应该是添加so文件吧,应该是放在jinlibs下吧?)
其实在android jinlibs和 project下libs两个是一样的:
注意:还有个jni文件夹(是放没有编译好的so文件的),而这个jinlibs是放的是已经编译好的文件。
添加两个配置:
再添加一个配置:
这样tensorflow的环境就配置好了。
7.创建模型调用类。
然后就是需要编写代码了,注意抽取框架,才好改自己的代码。
import android.content.res.AssetManager;import android.os.Trace;import org.tensorflow.contrib.android.TensorFlowInferenceInterface;
会自动提示:
有个就是android资源的问题:
第一种是res目录下存放的可编译的资源文件:
这种资源文件系统会在R.Java里面自动生成该资源文件的ID,所以访问这种资源文件比较简单,通过R.XXX.ID即可;
第二种是assets目录下存放的原生资源文件:
因为系统在编译的时候不会编译assets下的资源文件,所以我们不能通过R.XXX.ID的方式访问它们。
所以我们无法直接获取到assets的绝对路径,因为它们根本就没有。
遇到的问题:trace: Trace.beginSection(“feed”);
直接更改 minsdkversion 为18
代码:
package com.example.yanguokai.handerwriterreg;/** * Created by YANGUOKAI on 2017/8/1. *////////importimport android.content.res.AssetManager;import android.os.Trace;import org.tensorflow.contrib.android.TensorFlowInferenceInterface;///////importpublic class TFtest {//1.定义模型存放路径,注意的是android相关资源的获取的表示形式。 private static final String MODEL_PATH = "file:///android_asset/cxq.pb";//2.定义数据的维度 private static final int HEIGHT = 1; private static final int WIDTH = 2;//3.模型中变量的名称 private static final String INPUT_NAME = "input"; private static final String OUTPUT_NAME = "output";//4.用于存储模型的数据 private float[] inputs = new float[HEIGHT*WIDTH]; private float[] outputs = new float[HEIGHT*WIDTH];//5.tensorflow 接口对象 TensorFlowInferenceInterface inferenceInterface; //6.静态加载库文件 static { System.loadLibrary("tensorflow_inference"); } //7.利用assertManager来处理assert中的资源 TFtest(AssetManager assetManager){ //接口定义 inferenceInterface = new TensorFlowInferenceInterface(assetManager,MODEL_PATH); } //8.定义获取结果的函数 public float[] getAddResults(int a,int b){ //获取输入数据 inputs[0] = a; inputs[1] = b; //将输入数据feed给tensorflow Trace.beginSection("feed"); inferenceInterface.feed(INPUT_NAME,inputs,WIDTH,HEIGHT); Trace.endSection(); //运行操作 Trace.beginSection("run"); String[] outputNames = new String[]{OUTPUT_NAME}; inferenceInterface.run(outputNames); Trace.endSection(); //将输出保存 Trace.beginSection("fetch"); inferenceInterface.fetch(OUTPUT_NAME,outputs); Trace.endSection(); //返回保存的输出 return outputs; }}
最后就是在activity中使用 类:
定义一个点击
// 声明button Button button01 = (Button) findViewById(R.id.button_01); button01.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { TFtest tFtest = new TFtest(getAssets()); float[] outputs = tFtest.getAddResults(2,10); for(int i=0;i<outputs.length;i++){ Log.i("TAG","button01"+outputs[i]); } } });
运行结果:
整体框架已经搭好,中间遇到好多别人没有遇到的问题,自己在解决这些问题的时候也是只想着找到现成的解决方法,然后直接套用就好,说时候,也算是没有真正的去解决里面的问题吧,现在将所有的问题都贴出来,一个是方便下次再来做的时候遇到同样问题的可以有个参考,二个事以后是时候再来回看。
后面是时候将自己的模型导入了。
- 手写选择题识别-封装tensorflow模型-移植到android程序
- 手写选择题识别-c++线上调用 线下python跑出的tensorflow模型-占坑
- Tensorflow(3) MNIST手写数字识别与Android移植
- 手写选择题识别-实现android调用c++ oepncv项目
- 手写选择题识别-边学边记录
- 手写选择题识别-透视变换
- 基于Tensorflow的android手写数字识别
- Tensorflow移植到Android
- 将tensorflow训练好的模型移植到android
- 将tensorflow训练好的模型移植到android
- 将tensorflow训练好的模型移植到android
- 将tensorflow训练好的模型移植到android
- 将tensorflow训练好的模型移植到android
- Tensorflow小样例-分类模型(识别mnist手写数字)
- tensorflow Lenet5手写字体识别模型的保存与加载
- tensorflow识别手写数字
- Tensorflow MNIST 手写识别
- TensorFlow手写识别
- Android 关于arm64-v8a、armeabi-v7a、armeabi、x86下的so文件兼容问题
- HDU 4747 线段树 区间更新
- 怎么判断软件公司是否靠谱
- 工作小记录,server中调用update却被回滚。
- 【RabbitMQ】—— Exchange类型
- 手写选择题识别-封装tensorflow模型-移植到android程序
- 将其他编码文件转化为UTF8文件
- html css伪元素标签(二)灵活
- ES6数组扩展
- Gradle2.0用户指南翻译——第二章. 概述
- 进制转换(栈 && 16进制转换)
- 互动大屏,unity透明视频的实现方法:
- java 基础
- 7.31 A