一、开发背景
有一个现有的Android Studio工程,之前直接调用OpenCV的Java接口编程,没有用到JNI编程,现需要利用OpenCV库实现底层算法,故尝试在原工程上加入CMake方式的JNI编程。
二、步骤
1、原工程在创建时没有选择“include C++”选项,故需要手动添加一些文件夹和文件以及修改某些文件。如下
(1)在main目录创建cpp文件夹,用以放置源代码
(2)在main目录下创建jniLibs文件夹,用以放置要调用的动态库文件。
(3)在app目录下创建CMakeLists.txt文件,作为顶层编译控制文件。
(4)修改app目录下的build.gradle文件,加入一些本地编译相关的配置信息。
以上为所有需要修改和添加的内容,具体细节下面叙述。
2、将OpenCV android-sdk目录下的include文件夹复制到cpp文件夹,作为供编写算法的OpenCV头文件,如图:
3、将OpenCV android-sdk目录下的libs文件的对应平台的库文件复制到jniLibs文件夹下,如图(不是所有的库都用上,只是libopencv_java.so被用到,但全复制过来也无妨):
4、编写CMakeLists.txt文件,内容如下
cmake_minimum_required(VERSION 3.4.1) # CMake要求版本
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include) # 头文件包含目录,CMAKE_SOURCE_DIR代表工程顶层目录,即CMakeList所在目录
add_library(libopencv_java SHARED IMPORTED) #引入java动态库
set_target_properties(libopencv_java PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libopencv_java.so)
add_library(
FaceRecognitionForAndroid
SHARED
src/main/cpp/facerecognition.cpp
src/main/cpp/preprocess.cpp
src/main/cpp/org_opencv_face_recognition_FaceRecognitionForAndorid) #引入源文件生成动态库
find_library( #引入Android NDK的log库
log-lib
log )
target_link_libraries( FaceRecognitionForAndroid #链接所有的库生成最终库文件
libopencv_java
${log-lib} )
5、更改app目录下的build.gradle文件,更改后内容如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
defaultConfig {
applicationId "org.opencv.face.recognition"
minSdkVersion 22
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild { //添加:cmake编译默认配置信息
cmake {
cppFlags " -frtti -fexceptions -stdlib=libstdc++"
abiFilters 'armeabi-v7a'
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild { //添加:指定cmake文件的路径:和build.gradle同路径
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation project(':openCVLibrary249')
}
6、完成以上步骤,就可以在cpp文件夹内调用OpenCV的库编写C++算法了。当然,编写的算法想要被Java调用,还要根据JNI文件编写步骤编写对应的文件和Java类,从而调用自己编写的算法。
三、Bugfixed
在使用Android Studio编译依赖OpenCV2.4.9包的工程时,出现报错: ‘ext/atomicity.h’ file not found, 主要网上说时C++库的问题,要加入编译标志-stdlib=libstdc++, 但添加后问题并未解决。后来发现使用老版本的NDK就没有这个问题,而Android Studio的NDK时最新版本的。经测试,使用android-ndk-r14b-windows-x86_64版本的NDK即可解决问题。