zoukankan      html  css  js  c++  java
  • 使用Tensorflow从0开始搭建精灵宝可梦的检测APP

    使用Tensorflow从0开始搭建精灵宝可梦的检测APP

    本文为本人原创,转载请注明来源链接

    环境要求

    • Tensorflow1.12.0
    • cuda 9.0
    • python3.6.10
    • Android Studio
    • Anaconda

    安装Tensorflow

    1. 使用conda 安装GPU版Tensorflow

      conda install tensorflow-gpu=1.12.0

    2. 找到tensorflow的安装位置

      我的位置在:home/jiading/.conda/envs/tensorflow12/lib/python3.6/site-packages/tensorflow

    3. 通过conda安装的tensorflow是不包括models这一模块的,需要从Github上下载:https://github.com/tensorflow/models

      将它克隆到tensorflow文件夹下:

    4. 打开models esearchobject_detection,按照https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/installation.md提示的进行安装

    5. 运行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:

    下载地址:http://storage.googleapis.com/download.tensorflow.org/models/tflite/coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip

    当然也可以不选择预训练模型,而是从头训练。这样的话就不需要下载上面的文件,你只需要一个config文件即可。该网络的config文件在object_detection/samples/config/ssd_mobilenet_v1_coco.config。如何配置依然可以看这篇博文:https://www.cnblogs.com/gezhuangzhuang/p/10613468.html

    image-20200503161639791

    训练完成后,我们就可以在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脚本来做测试:

    image-20200503161710902

    将PATH_TO_FROZEN_GRAPH改为pb文件的位置

    image-20200503161746677

    需要一个labelmap文件,内容如下:

    image-20200503161820339

    用一个脚本很容易写出来,这个就不提了

    image-20200503161849333

    加载一张图片

    image-20200503161926627

    运行结果

    转换为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-Androidexamples-masterliteexamplesobject_detectionandroid下,打开后我们首先需要制作一个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

    最终效果:

    image-20200503162154544

    一点点换皮

    将原项目中的图标和软件名换掉之后:

    image-20200503162133025

  • 相关阅读:
    su命令Permission denied
    Linux网络故障
    nsswitch
    route命令
    GCC编译器原理(三)------编译原理三:编译过程(3)---编译之汇编以及静态链接【1】
    GCC编译器原理(三)------编译原理三:编译过程(2-2)---编译之语法分析
    GCC编译器原理(三)------编译原理三:编译过程(2-1)---编译之词法分析
    GCC编译器原理(三)------编译原理三:编译过程---预处理
    GCC编译器原理(二)------编译原理一:ELF文件(3)
    GCC编译器原理(二)------编译原理一:ELF文件(2)
  • 原文地址:https://www.cnblogs.com/jiading/p/12822286.html
Copyright © 2011-2022 走看看