上一篇文章讲解了Android studio配置opencv并实现不需要集成opencv manager就可以在手机上调用摄像头进行图像处理。本来打算先发一篇在Android studio上进行图像实时处理的文章,结果最近遇到了一个问题,就是很多opencv的处理函数需要用C++来实现更加方便,用java来写会非常的头疼。上网一查发现可以通过Android的JNI接口来实现调用本地C++代码,于是抓紧开始配置起来,这一配置就耗了两天时间,问题非常多,好在终于配置成功了,于是打算趁热打铁,赶紧记录下来,避免之后忘记。废话不多说,进入主题。
一:软件工具介绍:
1:Android studio3.6版本,我用的是目前最新的版本,遇到的问题也是最多的,下面会一一讲述
2:AndroidSDK
3:OpenCV-android-sdk
4:AndroidNDK
5:CMake
二:安装包相关内容现在
(1)安装配置Android studio,这一步不多说,网上做资料很多
(2)下载opencv for Android版,这个可以在官网下载,下载最新的版本就可以,下载下来后进行解压。也可以下载我上传的的这个版本,亲测能用。
下载地址:链接:https://pan.baidu.com/s/1ciZGQjA3lUtCTIyHGdopBw
提取码:wo97
(3)下载Android NDK,CMake,在setting页面中进行下载,如图
三:新建C++项目,并添加opencv相关包
(1)新建C++支持的项目,直接选择 Native C++
C++版本三种随便选,我选的C++11,然后Finish,等待新建完成
(2)项目建成后,直接可以在虚拟机或者手机上跑了,新版的Android studio和老版不一样,我们创建的Native c++项目自身已经配置好了JNI接口。接下来要把opencv配置到项目中,这和我上一篇博客内容是一模一样的配置方法:
依次点击
File–>New–>Import Module
1)选择H:\AndroidProgram\OpenCV-android-sdk\sdk\java
2)Module name: Android studio会自动填充这项为openCVLibrary343 (不同版本对应的数字也不一样),不用管它.
3)点击下一步,会出现三个复选框,都选上,点击Finish
4)File–>Project Structure
5)左边Dependencies栏下选择app
6)在右边挨着的上面一栏中可以看到+号
7)点击右边栏中的“+”,选择第三个Module Dependency
8)里面应该是对应的opencv的包文件,点击ok退出,然后再点击ok退出
9)对app的build.gradle和opencv的build.gradle文件进行版本号的修改,使得两个文件中版本号一致
10)删除opencv下AndroidManifest.xml中的<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" />
,配置完成,点击Build-Make project,等待构建完成。
配置这一步的目的不是因为C++代码需要,而是因为java代码中需要这些包,网上很多文章都没有这一步的配置,仅仅只配置jni接口的话,我们在activity中就无法调用opencv的函数。
四:配置opencv的JNI接口
(1)拷贝opencv所需的库文件和头文件
1)把opencv Android sdk下的OpenCV-android-sdk/sdk/native/jni/include文件夹拷贝到你的项目中src/main/cpp下面。
2)把opencv Android sdk下的OpenCV-android-sdk/sdk/native/libs文件夹拷贝到你的项目中src/main/下面。并修改名字为jniLibs。
完成后,Android studio中项目结构图如下:
(2)对CMake文件进行修改,打开CMakeLists.txt文件,添加如下代码,推荐直接复制,修改的地方只有最上面和最下面两部分,中间部分均为系统生成的内容,没有改变。
cmake_minimum_required(VERSION 3.4.1)
# 设置include文件夹的地址
include_directories(${CMAKE_SOURCE_DIR}/include)
# 设置opencv的动态库,注意这里需要把项目路径填写进去,尽量注意不要填写错误,
# 笔者在这里也遇到过路径错误导致找不到.so文件
add_library(libopencv_java3 SHARED IMPORTED)
set_target_properties(libopencv_java3 PROPERTIES IMPORTED_LOCATION
H:/AndroidProgram/Grsture02/app/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp)
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)
target_link_libraries( # Specifies the target library.
native-lib
libopencv_java3
# Links the target library to the log library
# included in the NDK.
${log-lib})
需要注意的是,设置include文件夹的地址:include_directories(${CMAKE_SOURCE_DIR}/include),这里直接写/include,不要写成/src/main/include这种格式,否则无法调用。还有最后面的target_link_libraries()下记得添加libopencv_java3。
(3)配置app的build.gradle文件,打开app的build.gradle文件,进行如下添加。显示图解,后面是代码块,请务必对应位置添加代码,尤其是结点不要搞错了:
1)添加的的第一部分,cmake后面加ndk{}
2)添加第二部分:
3)添加的第三部分
代码如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.example.grsture02"
minSdkVersion 24
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
}
}
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
}
sourceSets{
main{
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
splits {
abi {
enable true
reset()
include 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' //select ABIs to build APKs for
universalApk true //generate an additional APK that contains all the ABIs
}
}
project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
output.versionCodeOverride =
project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + android.defaultConfig.versionCode
}
}
}
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.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation project(path: ':opencv')
}
至此,opencv的jni接口配置就完成了。
(4)这个时候请先点击Build-Make project构建一下程序。然后打开native-lib.cpp文件,这是我们要写C++代码的文件,写过C++的应该都知道.cpp文件。先试着引入一下包,
输入#include <opencv2/opencv.hpp>,如果变成绿色而不是红色,那么恭喜你,配置成功了,可以开始在Android平台下用C++来开发opencv代码了。
如果发现还是红色,证明包没能正常导入,这个时候不要急,点一下“RUN app”,不出问题的话,会变成绿色的。不知道为什么,我在配置的时候,就是因为这个问题一直卡了一天,因为包名是红色,所以一直没有去点击“RUN app”,后来无意间点了一下,没想到跑了一下,所有的包就正常引入了。