深層学習、いわゆるディープラーニングを使用した画像処理が脚光を浴び始めてから結構経った気がします。
私は大学で画像関係の研究をしていましたが、当時勉強したSIFTとかHOGといった特徴量ベースの物体検出・認識はすっかり過去のものという雰囲気を感じて少し寂しい気もしています。
さて、ディープラーニングのプログラミング言語といえばPython!というのも、また広く知れ渡っている事実だと思います。
私自身、現在も画像関係の仕事をしているため、「そろそろPython環境をきっちり構築して真面目にディープラーニングの勉強に取り組もうかな」と思い続けているのですが、長らくWindows、C言語(C++)、VisualStudio、OpenCVという環境で遊んできたので、ついつい「新しい言語は面倒だなぁ」と感じて諸事情により職場にはインターネット接続できるパソコンがないため、Pythonだと環境構築が非常に困難かつ面倒なので二の足を踏んでいる状態です。
しかしながら、ディープラーニングを使うことで、使わないときとは比較にならないくらいお手軽かつ高精度に処理できるものが多々あることはわかりきっています。
そこで、ひとまずPythonのことは置いといて、ディープラーニングを利用することで受ける恩恵がどんなものかを知るために、学習済みモデルを使って物体検出プログラムを動かしてみようと思います。
OpenCVでは、dnnというモジュール内の機能を使うことでディープラーニングによる学習済みモデルを使った処理を実現でき、公式ドキュメントを見るとCaffe、TensorFlow、Torch、Darknet、DLDT、ONNXに対応していることがわかります。
OpenCV: Deep Neural Network module
後ほど登場するOpenCVのサンプルではYOLOという物体検出アルゴリズムを使用し、Darknetというフレームワークの学習モデル形式を使っていますので、ここでも同様にします。
私の開発環境は以下のとおりです。
- OS:Windows 11 Pro
- CPU:Intel Core i9-10920X 3.50 GHz
- RAM:64.0 GB (CFD W4U26666CX1-16GB x4)
- G/B:Geforce RTX 3060 (ASUS ROG-STRIX-RTX3060-O12G-GAMING)
- IDE:Visual Studio 2022 Professional
IDEですが、私の場合はオフラインでも使えるようにと有償版のProfessionalを利用していますが、オンライン環境下であれば無料版であるCommunityを使用しても問題ありません。
そして、開発言語ですが、もちろんPythonは使わずC++です。
OpenCVのバージョンは4.6.0(本記事の投稿時点では最新)で、公式サイトのLibrary -> Releases -> Windowsとリンクを辿ってダウンロードできるexe形式のものではなく、Gitから追加モジュールであるcontribを含めてダウンロードし、CMakeでビルドしたものを利用しています。
少し古い(2017年9月21日)ですが、contribについては以下の記事でわかりやすく紹介してくれていますし、記事中で紹介されているリンクを辿ってOpenCVのExampleを見てるだけでも結構楽しいのでおすすめです。
物体検出プログラムのコードはOpenCVのサンプルをほぼそのまま使います。
OpenCV: samples/dnn/object_detection.cpp
「ほぼ」そのままと言っていますが、そのままだと動かないとかではなく、個人的に使いにくいと感じたところを自分好みに書き換えただけで、変更点は以下の4点だけです。
- 検出結果が人物のものだけを描画(たくさん枠が描画されると邪魔)
- コマンドライン引数の一部(modelPathとconfigPath)をコード内で定義
- namdeWindowのオプション(WINDOW_NORMAL -> WINDOW_AUTOSIZE)
- 処理結果映像をVideoWriterで書き出し
あと必要となるものは、処理対象映像ファイルを除くと学習済みモデル関係です。
上のリンク先を見るとコマンドライン引数が以下のように書かれています。
$ example_dnn_object_detection --config=[PATH-TO-DARKNET]/cfg/yolo.cfg --model=[PATH-TO-DARKNET]/yolo.weights --classes=object_detection_classes_pascal_voc.txt --width=416 --height=416 --scale=0.00392 --input=[PATH-TO-IMAGE-OR-VIDEO-FILE] --rgb
つまり「yolo.cfg」、「yolo.weights」、「object_detection_classes_pascal_voc.txt」が必要になりますが、これらをどこから取ってきたらいいのかを調べるのに実は一番時間がかかりました。
今回は最新版であるYOLO v7を試してみたいと思いますので、以下のリンクから取得し、適当にファイル名を合わせました。
- yolo.cfg:https://github.com/AlexeyAB/darknet/blob/master/cfg/yolov7.cfg
- yolo.weights:https://github.com/WongKinYiu/yolov7/releases
- object_detection_classes_pascal_voc.txt:https://github.com/pjreddie/darknet/blob/master/data/coco.names
適切な場所に用意したファイルを配置し、先ほどのコマンドを参考に実行すれば難なく動くかと思います。
下の映像は、NHKクリエイティブ・ライブラリーで公開されている素材に対して物体検出を動かしてみた結果です。
閾値0.5のままですが、なかなかいい感じに検出できています。
Haar-Like特徴量やHOG特徴量等を使って人検出していたころは、サンプルコードと一緒に公開されている画像・映像以外で動かしてみるとイマイチな結果になることが多かったのですが、適当に選んだ映像でこれだけ精度良く検出できるのは素晴らしいですね。