OpenCV For Unityを使ってiPhone上でYOLOを動かす
はじめに
OpenCV for Unityには色々なサンプルが入っており、その中にYOLOを使ったものがあります。
YOLOとは画像認識のアルゴリズムで、比較的処理が高速なことが知られています。
OpenCV for Unityに含まれているYOLOのデモは以下の2つで、WebGLでのデモページからも試すことが出来ます。
- YoloObjectDetectionExample
- 画像を使ったYOLOのデモ
- YoloObjectDetectionWebCamTextureExample
- Webカメラを使ったYOLOのデモ
また、このデモをiPhone XSで動かした動画が以下になります。
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">iPhoneでYOLOです <a href="https://t.co/zrqRHj4mpE">pic.twitter.com/zrqRHj4mpE</a></p>— Nakaji Kohki (@kohki_nakaji) <a href="https://twitter.com/kohki_nakaji/status/1055786287209168896?ref_src=twsrc^tfw">2018年10月26日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
OpenCV for UnityはiOSを始めとして様々なプラットフォームに対応したアセットなのですが、2018/10/26現在の環境で動かすためにはいくつかの手順が必要でしたので、記しておきたいと思います。
手順
予めOpenCV for Unityをプロジェクトにインポートしておきます。
YOLOを使うためには、まずモデルデータをインポートする必要があります。ライセンスの関係でOpenCVForUnityのパッケージ自体には入っていないので、別途リポジトリからダウンロードしてきます。
必要なファイル以下の3つです。
- https://github.com/pjreddie/darknet/tree/master/data/coco.names
- https://github.com/pjreddie/darknet/blob/master/cfg/yolov3-tiny.cfg
- https://pjreddie.com/media/files/yolov3-tiny.weights
-
https://github.com/pjreddie/darknet/blob/master/data/person.jpg
- (YoloObjectDetectionExampleのみ必要)
これを、Assets/StreamingAssets/dnn以下に置いておく必要があります。
OpenCVForUnityの直下にあるStreamingAssetsに雛形があるので、フォルダ毎Assets直下に移動させると良いと思います。
ちなみにですが、StreamingAssets/dnn以下にあるドキュメントではcoco.namesの記述が抜けているのと、実行時のファイル参照エラーメッセージでは指定されているyoloのバージョンが異なっていました。罠っぽい…。
ここまでやると、エディタ上で実行ができる状態になります。
OpenCVForUnity/Examples/MainModules/dnn/YoloExample以下にあるシーンを再生してみてください。
<img width="587" alt="スクリーンショット 2018-10-26 21.25.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/55365/41d0e489-b4fa-65e3-2f2e-b8ac7d435143.png">
画像: YoloObjectDetectionExample.unityを再生した例
iPhoneで再生するためにはもう一つ手順が必要です。
iOSで実行した場合Utils.csのstring getFilePath (string filepath, bool refresh = false)という関数内にあるFile.Exists (destPath)がtrueを返してくれない事象を確認しました。そのため、モデルデータを読み込めず、正常に実行されません。
対処としては、ファイルの存在チェックを行わずにpathを返すようにすれば良いです。
if (File.Exists (destPath)) {
return destPath;
} else {
return String.Empty;
}
return destPath;
この状態でビルドすれば冒頭の動画のように実行出来ると思います。
Discussion