| |
| 原著者 | Anastasia Murzova |
| 互換性 | OpenCV >= 4.5 |
目標
このチュートリアルでは、以下の方法を学ぶ:
- TensorFlow (TF) 検出モデルのフリーズ済みグラフを取得する
- 変換したTensorFlowモデルをOpenCVのPython APIで実行する
上記の各項目を SSD MobileNetV1 の例を通して探求していく。
はじめに
OpenCV API を用いた TensorFlow モデルの移行パイプラインに関わる主要な概念を簡単に見ていこう。TensorFlow モデルを cv.dnn.Net に変換する最初のステップは、フリーズ済みの TF モデルグラフを取得することである。フリーズ済みグラフは、モデルのグラフ構造と、必要な変数(例えば重み)の保持された値を組み合わせて定義する。フリーズ済みグラフは protobuf (.pb) ファイルに保存される。OpenCV には .pb グラフを読み込むための専用関数がある。cv.dnn.readNetFromTensorflow と cv.dnn.readNet である。
必要要件
以下のコードを試せるようにするには、一連のライブラリをインストールする必要がある。ここではpython3.7+の仮想環境を使う。
virtualenv -p /usr/bin/python3.7 <env_dir_path>
source <env_dir_path>/bin/activate
OpenCV-Pythonをソースからビルドする場合は、OpenCV入門 の該当する手順に従うこと。
ライブラリのインストールを始める前に、requirements.txt をカスタマイズし、一部の依存関係を除外したり(たとえば opencv-python を)含めたりできる。以下の行は、先に有効化した仮想環境への要件のインストールを開始する。
pip install -r requirements.txt
実践
この章では、以下の点を扱う。
- TF分類モデルの変換パイプラインを作成し、推論を提供する
- 推論を行い、予測結果を処理する
モデルの準備
この節のコードは samples/dnn/dnn_model_runner モジュールにあり、以下の行で実行できる。
python -m dnn_model_runner.dnn_conversion.tf.detection.py_to_py_ssd_mobilenet
以下のコードには TF SSD MobileNetV1 モデルを取得するステップが含まれている。
tf_model_name = 'ssd_mobilenet_v1_coco_2017_11_17'
graph_extraction_dir = "./"
frozen_graph_path = extract_tf_frozen_graph(tf_model_name, graph_extraction_dir)
print("Frozen graph path for {}: {}".format(tf_model_name, frozen_graph_path))
extract_tf_frozen_graph 関数では、モデルアーカイブに含まれる frozen_inference_graph.pb を抽出し、その後の処理に用いる。
tf_model_tar = model_name + '.tar.gz'
model_link = DETECTION_MODELS_URL + tf_model_tar
tf_frozen_graph_name = 'frozen_inference_graph'
try:
urllib.request.urlretrieve(model_link, tf_model_tar)
except Exception:
print("TF {} was not retrieved: {}".format(model_name, model_link))
return
print("TF {} was retrieved.".format(model_name))
tf_model_tar = tarfile.open(tf_model_tar)
frozen_graph_path = ""
for model_tar_elem in tf_model_tar.getmembers():
if tf_frozen_graph_name in os.path.basename(model_tar_elem.name):
tf_model_tar.extract(model_tar_elem, extracted_model_path)
frozen_graph_path = os.path.join(extracted_model_path, model_tar_elem.name)
break
tf_model_tar.close()
上記のコードを正常に実行すると、以下の出力が得られる。
TF ssd_mobilenet_v1_coco_2017_11_17 was retrieved.
Frozen graph path for ssd_mobilenet_v1_coco_2017_11_17: ./ssd_mobilenet_v1_coco_2017_11_17/frozen_inference_graph.pb
モデルの推論を行うため、以下の 二階建てバスの写真(Pexels ライセンス)を使用する。
Double-decker bus
テストプロセスを開始するには、適切なモデル構成を与える必要がある。ここでは TensorFlow Object Detection API の ssd_mobilenet_v1_coco.config を使用する。TensorFlow Object Detection API フレームワークには、物体検出モデルを操作するための便利な仕組みが含まれている。
この構成を用いてテキストグラフ表現を生成する。.pbtxt を生成するために、対応する samples/dnn/tf_text_graph_ssd.py スクリプトを使用する。
python tf_text_graph_ssd.py --input ssd_mobilenet_v1_coco_2017_11_17/frozen_inference_graph.pb --config ssd_mobilenet_v1_coco_2017_11_17/ssd_mobilenet_v1_coco.config --output ssd_mobilenet_v1_coco_2017_11_17.pbtxt
正常に実行されると ssd_mobilenet_v1_coco_2017_11_17.pbtxt が作成される。
object_detection.py を実行する前に、SSD MobileNetV1 のテストプロセス構成のデフォルト値を見ておこう。これらは models.yml にある。
ssd_tf:
model: "ssd_mobilenet_v1_coco_2017_11_17.pb"
config: "ssd_mobilenet_v1_coco_2017_11_17.pbtxt"
mean: [0, 0, 0]
scale: 1.0
width: 300
height: 300
rgb: true
classes: "object_detection_classes_coco.txt"
sample: "object_detection"
これらの値を取得するには、フリーズ済みグラフ ssd_mobilenet_v1_coco_2017_11_17.pb モデルとテキストグラフ ssd_mobilenet_v1_coco_2017_11_17.pbtxt を与える必要がある。
python object_detection.py ssd_tf --input ../data/pexels_double_decker_bus.jpg
この行は次と等価である。
python object_detection.py --model ssd_mobilenet_v1_coco_2017_11_17.pb --config ssd_mobilenet_v1_coco_2017_11_17.pbtxt --input ../data/pexels_double_decker_bus.jpg --width 300 --height 300 --classes ../data/dnn/object_detection_classes_coco.txt
結果は次の通りである。
OpenCV SSD bus result
結果を補正するためにカスタマイズできる便利な引数がいくつかある。しきい値 (--thr) と非最大抑制 (--nms) の値である。