タイトル通り、AndroidにOpenCVを導入し、c++と連携してOpenCVを動かす所まで書きます。
実現する状況は以下の通りです。
- AndroidのJava上からOpenCVを動かす
- NDKを介してAndroidのJava上からc++のOpenCVを動かす
- (GitHubを介したpush&pullのみでプロジェクトを持ち運べるようにする)
最後は個人的な都合でやってます。
OpenCV4Android SDKはOpenCV Managerを介して利用することもできますが、今回はポータビリティに重点を置き、プロジェクトの共有ライブラリに.apkを含める形で進めます。
完全にネット上の知識のみの独学でやっているので、間違っている点やおかしな点があるかもしれません。
特にファイルの配置に関しては色々と無駄なことをやっていると思います。
アドバイスやコメント大歓迎です。
この記事の内容と、多少のサンプルコードを加えたプロジェクトをGitHub上で公開しています。
github.com
プロジェクトの作成
今回の記事で実行する手順です。
プロジェクトの開始
今回はc++との連携を行うため、プロジェクト開始時にInclude C++ supportにチェックを入れます。
ついでにc++11を有効に。
後は適当に選んでプロジェクトを開始します。
NDKのインストール
写真がありませんが、Include C++ supportにチェックを入れてプロジェクトを開始した場合、NDKのインストールが必要になります。
これはAndroidStudioからのメッセージに従ってインストールしていけば何も問題ありません。
以下の画面までたどり着いたら完了です。
OpenCV4Android SDKの導入
qiita.com
この項目は、こちらの記事を参考に作成しました。
ダウンロード・解凍・配置
以下のページからバージョンを選びSDKをダウンロードしてきます。
sourceforge.net
今回はopencv-3.2.0-android-sdk.zipをダウンロードしてきました。
zipファイルは解凍したあとでできるだけ動かさない場所に置くと良いでしょう。
プロジェクトへモジュールを導入
AndroidStudioで、File > new > Import Moduleを選択します。
以下の画面に、「[解凍したものを配置した場所]/OpenCV-android-sdk/sdk/java」を入力し、ライブラリの追加を行います。
この画面の後にももうひとつ画面が出ますが、特に弄る必要はありません。
実行後には、[プロジェクトディレクトリ]/import-summary.txtが開きます。
内容(抜粋)は以下のようになります。
ECLIPSE ANDROID PROJECT IMPORT SUMMARY ====================================== Ignored Files: -------------- The following files were *not* copied into the new Gradle project; you should evaluate whether these are still needed in your project and if so manually move them: * javadoc/ * javadoc/allclasses-frame.html * javadoc/allclasses-noframe.html * javadoc/constant-values.html * javadoc/help-doc.html * javadoc/index-all.html * javadoc/index.html * javadoc/org/ * javadoc/org/opencv/ * javadoc/org/opencv/android/ * javadoc/org/opencv/android/BaseLoaderCallback.html * javadoc/org/opencv/android/CameraBridgeViewBase.CvCameraViewFrame.html * javadoc/org/opencv/android/CameraBridgeViewBase.CvCameraViewListener.html * javadoc/org/opencv/android/CameraBridgeViewBase.CvCameraViewListener2.html ︙
インポートしたものが確認できます。
ライブラリをプロジェクトに追加
プロジェクトのapp/src/mainに、jniLibsという名前のディレクトリを作成し、[解凍したものを配置した場所]/sdk/native/libs内のファイルを全てコピーペーストします。
以下のようになります(※opencv320というディレクトリが追加されているのは一旦無視して下さい)。
モジュールの依存関係を設定
AndroidStudioで、File > Project Structureからappを選択し、Dependenciesタブの緑の'+'マークからModule depencencyを選択します。
すると先ほど取り込んだモジュールが表示されるので、それを選択しOKを押します。
以下のようになります。
gradleの設定
素の状態では、OpenCVのコンパイルに関する設定のAPIレベル等が低い状態です。
例えばcamera2 APIを利用しようと思った場合、これはAPIレベル21以降の実装であるため、build.gradleの設定無しではビルドができなくなります。
これを解消するため、build.gradleの設定を変更します。
app/build.gradleと、openCVLibrary320/build.gradleを開きます(320はバージョン名)。
編集前の内容は、それぞれ以下のように(抜粋)なっています。
app/build.gradle
apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion "25.0.3" defaultConfig { applicationId "com.wrongwrong.opencv4androidsample" minSdkVersion 22 targetSdkVersion 25 versionCode 1 ︙
openCVLibrary320/build.gradle
(編集前)
apply plugin: 'com.android.library' android { compileSdkVersion 14 buildToolsVersion "25.0.0" defaultConfig { minSdkVersion 8 targetSdkVersion 21 } ︙
このうちopenCVLibrary320/build.gradleのcompileSdkVersion, buildToolsVersion, minSdkVersion, targetSdkVersionの4項目を、app/build.gradleに合わせて書き換えます。
openCVLibrary320/build.gradle
(編集後)
apply plugin: 'com.android.library' android { compileSdkVersion 25 buildToolsVersion "25.0.3" defaultConfig { minSdkVersion 22 targetSdkVersion 25 } ︙
c++からOpenCVを利用する
次に、Androidのc++からOpenCVを利用するための設定を行います。
正直この辺りのことは全く理解できていません。
以下のリポジトリから、設定をコピペする形で設定を行いました。
github.com
([解凍したものを配置した場所]/OpenCV-android-sdk/sdkの配置)
持ち運びのためにやっていることなので、やらなくても良い手順です。
app直下にopencv320という名前のフォルダを作成し、[解凍したものを配置した場所]/OpenCV-android-sdk/sdkをコピペします。
app/build.gradleの設定
app/build.gradleに設定を追加します。
app/build.gradle
(編集前)
apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion "25.0.3" defaultConfig { applicationId "com.wrongwrong.opencv4androidsample" minSdkVersion 22 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { cppFlags "-std=c++11" } } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } ︙
追加した内容は、cmake内と、buildTypesの手前の内容です。
追加した部分1
cmake {
cppFlags "-std=c++11"
abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64'
}
追加した部分2
sourceSets { main { jniLibs.srcDirs = ['src/main/jniLibs'] } }
app/build.gradle
(編集後)
apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion "25.0.3" defaultConfig { applicationId "com.wrongwrong.opencv4androidsample" minSdkVersion 22 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { cppFlags "-std=c++11" abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64' } } } sourceSets { main { jniLibs.srcDirs = ['src/main/jniLibs'] } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } ︙
app/CMakeLists.txtの設定
初期状態CMakeLists.txtは以下の通りです(最初から入ってるコメントは邪魔なので消しました)。
app/CMakeLists.txt
(編集前)
cmake_minimum_required(VERSION 3.4.1) add_library( native-lib SHARED src/main/cpp/native-lib.cpp ) find_library( log-lib log ) target_link_libraries( native-lib ${log-lib} )
これを以下のように編集します
app/CMakeLists.txt
(編集後)
cmake_minimum_required(VERSION 3.4.1) # 以下3行追加 include_directories(./opencv320/sdk/native/jni/include) #置いた場所で変わる add_library( lib_opencv SHARED IMPORTED ) set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so) add_library( native-lib SHARED src/main/cpp/native-lib.cpp ) find_library( log-lib log ) # lib_opencv追加 target_link_libraries( native-lib lib_opencv ${log-lib} )
注意点として、include_directories(./opencv320/sdk/native/jni/include)の部分では、自分がsdk/jni/includeを置いた場所を指定する必要があります。
ここまでの設定で、Androidのc++からOpenCVを利用することができるようになります。
疑問
以下の点が疑問として残っていますので、追々調べていきます。
- 例えばg++などに渡す最適化のフラグはどのようにして渡すのか(そもそも渡せるのか)
- 無駄な手順が含まれていないか(全部やってから動くことは確認したが、途中でどう動かないか記録していない)
おまけ
掲載したサンプルプロジェクトの解説を書きました。
wrongwrong163377.hatenablog.com