tensorflow mobilenet_ssd_v2的訓練和移植到Android移動端,優化實時檢測手勢


參考文章

tensorflow+ssd_mobilenet實現目標檢測的訓練

TensorFlow基於ssd_mobilenet模型實現目標檢測

使用TransferLearning實現環視圖像的角點檢測——Tensorflow+MobileNetv2_SSD

MobileNet SSD V2模型的壓縮與tflite格式的轉換

使用TensorFlow Lite將ssd_mobilenet移植至安卓客戶端

整個項目代碼(包括models和android,不包括編譯的tensorflow):代碼地址
項目中數據只有一類手勢,android里面有量化和非量化兩種模型

環境准備

  1. 克隆models
    新建mobile_ssd_tf文件夾,git clone https://github.com/tensorflow/models 放到mobile_ssd_tf下面
  2. 編譯tensorflow
    git clone https://github.com/tensorflow/tensorflow,安裝protobuf,bazel等
    tensorflow編譯參考
    tensorflow 1.13.1,bazel 0.19.1(注意tf和bazel版本對應,不然出錯)
cd tensorflow/   
bazel build tensorflow/python/tools:freeze_graph
bazel build tensorflow/contrib/lite/toco:toco

數據制作

進入models/research/object_detection目錄,下面工作基本都在這個目錄下進行

mkdir ssd_data
  1. labelImg工具標注數據集,jpg格式圖片放到VOCdevkit/VOC2007/JPEGImages目錄下,xml文件放到VOCdevkit/VOC2007/Annotations文件夾下面
  2. train_test_split.py把xml分為train,test,val三部分,
  3. xml2csv.py把xml轉csv
  4. gen_tfrecords.py生成tfrecord
  5. 在ssd_data下面新建label_map.pbtxt
item {
id: 1    #id從1開始編號
name: 'name of class1'
}
item {
id: 2
name: 'name of class2'
}  

最終目錄如下

訓練

  1. 進入models/research/object_detection目錄

下面在這個目錄下進行工作

   mkdir ssd_model

從samples/config下面拷貝一個配置文件(就是要訓練的模型),放到ssd_model下面(我選的是ssd_mobilenet_v2_coco.config,還有其他各種版本的,看需要選擇),修改這個配置文件

num_classes:前景類別數目+1(背景)
input_path:上面生成的tfrecord路徑
label_map_path:label_map.pbtxt的路徑
fine_tune_checkpoint:預訓練模型的路徑(可以注釋掉從頭開始訓練)
其他學習率,batch_size,num_steps,height,width等等看情況調節

model zoo(model zoo給出了coco數據集上一些檢測模型的時間和mAP),下載預訓練模型放到ssd_model下面(也可以不下載,從頭開始訓練,我下的是這個ssd_mobilenet_v2_coco_2018_03_29.tar.gz)

  1. 訓練
python train.py --logtostderr --pipeline_config_pathssd_model/ssd_mobilenet_v2_coco.config --train_dir=ssd_data

:新版train.py在legacy目錄下,先把它copy到research下。
訓練生成的模型文件和日志都在ssd_data目錄下面。
tensorboard --logdir=ssd_data/查看訓練日志

報錯:from nets your-net-name ModuleNotFoundError: No module named 'nets'
research/slim下運行:
python setup.py build
python setup.py install

新版也可以用下面方法訓練

python model_main.py --alsologtostderr  --pipeline_config_path=...  --model_dir=...
  1. 測試
    (新版eval.py在legacy目錄下,所以先拷貝出來)
    這里將train產生的pipeline.config重命名為train_pipeline.config(因為eval也會產生pipeline.config,會覆蓋掉)
python eval.py --logtostderr --checkpoint_dir=ssd_data/ --eval_dir=ssd_data/ --pipeline_config_path=ssd_data/train_pipeline.config

ValueError: Image with id b'one_heart11.jpg' already added.
ssd_mobilenet_v2_coco.config和train_pipeline.config里面eval_config下num_examples值改為自己的,默認8000可能太大了

模型導出與轉換

  1. 導出pb格式:
python export_tflite_ssd_graph.py --pipeline_config_path=ssd_data/pipeline.config --trained_checkpoint_prefix=ssd_data/model.ckpt-200000 --output_directory=ssd_data/ --add_postprocessing_op=true

產生tflite_graph.pb和tflite_graph.pbtxt文件

  1. 導出tflite格式:(可以從上一步產生的tflite_graph.pbtxt中查看輸入節點,輸出節點名稱和shape)
    切換到第一步編譯的tensorflow目錄下面
bazel run tensorflow/contrib/lite/toco:toco 
--input_file=tflite_graph.pb 
--output_file=model.tflite 
--input_shapes=1,300,300,3 
--input_arrays=normalized_input_image_tensor 
--output_arrays='TFLite_Detection_PostProcess','TFLite_Detection_PostProcess:1','TFLite_Detection_PostProcess:2','TFLite_Detection_PostProcess:3' 
--inference_type=FLOAT 
--allow_custom_ops

或者執行

cd tensorflow/lite/python    
python tflite_convert.py  --graph_def_file=tflite_graph.pb --output_format=TFLITE --output_file=model.tflite --inference_type=FLOAT --input_arrays='normalized_input_image_tensor' --output_arrays='TFLite_Detection_PostProcess','TFLite_Detection_PostProcess:1','TFLite_Detection_PostProcess:2','TFLite_Detection_PostProcess:3' --input_shapes=1,300,300,3 --allow_custom_ops

加參數 --mean_values=128 --std_dev_values=128 --inference_type=QUANTIZED_UINT8可以量化,但是預訓練模型要選帶quantized的config文件,后面會在介紹訓練量化版本的模型。

將生成的model.tflite放到ssd_data目錄里,像下面一樣,然后測試(我已經把checkpoint等文件刪了,所以這個目錄少了很多模型文件,只有pb格式的和tflite格式的)

pc上測試tflite:
python test_tflite.py

移植到android項目

  1. 下載android項目
    tensorflow官方demo地址[https://github.com/tensorflow/examples/tree/master/lite/examples/object_detection/android]

svn https://github.com/tensorflow/examples/trunk/lite/examples/object_detection/android拉取android子文件夾
然后android studio加載項目

  1. 做些修改
    assets/文件夾下面放tflite模型文件
    labelmap2.txt放你的類別名稱
    修改名字detect2.tflite,labelmap2.txt(不改的話會覆蓋掉你的模型)
    我只有一類前景,所以改成下面的(???表示背景)
???
oneheart

改DetectorActivity.java:

TF_OD_API_IS_QUANTIZED = false;//如果之前沒量化,這里要改成false
TF_OD_API_MODEL_FILE = "detect2.tflite";
TF_OD_API_LABELS_FILE = "file:///android_asset/labelmap2.txt";

DetectorTest.java也有上面表示兩個文件路徑的變量,我也改了,可以全局查找,全部改為自己的。
我還改了TFLiteObjectDetectionAPIModel.java里面的labelOffset為0,因為我發現不改下標會有溢出。

  1. 結果
    模型大約18M,運行時間約300ms
    效果:

訓練量化版本和時間優化

TensorFlow Mobilenet SSD模型壓縮並移植安卓上以達到實時檢測效果

參考上面這篇文章,從量化,修改圖片尺寸和修改depth_multiplier等角度優化時間。(depth multiplier作為一個因子與網絡中各層的channel數相乘,depth_multiplier越小,網絡中feature map的channel數越少)
這次將samples/config/ssd_mobilenet_v2_quantized_300x300_coco.config拷貝出來放到ssd_model下面,從model zoo里面下ssd_mobilenet_v2_quantized_coco.tar預訓練模型放到ssd_model下面。
如上面修改配置文件,這里我還把圖片尺寸fixed_shape_resizer改為180x180。
我暫時沒有改depth_multiplier參數,可以試驗下0.75看看效果。
訓練前刪除ssd_data下之前生成的訓練的模型和日志,不然可能會有影響。

  1. 開始訓練
python3 train.py --logtostderr --pipeline_config_path=ssd_model/ssd_mobilenet_v2_quantized_300x300_coco.config --train_dir=ssd_data
  1. 導出pb模型
python export_tflite_ssd_graph.py --pipeline_config_path=ssd_data/pipeline.config --trained_checkpoint_prefix=ssd_data/model.ckpt-9571 --output_directory=ssd_data/ --add_postprocessing_op=true
  1. 導出tflite格式模型
python tflite_convert.py  --graph_def_file=tflite_graph.pb --output_format=TFLITE --output_file=model_quantized.tflite --inference_type=FLOAT --input_arrays='normalized_input_image_tensor' --output_arrays='TFLite_Detection_PostProcess','TFLite_Detection_PostProcess:1','TFLite_Detection_PostProcess:2','TFLite_Detection_PostProcess:3' --input_shapes=1,180,180,3 --allow_custom_ops --mean_values=128 --std_dev_values=128 --inference_type=QUANTIZED_UINT8
  1. 移植到android項目里面
    訓練好的模型文件放到assets/目錄下面
    修改DetectorActivity.java里面的幾個變量
   private static final int TF_OD_API_INPUT_SIZE = 180;
   private static final boolean TF_OD_API_IS_QUANTIZED = true;//這里改為true
   private static final String TF_OD_API_MODEL_FILE = "model_quantized.tflite";
   private static final String TF_OD_API_LABELS_FILE = "file:///android_asset/labelmap2.txt";
  1. 效果
    模型大約4M,運行時間約20-30ms
    運行效果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM