おぺんcv

画像処理エンジニアのブログ

OpenCVのサンプルコードでEnetを動かしてみた

はじめに

OpenCVのサンプルコードを使って、Enet(Semantic Segmentationのモデル)を試してみました

f:id:mizunashi:20181210195823p:plain

Enetとは

[1]で提案されている、Semantic Segmentationのネットワークです
リアルタイム向けに設計されており、SegNet等の従来のネットワークよりも演算量やパラメータ数が少なく、高速なのが特徴です
既に色々なフレームワークで実装されていますが、OpenCVではバージョン3.3から、dnnモジュールが追加されたのに伴い、 Enetの学習済みモデルとサンプルコードが提供されたようです

[1] ENet: A Deep Neural Network Architecture for Real-Time Semantic Segmentation

ビルド

BUILD_EXAMPLES=ONを指定してOpenCVをビルドすれば使用することができます
opencv/samples/dnnからsegmentation.cppとcommon.hppをもってきて自前でビルドするも良し

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

opencv_extra/testdata/dnn/download_models.pyを叩くとダウンロードできます
ただしそのまま叩くとdnnサンプルに含まれるすべてのモデルがダウンロードされるので、Enetだけ欲しい場合はスクリプトを修正すると良いでしょう
ちなみに、Cityscapes Dataset+Torchで学習したもののようです

実行

実行コマンドの例を示します

./example_dnn_segmentation enet --input=input.avi --zoo=models.yml --model=Enet-model-best.net --classes=enet-classes.txt --colors=colors.txt --target=1

以下、オプションと設定時の動作について解説します

  • enet

    • モデル名を指定します
    • モデル名に対応する設定をmodels.ymlから読み取ります
  • input=input.avi

    • 入力ファイルを指定します
    • cv::VideoCaptureを使用しており、--input=image_%03d.pngのように連番画像の指定も可能です(cv::VideoCaptureが連番対応してることを書いてて知った!)
  • --zoo=models.yml

    • models.ymlのパスを指定します
    • サンプルコードと同じopencv/samples/dnnにあります
    • 指定しない場合はカレントディレクトリのmodels.ymlを探します
  • --model=Enet-model-best.net

    • 学習済みモデルのパスを指定します
    • 指定しない場合は以下の環境変数からEnet-model-best.netを探します
      • OPENCV_DNN_TEST_DATA_PATH
      • OPENCV_TEST_DATA_PATH
  • --classes=enet-classes.txt

    • 分類クラスの定義ファイルを指定します
    • opencv/samples/data/dnn/enet-classes.txtから入手可能です
    • 指定しなくても動きますが、指定すると以下のようにクラス名と色付けの対応を表示してくれます

f:id:mizunashi:20181210094517p:plain
legend

  • --colors=colors.txt
    • 各クラスの色付けを指定します
    • 指定しない場合はランダムで色付けされます
    • TimoSaemann/ENetのものと同じ色設定を作成したのでよかったらお使い下さい
0 0 0
128 64 128
244 35 232
70 70 70
102 102 156
190 153 153
153 153 153
250 170 30
220 220 0
107 142 35
152 251 152
70 130 180
220 20 60
255 0 0
0 0 142
0 0 70
0 60 100
0 80 100
0 0 230
119 11 32
  • --target=1
    • 実行するデバイスを指定します
    • デフォルト値は0で、ターゲットはCPUです
    • --target=1ではOpenCLが使用されるので、GPUを積んでる人はこちらを指定したほうが高速に実行できると思います
    • ※2020/1/25追記:公開当時はNVIDIA GPUには対応してませんでした…対応後にNVIDIA GPUで計測した結果はこちら

結果

KITTIデータセットで実行した結果を動画にしました
上半分がネットワークへの入力解像度512x256の結果、下半分が1024x256の結果です
1024x256の方が若干精度が良いように見えます

処理時間は入力解像度512x256の場合、--target=0(CPU)で約80[msec]、--target=1(OpenCL)で約20[msec]でした…速い!
1024x256にするとOpenCLで2倍の約40[msec]かかりましたが、それでも十分速い印象です

おわりに

OpenCVでEnetを動かしてみました
趣味で作りたいプログラムにSemantic Segmentation(特に車載向け)を使うものがあり、以前からEnetには注目してたのですが、慣れ親しんだOpenCVで使えるようになって感激です!