您的位置:首页 > 移动开发 > Android开发

Android 使用OpenCV的三种方式(Android Studio)

2016-07-11 13:58 507 查看
原文链接:http://blog.csdn.net/sbsujjbcy/article/details/49520791

其实最早接触OpenCV是很久很久之前的事了,大概在2013年的5,6月份,当时还是个菜逼(虽然现在也是个菜逼),在那一段时间,学了一段时间的Android(并不算学,一个月都不到),之后再也没接触android,而是一直在接触Java
Web。那次接触OpenCV是因为一个学长的毕业设计,这次接触OpenCV是因为自己的毕业设计。2013年那年技术太菜,ndk环境都搭不好,当初还是eclipse环境,一直按照网上的教程去搭,下什么cygwin,简直就是个坑,网上的文章转来转去,都是过时的。后来一个机会看到了google官方的一个文档,就像发现了新大陆一样,发现ndk环境根本不需要装cygwin,装了你就坑了,装这个东西有好多G呢,时间浪费不说,简直误人子弟啊。后来在那年7月写下一篇博客

NDK开发环境

这段时间在填自己毕业设计的坑,要用到OpenCV,首先得下载到sdk吧,这个从官网上下载就好了 
OpenCV for Android

注意下载的是OpenCV for android。当前版本是3.0



解压后,里面的内容如下



samples目录下是样例代码,sdk目录下是我们需要用到的Java层和jni层的代码。apk目录是manager的apk安装包

其实OpenCV最简单的使用方式是使用manager,也就是使用apk目录下的安装包,安装对应的apk,将java层代码导入,使用OpenCVLoader.initAsync()加载库,之后你就可以直接用java代码调用Opencv相关的功能了。



但是这种方式除了安装我们自己的apk还需要安装上面提到的manager的apk,用户体验十分不好,不推荐使用,本文的三种方式将完全脱离这个manager的apk。

本文下面的三种方式的内容参考自文章 OpenCV4Android释疑: 透析Android以JNI调OpenCV的三种方式(让OpenCVManager永不困扰)

本篇文章使用android studio作为开发环境,由于实验性的构建工具对ndk支持还不好,所以使用旧的构建方式,在原来写的一篇博客基础上修改即可android studio下ndk开发

这正式介绍三种方式之前,我们需要做一些前期准备。

首先新建一个项目,将OpenCV中sdk目录下的native目录拷到项目根目录



然后新建Jni目录



在里面新建两个文件



编辑gradle.properties文件,增加下面的属性使用旧版的ndk功能(不添加会使用实验性的ndk构建工具)
<code class="hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">android.useDeprecatedNdk=<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">true</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>


在local.properties文件中配置ndk目录
<code class="hljs tex has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">ndk.dir=D<span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\:</span><span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\\</span>AndroidSDK<span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\\</span>sdk<span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\\</span>ndk-bundle</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>


编辑build.gradle,在android节点中增加下面的代码

sourceSets.main.jni.srcDirs = []
//禁止自带的ndk功能
sourceSets.main.jniLibs.srcDirs = ['src/main/libs','src/main/jniLibs']
//重定向so目录为src/main/libs和src/main/jniLibs,原来为src/main/jniLibs

task ndkBuild(type: Exec, description: 'Compile JNI source with NDK') {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def ndkDir = properties.getProperty('ndk.dir')

if (org.apache.tools.ant.taskdefs.condition.Os.isFamily(org.apache.tools.ant.taskdefs.condition.Os.FAMILY_WINDOWS)) {
commandLine "$ndkDir/ndk-build.cmd", '-C', file('src/main/jni').absolutePath
} else {
commandLine "$ndkDir/ndk-build", '-C', file('src/main/jni').absolutePath
}
}

tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}

task ndkClean(type: Exec, description: 'Clean NDK Binaries') {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def ndkDir = properties.getProperty('ndk.dir')

if (org.apache.tools.ant.taskdefs.condition.Os.isFamily(org.apache.tools.ant.taskdefs.condition.Os.FAMILY_WINDOWS)) {
commandLine "$ndkDir/ndk-build.cmd",'clean', '-C', file('src/main/jni').absolutePath
} else {
commandLine "$ndkDir/ndk-build",'clean', '-C', file('src/main/jni').absolutePath
}
}

clean.dependsOn 'ndkClean'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

在之前新建的Application.mk中增加下面的内容

<code class="hljs makefile has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-constant" style="box-sizing: border-box;">APP_STL</span> := gnustl_static
<span class="hljs-constant" style="box-sizing: border-box;">APP_CPPFLAGS</span> := -frtti -fexceptions
<span class="hljs-constant" style="box-sizing: border-box;">APP_ABI</span> := armeabi armeabi-v7a
<span class="hljs-constant" style="box-sizing: border-box;">APP_PLATFORM</span> := android-8
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>


在Android.mk中增加下面的内容

<code class="hljs ruby has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-constant" style="box-sizing: border-box;">LOCAL_PATH</span> <span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span>= <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$(</span>call my-dir)

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">include</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$(</span><span class="hljs-constant" style="box-sizing: border-box;">CLEAR_VARS</span>)

<span class="hljs-constant" style="box-sizing: border-box;">OpenCV_INSTALL_MODULES</span> <span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span>= on
<span class="hljs-constant" style="box-sizing: border-box;">OpenCV_CAMERA_MODULES</span> <span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span>= off

<span class="hljs-constant" style="box-sizing: border-box;">OPENCV_LIB_TYPE</span> <span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span>=<span class="hljs-constant" style="box-sizing: border-box;">STATIC</span>

ifeq (<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"$(wildcard $(OPENCV_MK_PATH))"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>)
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">include</span> ..\..\..\..\native\jni\<span class="hljs-constant" style="box-sizing: border-box;">OpenCV</span>.mk
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">include</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$(</span><span class="hljs-constant" style="box-sizing: border-box;">OPENCV_MK_PATH</span>)
endif

<span class="hljs-constant" style="box-sizing: border-box;">LOCAL_MODULE</span> <span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span>= <span class="hljs-constant" style="box-sizing: border-box;">OpenCV</span>

<span class="hljs-constant" style="box-sizing: border-box;">LOCAL_SRC_FILES</span> <span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span>=

<span class="hljs-constant" style="box-sizing: border-box;">LOCAL_LDLIBS</span> +=  -lm -llog

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">include</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$(</span><span class="hljs-constant" style="box-sizing: border-box;">BUILD_SHARED_LIBRARY</span>)
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li></ul>


这时候,使用gradle构建一下,如果能成功构建出so,说明配置没问题,如下图,点击as右侧的gradle展开,双击ndkBuild进行构建





下面开始讲第一种方法,纯jni层的代码,该方法基于上面的所有步骤,为静态链接库

声明java层的native方法

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> OpenCVHelper {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> {
System.loadLibrary(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"OpenCV"</span>);
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> native <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[] <span class="hljs-title" style="box-sizing: border-box;">gray</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[] buf, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> w, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> h);
}
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>


使用javah命令生成头文件,内容如下

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class cn_edu_zafu_opencv_OpenCVHelper */

#ifndef _Included_cn_edu_zafu_opencv_OpenCVHelper
#define _Included_cn_edu_zafu_opencv_OpenCVHelper
#ifdef __cplusplus
extern "C" {
#endif

/*
* Class:     cn_edu_zafu_opencv_OpenCVHelper
* Method:    gray
* Signature: ([III)[I
*/
JNIEXPORT jintArray JNICALL Java_cn_edu_zafu_opencv_OpenCVHelper_gray
(JNIEnv *, jclass, jintArray, jint, jint);

#ifdef __cplusplus
}
#endif
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

新建cpp文件,实现对应的方法,就是灰度处理

#include "cn_edu_zafu_opencv_OpenCVHelper.h"
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/opencv.hpp>

using namespace cv;

extern "C" {

JNIEXPORT jintArray JNICALL Java_cn_edu_zafu_opencv_OpenCVHelper_gray(
JNIEnv *env, jclass obj, jintArray buf, int w, int h);

JNIEXPORT jintArray JNICALL Java_cn_edu_zafu_opencv_OpenCVHelper_gray(
JNIEnv *env, jclass obj, jintArray buf, int w, int h) {

jint *cbuf;
cbuf = env->GetIntArrayElements(buf, JNI_FALSE );
if (cbuf == NULL) {
return 0;
}

Mat imgData(h, w, CV_8UC4, (unsigned char *) cbuf);

uchar* ptr = imgData.ptr(0);
for(int i = 0; i < w*h; i ++){
//计算公式:Y(亮度) = 0.299*R + 0.587*G + 0.114*B
//对于一个int四字节,其彩色值存储方式为:BGRA
int grayScale = (int)(ptr[4*i+2]*0.299 + ptr[4*i+1]*0.587 + ptr[4*i+0]*0.114);
ptr[4*i+1] = grayScale;
ptr[4*i+2] = grayScale;
ptr[4*i+0] = grayScale;
}

int size = w * h;
jintArray result = env->NewIntArray(size);
env->SetIntArrayRegion(result, 0, size, cbuf);
env->ReleaseIntArrayElements(buf, cbuf, 0);
return result;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

之后,需要将cpp文件编译进去,在Andorid.mk文件中加入

<code class="hljs fix has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">LOCAL_SRC_FILES :</span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;"> cn_edu_zafu_opencv_OpenCVHelper.cpp</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>


然后在java层写个测试方法测试一下是否进行灰度化了

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Bitmap bitmap = ((BitmapDrawable) getResources()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getDrawable</span>(
R<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.drawable</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ic</span>))<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getBitmap</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
int w = bitmap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getWidth</span>(), h = bitmap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getHeight</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
int[] pix = new int[w * h]<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
bitmap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getPixels</span>(pix, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, w, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, w, h)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
int [] resultPixes=OpenCVHelper<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.gray</span>(pix,w,h)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
Bitmap result = Bitmap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.createBitmap</span>(w,h, Bitmap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Config</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.RGB</span>_565)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
result<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setPixels</span>(resultPixes, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, w, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,w, h)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
img<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setImageBitmap</span>(result)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>


运行效果如下,灰度化后的结果



上面的这种方法生成的so库的大小见下图,大约有1.4M左右



第二种方法也是纯jni的,但是是动态链接库,在第一种基础上,修改Android.mk文件为

<code class="hljs ruby has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-constant" style="box-sizing: border-box;">LOCAL_PATH</span> <span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span>= <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$(</span>call my-dir)

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">include</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$(</span><span class="hljs-constant" style="box-sizing: border-box;">CLEAR_VARS</span>)

<span class="hljs-constant" style="box-sizing: border-box;">OpenCV_INSTALL_MODULES</span> <span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span>= on
<span class="hljs-constant" style="box-sizing: border-box;">OpenCV_CAMERA_MODULES</span> <span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span>= off

<span class="hljs-constant" style="box-sizing: border-box;">OPENCV_LIB_TYPE</span> <span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span>= <span class="hljs-constant" style="box-sizing: border-box;">SHARED</span>

ifeq (<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"$(wildcard $(OPENCV_MK_PATH))"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>)
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">include</span> ..\..\..\..\native\jni\<span class="hljs-constant" style="box-sizing: border-box;">OpenCV</span>.mk
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">include</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$(</span><span class="hljs-constant" style="box-sizing: border-box;">OPENCV_MK_PATH</span>)
endif

<span class="hljs-constant" style="box-sizing: border-box;">LOCAL_MODULE</span> <span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span>= <span class="hljs-constant" style="box-sizing: border-box;">OpenCV</span>

<span class="hljs-constant" style="box-sizing: border-box;">LOCAL_SRC_FILES</span> <span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span>= cn_edu_zafu_opencv_OpenCVHelper.cpp

<span class="hljs-constant" style="box-sizing: border-box;">LOCAL_LDLIBS</span> +=  -lm -llog

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">include</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$(</span><span class="hljs-constant" style="box-sizing: border-box;">BUILD_SHARED_LIBRARY</span>)
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li></ul>


注意上面的OPENCV_LIB_TYPE属性的改动,从STATIC改为了SHARED,这时候再用ndkBuild一下,你会发现会输出一些警告以及一部分红色的内容



生成的so库的大小为310k,小了好几倍



这时候如果你直接取运行程序,会报错误



原因是我们使用的是动态库加载方式,还需要将依赖的so加进去,这个so就是图中的libopencv_java3.so,他在我们的最开始加到项目里的native目录中



将它拷到我们的jniLibs目录中去,这里只拷贝armeabi和armeabi-v7a中的,至于其他的按需拷贝



这时候运行就不会报错了。

既然我们使用了动态链接库,那么我们同样也可以使用java层的接口,优点是java开发速度相对快一点。第三种方法在第二种方法基础上,使用纯java层代码进行处理。

在此之前,我们需要将sdk目录中的java代码拷到项目中去



但是org.opencv.engine包中是一个aidl,我们需要将它剪贴到aidl目录中去,就像这样子



最后还有一个资源文件attrs.xml,拷过来



build一下项目,不出意外应该会报错,这时候找到该类,引入自己的R文件包就可以了



再次build应该就不会有什么问题了。

java层的测试方法
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">OpenCVLoader<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.initDebug</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
Mat rgbMat = new Mat()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
Mat grayMat = new Mat()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
Bitmap srcBitmap = BitmapFactory<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.decodeResource</span>(getResources(), R<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.drawable</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ic</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
Bitmap grayBitmap = Bitmap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.createBitmap</span>(srcBitmap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getWidth</span>(), srcBitmap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getHeight</span>(), Bitmap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Config</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.RGB</span>_565)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
Utils<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.bitmapToMat</span>(srcBitmap, rgbMat)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;//convert original bitmap to Mat, R G B.</span>
Imgproc<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.cvtColor</span>(rgbMat, grayMat, Imgproc<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.COLOR</span>_RGB2GRAY)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;//rgbMat to gray grayMat</span>
Utils<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.matToBitmap</span>(grayMat, grayBitmap)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; //convert mat to bitmap</span>
img<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setImageBitmap</span>(grayBitmap)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>


注意使用OpenCVLoader.initDebug();进行初始化而不是使用OpenCVLoader.initAsync()

这种方法的特点是处理都在java层,不怎么会涉及jni层的代码,除非java层完成不了的工作会转移到jni层去。

三种方法各有各的优点,根据自己的情况进行选择。
如果c++特别好的,建议使用第一种方法
如果更习惯java代码的,并且java层的函数都能进行处理的,建议选择第三种方法
第二种方法建议在第三种方法不满足条件的情况下进行辅助使用,因为使用了第三种方法的前提是使用第二种方法的动态链接库。

最后附上源码
http://download.csdn.net/detail/sbsujjbcy/9275897

记录:

当文件使用标准库函数时要在加上对应头文件的时候加上using namespace std;

当生成对应的头文件时也可以到包文件的上一层目录输入javah -jni 包名.文件名,生成位置也是这里

另外一篇文章和这个刚好互补,链接:http://blog.csdn.net/qq_22033759/article/details/51460775

结合此文章可加深对主活动的理解:安卓使用opencv

数据传输直接强转,重新开辟int数组,和在原有数据上变动都可
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: