从0开始搭建精灵宝可梦的检测APP
使用Tensorflow从0开始搭建精灵宝可梦的检测APP
本文为本人原创,转载请注明来源链接
环境要求
- Tensorflow1.12.0
- cuda 9.0
- python3.6.10
- Android Studio
- Anaconda
安装Tensorflow
使用conda 安装GPU版Tensorflow
conda install tensorflow-gpu=1.12.0
找到tensorflow的安装位置
我的位置在:
home/jiading/.conda/envs/tensorflow12/lib/python3.6/site-packages/tensorflow
通过conda安装的tensorflow是不包括models这一模块的,需要从Github上下载:https://github.com/tensorflow/models
将它克隆到tensorflow文件夹下:
打开models\research\object_detection,按照https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/installation.md提示的进行安装
运行
python object_detection/builders/model_builder_test.py
测试是否安装成功
下载和处理数据集
我们采用的数据集是https://www.kaggle.com/lantian773030/pokemonclassification。如果你使用colab训练,可以直接将数据集下载到colab中:https://blog.csdn.net/qq_35654046/article/details/87621396
原始的数据集只有图像和类别,可以用于分类,但是用于目标检测的话需要在此基础上进一步标定数据,在图像中框出神奇宝贝的位置。
这里我们使用labelme这个软件进行标定。labelme可以直接通过pip安装:pip install labelme -i https://pypi.tuna.tsinghua.edu.cn/simp le
在终端(Bash和Windows的Powershell都可以)中直接输出Labelme即可打开软件.labelme的简单教程可以看这里:https://www.cnblogs.com/wangxiaocvpr/p/9997690.html
标定数据后,我们在各个神奇宝贝的文件夹中得到了和原图像同名的Json文件:
打开json文件,我们可以看到有很长的imageData:
这其实就是对原图像的储存,所以我们之后处理时只需要这个json文件即可,由此可以还原出原图像
如果要达到比较好的效果,要标定的数据还是不少的。
将labelme转换为voc格式
我们最终要把数据集转换为tfrecord,但是在此之前我们需要将其转换为规范的voc格式,以便于再转为tfrecord
这里我们使用Github上提供的脚本:https://github.com/veraposeidon/labelme2Datasets。这个项目的说明也是中文的,我就不多说了(可以使用我fork后修改的版本,下文有说改了哪些地方:https://github.com/JiaDingCN/labelme2Datasets)。
最后得到VOC格式的数据如下:
注意原项目的代码中有一两个小bug,这其实无伤大雅,改了就好了,但是原项目没有生成val数据集的功能,只能生成training和test.所以我改了一点:
原来的split_dataset只有test_ratio
:测试集比例,我加上了'val_ratio'
注意,其实理论上可以直接用这个工具生成coco形式的数据,然后使用tensorflow中tensorflow/models/research/object_detection/dataset_tools/create_coco_tf_record.py来生成tfrecord,但在我实际使用中发现create_coco_tf_record.py制作出来的是分散的数据,如下:
当然人家在代码中也说了:Please note that this tool creates sharded output files.
,是我自己没仔细看。这个格式应该也是能用的,但是我目前不知道方法,所以最后就没有用这个方法
将voc格式数据转换为tfrecord
最终我采用的是这篇博客中的代码,生成的tfrecord如下:
开始训练
这里我训练使用的是Tensorflow lite教程中推荐的COCO SSD MobileNet v1:
当然也可以不选择预训练模型,而是从头训练。这样的话就不需要下载上面的文件,你只需要一个config文件即可。该网络的config文件在object_detection/samples/config/ssd_mobilenet_v1_coco.config。如何配置依然可以看这篇博文:https://www.cnblogs.com/gezhuangzhuang/p/10613468.html
训练完成后,我们就可以在train_dir中看到得到的模型:
导出图
我们可以使用object_detection下的export_inference_graph.py导出图,但是对于ssd模型,官方推荐使用export_tflite_ssd_graph.py(亲测用上面的那个脚本导出的模型无法转换为tflite格式):
python export_tflite_ssd_graph.py --input_type image_tensor --pipeline_config_path /home/jiading/Pokemon/ssd_mobilenet_v1_0.75_depth_300x300_coco14_sync.config --trained.checkpoint_prefix /home/jiading/Pokemon/train/model.ckpt-2955 --output_directory /home/jiading/Pokemon/frozen_inference_graph.pb -add_postprocessing_op True --max_detection 10
测试
我们可以使用tensorflow的object_detection自带的jupyter notebook脚本来做测试:
将PATH_TO_FROZEN_GRAPH改为pb文件的位置
需要一个labelmap文件,内容如下:
用一个脚本很容易写出来,这个就不提了
加载一张图片
运行结果
转换为tensorflow lite模型
~/.conda/envs/tensorflow12/lib/python3.6/site-packages/tensorflow/models/research/object_detection$ tflite_convert --output_file=/home/jiading/Pokemon/tflite/detect.tflite --graph_def_file=/home/jiading/Pokemon/frozen_inference_graph/tflite_graph.pb --input_arrays='normalized_input_image_tensor' --output_arrays='TFLite_Detection_PostProcess','TFLite_Detection_PostProcess:1','TFLite_Detection_PostProcess:2','TFLite_Detection_PostProcess:3' --input_shape=1,300,300,3 --allow_custom_ops
部署在安卓端
安卓的例子在ObjectDetection-Android\examples-master\lite\examples\object_detection\android
下,打开后我们首先需要制作一个labelmap:
原本的例子会利用gradle下载模型,我们可以将地址替换掉
,将我们自己的这两个文件放进去:
部署时可能遇到的bug
我们可以比对自己的模型和原本的模型在输入输出上有没有区别:https://blog.csdn.net/killfunst/article/details/94301161
import numpy as np
import tensorflow as tf
# Load TFLite model and allocate tensors.
interpreter = tf.contrib.lite.Interpreter(model_path="")
interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
print(input_details)
print(output_details)
像我之前在导出图时设置的--max_detection 5
,但是看输出发现:
上面是我的,下面是原本模型的,改为10后再导出就没有问题了
如果还有问题,可以考虑将DetectorActivity中的private static final boolean TF_OD_API_IS_QUANTIZED
设置为false。同时,如果出现维度错误,可以考虑修改TFLiteObjectDetectionAPIModel.java下的private static final int NUM_DETECTIONS
最终效果:
一点点换皮
将原项目中的图标和软件名换掉之后:
从0开始搭建精灵宝可梦的检测APP的更多相关文章
- XNA 4.0 环境搭建和 Hello World,Windows Phone 游戏开发
XNA 4.0 环境搭建和 Hello World,Windows Phone 游戏开发 使用 Scene 类在 XNA 中创建不同的场景(八) 摘要: 平方已经开发了一些 Windows Phone ...
- 从0开始搭建SQL Server AlwaysOn 第一篇(配置域控)
从0开始搭建SQL Server AlwaysOn 第一篇(配置域控) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://www.cnb ...
- 从0开始搭建SQL Server AlwaysOn 第二篇(配置故障转移集群)
从0开始搭建SQL Server AlwaysOn 第二篇(配置故障转移集群) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://www ...
- 从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn)
从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://w ...
- 从0开始搭建SQL Server AlwaysOn 第四篇(配置异地机房节点)
从0开始搭建SQL Server AlwaysOn 第四篇(配置异地机房节点) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://www ...
- (转) 从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn)
原文地址: http://www.cnblogs.com/lyhabc/p/4682986.html 这一篇是从0开始搭建SQL Server AlwaysOn 的第三篇,这一篇才真正开始搭建Alwa ...
- (转)从0开始搭建SQL Server AlwaysOn 第二篇(配置故障转移集群)
原文地址: http://www.cnblogs.com/lyhabc/p/4682028.html 这一篇是从0开始搭建SQL Server AlwaysOn 的第二篇,主要讲述如何搭建故障转移集 ...
- ubantu16.04+mxnet +opencv+cuda8.0 环境搭建
ubantu16.04+mxnet +opencv+cuda8.0 环境搭建 建议:环境搭建完成之后,不要更新系统(内核) 转载请注明出处: 微微苏荷 一 我的安装环境 系统:ubuntu16.04 ...
- cAdvisor0.24.1+InfluxDB0.13+Grafana4.0.2搭建Docker1.12.3 Swarm集群性能监控平台
目录 [TOC] 1.基本概念 既然是对Docker的容器进行监控,我们就不自己单独搭建cAdvisor.InfluxDB.Grarana了,本文中这三个实例,主要以Docker容器方式运行. 本 ...
随机推荐
- (js描述的)数据结构[队列结构,优先级队列](3)
(js描述的)数据结构[队列结构](3) 一.队列结构的特点: 1.基于数组来实现,的一种受限的线性结构. 2.只允许在表头进行删除操作,在表尾进行插入操作. 3.先进先出(FIFO) 二.队列的一些 ...
- idle中上传jar包并使用的方法
创建一个lib目录,将jar包拉到该目录下. 需要导入的Jar包上,点击右键,选择Add as Library…
- 21.1 Math(数学运算)方法使用 、工具类
package day21_static.meathDemo; //Math: 包含一些基本的数学运算方法 //从api中搜Math,它都用的static修饰. public class MethDe ...
- Linux中vim编辑器 的 快捷键 --- 常用 的 都比较全
Linux中vim编辑器的功能非常强大,许多常用快捷键用起来非常方便,这里将我学vim入门时学的一些常用的快捷键分享给大家一下,希望可以帮助你们. 这个是我将鸟哥书上的进行了一下整理的,希望不要涉及到 ...
- mysql 主键和默认 设为索引的规则
一.mysql 表中如果是单主键的话,那这个主键也会被 系统默认建为 索引 二.mysql 表中如果是复合主键的话,那系统会遵循左对齐原则,即如复合主键 a 和 b字段和c字段..., 默认建的主键索 ...
- not found 什么时候触发
eq: BEGIN DECLARE EXIT HANDLER FOR NOT FOUND SET o_state = 999; select count(1) into ...
- JS中的offsetWidth/offsetHeight/offsetTop/offsetLeft、clientWidth/clientHeight/clientTop/clientLeft、scrollWidth/scrollHeight/scrollTop/scrollLeft
这是一组非常容易弄混的参数!都是描述某个盒子元素的宽度.高度以及上或左的距离偏移量. 1. offsetWidth / offsetHeight(不包括外边距) offsetWidth:返回元素的宽度 ...
- 使用Scanner接受用户键盘输入的值
第一步导入Scanner import java.util.*; 第二步创建Scanner对象 Scanner input = new Scanner(System.in); 第二步创建Scanner ...
- 【乱码问题】IDEA控制台使用了GBK字符集
什么Tomcat乱码设置IDEA的初始编码,瞎搞 终于在这个帖子看到了真相 https://blog.csdn.net/weixin_42617398/article/details/81806438 ...
- 架构师修炼之设计模式 - 策略模式(Strategy) 【Python与C#实现】
程序员,我为你祝福 愿你有一个灿烂的前程 愿你有情人终成眷属 愿你在尘世获得幸福 我只想成为架构师,走遍江湖! 目录 模式定义 模式分类 模式结构 实例(C#与Python版) 优点 缺点 使用场景 ...