AndroidでもOpenCV

自宅サーバHDD故障記事内、作り直したいものの1つ、OpenCVを使った画像加工アプリケーション。これを、Androidでも使いたくて試しました。

PerlOpenCVC/C++ライブラリを使うには、加工処理部分をPerl XSで実装しました。Androidでは、当然ですがJNI(NDK)を利用します。

まずはNDKのビルド環境。Windowsの場合、
1.素直にNDKをダウンロード&ビルドする(要Cygwin
2.Android全ソースをダウンロード&makeする
2−1.Ubuntu on VMWare on Windows
2−2.Cygwin on Windows
EclipseからAndroid本体のビルド環境を作るのは、Linuxじゃないと出来ないと思っていましたが、2−1の上にEclipseを入れて必要な設定をすると、Windowsでも出来そうな感じ。PCが重すぎて最後まで試してませんが。
2−2でも、EclipseからAndroid本体のソースを参照することは出来たので、開発時のデバッグに有用でした。
2は多大な紙面をさくので、手っ取り早く1のポイントをメモ。
更に、1でもEclipseのDCKを使って、ライブラリの作成からAndroidアプリの開発までほぼシームレスに行うこともできますが、ここでは何をやっているのか基本の理解のため、原始的な手順を記載します。

私が試した時点のNDKは、android-ndk-r4。これ以前のバージョンとは、ビルド手順や必要な設定ファイルが変わっていました。

1.http://developer.android.com/intl/ja/sdk/ndk/index.html
から、android-ndk-r4-windows.zipをダウンロードし、Cygwinで操作できるところに解凍します。ndkルート/samplesのサンプルを参考に、Android.mkやフォルダ構成を理解し、自作アプリを作成します。
基本的な構成は、
アプリルート/
          +AndroidManifest.xml
          +bin/
          +default.properties
          +jni/
          +C/C++の自作ライブラリソース
          +上のヘッダファイル
          +Android.mk
          +libs/(最終的なSharedライブラリ.soが作成されます)
          +res/
          +src/(自作Javaアプリパッケージ。例com/chiaki/OpenCV.java

2.Javaソースを書いたら、javahコマンドでC/C++のヘッダファイルを作成します。
(例)javah -classpath bin -d jni com.chiaki.OpenCV
   →アプリルート/jni/com_chiaki_OpenCV.hが作成されます。

3.2で出来たヘッダを参照して、C/C++のソースを書きます。

4.ライブラリに含めるC/C++のソースや出力するライブラリ名を指定し、Android.mkを作成します。このとき、シェアドライブラリ(.so)を作る場合はinclude $(BUILD_SHARED_LIBRARY)を、スタティックライブラリ(.a)を作る場合はinclude $(BUILD_STATIC_LIBRARY)を指定します。

5.2のヘッダと3のソースと4のAndroid.mkを、1の構成に配置し、アプリルート(AndroidManifest.xmlのある場所)で、ndkルート/ndk-buildコマンドを実行します。

6.アプリルート/libsに、ライブラリファイルが出力されます。

7.生成されたライブラリを、Androidアプリのプロジェクトに配置します。場所は、アプリルート/libs/armeabi/ライブラリファイル です。

8.この状態でAndroidアプリをビルド・実行して終了です。

次に、NDK用OpenCVです。
1.http://www.noritsuna.com/download/OpenCVForAndroidNDK-0.1-src.zip
からモジュールをダウンロードします。

2.ndkルート配下に解凍・配置します。
  (例)ndkルート/samples/opencv_androidとして、今回は解凍・配置しました。

3.上記配置の場合、opencv_android/apps/opencv/project/AndroidManifest.xmlを、opencv_android/sources/opencv/配下にコピーします。
(例)
opencv_android/
          +AndroidManifest.xml(コピーしたもの)
          +bin(ビルド後、opencvの各スタティックライブラリが生成されます)
          +jni(opencvモジュールソース&ヘッダと自作ライブラリソース(C/C++)&ヘッダ)
          +Android.mk
          +opencvのソースフォルダ
          +自作ライブラリソースとヘッダ(C/C++、.h)
          +…その他

4.Android.mk内、opencvモジュール(cv/cvaux/cxcore/ml/highgui)ビルド用の記述はそのまま(これ、参考になります)、最後のLOCAL_MODULEの指定以下を、サンプルアプリ用ライブラリの記述から、自作ライブラリの記述に変更します。
ポイントは、opencvモジュールライブラリ(libcv.a,libcvaux.a,libcxccore.a,libcvml.a,libcvhighgui.a)のリンクLOCAL_LDLIBSとLOCAL_STATIC_LIBRARIESの指定と、ヘッダLOCAL_C_INCLUDESとLOCAL_CFLAGSの指定を正確に。動的リンクを利用する場合は、LOCAL_LDLIBSに-ldlの指定も忘れずに。

5.opencv_android/sources/opencv(AndroidManifest.xmlを置いたフォルダ)で、ndkルート/ndk-buildコマンドを実行すると、opencv_android/sources/opencv/libs/amebri/配下に、opencvモジュールライブラリとともに、自作ライブラリが生成されます。

6.5の自作ライブラリを、Androidアプリのプロジェクト内libs/armebri配下に配置し、ビルド・実行して終了です。

自分のお試しアプリでは、cvCreate関数に渡すサイズパラメータを、cvGetSizeで取得した値にしているのですが、この関数処理内部でエラーが発生しているらしく、サイズを別の方法で指定するとうまくいきました。opencvのモジュールも、Android上で全て円滑に動くわけではなさそうです。