在 Android Studio 中配置 OpenCV 开发环境的方法

目前最新的 OpenCV 版本为 3.x,但因为一些特性上的需要,我选择使用 2.4.11 进行开发。

下载地址:https://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.4.11/

解压后的目录是:

├─apk
├─doc
├─samples
└─sdk
    ├─etc
    │  ├─haarcascades
    │  └─lbpcascades
    ├─java
    └─native
        ├─3rdparty
        ├─jni
        │  └─include
        └─libs

apk 下是 Manager 的安装包,这些安装包也可以从 Google Play 上按设备自动适配下载。虽然 Manager 可以方便调用,但是我用的时候经常在一个手机上正常,换一个手机就不正常,并且这些 Manager 不提供更丰富的自定义,因此弃之不用。
doc 下是一些技术文档,还蛮好用的,可作参考。samples 下面是几个示例程序,如果自己调试不出来的话,可以直接去 Google Play 下载下来看效果,仔细读读代码也蛮有收获。
sdk 下,我的理解,java 主要用于取代 Manager,native 是 c/c++ 的 include 部分,etc 下面有 haar 和 lbp 两套人脸检测的分类器,其区别在于,haar 使用浮点,而 lbp 使用整型,因此 lbp 更快,但是 haar 更准确。

配置 NDK 环境

参考 使用实验性的 Gradle 工具构建 Android NDK 环境

导入 Java 部分

[File] -> [New] -> [Import Module],选解压后的 sdk/java 文件夹,Next,Finish

此时会报 Gradle project sync failed.

修改 Library 属性

打开 openCVLibrary2411 文件夹下的 build.gradle 文件,修改如下:

apply plugin: 'com.android.model.library'

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

        defaultConfig.with {
            minSdkVersion.apiLevel = 21
            targetSdkVersion.apiLevel = 23

            buildConfigFields.with {
                create() {
                    type = "int"
                    name = "VALUE"
                    value = "1"
                }
            }
        }
    }
    android.buildTypes {
        release {
            minifyEnabled = false
            proguardFiles.add(file('proguard-rules.pro'))
        }
    }
}

此时可以 Try Again 来同步一下Gradle。应当能够正常同步。

这里主要是:

添加依赖关系

[Project Structure] -> [app] -> [Dependencies] -> [+] -> [Module dependency] -> [openCVLibrary2411]

此时会自动同步Gradle

导入 native 部分

OpenCV2411\sdk\native\libs 目录下的 armeabi 和 armeabi-v7a 文件夹复制到 app/libs 下,就是这样:

当然这样是比较简单粗暴的,也可以自己选择具体需要使用的库,以减小安装包体积。
在 app 的 build.gradle 文件的 model{} 中添加下述代码:

android.productFlavors {
    create("arm") {
        ndk.with {
            abiFilters.add("armeabi")

            File curDir = file('./')
            curDir = file(curDir.absolutePath)
            String libsDir = curDir.absolutePath + "\\libs\\armeabi\\"

            ldLibs.add(libsDir + "libopencv_contrib.a")
            ldLibs.add(libsDir + "libopencv_core.a")
            ldLibs.add(libsDir + "libopencv_highgui.a")
            ldLibs.add(libsDir + "libopencv_imgproc.a")
            ldLibs.add(libsDir + "libopencv_info.so")
            ldLibs.add(libsDir + "libopencv_java.so")
            ldLibs.add(libsDir + "libopencv_legacy.a")
            ldLibs.add(libsDir + "libopencv_ml.a")
            ldLibs.add(libsDir + "libopencv_ts.a")

        }
    }
    create("armv7") {
        ndk.with {
            abiFilters.add("armeabi-v7a")

            File curDir = file('./')
            curDir = file(curDir.absolutePath)
            String libsDir = curDir.absolutePath + "\\libs\\armeabi-v7a\\"

            ldLibs.add(libsDir + "libopencv_contrib.a")
            ldLibs.add(libsDir + "libopencv_core.a")
            ldLibs.add(libsDir + "libopencv_highgui.a")
            ldLibs.add(libsDir + "libopencv_imgproc.a")
            ldLibs.add(libsDir + "libopencv_info.so")
            ldLibs.add(libsDir + "libopencv_java.so")
            ldLibs.add(libsDir + "libopencv_legacy.a")
            ldLibs.add(libsDir + "libopencv_ml.a")
            ldLibs.add(libsDir + "libopencv_ts.a")

        }
    }
}

在同一文件的 android.ndk{} 下添加一行:

cppFlags.add("-I${file("D:\\OpenCV2411\\sdk\\native\\jni\\include")}".toString())

目录改为相对应的解压位置。