54
57

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【初心者向け】Tensorflow Object Detection API を使ってみた

Last updated at Posted at 2019-11-09

はじめに

RHEMS技研のIchiLabです。

今回はTensorFlowのObject Detection APIを使って、
自分が認識してほしい物体を検出させ、
最終的にAndroid端末でそれを試すというところまでやってみました。

多くの参考になるサイトは自分のためになりましたが、
それでも私は1つ2つだけのページだけでは解決できない点がとても多かったです。

本記事では、私が大なり小なりつまづいた部分をピックアップしながら記載しますので、
同じような苦労をする方が少しでも減ることがあれば幸いです。

追記:Cloud TPUを使用する場合の記事も書きました(2020/6/19~)
【TPUを使いたい人向け】Tensorflow Object Detection API を使ってみた 2

追記2:TensorFlow2.0で学習させる工程も追記しました。(2020/9/30~)
TF1については本記事では執筆時点のソースコードで説明したものになりますので、参考にする場合は説明に記載しているブランチでお試し下さい。

TensorFlow 1.15をTF1、TensorFlow 2.3.1をTF2として以下に記載していきます。

環境

TF1

TensorFlow 1.15

MacBook Pro
OS : Catalina 10.15
CPU : Intel Core i7 3.5GHz
Memory : 16GB 2133MHz

TF2

TensorFlow 2.3.1

Google Colabratory (GPU)

環境構築

基本的には下記の公式に書いてあるとおりです。

TF1

Object Detection API with TensorFlow 1

TF1については下記ブランチのソースコードをもとに記載しております。
(2019/11/9 本記事を執筆した時期に合わせております)

$ git clone -b tf_2_1_reference https://github.com/tensorflow/models.git

PYTHONPATHを設定するところでは、pwdで説明されていますが、省略せず記述すると以下のとおりです。
tensorflowではなくtfがルートディレクトリであるコンテナも存在しますので要確認)

$ export PYTHONPATH=$PYTHONPATH:/tensorflow/models/research:/tensorflow/models/research/slim

TF2

ローカル環境でももちろん構築は可能ですが、ここでは誰でも無料で高性能のGPUが使えてかつ環境構築が容易なColab環境で実施していくことにします。

Object Detection API with TensorFlow 2

Google Colabratoryでの環境構築

Colabでは初めにランタイムの設定をします。
「ランタイム」「ランタイムのタイプを変更」→ハードウェア アクセラレータを「GPU」にします。

TF2では最新のソースをcolabの環境に持ってきます。


import os
import pathlib

if "models" in pathlib.Path.cwd().parts:
  while "models" in pathlib.Path.cwd().parts:
    os.chdir('..')
elif not pathlib.Path('models').exists():
  !git clone --depth 1 https://github.com/tensorflow/models

インストールします。

%%bash
cd models/research/
protoc object_detection/protos/*.proto --python_out=.
cp object_detection/packages/tf2/setup.py .
python -m pip install .

今回は教師データやモデルの保存場所をGoogle Driveにしたいので、Colabからgdriveを読めるように設定します。

from google.colab import drive
drive.mount('/content/drive')

環境構築する上での注意点(TF2対応前にあった注意点)

(※本項目は当時TF2対応前のソースで起こった問題です。現在はTF1とTF2が共存され解決されています。)

もしDockerを使用してコンテナ内で動かす場合は、下記の公式ページの通り色々種類がありますが、
もしlatest(最新版)を使用する場合は注意が必要です。

Tensorflow - Docker

なぜなら、執筆時点の2019年11月現在ではObject Detection APIは
TF2には対応していない
からです。
(2020/7/10より対応されました)

参考:TensorFlow 2 meets the Object Detection API

pipコマンドでのインストール時も同様、TensorFlowのバージョン確認は必須です。
確認したい場合は、以下のようにコマンドを打つと良いでしょう。

$ pip list | grep tensor
tensorboard                        1.15.0     
tensorflow                         1.15.0rc3  
tensorflow-estimator               1.15.1 

もしバージョンをTF2からTF1に変更したい場合は、以下のコマンドを実行しましょう。
(今回の例では1.15に変更)

$ pip install tensorflow==1.15.0rc3

ちなみに、このバージョンの違いは結構重要なので補足しますが、
TensorFlowの公式では一応バージョンが2.0でも自動変換してくれるスクリプトを用意してくれています。
ただし、except for contrib(contribを除く)と記載されています。

Migrate your TensorFlow 1 code to TensorFlow 2

もしTensorFlow2.0でObject Detection APIのmodel_builder_test.pyを実行すると、
次のようになり失敗します。

AttributeError: module 'tensorflow' has no attribute 'contrib'

contribでエラーに引っかかっていますね。
つまり自動変換のスクリプトは今のところ使えないということです。

さて、無事model_builder_test.pyは実行してうまくOKと表示されましたでしょうか?
model_builder_test.pyは、models/researchディレクトリで以下を実行します。

TF1

$ python object_detection/builders/model_builder_test.py

(最新ソースは以下の名前に変更されている)
$ python object_detection/builders/model_builder_tf1_test.py

成功すると、以下のようにOKと表示されます。(長いので一部省略してます)

Running tests under Python 3.6.8: /usr/local/bin/python
[ RUN      ] ModelBuilderTest.test_create_faster_rcnn_model_from_config_with_example_miner  
...    

[ RUN      ] ModelBuilderTest.test_unknown_ssd_feature_extractor
[       OK ] ModelBuilderTest.test_unknown_ssd_feature_extractor
----------------------------------------------------------------------
Ran 16 tests in 0.313s

TF2

!python /content/models/research/object_detection/builders/model_builder_tf2_test.py

成功すると、以下のようにOKと表示されます。

Running tests under Python 3.6.9: /usr/bin/python3
[ RUN      ] ModelBuilderTF2Test.test_create_center_net_model
...   
[       OK ] ModelBuilderTF2Test.test_unknown_ssd_feature_extractor
----------------------------------------------------------------------
Ran 20 tests in 46.313s

OK (skipped=1)

環境構築は以上です。

教師データの準備

自分が認識してほしい物体を検出させるには、教師データを作成します。
教師データを作るためには、たくさんの検出させたい画像を用意しなければなりません。

もし自力で集めるのが大変な場合は、google-images-downloadという便利なツールも存在するので、
興味のある方はぜひ調べて使ってみて下さい。

さて、教師データの説明です。
教師データは、TensorFlow推奨のTFRecord形式として用意します。
TFRecordは、バイナリレコードのシリーズを保存するための単純な形で、
データがシリアライズ化(配列データとして保存)されて連続的に読み込めるようになっています。
TFRecord形式のデータを作るためには、大まかに2通りの方法があります。

  1. アノテーションツールを使用する
  2. ソースから自分で作る

アノテーションとは、いわゆるタグ付けです。
写真や動画を表示しながら、「この部分がこれだよ」と教えていく作業です。
私はこのためにVoTTというMicrosoftから出ているツールを使用しました。
VoTT

VoTTの使用上の注意

  • Export SettingsではTensorflow Recordsを選択する
  • Asset StateではOnly visited Assets以外に設定する
  • Active Learning(帽子のようなマーク)は押すとせっかくつけたタグ付けが消えることがあるので、あまり使用をおすすめしない
  • 1枚の画像に大量のタグ付けをすると処理が重くなるので、その場合は何枚かに切り取って分けたほうが良い

このように、色々と使いにくい点が目立つツールではありますが、
TFRecord形式に変換する面倒がなくなりますので、その点ではおすすめです。

ソースから自分で作る場合

TensorFlowで用意されているライブラリで、画像からTFRecord形式のファイルを生成することは可能です。
しかし、以下の公式チュートリアルで生成されるTFRecordと、
VoTTで生成されるTFRecordは若干要素名が異なり、一緒に混ぜて学習させることはできませんでした。
TFRecords と tf.Example の使用法

こちらのドキュメントの方が役立つでしょう。
using_your_own_dataset.md

この辺の話は、長くなるので別記事で私がまとめみましたので、宜しければご覧ください。
物体検出のためのTFRecordファイル作成備忘録

学習

ここからの説明について、ディレクトリは全てmodels/researchを基準にすることを前提として記載しています。

TFRecord形式のファイルが準備出来たら、いよいよ学習の開始です。
ここでは「転移学習」と呼ばれる、既存の学習モデルをもとに自分のオリジナルを学習させて、
よりカスタマイズされた学習モデルを作るという手法で進めていきます。
転移学習は、大規模なデータで事前に学習した重みを用いることで、
少量の訓練データでも十分な性能を得られることが期待されます。

学習モデルのダウンロード

まず、転移学習のための学習済みモデルをダウンロードします。

学習済みモデルは、以下のページからダウンロードできます。
なお、これらはTF1とTF2でモデルの構造が違いますので、バージョンの違うmodelで学習に使用することは出来ません。ご注意を。

TensorFlow 1 Detection Model Zoo

TensorFlow 2 Detection Model Zoo

TF1

今回はMobileNet v3を使って進めていきましょう。
この中で、ssd_mobilenet_v3_large_cocoというものをダウンロードします。

ダウンロードしたモデルは、object_detectionディレクトリに配置しましょう。
コマンドで実行するなら、以下のようにします。

$ wget http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v3_large_coco_2020_01_14.tar.gz
$ tar zxvf ssd_mobilenet_v3_large_coco_2020_01_14.tar.gz

TF2

今回はEfficientDet D1を試してみました。
本モデルはまだtfliteへの変換には対応していないそうなので、注意が必要です。

学習モデルのファイル構成

学習モデルのファイル構成は、基本的に以下のようになっています。

MobileNet v3
-checkpoint

  • frozen_inference_graph.pb
  • model.ckpt.data-00000-of-00001
  • model.ckpt.index
  • model.ckpt.meta
  • pipeline.config
  • saved_model /
    • saved_model.pb
    • variables /

EfficientDet D1

  • checkpoint /
    • checkpoint
    • ckpt-0.data-00000-of-00001
    • ckpt-0.index
  • pipeline.config
  • saved_model /
    • assets /
    • saved_model.pb
    • variables /
      • variables.data-00000-of-00001
      • variables.index

転移学習を始める際は、この中のpipeline.configというファイルの中身を編集して使用します。

トレーニングと評価のためのディレクトリ構造とファイル名

ここでは用意したTFRecordファイルのディレクトリについて説明します。
TFRecordファイルは、訓練(教師)用と検証用にディレクトリを分けます。
一般的に、比率は訓練:検証が8:2、つまり訓練用をデータの80%、残りの20%を検証用に分けるとされています。
(書籍「scikit-learnとTensorFlowによる実践機械学習」 P30より)
もちろん、きちんとその割合で分けていなくても一応学習は可能です。
以下、ディレクトリ構造です。(trainはtraining, valはvalidationの略)

  • test0001 /
    • label_map (.pbtxt) ラベルファイル
    • train /
      • TFRecord file(.tfrecord)訓練用ファイル
    • val /
      • TFRecord file(.tfrecord)検証用ファイル
    • save /
      • 学習したデータを保存するために用意したディレクトリ(最初は空でOK)

TFRecordファイル名は、バラバラではなく連番で統一させておきます。
例えば、ここでは次のように名付けておきます。

  • hoge0000.tfrecord
  • hoge0001.tfrecord
  • hoge0002.tfrecord
  • ...(以下同様に)

ここでのファイル名の付け方は、次のコンフィグファイルの設定に関連してきます。

コンフィグファイルの編集

先程ダウンロードしてきた学習済みモデルの中にある、pipeline.configを開きます。
ここではバッチサイズや重み付け、画像の拡張など様々なパラメータを調整することが出来ますが、よく編集するであろう項目の説明をしていきます。
(説明のために実際のconfigから抜粋しています)

pipeline.config
model {
    ssd {
        num_classes: 1

num_classes :
分類する数の設定です。
コンフィグファイルの比較的上部に書かれています。

pipeline.config
train_config: {
    batch_size: 32
    num_steps: 10000
    optimizer {
        momentum_optimizer: {
            learning_rate: {
                cosine_decay_learning_rate {
                    total_steps: 10000
                    warmup_steps: 10000
    fine_tune_checkpoint: "./object_detection/ssd_mobilenet_v3_large_coco/model.ckpt"
}

batch_size :
確率的勾配降下法を使う場合、異常値の影響を小さくするために、
データセットを幾つかのサブセットに分けて学習させます。
そのぞれぞれのサブセットに含まれるデータの数をバッチサイズと呼びます。
この値は機械学習の分野の慣習として2のn乗の値が使われることが多いです。
そして、この値は大きくするほど学習時に負荷がかかり、環境によってはプロセスが死んで学習してくれなくなることがあります。

num_steps :
学習を行うstep数です。
学習を実施する際のコマンドでもstep数は指定することができ、
私が試した限りではコマンドの指定が優先されます。

total_stepswarmup_steps :
他のモデルのconfigになかった項目なので調査中ですが、
total_stepsは、warmup_steps以上である必要があります。
(この条件に満たないとエラーが出て学習が始まりません)

fine_tune_checkpoint :
転移学習のモデルを指定します。
ダウンロードした学習モデルのあるディレクトリを「〜.ckpt」まで書けばOKです。
ssd_mobilenet_v3をダウンロードした時点ではこの項目が入っていませんでした。
そのため、私は自分で追加しました。
大抵のモデルには元からこの項目が存在します。
転移学習をしない場合はこの行は不要になります。

pipeline.config
train_input_reader: {
    tf_record_input_reader {
        input_path: "./object_detection/test0001/train/hoge????.tfrecord"
    }
    label_map_path: "./object_detection/test0001/tf_label_map.pbtxt"
}
eval_input_reader: {
    tf_record_input_reader {
        input_path: "./object_detection/test0001/val/hoge????.tfrecord"
    }
    label_map_path: "./object_detection/test0001/tf_label_map.pbtxt"
}

input_path :
用意した訓練用と検証用のTFRecordファイルのディレクトリを指定します。
例えば、今回の場合はhoge0000.tfrecordという連番で名付けたので、hoge????.tfrecordと書きます。

label_map_path :
用意したラベルを指定します。trainもevalも同じ指定で問題ありません。

学習開始

configファイルを書いたら、いよいよ学習の開始です。

TF1で学習

(※説明はtf_2_1_referenceのブランチのソースコードを元にしています。
現在でも私はこのソースでうまく動作を確認出来ていますので、執筆当時のままに残しておきます。)

学習には、object_detectionディレクトリにあるmodel_main.pyというファイルを使用します。
実行時の引数の説明です。

  • --model_dir
    学習データの保存先を指定します。
    指定したディレクトリには、「.ckpt~」というファイルが学習中に作られていきます。

  • --pipeline_config_path
    使用するconfigファイルを指定します。
    先程編集したコンフィグファイルを指定しましょう。

  • --num_train_steps
    学習回数を指定します。
    configで指定した数を実施するならこのオプションは不要ですが、
    もしconfigとは別の回数で学習させたい場合は、こちらで指定した回数が優先されます。(実際に試した結果)

以下、実行例です。

$ python object_detection/model_main.py \
--pipeline_config_path="object_detection/ssd_mobilenet_v3_large_coco/pipeline.config" \
--model_dir="./object_detection/test0001/save" \
--alsologtostderr

オプションが多くていちいち入力するのは面倒ですので、シェルスクリプトにしておくと、実行が楽になります。

#! /bin/bash

PIPELINE_CONFIG_PATH="./object_detection/ssd_mobilenet_v3_large_coco.config"
MODEL_DIR="./object_detection/test0001/save"
NUM_TRAIN_STEPS=10000

cd '/tensorflow/models/research'

python object_detection/model_main.py \
    --pipeline_config_path=$PIPELINE_CONFIG_PATH \
    --model_dir=$MODEL_DIR \
#    --num_train_steps=$NUM_TRAIN_STEPS \
    --alsologtostderr

「あれ、作ったシェルが実行できない…?」
という方はパーミッションの変更を忘れていませんか?

$ chmod 775 hoge.sh

学習開始するもプロセスが途中で死んでしまう場合

学習が始まったと思ったら、下記のように起こる場合があります。

~ session_manager.py:500] Running local_init_op.
~ session_manager.py:502] Done running local_init_op.
~  basic_session_run_hooks.py:606] Saving checkpoints for 0 into {チェックポイントを保存指定したディレクトリ/ファイル名}.ckpt
Killed

プロセスが死んでしまう理由はいくつかありますが、
いずれも動作環境のリソースが足りなくなって起こっている可能性が高いです。

ここでは、私がこの事象を経験した時に解決した手段を紹介します。

〜解決策その1.Docker Engineの設定を変更してみる〜

これはDockerコンテナ内で実施している場合に有効かもしれない手段です。
まず設定を開きます。
「Preferences」→「Advanced」タブを選択し、リソースを増やしてみましょう。

〜解決策その2.バッチサイズを小さくしてみる〜

これはpipeline.configの設定によって解決します。

どのようなパラメータの組み合わせでプロセスが死んでしまうかは、
動作環境や使用した教師データの量やサイズによって違うと思います。
まずはバッチサイズの値を小さくすることで解決できることがあるので、
ここで悩んだ人は試してみましょう。

学習データの確認

学習データは、model_main.pyを実行したときに指定した保存先のディレクトリに随時保存されていきます。
学習中に下記のようなSavingと表示されるタイミングでデータが保存されていきます。
この段階で、次で説明するTensorboardで学習中の状況が可視化できます。

INFO:tensorflow:Saving 'checkpoint_path' summary for global step 500: object_detection/test0001/save/model.ckpt-500
I1012 08:29:56.544728 139877141301056 estimator.py:2109] Saving 'checkpoint_path' summary for global step 500: object_detection/test0001/save/model.ckpt-500

TF2で学習

TF2ではColabを使用して学習する方法を記載します。

Colabでは、変数をフォーム入力で出来る機能がありますので、それを使用しました。

#@title params
pipeline = "/content/drive/My\\ Drive/tf2/pipeline.config" #@param {type:"string"}
save = "/content/drive/My\\ Drive/tf2/save/" #@param {type:"string"}
num_steps = 10000 #@param {type:"integer"}
last_model_path = "/content/drive/My\\ Drive/tf2/efficientdet_d1_coco17_tpu-32/checkpoint/ckpt-0" #@param {type:"string"}

!python /content/models/research/object_detection/model_main_tf2.py \
    --pipeline_config_path={pipeline} \
    --model_dir={save} \
    --alsologtostderr \
    --num_train_steps={num_steps} \
    --trained_checkpoint_dir={last_model_path}

学習には、object_detectionディレクトリにあるmodel_main_tf2.pyというファイルを使用します。
引数は基本的にTF1と同様です。

Tensorboard〜学習の可視化〜

学習データの可視化は必須であり、Tensorboardはそれにとても役立ちます。

Tensorboardの起動

tensorboardは以下のようなコマンドで起動できます。

$ tensorboard --logdir=object_detection/test0001/save
  • --logdir :
    学習開始時に指定した、学習データの保存先のディレクトリをここで指定します。
    過去に実施した学習結果の保存先を指定すれば、学習終了後でも再度見ることが可能です。

TensorboardをWebブラウザで確認するには、ローカルホストへアクセスします。
デフォルトではポート番号は6006です。

http://localhost:6006/

もしもDockerコンテナの環境で実行している場合は、docker runする時に-p 6006:6006とアクセスできるようにしておきましょう。
私はdocker-compose.ymlにポートの設定を記載しています。

ColabでのTensorboardの起動

ColabでもTensorBoardを使用することが出来ます。
ポートを意識しなくても良いので楽ですね。

%load_ext tensorboard
%tensorboard --logdir /content/drive/My\\ Drive/tf2/save

Tensorboardの見方

せっかく学習を可視化できても、見方がさっぱり分からないと辛いですよね。
私なりに調べた内容をまとめてみましたので、参考にして頂ければと思います。

GRAPHS

ソースコードの処理からグラフが自動生成されます。

項目 説明
Run ログが置かれているサブディレクトリを切り替えられる
Upload Tensorflowのモデルファイルをアップロード
Trace inputs ノードの依存関係を追いかけられる
Color 色分け方法を選ぶ
- Structure : モデル(ネットワーク)構成
- Device : 処理を行ったデバイス(CPU vs GPU)
- Compute time : 処理時間
- Memory : メモリ使用量
- TPU Compatibility : tensor processing unit上で実行

SCALARS

項目 説明
Show data download links グラフを保存できるリンクを表示させる。CSVかJSON形式を選択できる。
ignore outliners in chart scaling 外れ値を避けてグラフをスケーリングするかどうか(チェックを入れると避ける)
Tooltip sorting method ツールチップの並び順
- default : アルファベット順
- descending :値の大きい順
- ascending : 値の小さい順
- nearest : マウスカーソルに近い順
Smoothing グラフのスムージング
Horizontal Axis 折れ線グラフの横軸(X軸)の指定
- STEP : ステップ(実行回数)
- RELATIVE : 実行時間(初回からの差分)
- WALL : 時刻
- Runs : グラフの表示・非表示の切り替え

参考:TensorBoardによる学習の可視化
続いて、主要な各グラフについての説明です。
その前に、説明上知っておく必要がある単語の説明を記載しておきます。

  • IOU :
    IOUとは、Intersection(領域の共通部分) over Union(領域の和集合)の略で、2つの領域が「どれくらい重なっているか」を表す指標のことです。
    この値は1に近いほど教えた正解と推論が一致していることになります
  • Recall :
    再現率。見つけるべきもののうち、正しく見つけることができたものの割合。Sensitivity(敏感度)ともいう。

参考:IoU(評価指標)の意味と値の厳しさ
参考:【入門者向け】機械学習の分類問題評価指標解説(正解率・適合率・再現率など)

以下に、object_detection/metrics/coco_tools.pyに書いてある項目の説明を参考に抜粋します。

項目 説明
Precision/mAP 5刻みで5〜95の範囲のIOUしきい値を平均したクラスの平均精度。
Precision/mAP@.50IOU 50%IOUの平均精度
Precision/mAP@.75IOU 75%IOUの平均精度
Precision/mAP (small) 小さなオブジェクトの平均精度(32×32 px未満)
Precision/mAP (medium) 中サイズのオブジェクトの平均精度 (32×32 px〜96×96 px)
Precision/mAP (large) 大きなオブジェクトの平均精度 (96×96 px〜10000×10000 px)
Recall/AR@1 1回の検出で正しく見つけられた平均の割合
Recall/AR@10 10回の検出で正しく見つけられた平均の割合
Recall/AR@100 100回の検出で正しく見つけられた平均の割合
Recall/AR@100 (small) 100回検出されたsmallオブジェクトの平均再現率
Recall/AR@100 (medium) 100回検出されたmediumオブジェクトの平均再現率

IMAGES

画像データを表示します。
検証用データの正解と推論結果の差が、.ckptファイル(チェックポイント)単位で確認できます。

推論グラフへの変換

学習が終了したら、いよいよ推論グラフへデータを変換します。
具体的には、学習して作られた.ckptファイルを、.pbファイルへ変換します。

なお、変換するためのソースはobject_detectionディレクトリ内に複数用意されています。

  • export_inference_graph.py
  • export_tflite_ssd_graph.py

Androidで試すには、.tfliteという形式に変換しますので、後者の方を使用します。

export_inference_graph.pyの場合

実行時の引数の説明です。

  • --input_type :
    推論グラフには、ユーザーに応じて次の3つのいずれかを指定します

    • image_tensor :
      4次元テンソル [None, None, None, 3]
      通常これを指定すれば良いと思われます。
    • encoded_image_string_tensor : 1次元テンソル [None]
      エンコードされたPNGまたはJPEG画像を含む。
      複数の画像が提供される場合、画像の解像度は同一であることを想定します。
    • tf_example : 1次元文字列テンソル [None]
      シリアル化されたTFExample protosを含む複数の画像が提供される場合、画像の解像度は同一であることを想定します。
  • --pipeline_config_path :
    学習時に使用したconfigファイルを指定します。

  • --trained_checkpoint_prefix :
    学習データの保存先にできた「model.ckpt-XXXX」ファイルを指定します。
    XXXXには実施した学習Step数の1番最新(大きいもの)を指定します。
    例えば、10000回実施したなら「model.ckpt-10000」となります。

  • --output_directory :
    書き出したいディレクトリを指定します。
    指定したディレクトリには、最終的に初めのダウンロードしたモデルのファイル構成と全く同じ構成のファイルが出来上がります。

以下、実行例です。

$ python object_detection/export_inference_graph.py \
--input_type image_tensor \
--pipeline_config_path object_detection/ssd_mobilenet_v3_large_coco/pipeline.config \
--trained_checkpoint_prefix object_detection/test0001/save/model.ckpt-10000 \
--output_directory object_detection/test0001/output

export_tflite_ssd_graph.pyの場合

学習済みモデルを.tflite互換のモデルに変換するプログラムです。
引数は基本的にexport_inference_graph.pyと同様です。
--input_typeはありません)

以下、実行例です。

$ python object_detection/export_tflite_ssd_graph.py \
--pipeline_config_path=object_detection/ssd_mobilenet_v3_large_coco/pipeline.config \
--trained_checkpoint_prefix=object_detection/test0001/save/model.ckpt-10000 \
--output_directory=object_detection/test0001/tflite \
--add_postprocessing_op=true

--output_directoryで指定したディレクトリには、tflite_graph.pbtflite_graph.pbtxtの2つのファイルが出来ます。

exporter_main_v2.py.pyの場合(TF2)

TF2の場合はこちらのプログラムを使用します。
以下はColabでフォーム入力対応したものです。

#@title params
pipeline = "/content/drive/My\\ Drive/tf2/pipeline.config" #@param {type:"string"}
save = "/content/drive/My\\ Drive/tf2/save/" #@param {type:"string"}
export_dir = "/content/drive/My\\ Drive/tf2/export" #@param {type:"string"}

!python /content/models/research/object_detection/exporter_main_v2.py \
 --input_type encoded_image_string_tensor \
 --trained_checkpoint_dir {save} \
 --output_directory {export_dir} \
 --pipeline_config_path {pipeline}

TensorFlow Lite形式へ変換する

(※本項目はまだTF1版のみ記載しています。
TF2版はまだ試せていませんが、以下のリンクが公式の説明です)

Running TF2 Detection API Models on mobile

tflite形式へ変換するには、tflite_convertを使用します。
このコンバーターは元から入っているはずです。

tflite_convert --helpを打つと、usageが出てきてくれます。
追加するオプションが多いので、私は以下のようにシェルスクリプトでまとめました。
ディレクトリは自分に合わせて変更して下さい。
なお、--input_shapesはおそらく学習時のconfigのimage_resizerに合わせた値で良いと認識していますが、確証はありません…
数字の意味は、(バッチサイズ、入力画像の高さ、入力画像の幅、入力画像の深度(RGBチャンネル))となります。

Converter command line reference

#! /bin/bash

OUTPUT_FILE="object_detection/test0001/tflite/test.tflite"
GRAPH_DEF_FILE="object_detection/test0001/tflite/tflite_graph.pb"
INTERFACE_TYPE="FLOAT"
INPUT_ARRAY="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"

cd '/tensorflow/models/research'

tflite_convert \
    --output_file=$OUTPUT_FILE \
    --graph_def_file=$GRAPH_DEF_FILE \
    --inference_type=$INTERFACE_TYPE \
    --input_arrays=$INPUT_ARRAY \
    --input_shapes=$INPUT_SHAPES \
    --output_arrays=$OUTPUT_ARRAYS \
    --default_ranges_min=0 \
    --default_ranges_max=6 \
    --mean_values=128 \
    --std_dev_values=127 \
    --allow_custom_ops

なお、他のサイトで調べるとbazeltocoをインストールする説明を複数見つけましたが、それらをしなくてもこのコマンドラインだけで可能でした。
(正確にはそれらの方法も試しましたが、同じ結果でした)

なお、この時TensorFlowのバージョンが1.12.0rc0だと失敗しましたが、
1.15.0rc3にすると全く同じコマンドでうまくいきました

なお、公式ではPython APIを推奨する記述がされていました。
Converter command line reference

Androidで実際に動かしてみる

大変長くなりましたが、いよいよ本番です。

Android Studioのインストール

まずは「Android Studio」をインストールしておきましょう。
他のツールの方が使いやすい方はそちらでも構いません。

公式からサンプルをダウンロード

次に、公式からサンプル集をダウンロードしておきます。

$ git clone --depth 1 https://github.com/tensorflow/examples.git

サンプルの修正

Android Studioを起動したら、examples/lite/examples/object_detection/androidを開きます。

自分のtfliteファイルを入れる

examples/lite/examples/object_detection/android/app/src/main/assetsディレクトリに、自分のtest.tflitelabelmap.txtを配置します。
labelmap.txtは、自分でタグ付けしたタグ名が羅列されたテキストファイルです。

例えば、「apple」と「orange」という2種類のタグ名を用意したなら、次のようなテキストファイルになります。

labelmap.txt
???
apple
orange

重要なのは、1行目は???にすることです。

DetectorActivity.javaの編集

長いですが、examples/lite/examples/object_detection/android/app/src/main/java/org/tensorflow/lite/examples/detection/ディレクトリにあるDetectorActivity.javaを編集します。

DetectorActivity.java
private static final boolean TF_OD_API_IS_QUANTIZED = false; //true->false
private static final String TF_OD_API_MODEL_FILE = "test.tflite"; //detect.tflite -> my tflite
private static final String TF_OD_API_LABELS_FILE = "file:///android_asset/labelmap.txt"; //my txt

次に、examples/lite/examples/object_detection/android/app/ディレクトリにあるbuild.gradleを編集します。

40行目あたりにある以下をコメントアウトします。
(ここをコメントアウトしないと、ビルドした時にデフォルトのサンプルデータに置き換わってしまいます)

build.gradle
apply from:'download_model.gradle' //コメントアウトする

ビルドする

ここまで出来たらあとはビルドして端末で動かして見るだけです!
うまく試すことが出来たならおめでとうございます。

以下、Androidに関する参考サイト

Training and serving a realtime mobile object detector in 30 minutes with Cloud TPUs
How to Train Your Own Custom Model with Tensorflow Object Detection API and Deploy It into Android with TF Lite
Detecting Pikachu on Android using Tensorflow Object Detection

おわりに

いかがでしたでしょうか?
他のサイトのまとめページみたいに仕上がってしまいましたが、
少なくともTensorFlowのObject Detection APIを使用する上で必要そうな情報はかなり網羅出来たのではないかと思います。

特にTensorFlowはバージョンの違いで細かい挙動が異なり、
様々な参考サイトは当時使用しているバージョンがそれぞれ異なるので、同じ苦労をされた方も多いのではないかと思います。

まだまだ私自身も理解できていない部分が多いですが、少しでもお役に立てれば幸いです。
長文記事を読んで頂きありがとうございました。

54
57
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
54
57

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?