opencv for android 教程
要想在Android使用OpenCV,那么首先得搭建好开发环境,其实搭建开发环境并不难,只要理解其中的原理就自然手到擒来。开发环境搭建好后才能大展拳脚!
(之前一直是在VS中使用OpenCV,VS中的配置很简单;在Android中配置OpenCV对于刚开始接触Android和java的人来说,确实很麻烦;刚开始配置时参考的是这位大牛的文章:opencv for android 教程(环境搭建篇),但是之间老是出错,不是他写得有问题,主要是自己没能理解为什么这么做,不知道为什么自然遇到问题就无法变通,二是时间久了,有些东西可能就不一样了!写下这篇文章仅仅是根据前辈的文章和自己的理解,尽量通俗易懂,有什么表述不正确的地方,敬请指正!)
OpenCV4Android 环境配置分3个步骤:
一、Android开发环境配置
二、NDK环境配置
三、使用OpenCV
第一步很简单,开发Android程序的首要条件,网上教程多如牛毛;第二步就是在Android中调用C/C++的所需要的,而OpenCV是C/C++编写的库;第三步其实不能称之为环境配置了,因为前两步已经配置好了环境,第三步仅仅是如何正确的调用OpenCV库了,可以称之为方法篇了。
我已将下面用到的安装包、有点参考价值的资料上传到百度网盘:网盘下载
一、Android环境配置
如果自己的电脑上已经配置好了Android开发环境的话,可以跳过此步,进入第二步!
1)准备条件: Windows操作系统
JDK(Java SE Development Kit 8u20)
Android SDK
Eclipse
ADT
2)JDK下载地址:JDK_8u20
选择32位的(或者64位),如果选择了32位的那么之后下载的安装工具也同样选择32位的,以免出现问题(64位的也一样)。安装JDK是为了支持Java开发,安装路径为 D:\Java\jdk1.8.0_20,安装好后是环境变量设置
3)添加系统环境变量:JAVA_HOME
在系统环境变量Path的变量值后面追加;%JAVA_HOME%\bin
运行cmd.exe中输入javac -version
出现上面的情况说明安装成功。
4)Android SDK下载地址:Android SDK
选择VIEW ALL DOWNLOADS AND SIZES下的SDK tools only。按照下图提示进行选择下载
双击运行已经下载好的installer_r23.0.2-windows.exe,选择安装路径时选择合适的路径即可。
安装完成后添加系统环境变量如下图所示
在环境变量Path后面追加;%ANDROID_SDK_HOME%\tools
点击全部确定后,运行cmd.exe,输入命令android回车会运行Android SDK Manager,说明环境变量设置正确,然后在Android SDK Manager中选中以下的选项,下载相应的包(推荐),当然也可以按自己的需要下载,有时会失败,多试几次就行了!
5)Eclipse 下载地址:eclipse
按照下图提示下载
这个Eclipse版本是此时的最新版本。下载好后解压到文件夹D:\Android\eclipse ,eclipase文件夹下有eclipse.exe程序。
6)ADT下载地址:ADT
7)运行eclipse文件夹下的eclipse.exe
设置工作目录如下
点击上图中的OK按钮后进入Eclipse主界面。然后点击菜单栏的Help->Install New Software...,再弹出的对话框中点击Add...按钮,在弹出的对话框中Name:输入adt。
然后点击Archive...按钮,找到前一步下载的ADT的位置,选择下载的ADT压缩包,点击确定。
点击OK按钮后照下图提示操作
点击上图中的 Next> 按钮,直至 Finish。在安装过程中会提示警告信息,直接点击OK即可。
根据提示重启Eclipse后界面上会多出两个图标。然后选择菜单栏的Window->Preferences->Android设置SDK Location为 D:\Android\adt\sdk,点击Apply
如果是真机测试的话,现在暂时不需要下载其余的API和Tools,不用创建AVD;如果没有真机的话,点击菜单栏的Window->Android SDK Manager,如果需要就下载相应的API和Tools(下载速度比较慢)。
8)创建AVD
如果有真机的话,不太建议使用AVD,因为启动速度太慢等原因!创建过程就省略掉了!(如果需要请参照其他的网上教程)
9)新建Hello World项目
点击菜单栏Flie->New->Android Application Project,在弹出的的对话框中输入应用名称如下
点击Next,全部为默认选项,直至Finish。
手机通过USB数据线连接电脑,打开调试模式,最好关闭电脑上的手机助手,避免出现不必要的问题;右键工程文件Demo01->Run As->Android Application
选中已经连接的手机,单击OK则手机上出现如下界面
至此,Android开发环境的配置已经完成了。
二、NDK环境配置
如果已经熟练NDK开发或者已经配置好NDK开发环境的可以跳过此步骤
1)准备条件: Android-NDK
CDT
2)NDK下载地址:Android-NDK
我的电脑是Win7 64位操作系统(根据自己的操作系统选择,32位对应前面都选择32位),所以我的选择是
下载好后解压到某个文件夹,我的是 D:\Android\ndk,ndk文件夹下有build、docs和platforms等等文件夹和文件。
3)系统环境变量配置:ANDROID_NDK_HOME(名字个人喜好)如下
然后在系统变量Path后追加;%ANDROID_NDK_HOME%
然后点击全部确定后,运行cmd.exe,输入ndk-build命令,回车后出现
4)安装CDT插件
CDT下载地址:CDT
选择与自己的Eclipse版本相应的CDT包
下载完成后,安装方法与ADT的安装方法一样,点击菜单栏Help->Install New Software...在弹出的对话框中设置如下
Name为cdt,Archive...选择刚才下载的cdt离线包,点击OK后按照下图提示操作
点击Next,直至Finish,安装成功后根据提示重启Eclipse。(连网的情况下安装的,中间没提示安装错误)
新建工程时有C/C++选项时,说明CDT安装成功
5)测试NDK
在eclipse中点击菜单栏File->Import...->Android->Existing Android Code Into Workspce
点击Next>,添加HelloJni项目如下图所示
HelloJni是NDK中提供的例子,不需要选中tests项目,把HelloJni拷贝到当前工作目录中,点击Finish。
此时可以看见导入的HelloJni并没有提示错误,如果有错误可以单击菜单栏Project->Clean...,在弹出的对话框中选中HelloJni工程,然后点击OK,再点击菜单栏的
Project->Build Project,这是通常的解决办法,当然也要具体问题具体分析了。
然后右键工程文件HelloJni->Run As->Android Application,然后选择运行的设备,结果运行错误,为什么呢?因为并没有生成libhellojni.so库,所以暂时还不能运行!
6)HelloJni项目设置
右击HelloJni项目文件,点击New->Other...,在弹出的对话框后根据下图提示操作
点击Next>后进入下图
点击Finish后,再次右击HelloJni工程文件,点击Properties,弹出对话框如下图设置
主要设置的是ndk-build.cmd的目录,这样Eclipse会自动调用ndk-build命令操作,按照上图指示设置后,点击Apply,然后再按下图设置
按照上图设置完成Apply后,再按下图设置
GNU C / GNU C++ 的includes设置为一样的,其实就是cpp源文件中头文件的目录设置。可以打开这个文件夹,其中有jni.h 和string.h 等头文件,而这两个文件正是HelloJni.cpp中包含的头文件。如果需要更多的头文件,则需要设置相应的路径。
到这里可以右击HelloJni工程文件,点击Run As->Android Application->选择运行的设备->OK,运行结果如下图所示
显示结果为手机的使用的编译指令集,我的手机为HTC nexus one,可见使用的编译指令集为armeabi-v7a,这个对之后OpenCV Manager的安装版本的选择有帮助!
至此NDK的环境配置已经完成了,可能会有人问为什么没装Cygwin呢?其实这个是不需要的!
当然之间也遇到些错误,如HelloJni.c中下面这句有可能会提示错误!
[cpp] view plain copy- return(*env)->NewStringUTF(env,"HellofromJNI!CompiledwithABI"ABI".");
三、OpenCV的使用
在Android中使用OpenCV分三种情况:
一是纯java开发,使用OpenCV提供的java API,这种情况不需要NDK开发环境的配置,但是需要在手机上先安装好OpenCV Manager;
二是Android java部分主要是界面设计,而图像处理部分在jni中实现,涉及到OpenCV的方法时为纯C/C++,这种方法不用安装OpenCV Manager;
三是前两种方法同时使用!
下面将介绍前两种方法,弄明白前两种,第三种自然就明白了。下面的介绍是基于已经熟悉Android基本开发和NDK开发基本流程的情况下介绍的。关于jni的介绍和教程可以百度搜索传智播客的jni视频教程。
1)下载OpenCV4Android
OpenCV4Android下载地址OpenCV官方网站,我的下载的是OpenCV4Android 2.4.9,下载好后解压到D:\下,得到OpenCV-2.4.9-android-sdk这个文件夹,将文件夹下的sdk复制到E:\android-workspace目录下,然后导入到Eclipse工作目录下,方法为运行Eclipse,点击菜单栏的File->Import...->Android->Existing Android Code Into Workspace
点击Finish按钮后结果如下
至此准备工作就做好了。
2)使用OpenCV的Java API开发
创建一个新的Android项目,命名为OpenCVDemo01
工程项目新建好后,就要为该项目添加OpenCV的java支持包了。方法是右击项目文件OpenCVDemo01->Properties,在弹出的对话框中进行如下设置
然后可以看到如下结果
好了下面开始写代码,代码完全是copy自前辈大牛的,layout布局文件activity_main.xml如下
[html] view plain copy- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center_horizontal"
- android:orientation="vertical"
- tools:context="com.example.opencvdemo01.MainActivity">
- <Button
- android:id="@+id/btn_proc"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/gray_proc"
- />
- <ImageView
- android:id="@+id/imageview_lena"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@string/image_lena"
- />
- </LinearLayout>
- <?xmlversion="1.0"encoding="utf-8"?>
- <resources>
- <stringname="app_name">OpenCVDemo01</string>
- <stringname="hello_world">Helloworld!</string>
- <stringname="action_settings">Settings</string>
- <stringname="gray_proc">GrayProcess</string>
- <stringname="undo">Undo</string>
- <stringname="image_lena">lena</string>
- </resources>
- </pre><prename="code"class="java">publicclassMainActivityextendsActionBarActivity{
- privatebooleanbProc=false;
- privateButtonbtnProc;
- privateImageViewlenaView;
- privateBitmapbmp;
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.lena);
- lenaView=(ImageView)findViewById(R.id.imageview_lena);
- lenaView.setImageBitmap(bmp);
- btnProc=(Button)findViewById(R.id.btn_proc);
- btnProc.setOnClickListener(newOnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- if(!bProc){
- MatrgbMat=newMat();
- MatgrayMat=newMat();
- Utils.bitmapToMat(bmp,rgbMat);
- //OpenCV的javaAPI
- Imgproc.cvtColor(rgbMat,grayMat,Imgproc.COLOR_RGB2GRAY);
- BitmapgrayBmp=Bitmap.createBitmap(bmp.getWidth(),bmp.getHeight(),Config.RGB_565);
- Utils.matToBitmap(grayMat,grayBmp);
- lenaView.setImageBitmap(grayBmp);
- btnProc.setText(R.string.undo);
- bProc=true;
- }else{
- lenaView.setImageBitmap(bmp);
- btnProc.setText(R.string.gray_proc);
- bProc=false;
- }
- }
- });
- }
- @Override
- protectedvoidonResume(){
- super.onResume();
- //这里加载OpenCVManager
- OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9,this,mLoaderCallback);
- }
- privateBaseLoaderCallbackmLoaderCallback=newBaseLoaderCallback(this){
- @Override
- publicvoidonManagerConnected(intstatus){
- switch(status){
- caseLoaderCallbackInterface.SUCCESS:{
- }break;
- default:{
- super.onManagerConnected(status);
- }break;
- }
- }
- };
- }
至此OpenCV Java API的基本使用介绍完毕,其余的使用方法,参照官方文档,在doc文件夹下,opencv_tutorials.pdf做了详细介绍,并且上面我介绍的东西,上面基本上都有,呵呵,感觉有点白做功了。
- </pre><spanstyle="font-size:10px;"><strong></strong></span></p><p><strong>3)Android在jni中使用OpenCV</strong></p><p>同样新建工程OpenCVDemo02,新建好后,编写代码如下</p><p>activity_main.xml文件如下</p><p><prename="code"class="html"><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center_horizontal"
- android:orientation="vertical"
- tools:context="com.example.opencvdemo02.MainActivity">
- <Button
- android:id="@+id/btn_proc"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/gray_proc"
- />
- <ImageView
- android:id="@+id/imageview_lena"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@string/image_lena"
- />
- </LinearLayout>
- <?xmlversion="1.0"encoding="utf-8"?>
- <resources>
- <stringname="app_name">OpenCVDemo02</string>
- <stringname="hello_world">Helloworld!</string>
- <stringname="action_settings">Settings</string>
- <stringname="gray_proc">GrayProcess</string>
- <stringname="undo">Undo</string>
- <stringname="image_lena">lena</string>
- </resources>
[java] view plain copy
- publicclassMainActivityextendsActionBarActivity{
- privatebooleanbProc=false;
- privateButtonbtnProc;
- privateImageViewlenaView;
- privateBitmapbmp;
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.lena);
- lenaView=(ImageView)findViewById(R.id.imageview_lena);
- lenaView.setImageBitmap(bmp);
- btnProc=(Button)findViewById(R.id.btn_proc);
- btnProc.setOnClickListener(newOnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- if(!bProc){
- intwidth=bmp.getWidth();
- intheight=bmp.getHeight();
- int[]data=newint[width*height];
- bmp.getPixels(data,0,width,0,0,width,height);
- int[]result=imageProc(data,width,height);
- BitmapresultImg=Bitmap.createBitmap(width,height,Config.ARGB_8888);
- resultImg.setPixels(result,0,width,0,0,width,height);
- lenaView.setImageBitmap(resultImg);
- btnProc.setText(R.string.undo);
- bProc=true;
- }else{
- lenaView.setImageBitmap(bmp);
- btnProc.setText(R.string.gray_proc);
- bProc=false;
- }
- }
- });
- }
- @Override
- protectedvoidonResume(){
- super.onResume();
- System.loadLibrary("ImageProc");
- }
- publicnativeint[]imageProc(int[]data,intwidth,intheight);
- }
将OpenCVDemo02工程转换为C/C++工程,右击项目文件OpenCVDemo02->New->Other->C/C++->Convert to a C/C++ Project (Adds C/C++ Nature),在弹出的对话框中选择如下
到此你可能知道为什么没装Cygwin了吧。然后右击工程文件OpenCVDemo02->Properties,设置如下,其实和前面HelloJni设置一样
这些都是执行build project时的一些设置。
接着设置如下
同样的GNU C和GNU C++设置一样,设置完记得Apply一下哦,之后可以导出设置(Export Settings...),以后要用可以直接导入(Import Settings...),方便很多了。然后使用javah命令生成头文件,对于熟悉jni开发都知道,方法是运行cmd.exe,运行如下命令
运行上面的命令后会在src目录下生成一个头文件
这个自动生成的头文件内容如下
[cpp] view plain copy- /*DONOTEDITTHISFILE-itismachinegenerated*/
- #include<jni.h>
- /*Headerforclasscom_example_opencvdemo02_MainActivity*/
- #ifndef_Included_com_example_opencvdemo02_MainActivity
- #define_Included_com_example_opencvdemo02_MainActivity
- #ifdef__cplusplus
- extern"C"{
- #endif
- /*
- *Class:com_example_opencvdemo02_MainActivity
- *Method:imageProc
- *Signature:([III)[I
- */
- JNIEXPORTjintArrayJNICALLJava_com_example_opencvdemo02_MainActivity_imageProc
- (JNIEnv*,jclass,jintArray,jint,jint);
- #ifdef__cplusplus
- }
- #endif
- #endif
Android.mk的内容如下
[plain] view plain copy- LOCAL_PATH:=$(callmy-dir)
- include$(CLEAR_VARS)
- OPENCV_LIB_TYPE:=STATIC
- include../sdk/native/jni/OpenCV.mk
- LOCAL_MODULE:=ImageProc
- LOCAL_SRC_FILES:=ImageProc.cpp
- include$(BUILD_SHARED_LIBRARY)
Application.mk的内容如下
[plain] view plain copy- APP_STL:=gnustl_static
- APP_CPPFLAGS:=-frtti-fexceptions
- APP_ABI:=armeabi-v7a
- #include<ImageProc.h>
- #include<opencv/cv.hpp>
- #include<opencv2/highgui/highgui.hpp>
- #include<opencv2/core/core.hpp>
- usingnamespacecv;
- JNIEXPORTjintArrayJNICALLJava_com_example_opencvdemo02_MainActivity_imageProc
- (JNIEnv*env,jclassobject,jintArraydata,jintwidth,jintheight)
- {
- jint*buf;
- jbooleanisCopy=false;
- buf=env->GetIntArrayElements(data,&isCopy);
- if(buf==NULL){
- return0;
- }
- Matimage(height,width,CV_8UC4,buf);
- Mattemp;
- cvtColor(image,temp,CV_RGBA2GRAY);
- Matgray;
- cvtColor(temp,gray,CV_GRAY2RGBA);
- int*gray_ptr=gray.ptr<int>(0);
- intsize=width*height;
- jintArrayresult=env->NewIntArray(size);
- env->SetIntArrayRegion(result,0,size,gray_ptr);
- env->ReleaseIntArrayElements(data,buf,0);
- returnresult;
- }
这种方法不用安装OpenCV Manager,可以将OpenCV Manager卸载后再运行一遍。
下面做一些总结吧,刚开始学习一个东西时,基本都是重复前人的工作,在熟悉基本操作后,才开始自己的创作过程。关于Android.mk,Application.mk文件的介绍可以百度。学习OpenCV4Android,首先要有图像处理的基本知识,然后熟练OpenCV函数的使用,其次是Android应用开发的基本常识,最后自然是熟练jni编程了。
原博文地址:http://blog.csdn.net/Glouds/article/details/39375035
更多相关文章
- android:maxLength="" 设置字数限制无效
- Android中弹出对话框的实现
- Android设置TextView显示指定个数字符,超过部分显示...(省略号)的
- Android(安卓)Service生命周期及用法
- Android高手进阶教程(二)之----Android(安卓)Launcher抽屉类Slid
- [转]Android高手进阶教程(四)之----Android(安卓)中自定义属性(a
- 在Android上用PHP编写应用- PFA初探
- Android(安卓)RadioButton设置选中时文字和背景颜色同时改变
- 【Android】ViewPager实现图片左右滑动播放及添加点击事件