#はじめに
これは,OpenCV Advent Calendar 2016 8日目の記事です.関連記事は目次にまとめられています.また,OpenCV Advent Calendar 2015の22日目のdandelion1124さんの記事iOS向けopencv2.framework生成方法 with opencv_contribと合わせて見ると良いかもしれません.
さて,本記事は,タイトルにもあるようにOpenCV3.1系で実装されたDNNモジュールをiOS上で利用する方法,特に,DNNモジュールをiOSで使うためのOpenCVのフレームワーク化,また,その実効速度などのパフォーマンスについて,簡単にまとめた内容になっています.詳しい使い方までは言及しませんので,使用方法などの詳細は以下の記事が参考になります.
※上記2つの記事は2015年に書かれたもので最新のOpenCV3.1系のGithub上にあるコードとは若干異なるのに注意してください.
#手順1. DNNモジュールを含んだiOS用OpenCVフレームワークの生成法
##opencv本体とopencv_contribを用意する
まず,次のOpenCV本体とDNNモジュールなどが含まれているopencv_contribリポジトリ(いずれも必ずmaster branch)をgit cloneしてきます.
git clone https://github.com/opencv/opencv
git clone https://github.com/opencv/opencv_contrib
ここで注意して欲しいのが,git cloneする際は必ずmaster branchのを使うようにしてください.DNNモジュールは3.1系から実装されたモジュールなのですが,以下の図にあるようにmaster以外の,例えば,Tagsから3.1.0のbranchのものを使ってフレームワークを生成する際に以下のエラーに出くわすと思います.
Undefined symbols for architecture arm64:
"_png_init_filter_functions_neon", referenced from:
_png_read_filter_row in opencv2(pngrutil.o) ld:
symbol(s) not found for architecture arm64 clang: error:
linker command failed with exit code 1 (use -v to see invocation)
このエラーは,~/opencv-master/platforms/ios/build_framework.pyに以下の違いがあるからです.
if arch.startswith("armv"):
cmakecmd.append("-DENABLE_NEON=ON")
if arch.startswith("armv") or arch.startswith("arm64"):
cmakecmd.append("-DENABLE_NEON=ON")
もちろん,master以外のbranchにあるものを使って上記の訂正をすれば良いのですが,面倒なので,masterのを使うようにしましょう.
##手順2. OpenCV DNNモジュールを含んだフレームワークの生成
OpenCVの標準モジュールのみをiOSで利用したい場合,簡単なのはhttp://opencv.org/downloads.htmlから下図の赤線で囲まれているもの(2.4系なら↑,3.1系なら↓)をダウンロードして,Xcodeにドラッグアンドドロップするだけで使えるようになります.
ただ,標準モジュールには残念ながらDNNモジュールは含まれていないので,自分でビルドする必要があるわけです.DNNモジュールを含んだフレームワークの生成は簡単で,~/opencv_contrib-master/modules/dnn/CMakeLists.txtの上から1~10行までの部分を以下のように書き換えます.デフォルトの状態だとDNNモジュールを含まない設定になっているので,DNNモジュールを含んでビルドできるように書き換えます.
cmake_minimum_required(VERSION 2.8)
if(APPLE_FRAMEWORK OR WINRT
OR AARCH64 # protobuf doesn't know this platform
)
ocv_module_disable(dnn)
endif()
set(the_description "Deep neural network module. It allows to load models from different frameworks and to make forward pass")
set(OPENCV_MODULE_IS_PART_OF_WORLD OFF)
cmake_minimum_required(VERSION 2.8)
set(the_description "Deep neural network module. It allows to load models from different frameworks and to make forward pass")
set(OPENCV_MODULE_IS_PART_OF_WORLD OFF)
ここまで終わったら,後は,
python ~/opencv-master/platforms/ios/build_framework.py --contrib=~/opencv_contrib-master ios
とすれば,iosディレクトリにopencv2.frameworkが生成されて一件落着です!
##補足1: 実機でのビルドエラー対処
下のようなエラーが出た場合の対処法です.
Error: Unspecified error (Can't create layer "conv1/7x7_s2" of
type "Convolution") in cv::dnn::LayerData::getLayerInstance,
file E:/opencv_contrib-3.1.0/modules/dnn/src/dnn.cpp, line 122
上の,~/opencv_contrib-3.1.0/modules/dnn/src/dnn.cpp, line 122にある通り,master branch以外を使ってフレームワークを生成した場合に出るエラーの1つです.master branchを使えばこのエラーがでなくなっているようです.上のエラーの解決は簡単で**cv::dnn::initModule();**を追加すればOKです.
int main(int argc, char **argv)
{
String modelTxt = "bvlc_googlenet.prototxt";
String modelBin = "bvlc_googlenet.caffemodel";
String imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg";
int main(int argc, char **argv)
{
cv::dnn::initModule(); //Required if OpenCV is built as static libs
String modelTxt = "bvlc_googlenet.prototxt";
String modelBin = "bvlc_googlenet.caffemodel";
String imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg";
##補足2: deploy.prototxtの修正
OpenCV DNNモジュールでdeploy.prototxtを使うには以下のように書き換える必要があるので注意が必要です.
name: "GoogleNet"
layer {
name: "data"
type: "Input"
top: "data"
input_param { shape: { dim: 10 dim: 3 dim: 224 dim: 224 } }
}
name: "GoogleNet"
input: "data"
input_dim: 10
input_dim: 3
input_dim: 224
input_dim: 224
#OpenCV DNN moduleの実行速度の比較
詳細については画像ラボ(日本工業出版)(何月号かは追って追記します)に掲載予定なので,雑誌をお手にとっていただけると幸いです.ここでは,13th Annual International Conference on Mobile and Ubiquitous Systems: Computing, Networking and Services(MOBIQUITOUS)のWorkshopで発表したスライドの一部をSlideShareにアップしましたので,そちらと雑誌で補完頂ければと思います.
#おわりに
いつもお世話になってるQiitaに何か貢献を!ということで,今回の記事を書いてみましたが,初投稿ということもあり(言い訳),支離滅裂感も否めません...
でもでも,また,何かOpenCVで面白いDNN系の実装があったら,取り上げてみたいのと,Advent Calendarはとても良い企画だと思っているので,機会があったらまた参加してみたいです!
私事ですが,DeepLearning Advent Calendar 2016 8日目にも参加しているので,見て頂ければ幸いです.本記事同様,モバイル上でのDeepLearningについて自身の研究(画像認識)を踏まえて書いています.
また,Chainer Advent Calendar 2016 23日目にも参加していて,ここでは,モバイル上でのStyle変換のお話.Chainerで学習したモデルをiOSで利用したアプリについて自身の研究(スタイル変換)や各企業の動向を踏まえて書くつもりです.
またまた,今年読んだ一番好きな論文2016 Advent Calendar 2016 23日目にも参加していて,2016年に読んだ論文の中で、自分の中で一番インパクトのあった、面白かった論文を紹介する系のAdvent Calendarなのですが,記事を投稿すると,なんと!豪華な商品があたるチャンスがあるそうなので,参加してみました.笑 12/15以降はすべて埋まっているみたいですが,それ以外はまだ空きがあるそうなので,ぜひぜひ,参加して豪華賞品を掴みましょう!
(※大学院生限定なのでそこは注意してください!ただ,それ以外は縛りはなく,どの分野どんな論文でも良いみたいなので,気軽に参加できます.注意事項は本リンク先を御覧ください.)
#謝辞
今回,OpenCV Advent Calendarのお誘いをしていただいたdandelion1124さんにこの場を借りてお礼申し上げます.
#参考