您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 项目/工程管理 > Android使用OpenCV的三种方式(AndroidStudio)
其实最早接触OpenCV是很久很久之前的事了,大概在2013年的5,6月份,当时还是个菜逼(虽然现在也是个菜逼),在那一段时间,学了一段时间的android(并不算学,一个月都不到),之后再也没接触android,而是一直在接触javaweb。那次接触OpenCV是因为一个学长的毕业设计,这次接触OpenCV是因为自己的毕业设计。2013年那年技术太菜,ndk环境都搭不好,当初还是eclipse环境,一直按照网上的教程去搭,下什么cygwin,简直就是个坑,网上的文章转来转去,都是过时的。后来一个机会看到了google官方的一个文档,就像发现了新大陆一样,发现ndk环境根本不需要装cygwin,装了你就坑了,装这个东西有好多G呢,时间浪费不说,简直误人子弟啊。后来在那年7月写下一篇博客NDK开发环境这段时间在填自己毕业设计的坑,要用到OpenCV,首先得下载到sdk吧,这个从官网上下载就好了OpenCVforAndroid注意下载的是OpenCVforandroid。当前版本是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永不困扰)本篇文章使用androidstudio作为开发环境,由于实验性的构建工具对ndk支持还不好,所以使用旧的构建方式,在原来写的一篇博客基础上修改即可androidstudio下ndk开发这正式介绍三种方式之前,我们需要做一些前期准备。首先新建一个项目,将OpenCV中sdk目录下的native目录拷到项目根目录然后新建Jni目录在里面新建两个文件编辑gradle.properties文件,增加下面的属性使用旧版的ndk功能(不添加会使用实验性的ndk构建工具)android.useDeprecatedNdk=true在local.properties文件中配置ndk目录ndk.dir=D\:\\AndroidSDK\\sdk\\ndk-bundle编辑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/jniLibstaskndkBuild(type:Exec,description:'CompileJNIsourcewithNDK'){Propertiesproperties=newProperties()properties.load(project.rootProject.file('local.properties').newDataInputStream())defndkDir=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.dependsOnndkBuild}taskndkClean(type:Exec,description:'CleanNDKBinaries'){Propertiesproperties=newProperties()properties.load(project.rootProject.file('local.properties').newDataInputStream())defndkDir=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'在之前新建的Application.mk中增加下面的内容APP_STL:=gnustl_staticAPP_CPPFLAGS:=-frtti-fexceptionsAPP_ABI:=armeabiarmeabi-v7aAPP_PLATFORM:=android-8在Android.mk中增加下面的内容LOCAL_PATH:=$(callmy-dir)include$(CLEAR_VARS)OpenCV_INSTALL_MODULES:=onOpenCV_CAMERA_MODULES:=offOPENCV_LIB_TYPE:=STATICifeq($(wildcard$(OPENCV_MK_PATH)),)include..\..\..\..\native\jni\OpenCV.mkelseinclude$(OPENCV_MK_PATH)endifLOCAL_MODULE:=OpenCVLOCAL_SRC_FILES:=LOCAL_LDLIBS+=-lm-lloginclude$(BUILD_SHARED_LIBRARY)这时候,使用gradle构建一下,如果能成功构建出so,说明配置没问题,如下图,点击as右侧的gradle展开,双击ndkBuild进行构建下面开始讲第一种方法,纯jni层的代码,该方法基于上面的所有步骤,为静态链接库声明java层的native方法publicclassOpenCVHelper{static{System.loadLibrary(OpenCV);}publicstaticnativeint[]gray(int[]buf,intw,inth);}使用javah命令生成头文件,内容如下/*DONOTEDITTHISFILE-itismachinegenerated*/#includejni.h/*Headerforclasscn_edu_zafu_opencv_OpenCVHelper*/#ifndef_Included_cn_edu_zafu_opencv_OpenCVHelper#define_Included_cn_edu_zafu_opencv_OpenCVHelper#ifdef__cplusplusexternC{#endif/**Class:cn_edu_zafu_opencv_OpenCVHelper*Method:gray*Signature:([III)[I*/JNIEXPORTjintArrayJNICALLJava_cn_edu_zafu_opencv_OpenCVHelper_gray(JNIEnv*,jclass,jintArray,jint,jint);#ifdef__cplusplus}#endif#endif新建cpp文件,实现对应的方法,就是灰度处理#includecn_edu_zafu_opencv_OpenCVHelper.h#includestdio.h#includestdlib.h#includeopencv2/opencv.hppusingnamespacecv;externC{JNIEXPORTjintArrayJNICALLJava_cn_edu_zafu_opencv_OpenCVHelper_gray(JNIEnv*env,jclassobj,jintArraybuf,intw,inth);JNIEXPORTjintArrayJNICALLJava_cn_edu_zafu_opencv_OpenCVHelper_gray(JNIEnv*env,jclassobj,jintArraybuf,intw,inth){jint*cbuf;cbuf=env-GetIntArrayElements(buf,JNI_FALSE);if(cbuf==NULL){return0;}MatimgData(h,w,CV_8UC4,(unsignedchar*)cbuf);uchar*ptr=imgData.ptr(0);for(inti=0;iw*h;i++){//计算公式:Y(亮度)=0.299*R+0.587*G+0.114*B//对于一个int四字节,其彩色值存储方式为:BGRAintgrayScale=(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;}intsize=w*h;jintArrayresult=env-NewIntArray(size);env-SetIntArrayRegion(result,0,size,cbuf);env-ReleaseIntArrayElements(buf,cbuf,0);returnresult;}}之后,需要将cpp文件编译进去,在Andorid.mk文件中加入LOCAL_SRC_FILES:=cn_edu_zafu_opencv_OpenCVHelper.cpp然后在java层写个测试方法测试一下是否进行灰度化了Bitmapbitmap=((BitmapDrawable)getResources().getDrawable(R.drawable.ic)).getBitmap();intw=bitmap.getWidth(),h=bitmap.getHeight();int[]pix=newint[w*h];bitmap.getPixels(pix,0,w,0,0,w,h);int[]resultPixes=OpenCVHelper.gray(pix,w,h);Bitmapresult=Bitmap.createBitmap(w,h,Bitmap.Config.RGB_565);result.setPixels(resultPixes,0,w,0,0,w,h);img.setImageBitmap(result);运行效果如下,灰度化后的结果上面的这种方法生成的so库的大小见下图,大约有1.4M左右第二种方法也是纯jni的,但是是动态链接库,在第一种基础上,
本文标题:Android使用OpenCV的三种方式(AndroidStudio)
链接地址:https://www.777doc.com/doc-2897221 .html