Tech Sketch Bucket of Technical Chips by TIS Inc.

OpenCVによる画像認識アプリケーション with Google Glass(3)

Pocket

前回はGoogleGlassで画像認識を行うアプリケーションの基本的な実装を行いましたが、実行速度が低速であるという結果に終わりました。第三回はその部分のチューニングを行った内容を書きたいと思います。

画像認識のパフォーマンスチューニング

本投稿では特に影響の大きかった以下の3点について説明します。

① 画像サイズの影響

② ORB検出器のパラメーター調整

③ ガウシアンぼかしによる認識精度の向上

検証環境について

MacBook Air(Core i7, RAM 8GB)上でXCodeを使用し、C++で記述したコードをデスクトップアプリとして動かして検証しています。Google Glassに比べてかなりハイスペックな環境ですが、Androidのログからパフォーマンスのボトルネックとなっている部分がC++のコード内の特徴検出と特徴抽出の部分であることが事前の検証で分かりました(事前の検証内容の詳細は割愛します)。そのため、デスクトップアプリで処理の改善が見られればそれに相関する形でグラスアプリでの処理が改善すると考え、デスクトップ上での検証で問題なしと判断しました。また、Google Glassの開発環境ではコードを書いてから実行するまでに時間がかかり効率的に検証のサイクルが回せないことも大きな理由でした。

画像サイズの影響

画像の大きさは、画像処理において非常に大きな影響のあるパラメーターです。プログラム内で画像は解像度(1920 x 1080など)に相当するマトリックス(行列)として処理されます。ORBのアルゴリズムにおいては、全てのピクセルに対して特徴となりうるかを走査し、検出器で決められた個数だけ特徴として検出するという処理を行います。画像を検出するためには画像サイズが小さいほど速く処理できるのですが、画像が小さすぎると対象が潰れてしまってうまく検出できないという問題が発生します。そのため、画像サイズのパラメーターの調整は非常に重要なファクターとなります。

ここでは以下のメソッドを用いて特徴検出を行う前に画像のリサイズを行っています。第三引数のdsizeで画像サイズを直接指定するか、第四引数と第五引数のfxとfyで横方向・縦方向の倍率を指定することでリサイズできます。

void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR )

画像サイズが実行速度に与える影響の計測

Google Glassのカメラで撮影した画像(Rawサイズは3264 × 2448)をリサイズして特徴検出と処理時間を計測した結果が下のグラフになります。左の縦軸が処理時間(ms)、右が抽出できた特徴数になります。検出できる特徴の数は検出器のパラメーターで500個までと設定しているため、大きい画像でも500個しか特徴が検出されていないという結果になっています。棒グラフは左から元画像に対して0.5倍、0.3倍、0.2倍、0.1倍、0.08倍に相当するサイズです。実際に計測してみるとリサイズによる効果は想像よりもかなり大きいと感じました。

ocv_withglass_performancetest_imagesize

解像度326x224の画像から特徴検出した結果

ocv_withglass_performancetest_imagesize01

右図で○がついている部分が検出された特徴点です。認識対象の画像がある複数の部分に○が集まっていることがわかります。ORBのアルゴリズムでは単純にコーナーを検出するため認識対象の物体でなくても特徴として検出されてしまいますが、マッチングにより対象以外の特徴は除去することができます。また、認識対象のサイズや分かりやすさによって変化しますが、特徴の検出の様子から今回のケースでは326x224程度の解像度でも認識可能だと判断します。

ORB検出器パラメーターの調整

画像ピラミッド

ここではパラメーターの変更により実行速度の面で効果が見られた画像ピラミッドについて説明します。画像ピラミッドとは、複数の解像度の画像の集合のことです。画像認識分野では、サイズの変化や回転により認識できないという状況を回避するために様々なアルゴリズムが考えられています。画像ピラミッドを利用した場合、内部的に複数のスケールに対して処理を行うことで、サイズに変化に強いアルゴリズムになると言われています。下の画像のような画像ピラミッドを考えた場合、オリジナルのサイズから1/2倍、1/4倍、1/8倍まで画像を処理するという意味になります。

ocv_withglass_imagepyrm_messi

引用元:OpenCV 3.0.0-dev documentation - Image Pyramids

ORB検出器における画像ピラミッドパラメーターの影響

まずはORB検出器のコンストラクタについて説明したいと思います。

ORB::ORB(int nfeatures=500, float scaleFactor=1.2f, int nlevels=8, int edgeThreshold=31, int firstLevel=0, int WTA_K=2, int scoreType=ORB::HARRIS_SCORE, int patchSize=31)

それぞれの引数の意味は次のとおりです。

nfeatures抽出する特徴の数。
scalefactor, nlevels 画像ピラミッドの倍率と段数にあたる。
edgeThreshold特徴として認識するための領域のサイズを指定する。
WTA_K特徴量記述をどのように行うかを指定する。具体的には特徴量記述時に使用する特徴点の数を指定し、デフォルトの"2"の場合は2つの特徴点のペアから特徴量を記述する。
scoreType特徴点のランキングのために使用されるアルゴリズム。
patchSize特徴記述時の画像パッチのサイズを設定する。

表の2行目の画像ピラミッドの倍率と段数とは、scalefactorのnlevels冪乗の倍率の画像までのピラミッドを考えるという意味になります。例えば、scalefactor=1.2、nlevels=4であれば、1/1、1/(1.2)^1、1/(1.2)^2、1/(1.2)^3、1/(1.2)^4までの倍率の画像を含む画像ピラミッドを計算対象とすることを意味します。そして下のグラフは、画像ピラミッドのパラメーターを変更した場合の影響を調べたものです。横軸の上段はscalefactor、下段はnlevelsのパラメーターを表しています。

ocv_withglass_performancetest_imagepyramid

グラフを見て分かる通り、画像ピラミッドのパラメーターを変更することで実行速度において一定の効果が見られました。画像ピラミッドがどういうものであるか考えればわかりますが、これは処理する画像のピクセル数を減らすことから得られる効果です。また、画像ピラミッド内の各画像間でサイズの開きが大きくなったことからスケール変化に対して少し認識能力が弱くなってしまいます。そのため、このような調整する場合は、求める機能レベルと実効速度のバランスを取る必要があると思います。

ガウシアンぼかしによる認識精度の向上

ここまで行った検証内容を元にGoogle Glass上でアプリを実行したところ、実行速度の向上は確認された一方で、認識精度が著しく低下し、認識対象を検知することができなくなっていました。リサイズにより画像が粗くなってしまったためだと考えられます。

画像処理の分野では、一般に画像をぼかす(平滑化する)ことでノイズを低減する効果が期待できることが知られています。そこでガウス関数を利用したぼかしを用いることにより認識の精度の変化を検証しました。OpenCVにおいてはガウシアンぼかしを利用するためのメソッドが実装されています。実際にぼかしに使ったメソッドは以下のようなものです。

void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )

画像に対してガウシアンぼかしを施してORB検出器にかけたところ、特徴検出に変化が見られました。左がぼかしなしで特徴抽出した写真、右はガウス関数でぼかして特徴検出した写真です。ぼかしを行うことでノイズが低減され、画像の中でもより特徴らしい部分が特徴点として検出されることが確認できました。

ocv_withglass_notblurred ocv_withglass_blurred

検証とチューニングの結果

アプリケーションの実行結果

以上の検証結果を踏まえて変更したソースコードが以下になります。前回記事に記載したJava_com_orb_CameraActivity_detectImageメソッド内に画像の前処理の追加とORBコンストラクタのパラメーターに変更を行います。

画像の前処理

前処理として、解像度386x216まで画像を圧縮し、5x5のカーネルサイズでガウシアンフィルタをかけました。

特徴量計算処理

ORB特徴量抽出器の画像ピラミッドのパラメーターを変更しています。

実行結果

平均すると8fps程度の速度で動くアプリケーションとなり、体感的なストレスはかなり軽減されました。ただし、スケールの変化に弱くなったという印象はあります。

ocv_withglass_orb_prtsc_cp

まとめ

3回にわたってGoogle Glassで動く特定物体認識アプリケーションの開発について説明しました。ウェアラブルもOpenCVもホットでこれからどんどん伸びてくる面白い分野だと思うのでこれからも注目していきたいですね。

エンジニア採用中!私たちと一緒に働いてみませんか?