简单的调用OpenCV库的Android NDK开发 工具Android Studio

时间:2022-03-01 05:05:23

前言

本博客写于2017/08/11, 博主非专业搞安卓开发, 只是工作的需要倒腾了下Android NDK相关的开发, 博文中有什么不正确、不严格的地方欢迎指正哈    本文后续也许还会有删改, 就这样。

一、工具、开发环境

博主的操作系统是Windows 10 x64位,虽然感觉Windows 7更适合用来搞开发, 但是用着Win 10也是挺好使的(没必要在操作系统上有很大纠结,Win 10和Win 7都可以)。

1.搭建并测试JAVA开发环境

首先要搭建Java开发环境,Java开发环境的搭建教程网上可以找到,这里不予赘述; 测试是否搭建成功的时候,需要打开命令提示符依次输入java、javac、javah命令进行测试,显示如下界面结果就成功了:

简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio

图一    java命令测试
简单的调用OpenCV库的Android NDK开发    工具Android Studio
简单的调用OpenCV库的Android NDK开发    工具Android Studio
 图二    javac命令测试
简单的调用OpenCV库的Android NDK开发    工具Android Studio
简单的调用OpenCV库的Android NDK开发    工具Android Studio
 图三    javah命令测试

 

2.搭建Android开发环境

很长一段时间内,Eclipse + ADT插件是Android开发的主流,不过现在流行的是Android Studio。 还记得Android Studio刚出来的时候很是不被看好, 不过现在它也是很好用的安卓开发工具了,此文介绍的所需要的工具只有Android Studio。

网上有介绍说设置ndk-build环境变量的, 但是要弄明白一件事, 他们设置这个变量是因为他们的"NDK"这个依赖包是单独下载的, 并没有在Android Studio里面下载, 本文的"NDK"依赖包是在Android Studio里面下载的, 因此并不需要设置ndk-build环境变量。

开始正式搭建环境,我用的是Android Studio 2.2.3版本。 安装完Android Studio之后, 选择"File" -> "Settings" -> "Appearence & Behavior" -> "System Settings" -> "Android SDK", 配置 "SDK Platforms"
和 "SDK Tools" :

(1)"SDK
Platforms":这个是选择安卓SDK版本,根据自己想法跟需要下载,我下载了安卓4.4、5.0、7.1.1

简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio

 
(2)"SDK Tools":这个是选择SDK相关开发工具,基础的"NDK"包(必选)是必须有的,刚安装上Android
Studio的时候默认有什么包我忘了,"Android SDK Build-Tools"这个包应该不用自己勾选,默认就有。NDK开发现在提供了CMake的方式来进行编译调试,通过下载"CMake"跟"LLDB"这俩(可选)就可以用CMake来开发了,本文未基于CMake的方式进行编译调试,而是采用的传统的gradle方式(相对而言,我其实更推荐使用CMake的方式)。
简单的调用OpenCV库的Android NDK开发    工具Android Studio
 简单的调用OpenCV库的Android NDK开发    工具Android Studio
(3)正如(2)中所说的, 我采用的是gradle的方式进行的开发, 本文不介绍CMake的方式。 所以在采用gradle的基础上,才有了这第(3)步骤。
这一步就是为了更方便的进行gradle方式的开发而写的。 
可以将gradle经常用到的一些命令简化到菜单中,具体设置在"File" -> "Settings" -> "Tools" -> "External Tools"这里:
简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio
1) 添加javah,它用于生成头文件
简单的调用OpenCV库的Android NDK开发    工具Android Studio
简单的调用OpenCV库的Android NDK开发    工具Android StudioProgram:$JDKPath$/bin/javah

Parameters: -d
../jni -jni $FileClass$


Working directory: $SourcepathEntry$\..\java

最后单击"OK"按钮进行保存。

2) 添加ndk-build,它用于构建so包

简单的调用OpenCV库的Android NDK开发    工具Android Studio

简单的调用OpenCV库的Android NDK开发    工具Android StudioProgram: 你的NDK目录\build\ndk-build.cmd

Parameters: 什么都不用填

Working directory:$ModuleFileDir$\src\main

最后单击"OK"按钮进行保存。

3) 添加ndk-build
clean,它用于清理so包

简单的调用OpenCV库的Android NDK开发    工具Android Studio

简单的调用OpenCV库的Android NDK开发    工具Android StudioProgram: 你的NDK目录\build\ndk-build.cmd

Parameters: clean

Working directory:$ModuleFileDir$\src\main

最后单击"OK"按钮进行保存。



3.来一个栗子

一个NDK开发项目总体就分为生成so库、调用so库两部分,本博客栗子就是先将基于OpenCV的C++代码编译生成so库,再通过jni接口来实现对安卓摄像头的灰度化处理。

(1)首先新建一个工程

1)选择新建项目:

简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio

 2)填入一些基本信息, 不勾选"Include C++ Support", 然后Next:
简单的调用OpenCV库的Android NDK开发    工具Android Studio
 简单的调用OpenCV库的Android NDK开发    工具Android Studio3)默认就可以了,继续Next:
简单的调用OpenCV库的Android NDK开发    工具Android Studio
简单的调用OpenCV库的Android NDK开发    工具Android Studio 4)继续Next:
简单的调用OpenCV库的Android NDK开发    工具Android Studio
 简单的调用OpenCV库的Android NDK开发    工具Android Studio5)最后Finish:
简单的调用OpenCV库的Android NDK开发    工具Android Studio
简单的调用OpenCV库的Android NDK开发    工具Android Studio
 
(2)项目创建完毕了,开始向项目中导入OpenCV库
1)去OpenCV官网下载OpenCV for Android版本,  我下载的是2.4.9版本,下载下来的是一个压缩包, 名字是"OpenCV-2.4.9-android-sdk", 我们将其解压放到某个位置, 待会会用到。 我将其解压缩到了D:\Usual\Android目录下面。
2)选择导入组件:
简单的调用OpenCV库的Android NDK开发    工具Android Studio
简单的调用OpenCV库的Android NDK开发    工具Android Studio
3)选择文件夹
简单的调用OpenCV库的Android NDK开发    工具Android Studio
 简单的调用OpenCV库的Android NDK开发    工具Android Studio
在我这里, 就找到刚才解压位置OpenCV for Android包那里, 找到java文件夹然后"OK"开始确认。
简单的调用OpenCV库的Android NDK开发    工具Android Studio
简单的调用OpenCV库的Android NDK开发    工具Android Studio
接下来默认即可, "next"然后"finish"。
4)接下来还需要将OpenCV库添加到依赖:
简单的调用OpenCV库的Android NDK开发    工具Android Studio

简单的调用OpenCV库的Android NDK开发    工具Android Studio
 选择Project Structure之后, 弹出以下画面, 按图示进行操作来添加依赖:

简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio

 5)进行一些必要的小修改

切换到"Project"视图界面,

简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio

 将openCVLibrary249目录下的build.gradle向"app"->"src"下的build.gradle看齐, 也就是将前者的这四项参数修改的和后者一样:
简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio
 修改之后还需要单击"Sync Now"来更新一下:
简单的调用OpenCV库的Android NDK开发    工具Android Studio
简单的调用OpenCV库的Android NDK开发    工具Android Studio
 至此,算是正式导入成功OpenCV库。

(3)开始生成so库
首先分析一下项目, 整个项目要实现对安卓摄像头的实时灰度化, 我们在java类里面来实现摄像头画面的获取, 用C/C++代码来实现对一帧图像(一幅图像)的灰度化。
NDK开发将C/C++代码生成so库, 留一个对单幅图片进行灰度化的接口, 然后我们在Java层获取摄像头数据, 通过JNI调用所生成so库的接口, 对每一帧摄像头数据进行灰度化。
那么现在可以生成so库了。
 1)在app->src->main右键新建一个jni文件夹, 操作指示如图:
简单的调用OpenCV库的Android NDK开发    工具Android Studio
 简单的调用OpenCV库的Android NDK开发    工具Android Studio
单击"JNI Folder"会出现一个界面来确认操作, 选择界面上的"Finish"结束即可。

2)新建一个类OpencvClass,负责与C/C++代码对接。

简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio

 简单的调用OpenCV库的Android NDK开发    工具Android Studio

简单的调用OpenCV库的Android NDK开发    工具Android Studio

 3)开始生成C/C++头文件
打开新创建的类文件,添加一行代码:
 
 
 
 
 
 
 
1
    public native static int convertGray(long matAddrRgba, long matAddrgray);
 
 

接下来,右键单击类OpencvClass,来生成C/C++头文件

简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio

 生成成功后会在main文件夹下多出来一个jni文件夹,里面有个头文件:
简单的调用OpenCV库的Android NDK开发    工具Android Studio
 简单的调用OpenCV库的Android NDK开发    工具Android Studio
接下来新建一个.cpp文件,名字和该头文件一样,如下图所示操作:

简单的调用OpenCV库的Android NDK开发    工具Android Studio

 输入.cpp名字, 然后单击"OK"结束。

简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio

 4)开始写.c/.cpp源文件

上一步生成了头文件, 此头文件内容是:

<wiz_code_mirror>
 
 
 
 
 
 
 
1
/* DO NOT EDIT THIS FILE - it is machine generated */
2
#include <jni.h>
3
/* Header for class com_hoos_grayprocessing_OpencvClass */
4
5
#ifndef _Included_com_hoos_grayprocessing_OpencvClass
6
#define _Included_com_hoos_grayprocessing_OpencvClass
7
#ifdef __cplusplus
8
extern "C" {
9
#endif
10
/*
11
 * Class:     com_hoos_grayprocessing_OpencvClass
12
 * Method:    convertGray
13
 * Signature: (JJ)I
14
 */
15
JNIEXPORT jint JNICALL Java_com_hoos_grayprocessing_OpencvClass_convertGray
16
  (JNIEnv *, jclass, jlong, jlong);
17
18
#ifdef __cplusplus
19
}
20
#endif
21
#endif
 
 

其中, JNIEXPORT是接口声明, 我们需要在cpp源文件里将它实现, 这里当然需要我们有C/C++基础, 可以写出cpp文件的框架了:

 
 
 
 
 
 
 
1
//
2
// Created by HooS on 2017/8/14.
3
//
4
#include <com_hoos_grayprocessing_OpencvClass.h>
5
6
7
JNIEXPORT jint JNICALL Java_com_hoos_grayprocessing_OpencvClass_convertGray
8
  (JNIEnv *, jclass, jlong, jlong){
9
  
10
  }
 
 

在实现时, 接口的两个jlong类型需要用来传输OpenCV里面的Mat类型数据, 所以要略微修改一下那里:

<wiz_code_mirror>
 
 
 
 
 
 
 
1
//
2
// Created by HooS on 2017/8/14.
3
//
4
#include <com_hoos_grayprocessing_OpencvClass.h>
5
6
7
JNIEXPORT jint JNICALL Java_com_hoos_grayprocessing_OpencvClass_convertGray
8
  (JNIEnv *, jclass, jlong addrRgba, jlong addrGray){
9
  
10
  }
 
 

然后完善代码,完善JNI接口数据转换,实现单幅图像的灰度化功能:

 
 
 
 
 
 
 
1
//
2
// Created by HooS on 2017/7/25.
3
//
4
#include <com_hoos_ndkopencvtest_OpencvNativeClass.h>
5
6
7
JNIEXPORT jint JNICALL Java_com_hoos_ndkopencvtest_OpencvNativeClass_convertGray
8
  (JNIEnv *, jclass, jlong addrRgba, jlong addrGray){
9
       // 实现jlong类型到Mat类型的转换
10
       Mat& mRgb = *(Mat*)addrRgba;
11
       Mat& mGray = *(Mat*)addrGray;
12
       
13
       // 定义 int 和 jint 类型来接收函数返回值
14
       int conv;
15
       jint retVal;
16
       // 此处调用了toGray函数来对图片进行灰度化处理
17
       conv = toGray(mRgb, mGray);
18
19
       retVal = (jint)conv;
20
       return retVal;
21
  }
 
 

看注释可以知道, 我们还需要实现toGray函数来实现单幅图片的灰度化, 这个实现代码很简单, 为啥非得再麻烦些折腾些呢, 因为大项目往往会有好多源文件, 相互调用, 所以之前最好有多源文件编译的机会来锻炼一下, nao, 自己创造机会。

接下来,新建gray.h、gray.cpp文件来实现toGray这个函数。按照刚才新建.c/.cpp文件的操作来新建:

简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio

 gray.h  和 gray.cpp里面就是跟纯C/C++编程一样了, 写一个对单个图像进行灰度化的函数:
<wiz_code_mirror>
 
 
 
 
 
 
 
1
// this is gray.h
2
#include <stdio.h>
3
#include <opencv2/opencv.hpp>
4
5
using namespace cv;
6
using namespace std;
7
8
bool toGray(Mat img, Mat& gray);
 
 
 
 
 
 
 
 
 
1
// this is gray.cpp
2
#include "gray.h"
3
4
bool toGray(Mat img, Mat& gray)
5
{
6
    if (img.channels()  == 3)
7
            cvtColor(img, gray, CV_BGR2GRAY);
8
    else if (img.channels() == 4)
9
            cvtColor(img, gray, CV_BGRA2GRAY);
10
    else if (img.channels() == 1)
11
            gray = img;
12
    if(gray.rows == img.rows && gray.cols == img.cols)
13
        return true;
14
    else
15
        return false;
16
}
 
 

然后再修改下com_hoos_ndkopencvtest_OpencvNativeClass.h文件就好了,添加如下代码(在哪里添加应该都懂):

<wiz_code_mirror>
 
 
 
 
 
 
 
1
#include "gray.h"
2
3
using namespace cv;
4
using namespace std;
 
 

至此,C/C++源文件搞定。

5)写 Android.mk 和 Application.mk 文件

因为本文采用的gradle的方式来进行NDK开发的, 所以我们会用到 Android.mk 和 Application.mk文件,开始新建这两个文件:

简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio

 

简单的调用OpenCV库的Android NDK开发    工具Android Studio

 创建Application.mk文件的方法也是这样,我就不予赘述了。
两个文件内容如下,需要修改的地方都注释了:
 
 
 
 
 
 
 
1
# this is Android.mk
2
3
LOCAL_PATH := $(call my-dir)
4
5
include $(CLEAR_VARS)
6
7
#opencv
8
OPENCVROOT:= D:/Usual/Android/OpenCV-2.4.9-android-sdk  #这句代码等号右边写上自己的OpenCV安卓开发包的位置
9
OPENCV_CAMERA_MODULES:=on
10
OPENCV_INSTALL_MODULES:=on
11
OPENCV_LIB_TYPE:=SHARED
12
13
#思考下,参考我的修改一下就好了
14
include D:/Usual/Android/OpenCV-2.4.9-android-sdk/sdk/native/jni/OpenCV.mk
15
16
#这里写上自己的开发需要的源文件, 我这里需要两个
17
LOCAL_SRC_FILES := com_hoos_grayprocessing_OpencvClass.cpp gray.cpp
18
19
20
#设置生成的so库的名字  前面的lib和后缀名不用写
21
LOCAL_MODULE := MyLibs
22
23
LOCAL_LDLIBS += -llog
24
25
include $(BUILD_SHARED_LIBRARY)
 
 
<wiz_code_mirror>
 
 
 
 
 
 
 
1
# this is Application.mk
2
3
APP_STL := gnustl_static
4
APP_CPPFLAGS := -frtti -fexceptions
5
6
#这句是设置生成的cpu指令类型,可以根据自己需求来设置生成的平台, 一般这两个就够了
7
APP_ABI := armeabi-v7a x86
8
9
APP_PLATFORM := android-8    #这句是设置最低安卓平台,可以不弄
 
 

6)开始生成so库

简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio

 可以看到,多出来了一个libs文件夹,如图:
简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio
 至此,so库生成完成。

(4)JNI调用so库
这一部分将大体分析一下, 毕竟实现不同的功能类有不同的写法, 本文主要提供一个思路, 以待能够举一反三写出其他NDK开发实例来。这是这一部分的五个关键文件:
简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio

1)activity_main.xml

源内容如下:

 
 
 
 
 
 
 
1
<?xml version="1.0" encoding="utf-8"?>
2
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    xmlns:tools="http://schemas.android.com/tools"
4
    android:id="@+id/activity_main"
5
    android:layout_width="match_parent"
6
    android:layout_height="match_parent"
7
    android:paddingBottom="@dimen/activity_vertical_margin"
8
    android:paddingLeft="@dimen/activity_horizontal_margin"
9
    android:paddingRight="@dimen/activity_horizontal_margin"
10
    android:paddingTop="@dimen/activity_vertical_margin"
11
    tools:context="com.hoos.grayprocessing.MainActivity">
12
13
    <TextView
14
        android:layout_width="wrap_content"
15
        android:layout_height="wrap_content"
16
        android:text="Hello World!" />
17
</RelativeLayout>
 
 

根据实际情况, 我们不需要TextView, 而需要一个JavaCameraView来显示摄像头帧, 控件ID为"java_camera_view", 修改如下:

<wiz_code_mirror>
 
 
 
 
 
 
 
1
<?xml version="1.0" encoding="utf-8"?>
2
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    xmlns:tools="http://schemas.android.com/tools"
4
    android:id="@+id/activity_main"
5
    android:layout_width="match_parent"
6
    android:layout_height="match_parent"
7
    android:paddingBottom="@dimen/activity_vertical_margin"
8
    android:paddingLeft="@dimen/activity_horizontal_margin"
9
    android:paddingRight="@dimen/activity_horizontal_margin"
10
    android:paddingTop="@dimen/activity_vertical_margin"
11
    tools:context="com.hoos.grayprocessing.MainActivity">
12
13
    <org.opencv.android.JavaCameraView
14
        android:layout_width="fill_parent"
15
        android:layout_height="fill_parent"
16
        android:id="@+id/java_camera_view"
17
        />
18
</RelativeLayout>
 
 

2)AndroidManifest.xml

原内容是:

 
 
 
 
 
 
 
1
<?xml version="1.0" encoding="utf-8"?>
2
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
    package="com.hoos.grayprocessing">
4
    <application
5
        android:allowBackup="true"
6
        android:icon="@mipmap/ic_launcher"
7
        android:label="@string/app_name"
8
        android:supportsRtl="true"
9
        android:theme="@style/AppTheme">
10
        <activity android:name=".MainActivity">
11
            <intent-filter>
12
                <action android:name="android.intent.action.MAIN" />
13
14
                <category android:name="android.intent.category.LAUNCHER" />
15
            </intent-filter>
16
        </activity>
17
    </application>
18
19
</manifest>
 
 

因为应用需要摄像头权限, 所以需要在这个文件添加摄像头权限:

<wiz_code_mirror>
 
 
 
 
 
 
 
1
<?xml version="1.0" encoding="utf-8"?>
2
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
    package="com.hoos.grayprocessing">
4
    
5
    <uses-permission android:name="android.permission.CAMERA"/>
6
    
7
    <application
8
        android:allowBackup="true"
9
        android:icon="@mipmap/ic_launcher"
10
        android:label="@string/app_name"
11
        android:supportsRtl="true"
12
        android:theme="@style/AppTheme">
13
        <activity android:name=".MainActivity">
14
            <intent-filter>
15
                <action android:name="android.intent.action.MAIN" />
16
17
                <category android:name="android.intent.category.LAUNCHER" />
18
            </intent-filter>
19
        </activity>
20
    </application>
21
22
</manifest>
 
 

3)gradle.propertise

需要添加对以前版本的支持,在此文件内容的最后添加一行:

 
 
 
 
 
 
 
1
android.useDepredcatedNdk=true
 
 

4)build.gradle

原内容:

<wiz_code_mirror>
 
 
 
 
 
 
 
1
apply plugin: 'com.android.application'
2
3
android {
4
    compileSdkVersion 26
5
    buildToolsVersion "26.0.1"
6
    defaultConfig {
7
        applicationId "com.hoos.grayprocessing"
8
        minSdkVersion 21
9
        targetSdkVersion 26
10
        versionCode 1
11
        versionName "1.0"
12
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13
    }
14
15
    buildTypes {
16
        release {
17
            minifyEnabled false
18
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19
        }
20
    }
21
}
22
23
dependencies {
24
    compile fileTree(include: ['*.jar'], dir: 'libs')
25
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
26
        exclude group: 'com.android.support', module: 'support-annotations'
27
    })
28
    compile 'com.android.support:appcompat-v7:26.0.0-alpha1'
29
    testCompile 'junit:junit:4.12'
30
    compile project(':openCVLibrary249')
31
}
32
 
 

添加内容, 指明生成的so库的路径:

 
 
 
 
 
 
 
1
apply plugin: 'com.android.application'
2
3
android {
4
    compileSdkVersion 26
5
    buildToolsVersion "26.0.1"
6
    defaultConfig {
7
        applicationId "com.hoos.grayprocessing"
8
        minSdkVersion 21
9
        targetSdkVersion 26
10
        versionCode 1
11
        versionName "1.0"
12
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13
    }
14
15
    sourceSets.main{
16
        jniLibs.srcDirs = ['src/main/libs']
17
        jni.srcDirs = []
18
    }
19
20
    buildTypes {
21
        release {
22
            minifyEnabled false
23
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
24
        }
25
    }
26
}
27
28
dependencies {
29
    compile fileTree(include: ['*.jar'], dir: 'libs')
30
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
31
        exclude group: 'com.android.support', module: 'support-annotations'
32
    })
33
    compile 'com.android.support:appcompat-v7:26.0.0-alpha1'
34
    testCompile 'junit:junit:4.12'
35
    compile project(':openCVLibrary249')
36
}
37
 
 

5)MainActivity.java

部分注释在代码中,

<wiz_code_mirror>
 
 
 
 
 
 
 
1
package com.hoos.grayprocessing;
2
3
import android.support.v7.app.AppCompatActivity;
4
import android.os.Bundle;
5
import android.util.Log;
6
import android.view.View;
7
8
import org.opencv.android.BaseLoaderCallback;
9
import org.opencv.android.CameraBridgeViewBase;
10
import org.opencv.android.JavaCameraView;
11
import org.opencv.android.LoaderCallbackInterface;
12
import org.opencv.android.OpenCVLoader;
13
import org.opencv.core.CvType;
14
import org.opencv.core.Mat;
15
16
public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2{
17
    
18
    private static String TAG = "MainActivity";
19
    // 初始化一个实例,用来获取摄像头帧
20
    JavaCameraView javaCameraView;
21
    Mat mRgba;  // 用来存储原始摄像头数据
22
    Mat mGray;  // 用来存储灰度化后的帧数据
23
24
    // 静态加载之前生成的so库——Mylins
25
    static{
26
        System.loadLibrary("MyLibs");
27
    }
28
29
    // 回调开初始化帧数据
30
    BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
31
        @Override
32
        public void onManagerConnected(int status) {
33
            switch(status){
34
                case BaseLoaderCallback.SUCCESS:
35
                    javaCameraView.enableView();
36
                    break;
37
                default:
38
                    super.onManagerConnected(status);
39
                    break;
40
            }
41
            super.onManagerConnected(status);
42
        }
43
    };
44
45
    @Override
46
    protected void onCreate(Bundle savedInstanceState) {
47
        super.onCreate(savedInstanceState);
48
        setContentView(R.layout.activity_main);
49
50
        // 与java_camera_view控件绑定
51
        javaCameraView = (JavaCameraView)findViewById(R.id.java_camera_view);
52
        javaCameraView.setVisibility(View.VISIBLE);
53
        javaCameraView.setCvCameraViewListener(this);
54
    }
55
56
    @Override
57
    protected void onPause(){
58
        super.onPause();
59
        if(javaCameraView!=null)
60
            javaCameraView.disableView();
61
    }
62
63
    protected void onDestroy(){
64
        super.onDestroy();
65
        if(javaCameraView!=null)
66
            javaCameraView.disableView();
67
    }
68
69
    // 判断是否加载成功OpenCV库
70
    protected void onResume(){
71
        super.onResume();
72
        if(OpenCVLoader.initDebug()){
73
            Log.i(TAG, "Opencv loaded successfully");
74
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
75
        }
76
        else{
77
            Log.i(TAG, "Opencv not loaded");
78
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9, this, mLoaderCallback);
79
        }
80
    }
81
82
    @Override
83
    public void onCameraViewStarted(int width, int height) {
84
        // 初始化这两个Mat类型
85
        mRgba = new Mat(height, width, CvType.CV_8UC4);
86
        mGray = new Mat(height, width, CvType.CV_8UC1);
87
    }
88
89
    @Override
90
    public void onCameraViewStopped() {
91
        mRgba.release();
92
    }
93
94
    @Override
95
    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
96
        // 得到摄像头原始帧数据
97
        mRgba = inputFrame.rgba();
98
        // 调用OpencvClass类的方法来对帧数据进行灰度化
99
        OpencvClass.convertGray(mRgba.getNativeObjAddr(), mGray.getNativeObjAddr());
100
101
        return mGray;
102
    }
103
}
 
 

此外, 出现了如下提示"Gradle files have changed ...", 请单击右边的"Sync Now"来进行更新。

简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio

 
(4)在x86的Android 5.0的虚拟机器上运行了下,
木有问题

简单的调用OpenCV库的Android NDK开发    工具Android Studio

简单的调用OpenCV库的Android NDK开发    工具Android Studio

当然了,想要虚拟安卓机能用电脑或者usb外置摄像头需要修改虚拟机一点参数:
1)鼠标左键单击下图红色标记按钮:
 简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio
 2)鼠标左键单击下图红色标记按钮(前提是你已经创建了一个虚拟机,
建议创建x86的虚拟机):简单的调用OpenCV库的Android NDK开发    工具Android Studio
简单的调用OpenCV库的Android NDK开发    工具Android Studio3) 鼠标左键单击下图红色标记按钮:
简单的调用OpenCV库的Android NDK开发    工具Android Studio
 简单的调用OpenCV库的Android NDK开发    工具Android Studio
4)将参数 "Front" 或者 "Back" 的其中任意一个改成Webcam0就可以了, 这样只要电脑内置或者外置摄像头可用虚拟机就可以调用了。

简单的调用OpenCV库的Android NDK开发    工具Android Studio简单的调用OpenCV库的Android NDK开发    工具Android Studio