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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_24118527/article/details/87923390

目录

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版本

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

以OpenCV 3.4.1为例

点击这里下载OpenCV 3.4.1 for Android

下载完成后,打开压缩包

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

选择SDK文件夹

然后选择java

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

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

至此,OpenCV 3.4.1 for Android下载完成


配置SDK manager

首先打开桌面上的Android Studio

点击configure,进入配置选项

选择SDK manager

打开后,在右边选择SDK Tools

SDK Tools的页面是这样的

我们选择CMake和NDK

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

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

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

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

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

最好翻一下墙

接下来新建Android工程

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

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

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

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

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


配置OpenCV

进入刚刚新建好的工程中

选择Import Module导入模块

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

选择确定即可

点击Finish后遇到这个报错

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

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

API版本要求如下:

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

API版本要求如下:

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

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

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

选择右边的Dependencies

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

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

导入成功

点击运行,就没有报错了


导入动态库

笔者曾看过一些其他教程,里面需要我们先在手机上下载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,那么我自己写应用程序时不需要添加那些动态链接库,也可以调用之前下载好的那个应用程序里面的动态链接库了

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

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

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

选择native

这里面有两个文件夹

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

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

动态链接库和静态链接库的区别可以我的另一篇文章:

https://blog.csdn.net/qq_24118527/article/details/78569578

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

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

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

回到Android Studio

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

点击运行即可

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


示例代码

一个简单的示例程序,测试我们写的代码能否调用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


测试效果


参考博客:

https://blog.csdn.net/qq_36992688/article/details/79214273

猜你喜欢

转载自blog.csdn.net/qq_24118527/article/details/87923390