LoginSignup
56
64

More than 5 years have passed since last update.

Android StudioでOpenCVを使えるようにする

Last updated at Posted at 2015-10-18

Android Studioで、OpenCV (C++)を使う必要があったので、まとめてみました。
Android開発は、始めたばかりなので、間違っているところがありましたら、教えて頂けるとありがたいです。

試した環境は、以下の通り。

  • Android Studio 1.4
  • OSX 10.11
  • OpenCV 3.0.0 (for Android)

※ OpenCV for Androidは、以下のフォルダにインストールされているものとす。

/Users/<name>/Library/Android/OpenCV-3.0.0-android-sdk/

まず、OpenCVを使用するアプリケーションの作成

新規プロジェクトを作成する場合

「New Project...」で「My Application」という名前の「Blank Activity」を作成したとする。
「Import Module...」で以下のフォルダをインポートする。

/Users/<name>/Library/Android/OpenCV-3.0.0-android-sdk/sdk/java/

「openCVLibrary300」という名前でライブラリがインポートされる。
settings.gradle にopenCVの依存関係が追加される。

settings.gradle
include ':app'
include ':openCVLibrary300' // <--- 追加される

/app/build.gradleを以下のように修正

/app/build.gradle
...
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.0'
    compile 'com.android.support:design:23.1.0'
    compile project(':openCVLibrary300') // <--- 追加する
}

OpenCVのSDKに付属のサンプルを試す場合

SDKに付属のサンプルは、以下の場所にある。

/Users/<name>/Library/Android/OpenCV-3.0.0-android-sdk/samples/

サンプルを開く場合、Android Studioの「Open...」で直接開かずに、「Import Project...」で開きたいサンプルのフォルダを選択し、インポート先をユーザフォルダの下などの別フォルダにする。
そうすると、同じフォルダにOpenCVのライブラリをインポートした状態のプロジェクトが作成される。

OpenCVのライブラリのロードをどうする?

OpenCVは、C/C++で書かれたライブラリである。Android向けには、JavaからOpenCVを使用するためのJava Wrapperも提供されている。Java Wrapperを使用する場合でも、アプリが起動するためには、C/C++の共有ライブラリ(libopencv_java3.so)をロードする必要がある。

OpenCVの共有ライブラリをロードする方法として、以下の二つがある。

A: OpenCV Managerを使用する
  • OpenCVの共有ライブラリを含まないため、配布するアプリのサイズは小さくなる。
  • ただし、ユーザ環境にOpenCV Managerがインストールされている必要がある。
  • アプリケーションの起動時に、OpenCV Managerがインストールされていない環境では、OpenCV Managerのダウンロード/インストールを要求される。
  • OpenCV Managerは、必ずしも最新バージョンのOpenCVに対応していない。
B: 共有ライブラリをアプリケーションパッケージ(.apk)に含める
  • 共有ライブラリを含む分、配布するアプリのサイズは大きくなる。
  • OpenCV Managerは不要。
  • 最新バージョンのOpenCVが使用できる。

OpenCV Managerを使用する方法

ActivityクラスのonResumeで、OpenCVLoader.initDebug()を使って、OpenCV Managerを呼び出す。
詳細は、"/OpenCV-3.0.0-android-sdk/samples/image-manipulations/"などを参照。

ImageManipulationsActivity.java
public class ImageManipulationsActivity extends Activity implements CvCameraViewListener2 {

    @Override
    public void onResume()
    {
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
        } else {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

共有ライブラリを.apkに含める方法

プロジェクトの"app/src/main"の下の"jniLibs"フォルダを作成。
"/OpenCV-3.0.0-android-sdk/sdk/native/libs/"の下のディレクトリを"jniLibs"の下にコピー。
コピー先の各フォルダの"libopencv_java3.so"を残して、".a"ファイルは削除する。

フォルダ構成
main/
    src/
        jniLibs/
            arm64-v8a/
                libopencv_java3.so
            armeabi/
                libopencv_java3.so
            armeabi-v7a/
                libopencv_java3.so
            mips/
                libopencv_java3.so
            mips64/
                libopencv_java3.so
            x86/
                libopencv_java3.so
            x86_64/
                libopencv_java3.so

プロジェクトのActivityクラスを以下のように修正。
OpenCVのサンプル、"image-manipulations"の例。

ImageManipulationsActivity.java
public class ImageManipulationsActivity extends Activity implements CvCameraViewListener2 {

    /* --- 追加 (共有ライブラリをロードする) --- */
    static {
        System.loadLibrary("opencv_java3");
    }

    @Override
    public void onResume()
    {
        super.onResume();
        /* --- OpenCV Managerの呼び出しをコメントアウト --- */
/*      if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
        } else */ {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

NDKを使用して、C/C++からOpenCVを使用する

OpenCV Managerを使っても出来そうですが、調べていません。ここでは、共有ライブラリを.apk内に含めることとします。
上記の「共有ライブラリを.apkに含める方法」のところまでは同じ。

OpenCVのサンプル、"face-detection"を使用して説明する。

./gradle/wrapper/gradle-wrapper.prpertiesを修正
gradle-wrapper.properties
#Sun Oct 11 14:07:25 JST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
# 修正前
#distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
# 修正後
distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip

Gradle-Wrapperに、他にどのバージョンが存在するかは、以下で確認可能
https://services.gradle.org/distributions
(2015.10.11現在、2.5しかダメ)

Gradle wrapperを使用するように変更

"preferences" > "Build, Execution, Deployment" > "Gradle" を開く。
"Project-level settings"を"Use local gradle distribution"から"Use default gradle wrapper (recommended)"に変更する。

./build.gradleを修正
./build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        // classpath 'com.android.tools.build:gradle:1.3.0' // 修正前
        classpath 'com.android.tools.build:gradle-experimental:0.2.0' // 修正後

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

他にどういうバージョンがあるかは、以下で確認可能
https://jcenter.bintray.com/com/android/tools/build/gradle-experimental/

./app/build.gradleを修正
./app/build.gradle[修正前]
apply plugin: 'com.android.application'

android {
    compileSdkVersion 14
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "org.opencv.samples.facedetect"
        minSdkVersion 8
        targetSdkVersion 8

        ndk {
            moduleName "detection_based_tracker"
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

dependencies {
    compile project(':openCVLibrary300')
}
./app/build.gradle[修正後]
apply plugin: 'com.android.model.application'

model {
    android {
        compileSdkVersion = 14
        buildToolsVersion = "23.0.1"

        defaultConfig.with {
            applicationId = "org.opencv.samples.facedetect"
            minSdkVersion.apiLevel = 8
            targetSdkVersion.apiLevel = 8
            versionCode = 1
            versionName = "1.0"
        }
    }
    android.buildTypes {
        debug {
            ndk.with {
                debuggable = true
            }
        }
        release {
            minifyEnabled = false
            proguardFiles += file('proguard-rules.pro')
        }
    }

    compileOptions.with {
        sourceCompatibility=JavaVersion.VERSION_1_7
        targetCompatibility=JavaVersion.VERSION_1_7
    }

    android.ndk {
        moduleName = "detection_based_tracker"

        cppFlags += "-Werror"
        cppFlags += "--debug"
        cppFlags += "-frtti"
        cppFlags += "-fexceptions"
        cppFlags += "-I${file('/Users/<name>/Library/Android/OpenCV-3.0.0-android-sdk/sdk/native/jni/include')}".toString()
        cppFlags += "-I${file('src/main/jni')}".toString()

        ldLibs += ["android", "log", "stdc++", "dl", "z"]
        stl = "gnustl_static"
    }
    android.productFlavors {
        create("arm") {
            ndk.with {
                abiFilters += "armeabi"

                File curDir = file('./')
                curDir = file(curDir.absolutePath)
                ldLibs += curDir.absolutePath + "/src/main/jniLibs/" + "armeabi" + "/libopencv_java3.so"
            }
        }
        create("arm7") {
            ndk.with {
                abiFilters += "armeabi-v7a"

                File curDir = file('./')
                curDir = file(curDir.absolutePath)
                ldLibs += curDir.absolutePath + "/src/main/jniLibs/" + "armeabi-v7a" + "/libopencv_java3.so"
            }
        }
        create("arm8") {
            ndk.with {
                abiFilters += "arm64-v8a"

                File curDir = file('./')
                curDir = file(curDir.absolutePath)
                ldLibs += curDir.absolutePath + "/src/main/jniLibs/" + "arm64-v8a" + "/libopencv_java3.so"
            }
        }
        create("x86") {
            ndk.with {
                abiFilters += "x86"

                File curDir = file('./')
                curDir = file(curDir.absolutePath)
                ldLibs += curDir.absolutePath + "/src/main/jniLibs/" + "x86" + "/libopencv_java3.so"
            }
        }
        create("x86-64") {
            ndk.with {
                abiFilters += "x86_64"

                File curDir = file('./')
                curDir = file(curDir.absolutePath)
                ldLibs += curDir.absolutePath + "/src/main/jniLibs/" + "x86-64" + "/libopencv_java3.so"
            }
        }
        create("mips") {
            ndk.with {
                abiFilters += "mips"

                File curDir = file('./')
                curDir = file(curDir.absolutePath)
                ldLibs += curDir.absolutePath + "/src/main/jniLibs/" + "mips" + "/libopencv_java3.so"
            }
        }
        create("mips-64") {
            ndk.with {
                abiFilters += "mips64"

                File curDir = file('./')
                curDir = file(curDir.absolutePath)
                ldLibs += curDir.absolutePath + "/src/main/jniLibs/" + "mips64" + "/libopencv_java3.so"
            }
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile project(':openCVLibrary300')
}
./openCVLibrary300/build.gradleを修正
./openCVLibrary300/build.gradle[修正前]
apply plugin: 'com.android.library'

android {
    compileSdkVersion 14
    buildToolsVersion "23.0.1"

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 8
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}
./openCVLibrary300/build.gradle[修正前]
apply plugin: 'com.android.model.library'

model {
    android {
        compileSdkVersion = 14
        buildToolsVersion = "23.0.1"

        defaultConfig.with {
            minSdkVersion.apiLevel = 8
            targetSdkVersion.apiLevel = 8
        }
    }

    android.buildTypes {
        debug {
            ndk.with {
                debuggable = true
            }
        }
        release {
            minifyEnabled = false
            proguardFiles += file('proguard-rules.pro')
        }
    }

    compileOptions.with {
        sourceCompatibility=JavaVersion.VERSION_1_7
        targetCompatibility=JavaVersion.VERSION_1_7
    }
}

C/C++コードのDebug

  1. プロジェクトのC/C++のコードに、ブレークポイントを設定する。
  2. ツールバーの"Select Run/Debug Configuration"をドロップダウン。
  3. "<アプリケーション名>-native"を選択。
    • 無ければ、"Edit Configurations..."を選択。
    • 開いた画面(Run/Debug Configurations)の左上の[+]ボタンで、"Android Native"を追加する。
      • ⇒ 選択肢に"<アプリケーション名>-native"が追加される。
  4. "Run"または"Debug"で、アプリケーションを実行。
    • ⇒ ブレークポイントで停止する。

おしまい

56
64
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
56
64