本文中,我们主要为大家介绍以下内容:
- OpenCV4Android SDK下载
- Android项目中导入OpenCV Module
- Android项目中剔除OpenCVManager apk的依赖
- 使用OpenCV完成图像灰度化
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法(更多介绍参见百度百科)
简单来说,OpenCV就是一个用于图像处理及计算机视觉的跨平台开源算法库,我们可以利用OpenCV内部提供的算法进行图像处理应用开发,或者从事计算机视觉相关方向的研发工作。
那么如何在Android平台使用OpenCV呢?我们一起来看下。
OpenCV4Android SDK
和大多数开源库一样,针对不同的平台打包不同的SDK依赖库,OpenCV也是一样的。我们可以在其官网下载OpenCV4Android SDK,这是OpenCV Android平台的依赖库,其内部包含OpenCV 在Android平台的demo项目代码以及OpenCV 源码文件。
首先打开OpenCV官网:OpenCV官网(opencv.org/)
进入官网后点击右上角的release菜单,如下图:
OpenCV发布过的所有版本,每个版本内部都会列举各个平台的依赖包,我们选择最新版本4.2.0中的Android下载4.2.0版本对应的Android平台依赖包,如下图:
- sdk:
OpenCV源码目录,该目录包含OpenCV java module,OpenCV libs文件以及OpenCV C++源码文件 - samples:
OpenCV Android示例项目目录
导入OpenCV4Android SDK
在Android Studio内新建Android项目(PS:记得勾选C++支持),构建成功后,切换到Project视图,如下所示:
import eclipse adt project,随后点击next,在接下来的窗口中选在OpenCV_SDK_PATH/sdk/java,命名导入的Module名称为lib_opencv,如下图所示:
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"
}
}
运行效果如下: