Android studio3.5.2配置OpenCV4.2.0 C++(OpenCV4版本都适用)及配置过程中产生的一些问题
前言
这篇文章的出现完全基于巧合,对于一个没有配置过环境的孩子,作者第一次感受到了配置环境的痛苦,OpenCV给了这个卑微的作者惨痛的教训,配置环境本身就是一件令人痛苦的事情,某些傻孩子却偏偏还要选择使用最新版本,对于本就不富裕的家庭来说更是雪上加霜,奉劝看到这篇文章的朋友们,千万不要在初学的时候选用最新版本,不然你会发现你非常无助,网上的攻略全部只能作为参考,所有的内容都需要自己进行尝试和改进,对于初学者来说十分痛苦。下面请各位一起见证一下这份痛苦。
准备工作
到此网址下载OpenCV4.2.0(4版本的应该都可以),点击Android按钮下载。
自行准备一份Android studio,(旧版本一些操作按钮位置可能与文章中不同)准备工作就完成了。
一、创建项目
首先创建一个native C++项目,此处建立native C++项目的目的是为了使用C++编写OpenCV,建立空白项目没有自带CMakeLists.txt文件,需要CMakeLists.txt文件让Android studio与OpenCV C++库进行连接。点击左上角file中new中的new project选项,找到如下图中Native C++,此处的native C++文件相当于旧版本Android studio在建立新项目时勾选Include C++ support选项。
创建界面中根据需求将language改为Java,将Minimum API level尽量改到一个较低版本,这样可以让大部分机器适应程序,如果过高的话会导致一些机器不支持,此处不予演示。
点击next选项后将其中的C++ Standard改为C++ 14,此处如果忘选择标准的话可以在后面的CMakeLists.txt中自行添加。
点击finish按钮后就成功创建出了一个新项目。
二、基本依赖项配置
1、下载所需工具
项目创建完成后,点击file中的settings选项或者点击右上角第五个按钮(上图中的第五个选项),点击SDK Tools选项,勾选下方的两个选项,将隐藏的文件和列表展开,选择LLDB、NDK的任意一个版本(此教程中使用的版本为21.1.6352462,后续的一些涉及版本号的操作时按照个人下载的版本为准)、CMake的任意版本(此处为3.10.2.4988404),点击apply后等待所有安装完成(注意需要留存较大的内存空间,这几个加起来至少几个G),点击OK后完成这部分配置。
2.导入opencv android
然后点击file中的new中的import Module选项,选择下载好的OpenCV中的sdk中的java文件夹,修改名字(此处推荐修改成OpenCVLibrary+对应的版本号以便于后续使用中方便了解module的作用),点击next后不用修改,直接点击finish。
点击左侧文件列表中的OpenCVLibrary420文件夹中的build.gradle文件,(根据排版方式不同位置也不太相同,但都是OpenCVLibrary420下的build.gradle文件(在Android排版下build.gradle文件同一在一个gradle scripts文件夹中,根据后方的括号内识别),点开后上方文件名应该为OpenCVLibrary420且文件初始应该如下图所示,文件排版方式按个人喜好更改,点击图中的Project下拉菜单即可修改,一般本人会使用project或者Android,根据需求可以进行不同的选择)
将其中的com.android.application改为com.android.library,将applicationID“opg.opencv”删除,修改后代码如下。
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
defaultConfig {
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
三、配置opencv
1.使opencv成为依赖项
下一步点击file中的project structure选项或点击上图中的第一个按钮,点击左侧的SDK Location选项,将NDK一栏中选择对应的NDK文件所在位置。
注意,NDK所在的默认路径是C盘的隐藏目录下(win10查看隐藏文件的方法点击查看勾选选项),此处的参考路径为C:\Users\17485\AppData\Local\Android\Sdk\ndk\21.1.6352462,建议在文件夹中寻找到这个路径后复制到NDK location中,或者在寻找路径的时候点击上方的类似于眼睛的按钮就可以看到隐藏的目录。
随后点击Modules选项,将其中的OpenCVLibrary420的Sdk version和tools version改为和app中的Sdk version和tools version相同的版本,然后点击apply
随后点击Dependencies选项,点击其中的app,然后点击“+”后选择Module Dependency,选择OpenCVlibrary420点击OK,
如果文件中出现下图所示的OpenCVliability420则说明添加成功,如果在选择添加的时候没有找到类似于OpenCVLibrary420的文件时,可能的原因为前一步中build.gradle文件配置存在错误,可以尝试重新进行上一步操作,随后点击apply然后点击ok,相应的配置文件中就会按照这些配置的情况修改完毕。
2.拷贝opencv文件到工程中
配置完之后,要将下载好的OpenCV中的两个文件复制到工程中。找到下载好的OpenCV的库,拷贝其中的在目录sdk\native\jni下的include文件夹(include文件夹内部在OpenCV3版本貌似会有两个include,在4中只有一个opencv2,如果是三版本的话建议将两个文件都复制,但是更建议看网上的其他版本,目前感觉有些许配置差异,教程中将尽量避免),复制到app\src\main\cpp下,具体截图如下。(OpenCV3应该会有一些差异,因为文件夹中有两个文件夹,所以存放的形式上会有所差异,这个也是困扰过本人的一个问题,后来发现只要文件夹下只有一个文件加当前版本的Android studio就会按这种方式储存)
随后按下图所示创建一个名为jniLibs的文件夹,选中此选项后再按下图选中对话框的选项,然后将其中的jni改为jniLibs(注意‘L’为大写,此处一定要大写,因为后面配置中会需要输入他的名字,如果小写可能会出现不识别的问题),同样也可以直接创建一个package,将其改名为jniLibs即可。
将OpenCV中的sdk\native文件夹中的libs文件复制到创建好的jniLibs文件夹中,如下图所示。(OpenCV3中应该存在多于示例中OpenCV4的4个文件夹,大约有7个左右,应该根据版本的不同有所变化,后续添加中一定要注意有地方与所演示的OpenCV4的一些区别)
四、修改工程的配置文件
1.build.gradle
下一步是比较重要的一步,也是其中最折磨人的一步——修改app的build.gradle,此文件的位置如下图所示。
首先,将android节点下的sourceSets改为:
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs/libs']
}
}
如果android节点下没有就直接将上方的话添加在节点中,如果创建方法按照之前所说的创建一个jni文件夹的话这一部分中只需在jniLibs后方添加一个libs,如果直接创建了一个文件夹的话应该是没有sourceSets节点的,一定注意之前的文件夹名字没有创建错误,否则这一步操作的文件夹名字应该按个人的文件夹名字进行修改。(本人没进行尝试,不确保正确性)
然后,将android节点下的defaultConfig节点下的externalNativeBuild改为:
externalNativeBuild {
cmake {
cppFlags "-std=c++14 -frtti -fexceptions"
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
arguments '-DANDROID_STL=c++_shared'
}
}
}
此处cmake节点中的配置缺少会导致出现一下错误,再将整体代码放出后会进行讲解。
完整代码如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.example.opencv420"
minSdkVersion 15
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-std=c++14 -frtti -fexceptions"
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
arguments '-DANDROID_STL=c++_shared'
}
}
}
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"//按自身struct下载的版本来
}
}
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs/libs']
}
}
}
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: ':OpenCVLibrary420')
}
注意,dependencies里面的最后一句话是根据module的名字决定的,如果module名字有差异,请不要修改成本例子的形式。可能对于大家来说此处只添加、修改了几行代码,其实本人在尝试配置过程中因为各式各样的错误进行了大量的尝试,由于本人没有接触过Android的开发工作,所以很多配置并不清楚具体是更改什么内容的,目前教程中的都是经过多番尝试(不停地注释看工程是否报错,经常一个配置就需要1-2分钟,做的时候挺绝望的)后得到的最简版的,在后续开发中如果还存在问题,本教程中可能无法给出解决措施。
下面说一下几个碰到的错误:
- Gradle project cmake.path is XXX but that file doesn’t exist
这个问题是由于android节点下的externalNativeBuild节点中CMakeLists.txt文件存放的位置与所输入的位置有误,如果是此案例下版本的Android studio且创建的是native C++项目,那路径应该与案例中的相同。案例中的CMakeLists.txt文件位置参考如下:
- app配置文件成功但是闪退
(1)第一种可能:android节点下的defaultConfig节点下的externalNativeBuild中缺少arguments ‘-DANDROID_STL=c++_shared’,这个错误目前只知道解决方法,不太清楚其中的工作原理,在此不进行说明。
(2)第二种可能:报错为java.lang.UnsatisfiedLinkError: dlopen failed: library “libopencv_java4.so” not found ,原因是android节点下的sourceSets下的路径存在错误,这个具体见上文,此处本例中的路径为jni.srcDirs = [‘src/main/jniLibs/libs’],附此文件夹所在位置截图:
2.CMakeLists.txt
然后进行下一步工作,同样一个让本人卡了很久的问题,具体问题会向上一步一样在教程之后有一个总结,下面进行第一步,找到app文件夹下的src文件夹下的main文件夹下的cpp文件夹下的CMakeLists.txt文件(如上图所示,虽然上图目的不是展示CMakeLisits.txt文件的),然后在cmake_minimum_required(VERSION 3.4.1)下面添加
include_directories(${CMAKE_SOURCE_DIR}/include)
add_library(libopencv_java4
SHARED
IMPORTED)
set_target_properties(libopencv_java4
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/../jniLibs/libs/${ANDROID_ABI}/libopencv_java4.so)
切记,你的OpenCV版本是4且CMakeLists.txt文件位置与例子中相同的时候才可以直接复制粘贴,否则你需要了解这些代码如何根据自己的情况修改,下面我将叙述一下。首先第一步include_directories是要找到之前OpenCV中复制过来的jni文件夹下的include文件夹,而${CMAKE_SOURCE_DIR}意思是当前工程中CMakeLisits.txt文件所在位置,所以要根据个人当前CMakeLisits.txt文件的位置对相对路径进行修改。下一步,add_library中libopencv_java4最后是3还是4,这个看你的OpenCV版本而定,下面先展示一下如何确定是3还是4,首先看一下这张图
这个图中相信已经反映了很多问题,检查一下jniLibs文件夹中的libs文件夹中的每个文件夹的文件,根据其中的名字修改add_library中的libopencv_java。
下一步,修改set_target_properties,其中${CMAKE_SOURCE_DIR}是活的当前路径,由于本例子中的jniLibs文件夹与cpp文件夹同级,所以首先返回了上一步,${ANDROID_ABI}这句的含义其实本人没有完全研究明白,但大致的意思应该为根据Android机型的不同所使用的库也有所不同,然后后面的libopencv_java修改原理同上。(此处截图可以参考上两张图)。
随后,在target_link_libraries中添加libopencv_java4(此处是3还是4同理),具体改完后为
target_link_libraries( # Specifies the target library.
native-lib
libopencv_java4 # 链接opencv的so
# Links the target library to the log library
# included in the NDK.
${log-lib} )
最终本案例中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_minimum_required(VERSION 3.4.1)
# 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.
include_directories(${CMAKE_SOURCE_DIR}/include)
add_library(libopencv_java4
SHARED
IMPORTED)
set_target_properties(libopencv_java4
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/../jniLibs/libs/${ANDROID_ABI}/libopencv_java4.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)
# 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.
native-lib
libopencv_java4 # 链接opencv的so
# Links the target library to the log library
# included in the NDK.
${log-lib})
然后就是检验当前配置后的结果的时候了,点击下图中的第三个按钮(长得像大象的那个)
如果没有出现错误,那恭喜你,配置环节已经全部成功,如果出现问题,可以到教程上面看看有没有碰到同样的错误。
本人在此处碰到的一些问题:
- executing external native build for cmake XXX(困扰我最久的问题)
网上有很多很多关于此问题的解决方法,但对于我来说一个都不适用,后来终于发现了这个问题产生的原因,add_library中libopencv_java最后的数字存在错误,一定要观察到底是OpenCV3还是OpenCV4,此问题在给出CMakeLists.txt文件代码前进行过详细的叙述,这里不再进行详细的说明。(如果此方法没有解决建议看看网上其他出现的相同错误地解决方法) - FAILURE: Build failed with an exception.
Error while executing process XXX with arguments {-C XXX app.cxx\cmake\debug\armeabi-v7a native-lib}
ninja: Entering directory XXX
这个错误出现的原因有两个,第一种是由于include_directories下的路径出现问题,第二种是set_target_properties下的路径出现问题,这里具体的修改方法是修改其中的路径,此部分在上文中同样进行了详细的叙述,此处不进行过多的介绍。
五. 测试准备工作
下面有一个用来测试OpenCV库是否连接的函数,找到app文件夹下的src文件夹下的src文件夹下的java文件夹下的应该是唯一一个文件下的MainActivity,具体位置如下图
将整体文件更改为(建议把初始内容注释作为保留)(第一行的package保留)
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import org.opencv.android.OpenCVLoader;
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("loading");
initLoadOpenCVLibs();
}
private void initLoadOpenCVLibs() {
boolean success = OpenCVLoader.initDebug();
if (success) {
System.out.println("loading success");
Log.d("test", "initLoadOpenCVLibs:OpenCV加载成功!");
} else {
System.out.println("loading failed");
Log.d("test", "initLoadOpenCVLibs:OpenCV加载失败!");
}
}
}
然后打开你的模拟器或者手机尝试运行此程序,运行点击下图三角按钮:
如果出现
Installation did not succeed. The application could not be installed: INSTALL_PARSE_FAILED_NO_CERTIFICATES APK signature verification failed.
原因是软件缺少安全签名导致模拟器不认,所以我们需要添加一个签名。
六、设置签名
首先在上方的build中找到Generate Signed Bundle/APK…(不同版本的Android studio存在差异)
选中APK后点击next
点击其中的create new选项,点击第一行Key store path的后面的文件夹按钮,找到项目存储的路径后,点击到app文件夹(参考路径:C:\Users\17485\AndroidStudioProjects\OpenCV420\app),在下方file name中随意填入一个名字(本例子中填入的为aaa),然后点击ok
在上下的两个password和confirm中填入密码(本例子中填入的为123456,后续例子中需要用到),然后其余的空可以随便填一下,然后点击ok。
报的错误先不用管他(后面如果app需要正规的签名的话请根据自身需求进行修改,本例子中的目的是为了让项目正常运行),然后点击next,
把v1和v2选项全部勾选上,然后点击finish。
此时的签名文件就已经创建好了。
七、测试最终工作
然后再回到app的build.gradle里,在Android节点下添加(添加的具体文件名、密码、路径等按自身情况进行修改)(只有完全按照本教程步骤走的才可以直接复制)
signingConfigs {
debug {
keyAlias 'aaa'
keyPassword '123456'
storeFile file('aaa.jks')
storePassword '123456'
v2SigningEnabled false
}
release {
keyAlias 'aaa'
keyPassword '123456'
storeFile file('aaa.jks')
storePassword '123456'
v2SigningEnabled false
}
}
然后重新点击那个像大象(第三个)一样的按钮进行配置文件的编译,再点击运行,
然后在view中选中tool window点击其中的logcat选项,
然后在最下方的输入栏中输入,initLoadOpenCVLibs:OpenCV,如果出现initLoadOpenCVLibs:OpenCV加载成功!则说明配置成功,函数库也连接成功,自此可以使用所有成功截图如下:
如果出现错误,找到第二个下拉菜单的如下图所示的包(具体名字会根据工程文件的名字的不用有所差异,大致为com.example.‘工程名’)(括号数字不用在意)
然后找到initLoadOpenCVLibs:OpenCV加载失败!处,往前看程序返回的报告,里面应该会有error,根据具体error的不同进行解决,本教程中出现过错误但忘了怎么出的错误和解决方法了,由于这个错误出现的情况较多,教程中也不能一言以蔽之,所以只能由各位自己寻找。
自此,工程可以*地使用OpenCV库了,后续的开发工作这里也帮不上各位,只能在此对各位进行祝福。
本文地址:https://blog.csdn.net/Sluonbby/article/details/107183904
上一篇: 词条国际化开发规范Demo
下一篇: Pygame 打字游戏项目实例