本文中,我们主要为大家介绍以下内容:
OpenCV
是一个基于BSD
许可(开源)发行的跨平台计算机视觉库,可以运行在Linux
、Windows
、Android
和Mac OS
操作系统上。它轻量级而且高效——由一系列 C
函数和少量 C++
类构成,同时提供了Python
、Ruby
、MATLAB
等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法(更多介绍参见百度百科)
简单来说,OpenCV
就是一个用于图像处理及计算机视觉的跨平台开源算法库,我们可以利用OpenCV
内部提供的算法进行图像处理应用开发,或者从事计算机视觉相关方向的研发工作。
那么如何在Android
平台使用OpenCV
呢?我们一起来看下。
和大多数开源库一样,针对不同的平台打包不同的SDK
依赖库,OpenCV
也是一样的。我们可以在其官网下载OpenCV4Android SDK
,这是OpenCV
Android
平台的依赖库,其内部包含OpenCV
在Android
平台的demo
项目代码以及OpenCV
源码文件。
首先打开OpenCV
官网:OpenCV官网(https://opencv.org/)
进入官网后点击右上角的release
菜单,如下图:
随后在这个页面我们就可以看到当前OpenCV
发布过的所有版本,每个版本内部都会列举各个平台的依赖包,我们选择最新版本4.2.0
中的Android
下载4.2.0版本对应的Android
平台依赖包,如下图:
下载完成后解压,我们可以得到如下文件目录:
其中各目录包含的主要内容如下:
OpenCV
源码目录,该目录包含OpenCV java module
,OpenCV libs
文件以及OpenCV C++
源码文件OpenCV Android
示例项目目录在Android Studio
内新建Android
项目(PS:记得勾选C++支持),构建成功后,切换到Project
视图,如下所示:
随后在项目名称(图中OpenCV01处)右键依次选择new->Module,选择完成后弹出下图界面:
向下滚动选择import eclipse adt project
,随后点击next
,在接下来的窗口中选在OpenCV_SDK_PATH/sdk/java
,命名导入的Module
名称为lib_opencv
,如下图所示:
点击next,不做操作继续点击finish
(PS:上述步骤是通用的Module
导入方式)
等待项目导入完成,切换到Android
视图,导入成功的项目结构如下图所示:
从上图可以看出,目前lib_opencv
这个module
处于不可用状态,我们修改该module
的build.gradle
文件,如下图所示:
在这里我们修改了lib_opencv
的构建类型为library
,删除了原始文件中包含的applicationid
,buildtoolsversion
信息,重新构建模块即可发现该module
已经处于可用状态,随后在app
Module
内部依赖lib_opencv
Module
,app
Module
的build.gradle
文件如下图:
至此我们就完成了OpenCV java 模块的导入。
打开app模块的MainActivity,在其onResume中进行OpenCV的初始化,代码如下:
private ImageView mImageView;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
super.onManagerConnected(status);
if (status == LoaderCallbackInterface.SUCCESS) {
//服务启动成功,灰度化图片显示到ImageView上
filterImage();
}
}
};
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = findViewById(R.id.sample_image);
}
@Override
protected void onResume() {
super.onResume();
if (!OpenCVLoader.initDebug()) {
//启动OpenCV服务
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, getApplicationContext(), mLoaderCallback);
} else {
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
//灰度化图片,暂不做代码说明,复制即可
private void filterImage() {
Mat imgMat = null;
try {
imgMat = Utils.loadResource(this, R.drawable.demo);
Imgproc.cvtColor(imgMat, imgMat, Imgproc.COLOR_RGB2BGRA);
Mat resultMat = imgMat.clone();
Imgproc.Canny(imgMat, resultMat, 80, 90);
Bitmap bitmap = Bitmap.createBitmap(resultMat.cols(), resultMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(resultMat, bitmap);
mImageView.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
哇,看起来成功了,运行一下看下呢?
我去,OpenCV Manager
是个什么鬼?原来OpenCV
考虑到应用包体积,提供了一个应用,其内部封装了OpenCV
所需要的so
库,那么就没有办法不安装OpenCV Manager
这个应用吗?毕竟我们是面向用户的,我们总不可能要求用户下载我们的应用之前再去下载一个OpenCV Manager
吧?
作为一个拥有OpenCV
源码的开发,我们是站在上帝视角的,可以随意造作,那么自己加载OpenCV
的so
文件不就好,首先看下OpenCV
SDK
里面的so
文件都在哪儿呢?在OPENCV_SDK_PATH/sdk/native/libs
下,废话不多说,首先把该目录下的所有文件拷贝到app
模块的app/src/main/jniLibs
目录下(jniLibs
目录需新建,区分大小写),如下图所示:
随后就是加载so
文件了,按理说OpenCV
SDK
里面应该有so
包加载代码或者类,搜索上图中的opencv_java4.so
试下,果然找到了一个类,如下:
public class OpenCVNativeLoader implements OpenCVInterface {
public void init() {
System.loadLibrary("opencv_java4");
Logger.getLogger("org.opencv.osgi").log(Level.INFO, "Successfully loaded OpenCV native library.");
}
}
进而修改MainActivity
代码如下:
private ImageView mImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = findViewById(R.id.sample_image);
new OpenCVNativeLoader().init();
}
@Override
protected void onResume() {
super.onResume();
filterImage();
}
private void filterImage() {
Mat imgMat = null;
try {
imgMat = Utils.loadResource(this, R.drawable.demo);
Imgproc.cvtColor(imgMat, imgMat, Imgproc.COLOR_RGB2BGRA);
Mat resultMat = imgMat.clone();
Imgproc.Canny(imgMat, resultMat, 80, 90);
Bitmap bitmap = Bitmap.createBitmap(resultMat.cols(), resultMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(resultMat, bitmap);
mImageView.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
运行下,有可能运行失败,如果你是高版本的NDK
的话,就会应用崩溃,爆出如下错误:
这是因为我们没有指定C++
标准库,在build.gradle defaultconfig
节点添加如下代码(这里就是刚开始新建为C++
支持项目的原因,当然也可以选择降低ndk
版本):
externalNativeBuild {
cmake {
cppFlags "-std=c++11 -frtti -fexceptions"
arguments "-DANDROID_STL=c++_shared"
}
}