この記事はOpenCV Advent Calendar 2023の16日目の記事です。
はじめに
https://github.com/opencv/opencv/pull/21066でdnnモジュール(Inference Engine backend)のONNXモデル読み込みがサポートされるようになりました。この記事ではこの機能について紹介していきます。
OpenVINOにおけるモデル読み込み
OpenCVのdnnモジュールの話に入る前にOpenVINOにおけるモデル読み込みについて確認していきます。https://docs.openvino.ai/2021.4/openvino_docs_IE_DG_ONNX_Support.html?sw_type=switcher-pythonによると
Starting with the 2020.4 release, OpenVINO™ supports reading native ONNX models. The
IECore.read_network()
method provides a uniform way to read models from IR or ONNX format, it is a recommended approach to reading models.
とあり、OpenVINO 2020.4
の時点でONNXモデルの読み込みに対応していることがわかります。さらにOpenVINO Workflow(https://docs.openvino.ai/2023.2/openvino_workflow.html)を見ていきましょう。
※上図はhttps://docs.openvino.ai/2023.2/openvino_workflow.htmlより引用
着目すべき点は以下の通りです。
- TensorFlow、ONNX、PaddlePaddleなどのモデル:
convert_model()
もしくはread_model()
で読み込まれる - OpenVINO IR:
read_model()
で読み込まれる
この図からもわかるようにOpenVINOはOpenVINO IRだけでなく、その他のDNNフレームワークのモデルもサポートしていることがわかります。
従来のInference Engine backend
ここまでの説明から、OpenVINO自体はONNXモデルも読み込めることがわかりました。それでは本題のOpenCV dnnモジュールについて確認していきます。
従来のdnnモジュール(Inference Engine backend)は、cv2.dnn.readNetFromModelOptimizer の
- [in] xml XML configuration file with network's topology.
- [in] bin Binary file with trained weights.
にあるように、OpenVINO IRを読み込むことが前提となっていました。そのため、手元にONNXモデルがあってもModel Preparation — OpenVINO™ documentationにある手順でOpenVINO IRに変換する作業が必要になってきます。普段、OpenVINOを使わない人からするとこの変換作業が煩雑に感じてしまうかもしれません。
現行のInference Engine backend
https://github.com/opencv/opencv/pull/21066がマージされたので、dnnモジュール(Inference Engine backend)でONNXモデル読み込みがサポートされるようになりました。そのため、ONNXモデルがあれば、わざわざOpenVINO IRに変換せずともInference Engineの恩恵を受けられるようになりました。
効果検証
それではONNXモデルを入力とし、以下の2つのbackendを用いてinference時間を計測していきます。
- cv2.dnn.DNN_BACKEND_OPENCV
- cv2.dnn.DNN_BACKEND_INFERENCE_ENGINE
計測環境
計測環境は下表の通りです。
名称 | スペック、バージョン |
---|---|
CPU | Intel Core i7-9800X CPU @ 3.80GHz |
メモリ | 32GB |
OS | Ubuntu 22.04 |
Python | 3.10.12 |
opencv-python | 4.8.1.78 |
openvino | 2023.2.0 |
今回、環境構築を簡略化するためにhttps://hub.docker.com/r/openvino/ubuntu22_devにあるopenvino/ubuntu22_dev:2023.2.0
を用いました。
docker run -it --device /dev/dri:/dev/dri --rm openvino/ubuntu22_dev:2023.2.0 bash
ソースコード
今回、@UnaNancyOwenさんのhttps://qiita.com/UnaNancyOwen/items/650d79c88a58a3cc30ceにあるYOLOXのinferenceコードをベースにすることにします。具体的なinferenceコードはhttps://gist.github.com/UnaNancyOwen/802b724b46977115d94332b5971775b4を参照ください。
ここでは下記の変更前後でinference時間がどのようになるかを見ていきます。
- self.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
+ self.setPreferableBackend(cv2.dnn.DNN_BACKEND_INFERENCE_ENGINE)
計測結果
計測結果は以下の通りです。たった1行の変更でそれなりに高速化が図れるのは嬉しいですね。
backend | inference time(ms) |
---|---|
cv2.dnn.DNN_BACKEND_OPENCV | 134.383 |
cv2.dnn.DNN_BACKEND_INFERENCE_ENGINE | 89.332 |
出力結果
お馴染みの画像ですがhttps://github.com/pjreddie/darknet/blob/master/data/dog.jpgを入力にしたinferenceの結果は以下の通りです。
おわりに
本記事では、dnnモジュール(Inference Engine backend)でサポートされたONNXモデル読み込みについて紹介しました。OpenCVをIntel CPUで動かす場合にはぜひ使ってみてください。