前言:
一. 前期准备
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)从OpenCV官网https://opencv.org/releases/ 下载Android版本并解压。
2)从Dlib 官网http://dlib.net/ 下载dlib-19.18版本并解压。
打开Android Studio创建支持Native C++的项目,选择支持java,然后选择支持c++ 14新特性,,点击Finish创建项目。
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数据的转换,这个内容这里就先不介绍,后续博客会介绍这些。添加前后的代码结构对比如下图:
打开项目,然后依次"File---> New ---> Import Module",然后打开OpenCV-android-sdk解压目录下的"../sdk/java"文件
Module Name更改为"OpenCVLibrary420",然后依次点击"Next"、"Finish"。在项目中会添加"OpenCVLibrary420"的包名。
需要将"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'
}
}
}
打开"File --> Project Structure-->Dependencies",然后点击"app, "+" 号,选择第3项”Module Dependency",然后勾选"OpenCVLibrary420",点击"OK"即可。
修改的内容主要是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')
}
这里修改的参数较多,直接附上我的"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库。 如果有什么问题,可以添加QQ:396793304,或加QQ群:210250364一起交流讨论。