目录

前言:

一. 前期准备

1.1. OpenCV及Dlib库下载

1.2. 创建项目

1.3. 拷贝依赖库

二. 环境配置 

2.1. 导入OpenCV库

2.2. 修改"OpenCVLibrary420"的"build.grade"

2.3. app添加依赖"OpenCVLibrary420"包

2.4. 修改app的"build.grade"文件

2.5. 修改"CMakeLists.txt"


 

前言:

      本人一直在做图像识别、人脸识别、人脸疾病检测等相关算法工作。一般Windows下封装成dll动态库,Linux下封装成SO共享库。Android就使用 NDK技术封装成支持ARM平台的SO库。

     我使用的版本是Android Studio 3.4.1、OpenCV-4.2.0、Dlib-19.18。

一. 前期准备

1.1. OpenCV及Dlib库下载

        1)从OpenCV官网https://opencv.org/releases/ 下载Android版本并解压。

opencv安卓开发 opencv android开发_CMake

        2)从Dlib 官网http://dlib.net/ 下载dlib-19.18版本并解压。 

opencv安卓开发 opencv android开发_OpenCV_02

1.2. 创建项目

        打开Android Studio创建支持Native C++的项目,选择支持java,然后选择支持c++ 14新特性,,点击Finish创建项目。

 

opencv安卓开发 opencv android开发_android_03

opencv安卓开发 opencv android开发_android_04

opencv安卓开发 opencv android开发_CMake_05

opencv安卓开发 opencv android开发_opencv安卓开发_06

 

1.3. 拷贝依赖库

1)在"src/main/cpp"目录下创建四个包”common"、"include"、"libs"、"source"。("common"用来存放公共工具类,"include"用于存放依赖库的包含目录,即opencv和dlib库的头文件。"libs"用来存放静态库文件,“source"主要放C++源代码)将"CMakeLists.txt"文件移动到app目录下,移动后需要修改“build.gradle"中的"CMakeLists.txt"文件路径。这里也可以不移动,只是自己试的不移动的话会遇到一些问题。更改前为:

externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }

更改后为: 

externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
            version "3.10.2"
        }
    }

2) 将解压后的"../OpenCV-android-sdk/sdk/native"目录下的libs文件夹拷贝到"src/main/cpp/libs"目录下,并重命名为"opencv2";

3) 将解压后的"../OpenCV-android-sdk/sdk/native/jni/include"目录下的opencv2文件夹拷贝到"src/main/cpp/include"目录下。

4) 将解压后的Dlib目录下的"../dlib"文件夹拷贝到"src/main/cpp/include"目录下。

common目录放的是JNI公共工具类,主要处理Andord 位图Bitmap到OpenCV Mat数据的转换,这个内容这里就先不介绍,后续博客会介绍这些。添加前后的代码结构对比如下图:

opencv安卓开发 opencv android开发_android_07

 

opencv安卓开发 opencv android开发_opencv安卓开发_08

 

二. 环境配置 

2.1. 导入OpenCV库

      打开项目,然后依次"File---> New ---> Import Module",然后打开OpenCV-android-sdk解压目录下的"../sdk/java"文件

Module Name更改为"OpenCVLibrary420",然后依次点击"Next"、"Finish"。在项目中会添加"OpenCVLibrary420"的包名。

opencv安卓开发 opencv android开发_android_09

opencv安卓开发 opencv android开发_opencv安卓开发_10

opencv安卓开发 opencv android开发_opencv安卓开发_11

2.2. 修改"OpenCVLibrary420"的"build.grade"

需要将"OpenCVLibrary420"改成以库的方式存在,然后修改版本号和app的build.grade文件版本号一样。附上我的"build.grade"内容。注意这块内容的修改很关键。

//apply plugin: 'com.android.application'(原始内容)
apply plugin: 'com.android.library'      //添加内容

android {
    //compileSdkVersion 28
    //buildToolsVersion "28.0.3"
    //更改编译版本和app的build.grade一样
    compileSdkVersion 29   
    buildToolsVersion "29.0.2"

    defaultConfig {
        //applicationId "org.opencv"    // 原有内容
        // 添加内容,是从app的build.grade中拷贝过来,要保持一致
        minSdkVersion 15
        targetSdkVersion 29
    }

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

2.3. app添加依赖"OpenCVLibrary420"包

        打开"File --> Project Structure-->Dependencies",然后点击"app, "+" 号,选择第3项”Module Dependency",然后勾选"OpenCVLibrary420",点击"OK"即可。

opencv安卓开发 opencv android开发_CMake_12

 

opencv安卓开发 opencv android开发_android_13

 

opencv安卓开发 opencv android开发_android_14

2.4. 修改app的"build.grade"文件

       修改的内容主要是CMake的一些编译参数、C++的风格和要编译生成的ARM平台的SO库。修改后的内容可参考如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "com.example.facedetection"
        minSdkVersion 15
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                arguments "-DANDROID_ARM_NEON=TRUE","-DCMAKE_BUILD_TYPE=Release","-DANDROID_TOOLCHAIN=clang"
                cppFlags "-std=c++14 -frtti -fexceptions -ljnigraphics"
            }
            // ndk编译生成so库
            ndk{
                abiFilters 'x86','x86_64','armeabi-v7a','arm64-v8a'
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
            version "3.10.2"
        }
    }
    //包含头文件
    sourceSets {
        main{
            jniLibs.srcDirs = ['src/main/cpp/libs/opencv2']
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    implementation project(path: ':OpenCVLibrary420')
}

2.5. 修改"CMakeLists.txt"

     这里修改的参数较多,直接附上我的"CMakeLists.txt"内容。

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.
# 指定cmake的最小版本,确保能使用某些新特性构建项目
cmake_minimum_required(VERSION 3.4.1)
# 输出详细信息
set(CMAKE_VERBOSE_MAKEFILE on)
# 支持-std=gnu++14
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++14")

# 包含头文件目录
include_directories(src/main/cpp/include)
# 设置库目录
set(LIBRARY_DIRS "${CMAKE_SOURCE_DIR}/src/main/cpp/libs/opencv2")

# 添加opencv动态库
add_library(libopencv_java4 SHARED IMPORTED)   #动态加载方式

# 指定库路径
set_target_properties( # Specifies the target library.
        libopencv_java4

        # Specifies the parameter you want to define.
        PROPERTIES IMPORTED_LOCATION

        # Provides the path to the library you want to import.
        "${LIBRARY_DIRS}/${ANDROID_ABI}/libopencv_java4.so" )

# 设置dlib目录
# 如果使用下面的就是用的dlib的cmake文件,编译会比较慢,如果要使用可取消下行注释
# include(src/main/cpp/include/dlib/cmake)


# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
        face-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        # 这里可能需要加载多个文件,将文件依次填写在下面即可
        ${SRC_LIST}
        src/main/cpp/source/face-lib.cpp
        )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        face-lib
        #dlib
        jnigraphics
        libopencv_java4

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

# 指定release编译选项
# 下面方法有时可能会有些问题,就是不能指定编译Release版本,后面有时间再解决这个问题
# set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s -O3 -Wall")
# set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s -O3 -Wall")

至此,Androd  + C/CPP + OpenCV/Dlib的整个开发环境已经搭建完成,并能使用Cmake 生成支持ARM平台的C++ SO库。