移動端目標識別(3)——使用TensorFlow Lite將tensorflow模型部署到移動端(ssd)之Running on mobile with TensorFlow Lite (寫的很亂,回

 承接移動端目標識別(2)html

 

使用TensorFlow Lite在移動設備上運行java

        在本節中,咱們將向您展現如何使用TensorFlow Lite得到更小的模型,並容許您利用針對移動設備優化的操做。   python

TensorFlow Lite是TensorFlow針對移動和嵌入式設備的輕量級解決方案。它支持端上的機器學習推理,具備低延遲和小二進制模型大小。android

TensorFlow Lite使用了許多技術,例如容許更小和更快(定點數學)模型的量化內核。ios

        對於本節,您須要從源代碼構建TensorFlow以得到對SSD模型的TensorFlow Lite支持。您還須要安裝bazel構建工具。c++

(好像我之前博客有教程,不過網上的編譯仍是可能有各類問題,解決問題也算是base skill吧,多動手!)git

爲了使這些命令更容易運行,讓咱們設置一些環境變量:(設置環境變量,而不把一些變量直接寫在代碼裏面也是安全和規範的方式)github

  export CONFIG_FILE=PATH_TO_BE_CONFIGURED/pipeline.config  # pipeline.config 是使用tensorflow models object detection api中要配置的
  export CHECKPOINT_PATH=PATH_TO_BE_CONFIGURED/model.ckpt # 訓練後保存的模型文件。(我比較奇怪的是,這在pipeline.config中不是有的嗎,可能還得繼續日後看才知道。) export OUTPUT_DIR=/tmp/tflite # 輸出的文件

這裏的pipeline.config 咱們選擇:ssdlite_mobilenet_v2_coco.config (其實,下載model zoom裏面ssdlite_mobilenet_v2_coco 有pipeline.config,我後面也用這個)
這裏的model.ckpt咱們從model zoom裏面(就不用本身的模型啦)選擇和pipeline對應的:ssdlite_mobilenet_v2_coco http://download.tensorflow.org/models/object_detection/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz
model zoom :https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md
output 就默認吧。

        咱們從一個檢查點開始,得到一個TensorFlow凍結圖,其中包含咱們能夠與TensorFlow Lite一塊兒使用的兼容操做。windows

        首先,您須要安裝這些python庫。而後,要獲取凍結圖,請使用如下命令從models / research目錄運行export_tflite_ssd_graph.py腳本(爲此我還紅專門從源代碼編譯安裝將tensorflow 1.3升級1.9):api

 object_detection/export_tflite_ssd_graph.py \
    --pipeline_config_path=$CONFIG_FILE \
    --trained_checkpoint_prefix=$CHECKPOINT_PATH \ --output_directory=$OUTPUT_DIR \ --add_postprocessing_op=true

在/tmp/tflite目錄中,咱們如今應該看到兩個文件:tflite_graph.pb(18.5MB)和tflite_graph.pbtxt(53.1MB)。請注意,
add_postprocessing標誌使模型可以利用自定義優化的檢測後處理操做,該操做能夠被視爲替換tf.image.non_max_suppression。
確保不要將在同一目錄中的export_tflite_ssd_graph與export_inference_graph混淆。兩個腳本都輸出凍結的圖形:export_tflite_ssd_graph將
輸出咱們能夠直接輸入到TensorFlow Lite的凍結(frozen)圖形,而且是咱們將要使用的圖形。
接下來,咱們將經過使用TensorFlow Lite優化轉換器TOCO來得到TensorFlow Lite優化模型。這將經過如下命令將生成的凍結圖形(tflite_graph.pb)轉換爲TensorFlow Lite  flatbuffer format(detect.tflite)。
對於量化模型,請從tensorflow /目錄(就是源碼編譯的那個目錄)運行(注意要使用bazel-0.12或以上的編譯,我以前就是沒有source ~/.bashrc 致使一直用的是bazel-0.5.4報錯了。能夠用bazel version看版本。):
bazel run --config=opt tensorflow/contrib/lite/toco:toco -- \
--input_file=$OUTPUT_DIR/tflite_graph.pb \
--output_file=$OUTPUT_DIR/detect.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=QUANTIZED_UINT8 \ --mean_values=128 \ --std_values=128 \ --change_concat_input_ranges=false \ --allow_custom_ops


而後就進入漫長的編譯等待(通常是第一次編譯耗時,後面再運行就不會了)。其實,tensorflow也是根據須要的操做opeater進行編譯的

INFO: Build completed successfully, 3249 total actions
2018-07-28 19:41:25.155435: I tensorflow/contrib/lite/toco/import_tensorflow.cc:1366] Converting unsupported operation: TFLite_Detection_PostProcess
2018-07-28 19:41:25.165617: I tensorflow/contrib/lite/toco/graph_transformations/graph_transformations.cc:39] Before Removing unused ops: 1070 operators, 1570 arrays (0 quantized)
2018-07-28 19:41:25.194800: I tensorflow/contrib/lite/toco/graph_transformations/graph_transformations.cc:39] Before general graph transformations: 1070 operators, 1570 arrays (0 quantized)
2018-07-28 19:41:25.224629: I tensorflow/contrib/lite/toco/graph_transformations/graph_transformations.cc:39] After general graph transformations pass 1: 116 operators, 310 arrays (1 quantized)
2018-07-28 19:41:25.226254: I tensorflow/contrib/lite/toco/graph_transformations/graph_transformations.cc:39] Before pre-quantization graph transformations: 116 operators, 310 arrays (1 quantized)
2018-07-28 19:41:25.227209: F tensorflow/contrib/lite/toco/tooling_util.cc:1589] Array FeatureExtractor/MobilenetV2/Conv/Relu6, which is an input to the DepthwiseConv operator producing the output array FeatureExtractor/MobilenetV2/expanded_conv/depthwise/Relu6, is lacking min/max data, which is necessary for quantization. Either target a non-quantized output format, or change the input graph to contain min/max information, or pass --default_ranges_min= and --default_ranges_max= if you do not care about the accuracy of results.
Aborted (core dumped)

此命令設置每一個攝像機圖像幀調整爲300x300像素後,並輸入張量normalized_input_image_tensor。量化模型的輸出被命名 'TFLite_Detection_PostProcess', 'TFLite_Detection_PostProcess:1', 'TFLite_Detection_PostProcess:2', and 'TFLite_Detection_PostProcess:3' 並表示四個數組:detection_boxes,detection_classes,detection_scores和num_detections。此命令中使用的其餘標誌的文檔在此處:https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/lite/toco/g3doc/cmdline_reference.md。若是成功運行,您如今應該在/tmp/tflite目錄中看到第三個文件名爲detect.tflite(而後,發現是 0 bytes,什麼狀況??,不過unint8不行,下面float是能夠的)。此文件包含圖形和全部模型參數,能夠經過Android設備上的TensorFlow Lite解釋程序運行。對於浮點模型,請從tensorflow /目錄運行:

bazel run --config=opt tensorflow/contrib/lite/toco:toco -- \
--input_file=$OUTPUT_DIR/tflite_graph.pb \
--output_file=$OUTPUT_DIR/detect.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

而後輸出的detect.tflite (18MB)


在Android上運行咱們的模型
要在設備上運行咱們的TensorFlow Lite模型,咱們須要安裝Android NDK和SDK。目前推薦的Android NDK版本爲14b,能夠在NDK Archives頁面上找到(https://developer.android.com/ndk/downloads/older_releases.html#ndk-14b-downloads)。
Android SDK和構建工具能夠單獨下載,也能夠做爲Android Studio的一部分使用。要構建TensorFlow Lite Android演示,構建工具須要API> = 23(但它將在API> = 21的設備上運行)。其餘詳細信息可在TensorFlow Lite Android App頁面上找到。
接下來,咱們須要將應用程序指向新的detect.tflite文件,併爲其指定新標籤的名稱。具體來講,咱們將使用如下命令將TensorFlow Lite  flatbuffer 複製到app 資源目錄:

cp /tmp/tflite/detect.tflite tensorflow/contrib/lite/java/demo/app/src/main/assets/
(官網上面是:cp /tmp/tflite/detect.tflite \
//tensorflow/contrib/lite/examples/android/app/src/main/assets )

咱們還須要將新的labelmap labels_list.txt複製到assets目錄,這裏就直接用已經有的labels_mobilenet_quant_v1_224.txt。
咱們如今將編輯BUILD文件以指向這個新模型。首先,打開BUILD文件tensorflow/contrib/lite/examples/android/BUILD。而後找到assets部分,
並替換該行,「@tflite_mobilenet_ssd_quant//detect.tflite」(默認狀況下指向COCO預訓練模型帶有新TFLite模型的路徑「tensorflow/contrib/lite/examples/android/assets/detect.tflite」。
最後,更改assets部分以使用新的標籤映射(這個我沒改哈)。
咱們還須要告訴咱們的應用程序使用新的標籤映射。爲此,在文本編輯器中打開
tensorflow/contrib/lite/examples/android/src/org/tensorflow/demo/DetectorActivity.java文件,找到TF_OD_API_LABELS_FILE的定義。
更新此路徑以指向新的標籤映射文件:「file///android_asset/labels_list.txt」。(沒有就不用改這個操做,我沒改)
請注意,若是量化了模型,則標誌TF_OD_API_IS_QUANTIZED設置爲true,若是模型是浮點,則標誌TF_OD_API_IS_QUANTIZED設置爲false(沒有找到這個flag,估計是後面改掉了)。
如今,對於量化模型,DetectorActivity.java的這一新部分應以下所示:
  private static final boolean TF_OD_API_IS_QUANTIZED = true;(沒有找到,就不處理) private static final String TF_OD_API_MODEL_FILE = "detect.tflite"; private static final String TF_OD_API_LABELS_FILE = "file:///android_asset/labels_list.txt";(這個我保留原樣"file:///android_asset/coco_labels_list.txt")
複製TensorFlow Lite文件並編輯BUILD和DetectorActivity.java文件後,您能夠構建演示應用程序,從tensorflow目錄運行此bazel命令:


 bazel build -c opt --config=android_arm{,64} --cxxopt='--std=c++11' "//tensorflow/contrib/lite/examples/android:tflite_demo"
而後報錯了:
bazel build -c opt --config=android_arm{,64} --cxxopt='--std=c++11' "//tensorflow/contrib/lite/examples/android:tflite_demo"
WARNING: The following configs were expanded more than once: [android, cross_compile]. For repeatable flags, repeats are counted twice and may lead to unexpected behavior.
WARNING: option '--crosstool_top' was expanded to from both option '--config=cuda' (source /home/lyz/code/tensorflow/.tf_configure.bazelrc) and option '--config=android_arm' (source command line options)
WARNING: option '--cpu' was expanded to from both option '--config=android_arm' (source command line options) and option '--config=android_arm64' (source command line options)
WARNING: option '--fat_apk_cpu' was expanded to from both option '--config=android_arm' (source command line options) and option '--config=android_arm64' (source command line options)
ERROR: No default_toolchain found for cpu 'arm64-v8a'. Valid cpus are: [
  k8,
  local,
  armeabi-v7a,
  x64_windows,
  x64_windows_msvc,
  x64_windows_msys,
  s390x,
  ios_x86_64,
]
將命令修改成(android知識不太懂,可是個人手機能夠armeabi-v7a):

bazel build -c opt --config=armeabi-v7a --cxxopt='--std=c++11' "//tensorflow/contrib/lite/examples/android:tflite_demo"
仍是報錯:
~/code/tensorflow$ bazel build -c opt --config=armeabi-v7a --cxxopt='--std=c++11' "//tensorflow/contrib/lite/examples/android:tflite_demo"
INFO: Options provided by the client:
  Inherited 'common' options: --isatty=1 --terminal_columns=102
INFO: Reading rc options for 'build' from /home/lyz/code/tensorflow/tools/bazel.rc:
  'build' options: --distinct_host_configuration=false --define framework_shared_object=true --define=use_fast_cpp_protos=true \
--define=allow_oversize_protos=true --define=grpc_no_ares=true --spawn_strategy=standalone --genrule_strategy=standalone -c opt
INFO: Reading rc options for 'build' from /etc/bazel.bazelrc:
  'build' options: --action_env=PATH --action_env=LD_LIBRARY_PATH --action_env=TMPDIR --test_env=PATH --test_env=LD_LIBRARY_PATH
INFO: Reading rc options for 'build' from /home/lyz/code/tensorflow/.tf_configure.bazelrc:
  'build' options: --action_env PYTHON_BIN_PATH=/usr/bin/python --action_env PYTHON_LIB_PATH=/usr/lib/python2.7/dist-packages --
python_path=/usr/bin/python \
--define with_jemalloc=true --define with_gcp_support=true --action_env TF_NEED_OPENCL_SYCL=0 --action_env TF_NEED_CUDA=1 \
--action_env CUDA_TOOLKIT_PATH=/usr/local/cuda-8.0 --action_env TF_CUDA_VERSION=8.0 --action_env CUDNN_INSTALL_PATH=/usr/local/cuda-8.0 \
--action_env TF_CUDNN_VERSION=6 --action_env TF_NCCL_VERSION=1 --action_env TF_CUDA_COMPUTE_CAPABILITIES=5.2,5.2 \
--action_env LD_LIBRARY_PATH=:/usr/local/cuda/lib64 --action_env TF_CUDA_CLANG=0 --action_env GCC_HOST_COMPILER_PATH=/usr/bin/gcc \
--config=cuda --define grpc_no_ares=true --strip=always
INFO: Found applicable config definition build:cuda in file /home/lyz/code/tensorflow/tools/bazel.rc: --crosstool_top=@local_config_cuda//crosstool:toolchain 、
--define=using_cuda=true --define=using_cuda_nvcc=true
ERROR: Config value armeabi-v7a is not defined in any .rc file

如今經過(其實還沒成功...)Android Debug Bridge(adb)在支持調試的Android手機上安裝演示:
   adb install bazel-bin/tensorflow/contrib/lite/examples/android/tflite_demo.apk
-------------------------------------------------------------------------------------------------------------------這裏暫時hold住
上面就是https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/running_on_mobile_tensorflowlite.md 的內容了,可是仍是報錯,就說明缺乏了一些配置。
由於報錯信息是:ERROR: Config value armeabi-v7a is not defined in any .rc file,回到以前tensorflow lite的介紹,並找到Android Demo App:https://www.tensorflow.org/mobile/tflite/demo_android?hl=zh-cn

Android演示應用
GitHub上提供了使用TensorFLow Lite的示例Android應用程序(https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/lite/java/demo)。該演示是一個示例相機應用程序,
使用量化的Mobilenet模型或浮點Inception-v3模型連續分類圖像。要運行演示,須要運行Android 5.0(API 21)或更高版本的設備。
在演示應用程序中,使用TensorFlow Lite Java API進行推理。該演示應用程序實時對幀進行分類,顯示最可能的分類。它還顯示檢測對象所用的時間。將演示應用程序添加到您的設備有三種方法:
一、下載預編譯好的二進制APK。(http://download.tensorflow.org/deps/tflite/TfLiteCameraDemo.apk?hl=zh-cn)
二、使用Android Studio構建應用程序。
三、下載TensorFlow Lite的源代碼和演示,並使用bazel構建它。


下載預先構建的二進制文件:嘗試演示的最簡單方法是下載預先構建的二進制APK。安裝APK後,單擊應用程序圖標以啓動該程序。第一次打開應用程序時,它會要求運行時權限以訪問設備相機。演示應用程序打開設備的後置攝像頭,識別攝像機視野中的物體。
在圖像的底部(若是設備處於橫向模式,則位於圖像的左側),它顯示分類的前三個對象和分類延遲。

使用JCenter的TensorFlow Lite AAR在Android Studio中構建:使用Android Studio嘗試更改項目代碼並編譯演示應用程序:
× 安裝最新版本的Android Studio。
× 確保Android SDK版本大於26且NDK版本大於14(在Android Studio設置中)。
× 將tensorflow/contrib/lite/java/demo目錄導入爲新的Android Studio項目。
× 安裝它請求的全部Gradle擴展。

如今您能夠構建並運行演示應用程序。構建過程下載量化的Mobilenet TensorFlow Lite模型,並將其解壓縮到assets目錄:tensorflow/contrib/lite/java/demo/app/src/main/assets/。
TF Lite Android App頁面上提供了一些其餘詳細信息(https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/lite/java/demo/README.md)。




報錯信息爲:

ERROR: /home/xxxx/code/tensorflow/third_party/clang_toolchain/cc_configure_clang.bzl:3:1: file '@bazel_tools//tools/cpp:cc_configure.bzl' does not contain symbol 'cc_autoconf_impl'
ERROR: error loading package '': Extension file 'third_party/clang_toolchain/cc_configure_clang.bzl' has errors
ERROR: error loading package '': Extension file 'third_party/clang_toolchain/cc_configure_clang.bzl' has errors

解決方案是:這是bazel版本的問題,參考這個:https://github.com/tensorflow/serving/issues/851,裝過bazel 版本便可.


通過最後測試,是代碼的問題,代碼升級到最新,按照官網是能夠的,接下來就是模型調整,壓縮設計的問題了,能夠開啓落地之路啦
相關文章
相關標籤/搜索