下载并集成 OpenCV
下载
首先到 OpenCV 官网,下载 Android 版本
下载后的目录结构如下
导入项目并做修改
打开 Android Studio,新建项目
然后 File ——> New ——> Import Module,选择 D:\Downloads\opencv-4.2.0-android-sdk\OpenCV-android-sdk\sdk
(该目录根据你自己下载的位置而定),引入的时候会让你输入模块名,我是填 opencv,你们可以随意用自己喜欢的名字
对 opencv 的 build.gradle 做 2 处修改
- compileSdkVersion 和 targetSdkVersion 都改为最新版
2. 编译的 Java 版本改为最新的
国内被墙,gradle 同步失败问题
修改项目根目录的 build.gradle 文件,通用模板如下(包括flutter同步失败,证数错误等问题,都可以使用该模板解决)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
//使用阿里云国内镜像
maven{ url 'https://maven.aliyun.com/nexus/content/groups/public/'}
maven{url 'https://maven.aliyun.com/repository/google'}
maven{url 'https://maven.aliyun.com/repository/jcenter'}
mavenCentral()
mavenLocal()
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
//https://github.com/JakeWharton/butterknife
classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.1'
//https://github.com/greenrobot/greenDAO
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
//AOP方案一
// classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4'
//AOP方案二:
// classpath 'org.aspectj:aspectjtools:1.8.13'
// classpath 'org.aspectj:aspectjweaver:1.8.13'
}
}
allprojects {
repositories {
maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/gradle-plugin' }
mavenCentral()
// 用来引入 rxpermission, GreenDaoUpgradeHelper 等第三方库
maven { url 'https://jitpack.io' }
mavenLocal()
// bmob后台数据库,用来更新apk
maven { url "https://raw.github.com/bmob/bmob-android-sdk/master" }
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
testOnly 问题
Android Studio 3.0会在debug apk的manifest文件application标签里自动添加 android:testOnly="true"属性,导致IDE中run跑出的apk在大部分手机上只能用 adb install -t <apk>
来安装
在项目根目录的 gradle.properties 中添加 android.injected.testOnly=false
同步一下,至此,编译成功
原理讲解
修改 MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化
if (OpenCVLoader.initDebug()) {
Toast.makeText(this, "OpenCVLoader初始化成功", Toast.LENGTH_SHORT).show();
}
}
}
OpenCVLoader 会尝试加载OpenCV 要用到的所有 so 库,如果全部加载成功并返回true,则说明集成正确。
在 OpenCV 3.0 之前,要使用 OpenCV 的功能,都必须额外安装一个 OpenCV Manager 的 apk,但 3.0 版本之后就不用了, OpenCV 的所有功能都已经被集成进 so 了,只需要调用OpenCVLoader.initAsync 然后 OpenCV 会在初始化完毕之后回调 LoaderCallbackInterface 接口的 onManagerConnected 来通知我们初始化完毕。
initDebug 代码如下
public class OpenCVLoader
{
public static boolean initDebug()
{
return StaticHelper.initOpenCV(false);
}
(略去后面代码)
}
initOpenCV 代码如下
class StaticHelper {
public static boolean initOpenCV(boolean InitCuda)
{
boolean result;
String libs = "";
if(InitCuda)
{
loadLibrary("cudart");
loadLibrary("nppc");
loadLibrary("nppi");
loadLibrary("npps");
loadLibrary("cufft");
loadLibrary("cublas");
}
Log.d(TAG, "Trying to get library list");
try
{
System.loadLibrary("opencv_info");
libs = getLibraryList();
}
catch(UnsatisfiedLinkError e)
{
Log.e(TAG, "OpenCV error: Cannot load info library for OpenCV");
}
Log.d(TAG, "Library list: \"" + libs + "\"");
Log.d(TAG, "First attempt to load libs");
if (initOpenCVLibs(libs))
{
Log.d(TAG, "First attempt to load libs is OK");
String eol = System.getProperty("line.separator");
for (String str : Core.getBuildInformation().split(eol))
Log.i(TAG, str);
result = true;
}
else
{
Log.d(TAG, "First attempt to load libs fails");
result = false;
}
return result;
}
(略去后面代码)
}
加载成功后,日志会打印如下两段内容
加载和初始化库的两类函数
在 OpenCVLoader.java 中,有两类函数用来加载 OpenCV 库
- 同步函数 initDebug(boolean InitCuda)
- 异步函数 initAsync(String Version, Context AppContext, LoaderCallbackInterface Callback)
源码如下,从注释可以看出,两类函数的功能都是一样的 —— 从应用程序包中,加载并初始化 OpenCV 库,它差不多类似 system.loadLibrary(“opencv_java”)
public class OpenCVLoader {
/**
* Current OpenCV Library version
*/
public static final String OPENCV_VERSION = "4.2.0";
/**
* Loads and initializes OpenCV library from current application package. Roughly, it's an analog of system.loadLibrary("opencv_java").
* @return Returns true is initialization of OpenCV was successful.
*/
public static boolean initDebug()
{
return StaticHelper.initOpenCV(false);
}
/**
* Loads and initializes OpenCV library from current application package. Roughly, it's an analog of system.loadLibrary("opencv_java").
* @param InitCuda load and initialize CUDA runtime libraries.
* @return Returns true is initialization of OpenCV was successful.
*/
public static boolean initDebug(boolean InitCuda)
{
return StaticHelper.initOpenCV(InitCuda);
}
/**
* Loads and initializes OpenCV library using OpenCV Engine service.
* @param Version OpenCV library version.
* @param AppContext application context for connecting to the service.
* @param Callback object, that implements LoaderCallbackInterface for handling the connection status.
* @return Returns true if initialization of OpenCV is successful.
*/
public static boolean initAsync(String Version, Context AppContext,
LoaderCallbackInterface Callback)
{
return AsyncServiceHelper.initOpenCV(Version, AppContext, Callback);
}
}
实际使用上,我们一般会先调用其同步方法判断是否已加载成功,如果未成功再调用异步加载函数,比如
if(OpenCVLoader.initDebug()) {
//执行你需要的opencv函数
} else {
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, baseLoaderCallback);
}