Python
OpenCV
RaspberryPi
ARM
opencv-for-embedded

ARMでの組み込みのためのアプローチの資料

More than 1 year has passed since last update.

ARMでの組み込みのためのアプローチの資料[1]を見つけたので、
参考のためメモする。

その資料「OpenCV for Embedded: Lessons Learned」
は15ページの資料で簡潔にまとまっています。
6ページ目には、それらの手順が簡潔に書いてあります。

・Prototyping(x86)
・Porting
regression tests
・Profiling
performance tests
・Bottleneck optimization
・Fine Tuning
・Productization

それに対して、私の場合だとどのようであるのかをPythonの場合を参考まで記します。

・Prototyping(x86)
 OpenCV+Python+Numpy+matplotlib+scikit-learnなどを使う。
 画像認識の場合だと、解像度を変更する、面積縮小ではなくてリサンプリングに置き換えられるか、領域を削減できないかといった、アルゴリズムを知っているからこそできるアプローチをとる。
 Pythonの場合だと、試行錯誤をすることが簡単なので、初めて使うアルゴリズムでもデータ構造が理解しやすいのがうれしい点です。(すべてのオブジェクトをprintできること、全てのデータメンバーを参照できること、数値データをmatplotlibでMATLABと同様な豊富なグラフ描画関数を使ってチェックができます。)

 また、このプロトタイピング段階で、ソフトウェアの設計を見直して、メンテナンスしやすい構造に分離しておく。
Documentation commentを書いて、それぞれの関数、クラス、メソッドが何を実現するものかを、第三者がわかるようにしておく。

 もちろんこの段階からバージョン管理をしておきます。SVNを使って、localなHD上にレポジトリをおいて、自分自身のためにバージョン管理しておく。他のOSに移植することを想定して文字コードはunicodeにしておく。

・Porting
 Linux(ARM)に移行しても、
 OpenCV+Python+Numpy+matplotlib+scikit-learnなどを使う。
 これらのライブラリはapt-get install ライブラリ名
 として、移植することができる。

 RegressionTest

 テストはunitTestを使う。数値データの一致の度合いを比較するには、numpyに用意されているnumpy.testing.assert_almost_equal(actual, desired[, ...])などを使うのがよい。
 unitTestはCppUnitと同様の考え方でできているので、将来C++でのCppUnitへの移植も対応がつきやすい。

・Profiling

 PerformanceTest

 標準のライブラリの中にProfiling機能がある。
 これらのunitTestやperformanceをOSやCPUの種類によらず、共通のソースで行うことができます。

  
 
・Bottleneck optimization
  対象とするCPUがシングルコアか、複数コアかによって異なってくる。組み込みのCPUでも複数コアがあるので、[2]の資料を参考にRaspberryPi2などでの高速化をはかることができそうだ。ZynqなどのARM dual core+FPGAの構成でも、複数コアであることを利用した書き換えができるだろう。
 何が律速になっているかで、アプローチが異なってくる。

・Fine Tuning
Pythonの場合にはC++で記述されたpydファイルのモジュールの性能が効いてくる。
 pydファイルを作るときのbuildの条件が、対象のCPUに対して最適になっているかで
 性能が格段に違うことを理解している。
 私のレベルでは、まずはプロトタイピングの時点で、データの処理量を減らすことでの改良であって、C++で書かれたコード部分の最適化には達していない。
 ARMの組み込みの場合だと、NEON命令を上手に使いこなせているかが、ポイントとなるらしい。NEON命令の使い方は、OpenCVのモジュールのソースコードを読み取っていくのがよいらしい。

#if CV_NEON
#endif
で囲まれた部分のコードを
c:\opencv\sources\modules\imgproc\src*.cpp
などから見つけ出して、まねていくことにしよう。

PythonでCPU律速の場合だと、Cythonを使うことで速度の改善がはかれる。
画像処理・認識の場合だとnumpyをいかに効率的に利用できているかで
実行速度が格段に違ってくる。
numpyをbuildする際に、MKLなどの線形代数を高速化するライブラリを使って
buildしなおせば、pythonでの記述が同じでも高速化されるそうです。

・Productization

<付記>
OpenCV のPython bindingの場合だと、まだgpuを利用することができないのが残念である。
もちろんOpenCVとは無関係のGPUのpythonライブラリがあるのは知っているのですが、
GPUの性能を活かせるARMの組み込みボード(Jetson TK1)を使っていないために、Pythonからどれだけ使い物になるのかを知っている方がいらっしゃれば教えていただきたいと思っています。

ARMのリソースは、PCとは格段に違いますから、実装する必要のある全てが、そのARMボードで実現できるかどうかの見極めには用心してください。実装すべき必要のある全てが、十分に明確になっていない場合には、十分に余力のあるARMボードを選ぶようにしておきましょう。コア数は2つで十分なのか(64bitコアで4コアならば, Raspberry Pi3)、GPUを必要とするのか(Jetson
TX1)、FPGAを必要とするのかどうか。
選択肢は増えてきています。

URL
[1]:OpenCV for Embedded: Lessons Learned
http://www.slideshare.net/YuryGorbachev1/opencv-for-embedded-lessons-learned

[2]:
Parallel Pythonを使ってRaspberry Pi 2 の4コアCPUを使いきってみる
http://qiita.com/akidn8/items/ea3dcae810ff36fd5401