当前位置:首页 > IT技术 > 移动平台 > 正文

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)
2021-10-28 15:18:57

目录

​OpenCV​

​OpenCV的下载​

​配置SDK manager​

​配置OpenCV​

​导入动态库​

​示例代码​

​测试效果​

​参考博客:​



近期课题需要用Android实时处理视频,所以做了一些这方面的工作

本文示例代码地址:​​https://github.com/nikolajohn/OpenCVtest​

推荐一个基于Android OpenCV的目标检测项目:​​https://github.com/nikolajohn/OpenCVForAndroid​



OpenCV

OpenCV全称Open Source Computer VisoVision Library,是一个基于BSD开源协议的跨平台计算机视觉库。OpenCV实现了多种实时且高效的计算机视觉和图像处理通用算法,并且可以利用计算机底层硬件平台进行硬件加速。



OpenCV的下载

打开OpenCV主页:​​https://opencv.org/​

并选择发行的Release版本

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_Android

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_OpenCV_02

这里可以选择我们需要的OpenCV版本

以OpenCV 3.4.1为例

点击这里下载OpenCV 3.4.1 for Android

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_android_03

下载完成后,打开压缩包

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_Android_04

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_动态链接库_05

我们可以先看一下,这里面都有什么

选择SDK文件夹

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_c++_06

然后选择java

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_c++_07

可以发现,这和我们自己新建的Android工程目录下的文件很像

待会儿会提到,这个目录将以Module的形式加载到我们自己新建的Android项目中

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_动态链接库_08

至此,OpenCV 3.4.1 for Android下载完成



配置SDK manager

首先打开桌面上的Android Studio

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_c++_09

点击configure,进入配置选项

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_c++_10

选择SDK manager

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_动态链接库_11

打开后,在右边选择SDK Tools

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_OpenCV_12

SDK Tools的页面是这样的

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_android_13

我们选择CMake和NDK

CMake是一个跨平台的编译工具,能够输出各种各样的makefile文件,这个在之后OpenCV编译阶段需要用到

NDK是Android平台下的一个开发工具包,使用NDK可以快速地开发C、C++的以.so为后缀的动态库,并自动将.so动态库与应用打包成.apk文件,这也是后面需要用到的

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_OpenCV_14

选择好后,点击Apply应用,即可开始下载

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_动态链接库_15

下载之前,会提醒你要下载的版本,点击确定即可

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_c++_16

稍微等待一下,速度还是挺快的

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_OpenCV_17

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_Android_18

最好翻一下墙

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_动态链接库_19

接下来新建Android工程

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_OpenCV_20

填写项目名称,记得勾选上支持C++,因为我们用到的OpenCV是用C、C++编写的

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_动态链接库_21

SDK版本我们选择默认即可,一般来说是API 15

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_c++_22

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_Android_23

接下来的默认Activity,名字可以直接用默认的MainActivity,也可以修改一下

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_动态链接库_24

接下来是选择C++支持相关的一些选项,记得和下图选择一样即可

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_OpenCV_25

至此,配置好NDK和C++支持的Android工程新建完成

 



配置OpenCV

进入刚刚新建好的工程中

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_OpenCV_26

选择Import Module导入模块

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_android_27

选一下路径,就是我们下载好OpenCV 3.4.1 for Android后提到的那个文件夹

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_Android_28

选择确定即可

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_Android_29

点击Finish后遇到这个报错

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_c++_30

这是我们的项目API版本和刚导入模块的API版本不一致导致的

我们的项目API版本要求在这里打开

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_Android_31

API版本要求如下:

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_OpenCV_32

刚导入的Module的API版本要求如下:

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_动态链接库_33

API版本要求如下:

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_动态链接库_34

把Module里面的API版本要求根据我们自己新建项目的API版本要求修改即可

这时候可能还会有其他的报错,但是先不用管,把下面的配置工作先做完

接下来导入模块,首先打开Project Structure

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_c++_35

选择右边的Dependencies

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_Android_36

选择右边的小加号,添加Module Dependency

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_OpenCV_37

选择OpenCVLibrary341,就是我们刚刚导入的Module

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_c++_38

导入成功

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_OpenCV_39

点击运行,就没有报错了



导入动态库

笔者曾看过一些其他教程,里面需要我们先在手机上下载OpenCV Manager

然后才能运行我们自己的Android应用程序

这显然是没有必要的

OpenCV Manager是OpenCV 用于管理Android下的OpenCV动态链接库的

通过OpenCV Manager这个东西,可以实现只要在同一个设备上,都可以共享OpenCV的动态链接库

什么意思呢?

就是说我现在用Android去调用OpenCV

其实我是不能直接用java调用C++的,我的java代码只能Import其他的java包

也就是说,我的java代码只能去调刚导入的那个Module里面的包

而Module里面的java代码也是不能直接调用C++的,而是需要以动态链接库的形式,间接地调用C++

那么这些动态链接库怎么来的呢?

第一种方法比较简单,其实我们之前下载的OpenCV 3.4.1 for Android里面就已经包含了这些动态链接库

我们只需要把它放进我们的项目里面来就好了

第二种方法就是使用所谓的OpenCV Manager

我先要下载一个OpenCV Manager应用程序,这个OpenCV Manager里面是带有这些动态链接库的

然后只要我现在的手机上有这个OpenCV Manager,那么我自己写应用程序时不需要添加那些动态链接库,也可以调用之前下载好的那个应用程序里面的动态链接库了

我比较推荐第一种方法,做法如下:

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_OpenCV_40

选择Directory,新建一个目录,命名为jniLibs

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_动态链接库_41

回到我们刚刚下载的OpenCV 3.4.1 for Android

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_Android_42

选择native

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_android_43

这里面有两个文件夹

libs里面放的是动态链接库,文件以.so结尾

staticlibs里面放的是静态库,文件以.a结尾

我们用的是动态链接库,因此选择libs文件夹打开

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_Android_44

把这个目录下的所有文件复制一下

这些文件夹的名字表示不同的处理器架构

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_Android_45

回到Android Studio

直接在刚刚新建好的目录下粘贴即可

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_c++_46

点击运行即可

至此,动态链接库的导入完成



示例代码

一个简单的示例程序,测试我们写的代码能否调用OpenCV

JavaActivity

package cn.edu.zju.myopencv;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

import java.io.InputStream;

public class JavaActivity extends AppCompatActivity {



// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}


private double max_size = 1024;
private int PICK_IMAGE_REQUEST = 1;
private ImageView myImageView;
private Bitmap selectbp;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_java);
staticLoadCVLibraries();
myImageView = (ImageView)findViewById(R.id.imageView);
myImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
Button selectImageBtn = (Button)findViewById(R.id.select_btn);
selectImageBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// makeText(MainActivity.this.getApplicationContext(), "start to browser image", Toast.LENGTH_SHORT).show();
selectImage();
}

private void selectImage() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"选择图像..."), PICK_IMAGE_REQUEST);
}
});

Button processBtn = (Button)findViewById(R.id.process_btn);
processBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// makeText(MainActivity.this.getApplicationContext(), "hello, image process", Toast.LENGTH_SHORT).show();
convertGray();
}
});

}

private void staticLoadCVLibraries() {
boolean load = OpenCVLoader.initDebug();
if(load) {
Log.i("CV", "Open CV Libraries loaded...");
}

}

private void convertGray() {
Mat src = new Mat();
Mat temp = new Mat();
Mat dst = new Mat();
Utils.bitmapToMat(selectbp, src);
Imgproc.cvtColor(src, temp, Imgproc.COLOR_BGRA2BGR);
Log.i("CV", "image type:" + (temp.type() == CvType.CV_8UC3));
Imgproc.cvtColor(temp, dst, Imgproc.COLOR_BGR2GRAY);
Utils.matToBitmap(dst, selectbp);
myImageView.setImageBitmap(selectbp);
}


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
Uri uri = data.getData();
try {
Log.d("image-tag", "start to decode selected image now...");
InputStream input = getContentResolver().openInputStream(uri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(input, null, options);
int raw_width = options.outWidth;
int raw_height = options.outHeight;
int max = Math.max(raw_width, raw_height);
int newWidth = raw_width;
int newHeight = raw_height;
int inSampleSize = 1;
if(max > max_size) {
newWidth = raw_width / 2;
newHeight = raw_height / 2;
while((newWidth/inSampleSize) > max_size || (newHeight/inSampleSize) > max_size) {
inSampleSize *=2;
}
}

options.inSampleSize = inSampleSize;
options.inJustDecodeBounds = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
selectbp = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);

myImageView.setImageBitmap(selectbp);

} catch (Exception e) {
e.printStackTrace();
}
}
}
}


相应的layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_java"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cn.edu.zju.myopencv.JavaActivity"
android:orientation="vertical"
>

<Button
android:id="@+id/select_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="选择图片" />

<Button
android:id="@+id/process_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="处理" />

<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</LinearLayout>

这里都是些很简单的代码,主要为了测试功能

大家不用自己打了,直接去github下载即可

地址:​​https://github.com/nikolajohn/OpenCVtest​



测试效果

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_android_47

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_OpenCV_48

Android Studio 3.2.1 配置 OpenCV 详解(2019年2月)_动态链接库_49



本文摘自 :https://blog.51cto.com/u