OpenCVのサンプル face-detection をAndroid Studioでビルド、実行する
1. はじめに
Android Studio 1.4では、NDKをサポートしているようなので、練習として、OpenCV for Android OpenCV > PLATFORMS > ANDROID のサンプル face-detection をAndroid Studioでビルド、実行します。
2. OpenCV for Android SDKのインストール
OpenCV > DOWNLOADS より、OpenCV for Android をダウンロードします。記事執筆時の最新バージョンは、3.1です。zipファイルを適当なディレクトリに展開します。
$ cd ~/src $ unzip OpenCV-3.1.0-android-sdk.zip
3. face-detectionのAndroid Studioへのインポート
OpenCV-android-sdk/samplesにあるface-detectionをAndroid Studioにインポートします。Android StudioのQuick StartのImport project (Eclipse ADT, Gradle, etc.)を使って、Select Eclipse or Gradle Project to importで、face-detectionを選択して、OKをします。
3. build.gradleの修正
サンプル face-detectionをAndroid Studioにインポートすると、次のようなエラーが出ます。
Failed to sync Gradle project 'face-detection' Error:Cause: failed to find target with hash string 'android-14' in: /Users/osabe/src/android-sdk-macosx openAndroidSdkManager"
このエラーは、build.gradleで、compileSdkVersionが14に指定されているが、Android SDKのパッケージリポジトリにandroid-14がないのが原因です。また、本サンプルでは、android.hardware.camera2 の機能を使用していますが、これは、API level 21から利用可能です( android.hardware.camera2 )。そこで、build.gradleで、compileSdkVersion、minSdkVersionの値を修正します。
修正箇所
- openCVLibrary310の下のbuild.gradleファイル
compileSdkVersion 14 buildToolsVersion "23.0.2" defaultConfig { minSdkVersion 8 targetSdkVersion 21 }
を
compileSdkVersion 21 buildToolsVersion "23.0.2" defaultConfig { minSdkVersion 21 targetSdkVersion 21 }
に修正。
– openCVSamplefacedetectionの下のbuild.gradleファイル
compileSdkVersion 14 buildToolsVersion "23.0.2" defaultConfig { applicationId "org.opencv.samples.facedetect" minSdkVersion 8 targetSdkVersion 8 ndk { moduleName "detection_based_tracker" } }
を
compileSdkVersion 21 buildToolsVersion "23.0.2" defaultConfig { applicationId "org.opencv.samples.facedetect" minSdkVersion 21 targetSdkVersion 21 ndk { moduleName "detection_based_tracker" } }
に修正。
4. gradle.propetiesファイルの作成
Gradle projectをsyncすると、次のようなエラーが発生する。
Error:(12, 0) Error: NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin. For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental. Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.
Top / OS関係 / Android / AndroidStudio /AndroidStudio によると、トップディレクトリに、次の内容のファイル gradle.propertiesを作成するといい。
android.useDeprecatedNdk=true
ファイルを作成して、プロジェクトをsyncする。
5. local.propertiesファイルの修正
4で、gradle.propertiesファイルを作成し、プロジェクトをsyncすると、次のエラーが発生する。
Error:Execution failed for task ':openCVSamplefacedetection:compileDebugNdk'. > NDK not configured. Download the NDK from http://developer.android.com/tools/sdk/ndk/.Then add ndk.dir=path/to/ndk in local.properties. (On Windows, make sure you escape backslashes, e.g. C:\\ndk rather than C:\ndk)
トップディレクトリのlocal.propertiesファイルに、
ndk.dir=<android ndkの絶対パス>
を記述する。その後、プロジェクトをClean Project、Rebuild Projectする。
6. ビルド失敗に対する対策(openCVSamplefacedetectionのbuild.gradleを編集)
プロジェクトをRebuildすると、次のエラーが発生する。
Error:(2, 33) opencv2/core/core.hpp: No such file or directory
AndroidStudioでOpenCVのサンプルを動かす によると、このエラーは、Android Studioでのビルドで、Android.mkの設定が反映されないのが原因。ビルド時に、ndk-buildを実行するタスクを追加する。次のように、openCVSamplefacedetectionのbuild.gradleのandroidブロック内で、
sourceSets.main.jni.srcDirs = [] task buildNative(type: Exec, description: 'Compile JNI source via NDK') { def ndkDir = "/Users/foo/src/android-ndk-r10e" commandLine "$ndkDir/ndk-build", '-C', file('src/main/jni').absolutePath, '-j', Runtime.runtime.availableProcessors(), 'all' } tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn buildNative }
を追加する。ファイル修正後、再度、Rebuild。
7. Rebuild失敗に対する対策
6で、openCVSamplefacedetectionのbukld.gradleの修正後、プロジェクトをRebuildすると、次のエラーが発生する。
Error:(15) ../../sdk/native/jni/OpenCV.mk: No such file or directory
AndroidStudioでOpenCVのサンプルを動かす によると、OpenCVのsdkを、プロジェクトから認識できないのが原因で、openCVSamplefacedetection/src/main/jniにあるAndroid.mkファイルを次のように修正する。
include ../../sdk/native/jni/OpenCV.mk
を
include <OpenCV sdkの絶対パス>/sdk/native/jni/OpenCV.mk
に修正する。修正後、Rebuild。face-detection/openCVSamplefacedetection/src/main/libs/armeabi-v7aディレクトリに、libdetection_based_tracker.so ファイルが生成されれば、ビルドが成功する。
8. アプリ実行
アプリをRunすると、次のようなエラーが発生する。
03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect D/AndroidRuntime: Shutting down VM 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: FATAL EXCEPTION: main 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: Process: org.opencv.samples.facedetect, PID: 21512 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/org.opencv.samples.facedetect-2/base.apk"],nativeLibraryDirectories=[/data/app/org.opencv.samples.facedetect-2/lib/arm64, /vendor/lib64, /system/lib64]]] couldn't find "libdetection_based_tracker.so" 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: at java.lang.Runtime.loadLibrary(Runtime.java:367) 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: at java.lang.System.loadLibrary(System.java:1076) 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: at org.opencv.samples.facedetect.FdActivity$1.onManagerConnected(FdActivity.java:67) 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: at org.opencv.android.AsyncServiceHelper$3.onServiceConnected(AsyncServiceHelper.java:319) 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1223) 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1240) 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:739) 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:95) 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: at android.os.Looper.loop(Looper.java:148) 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5417) 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 03-29 11:12:54.312 21512-21512/org.opencv.samples.facedetect E/AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 03-29 11:12:54.319 21512-21512/org.opencv.samples.facedetect I/Process: Sending signal. PID: 21512 SIG: 9
face-detection/openCVSamplefacedetection/build/outputs/apkディレクトリに生成したapkファイルをunzipで展開すると、ダイナミックファイルが含まれていないのが、エラーの原因( AndroidStudioでOpenCVのサンプルを動かす ) 。そこで、シンボリックをはる。
$ cd face-detection/openCVSamplefacedetection/src/main $ ln -s libs jniLibs
9. OpenCV Managerのインストール
アプリを再度、Runする。今度は、OpenCV Managerがインストールされていないので、インストールしろというメッセージが出る。そこで、OpenCV Mangerをインストールする。
10. アプリを再度、実行
アプリが動作するようになる。ただし、Nexus 6Pでは、logcatに次のエラーを出して、アプリが実行できない。
03-29 11:23:24.338 23120-23120/? E/AndroidRuntime: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/org.opencv.samples.facedetect-1/base.apk"],nativeLibraryDirectories=[/data/app/org.opencv.samples.facedetect-1/lib/arm64, /vendor/lib64, /system/lib64]]] couldn't find "libdetection_based_tracker.so"
NDK r10 b 32 bit or 64 bit or compile using both and how to achieve it によると、原因は、Android Studioが生成するjniのダイナミックライブラリが32bitの物に対して、Nexus 6PのCPUがarm 64bitであるため。そこで、face-detection/openCVSamplefacedetection/src/main/jni ディレクトリにある Application.mk ファイルを次のように修正する。
APP_ABI := armeabi-v7a arm64-v8a
修正後、プロジェクトをBuild Clean、Rebuild。再度、アプリ実行する。正常実行される。
11. 参考サイト
OpenCV > PLATFORMS > ANDROID
OpenCV > DOWNLOADS
android.hardware.camera2
NDK r10 b 32 bit or 64 bit or compile using both and how to achieve it
AndroidStudioでOpenCVのサンプルを動かす