その後のその後

iOSエンジニア 堤 修一のブログ github.com/shu223

『OpenCV 3.0 on iOS』 #yidev 第19回勉強会

第19回 yidev(横浜iPhone開発者勉強会)にて、『OpenCV 3.0 on iOS』という発表をさせていただきました。


概要

OpenCV 3.0 の話、というよりは、最新版の3.0をベースとしつつ、「Core Image や vImage や GPUImage という便利で高速な画像処理ライブラリが存在する昨今においても OpenCV も依然として魅力的ですよ 」というのが発表の主題です。

なぜ今OpenCVか?

スライド内では、理由として以下の3つを提示しています。

圧倒的に機能が豊富

この点については、正直なところ Core Image、vImage、GPUImage は目じゃないかと。「2500以上のアルゴリズム・機能」と言われてもピンと来ないと思うので、具体的に「Core Image 等にはない OpenCV の機能」の一例をこの後のスライドで示しています。


Google のサポートもあり、コンピュータビジョン分野における最新の研究成果/アルゴリズムが日々 OpenCV に実装されていっています。

クロスプラットフォーム

iOS、Android、Linux、Mac OS X、Windows 等々をサポートしてます。


言語は C++ で、ちょうどゲームフレームワーク業界における Cocos2d-x を彷彿とさせられますが、ただ言語的に共用できます、というだけではなくて、iOSでは並列化処理としてGCDが用いられるようになっていたりと、ちゃんとそれぞれのプラットフォームにおける最適化も考慮されてたりもします。

今が熱い

2.0 が出たのが2009年で、そして今年 4/24 に 3.0.0 RC1 がリリースされたばかり。


6年ぶりのメジャーアップデートで、個人的には今が熱いと感じています。

OpenCVでできることの一例

スライドより一部抜粋します。繰り返しになりますが、下記に挙げたものは Core Image や vImage ではできない機能ばかりです。

顔「以外」のものを検出

同梱の学習ツールを使い、分類器自体を自作できるので、車・動物・ロゴ等々、任意の対象を検出可能です。



参考:「顔以外」のものを画像認識する on iOS - Qiita

顔を「認識」する

Core Image の CIDetector は顔の位置を「検出」するものであり、その顔が誰のものであるかという「認識」はできません。OpenCV では「Eigenfaces」「Fisherfaces」など複数の手法が実装されています。


文字の「検出」と「認識」

3.0.0 より、下記画像のように、画像内の文字の領域を検出する機能が入りました。



その内容を「認識」する機能も追加されていて、そちらについてはオープンソースのOCRエンジン「Tesseract」を利用する方式と、HMM方式の2種類が実装されています。

物体追跡

映像内の物体を追跡する手法は3.0.0以前にもいくつかあったようですが、3.0.0よりTrackerというクラスが追加されていて、その中の TLD(Tracking Learning Detection)というやつは紹介動画のインパクトがすごいです。



3:14あたりからのシーンを見ると、パンダが向きを変えてまったく見え方が変わっていっても、トラッキングがはずれていないことが見て取れます。右側には逐次学習している様子が表示されています。



さすがにこれがiOSでリアルタイムに動くかというと直感的には(処理性能的に)厳しそうな気がしますが、いずれ試してみたいと思っています。

High Dynamic Range Imaging (HDR)

下記画像のように、露出を変えて撮影した複数の写真を統合して、HDR写真を生成することができます。


画像修復・補間(Inpainting)

写真に意図せず写りこんでしまった物体等を取り除き、それによって欠損した領域を自動修復してくれる機能です。



この機能は実際にiOSで実装してみましたが、実質的には関数を1つ呼ぶだけの簡単実装で上記画像の効果を得られました。

cv::inpaint(srcMat, maskMat, dstMat, 3, cv::INPAINT_NS);


参考:http://d.hatena.ne.jp/shu223/20150512/1431341853

vImage との併用

下記のように cv::Mat から vImage_Buffer に変換することで、 OpenCV と vImage を併用することができます。

#import <Accelerate/Accelerate.h>

// ...

cv::Mat src, dst;

// ...

dst.create(cvRound(src.rows*0.75), cvRound(src.cols*0.75), src.type());

vImage_Buffer srcbuf = { src.data, src.rows, src.cols, src.step };
vImage_Buffer dstbuf = { dst.data, dst.rows, dst.cols, dst.step };

vImageScale_Planar8( &srcbuf, &dstbuf, NULL, kvImageNoFlags ); 


先ほどから vImage(Accelerate.framework)を比較対象のように書いてますが、やはり Apple 自身によって CPU にカリカリに最適化された vImage は処理性能の面で非常に魅力的です。この手法により、vImage にある拡大縮小や畳込み等の処理はそちらを使う、という選択肢がとれるようになります。

その他スライドに書いたこと

  • 導入方法について(CocoaPods)
  • Swift からの利用
  • パフォーマンスについて
    • GPUの利用
    • 並列化技術のサポート
    • NEON