这几周朋友几篇文章介绍了改安装目录的文章. 关联文章的地址
最近android开发异常炽热,随着手机性能越来越高,图像处程序也越来越重要,
由于opencv for android 网上教程大多为英文文档,中文教程都为零碎篇章,
很少有完全的opencv for android 教程
博主最近正在学习opencv for android 其中走了很多弯路
所以将一些经验写下 帮助大家少走弯路!
只合适初学者 请大神教正,或者绕道吧,走好不送!
注意本文只担任环境的搭建 不担任讲授
按照文章来确保能搭建一个完美的opencv for android 的开发环境
但是详细的理解 须要读者自己实验和摸索!
win7/win8 环境
我是win8环境
java SDK 6 / 7
我是用的6
eclipse for java EE IED
我是32位版
ADT插件
CDT插件
Android SDK
Android NDK
我的是r8版
cygwin
Sequoyah
opencv for android
我用的是2.4.5
如果你还没有JDK的话,可以去这里下载,接下来的工作就是安装提示一步一步走。设置环境变量步调如下:
- 我的电脑->属性->高级->环境变量->系统变量中添加以下环境变量:
- JAVA_HOME值为: D:\Program Files\Java\jdk1.6.0_18(你安装JDK的目录)
- CLASSPATH值为:.;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\bin;
- Path: 在开始追加 %JAVA_HOME%\bin;
- NOTE:前面四步设置环境变量对搭建Android开发环境不是必须的,可以跳过。
安装实现当前,可以在检查JDK是否安装成功。打开cmd窗口,输入java –version 查看JDK的版本信息。涌现相似下面的画面表示安装成功了:
1.下载
2.解压到任意目录
3.去目录启动
4.设置工作路径
5.安装实现
在Android Developers下载android-sdk_r05-windows.zip,下载实现后解压到任意路径。
- 运行SDK Setup.exe,点击Available Packages。如果没有涌现可安装的包,请点击Settings,选中Misc中的"Force https://..."这项,再点击Available Packages 。
- 选择希望安装的SDK及其文档或者其它包,点击Installation Selected、Accept All、Install Accepted,开始下载安装所选包
- 在用户变量中新建PATH值为:Android SDK中的tools绝对路径(本机为D:\AndroidDevelop\android-sdk-windows\tools)。
运行 android –h 如果有相似以下的输出,标明安装成功:
ADT是专门给eclipse开发android的插件
- 打开 Eclipse IDE,进入菜单中的 "Help" -> "Install New Software"
- 点击Add...按钮,弹出对话框要求输入Name和Location:Name自己随意取,Location输入http://dl-ssl.google.com/android/eclipse。如下图所示:
然后就是按提示一步一步next。
实现当前:
- 选择Window > Preferences...
- 在左边的面板选择Android,然后在右侧点击Browse...并选中SDK路径,本机为:
D:\AndroidDevelop\android-sdk-windows - 点击Apply、OK。配置实现。
创建android AVD模拟器:
NDK + Cygwin 环境搭建:
安装Android NDK:
安装Cygwin:
由于NDK开发大都涉及到C/C++在GCC环境下编译、运行,所以在Windows环境下,须要模拟Linux模拟编译环境,下载地址:
下载后是个setup.exe文件,应用进程如下:
第一步:运行setup程序,第一步图略,直接点击Next进入下一步。
第二步:选择安装方法,第一次可以采取Direct Connection在线下载安装,如有现成的离线包,可以选择离线安装(Install from Local Directory)。
第四步:设置本地包暂存路径
暂存目录默许是放到setup.exe的同级目录下,下载后名字相似ftp%3a%2f%2fcygwin.mirrors.pair.com%2f这样格式。
第五步:设置网络连接方法
第六步:选择下载站点地址
起初实验几个看哪个速度快就用哪个地址(如果感到不快就点取消,再次来过)。
第七步:等待加载安装项载入,选择安装项
我们编译NDK,在默许设置下,只要选择Devel(点击列表中Devel,将前面的Default改成Install,图中箭头所示),其它均为默许状态。
第八步:等待下载实现
下载实现时光决定于你选择的安装包数量及网络连接速度,比如按照本文默许的选择方法,可能须要4-5个小时,下载后压缩包约750M,下载实现后会自动安装到上文设置的安装目录。
安装实现后,先运行Cygwin一次(Cygwin.bat),以便创建一些用户环境文件,分离输入:
make -v
和,
gcc -v
如果检测成功,会有make和gcc相关版本信息打印出来,如下图。
可以在cygwin中通过vim修改,也可以在windows安装目录中修改 home\<你的用户名>\.bash_profile 文件中最后添加环境变量
NDKROOT=/cygdrive/e/Andriod/develop/android-ndk-r8
export NDKROOT
其中NDK=/cygdrive/<你的盘符>/<android ndk 目录> ,"NDK"这个名字随意起,当前经常用不要太长。
重启cygwin,输入:
cd $NDK
可进入ndk对应目录说明设置OK。
3.用ls命令查看libs/armeabi/下是否生成了so文件,有libhello-jni.so说明ndk运行正常。
$ ls libs/armeabi/
gdb.setup gdbserver libhello-jni.so
也可以到E:\android\android-ndk-r8\samples\hello-jni\libs\armeabi目录下看有没有生成的.so文件。
2)导入NDK的hello-jni示例到Eclipse中
1.在Eclipse中新建一个Android工程HelloJni。
在Create Android Project时勾选“Create project from existing source”,Location中填E:\android\android-ndk-r8\samples\hello-jni
2.直接以Android Aplication运行com.example.hellojni.HelloJni项目。要先有.so文件才能运行起来。 os放在工程根目录下
CDT插件的安装:
不同eclipse版本要下载对应的包,否则安装不了。
Help-->About Eclipse 下可以看到自己用的版本,我的是 Version: Helios Service Release 2 即Helios版本
http://www.eclipse.org/downloads/download.php?file=/tools/cdt/releases/helios/dist/cdt-master-7.0.2.zip
cdt-master-7.0.2.zip:这个是CDT的离线安装包。(由于文件比较大推荐应用离线包,7.0.2的54.8M,8.1.1的103MB)
安装:Eclipse -> Help -> Install New Software,点击add。
Name:CDT_版本。
Location:点击Archive,定位到下载的“cdt-master-7.0.2.zip”文件。
如果Location的下面涌现“Duplicate location”错误,请到Window -> preferences -> Install/Update -> Avaliable Software Site中找到remove掉。
如果涌现缺少eclipse包说明你下载的版本和eclipse版本不匹配,从新下载匹配的从新安装就可以了。
安装实现重启后,在Eclispe中新建一个项目,如果涌现了C/C++项目,则标明CDT插件安装成功了。
安装Sequoyah插件:
官方网址:http://www.eclipse.org/sequoyah/downloads/
打开上面网址就可以看到详细的安装说明了
Location:http://download.eclipse.org/sequoyah/updates/2.0/
For Helios SR2 Sequoyah version: http://download.eclipse.org/sequoyah/updates/1.0.2/
注:只是安装1.0.2的没有出来“本机开发”的配置所以没法用,本人从新安装了2.0的可以了,这个应该直接安装最新版2.0的就可以了。
在安装界面不要勾选“Group items by category”复选框,选中涌现了列表为空(There are no categorized items)的情况。
在“window –> preferences ->Android -> 本机开发”中添加NDK的路径。
重启后右键之前建立的“HelloJni”项目,在“Android Tools”选项中包含“Add Native Support…”选项即成功。
opecnv for android 开发环境搭建:
opencv for android SDK 安装:
进入官网(http://opencv.org/)下载OpenCV4Android并解压,其目录结构如下:
其中,sdk目录即是我们开发opencv所须要的类库;samples目录中存放着多少opencv应用示例(包括人脸检测等),可为我们进行android下的opencv开发提供参考;doc目录为opencv类库的应用说明及api文档等;而apk目录则存放着对应于各内核版本的OpenCV_2.4.3.2_Manager_2.4应用安装包。此应用用来管理手机设备中的opencv类库,在运行opencv应用之前,必须确保手机中已安装了OpenCV_2.4.3.2_Manager_2.4_*.apk,否则opencv应用将会因为无法加载opencv类库而无法运行。
2.2 将SDK引入工作空间
(1) 选择一个路径,新建文件夹做为工作空间(我在E盘根目录下新建workspace目录来做为工作空间);
(2) 将OpenCV-2.4.3.2-android-sdk中的sdk目录copy至工作空间,并将其更名为OpenCV-SDK(是否更改名称无所谓,这是我个人习气而已);
(3) 以新建的目录为工作空间,打开eclipse;
(4) 将OpenCV-SDK引入到工作空间中,如下图所示:
应用java API开发android:
创建工程
(1) 打开eclipse,创建android应用工程GrayProcess;
(2) 将测试图像lena.jpg添加到资源目录res/drawable-hdpi中;
(3) 在Package Explorer中选择项目GrayProcess,单击右键在弹出菜单中选择Properties,然后在弹出的Properties窗口中左侧选择Android,然后点击右下方的Add按钮,选择OpenCV Library 2.4.3并点击OK,操纵实现后,会将OpenCV类库添加到GrayProcess的Android Dependencies中,如下图所示:
<resources> <string name="app_name">GrayProcess</string> <string name="hello_world">Hello world!</string> <string name="menu_settings">Settings</string> <string name="title_activity_main">MainActivity</string> <string name="str_proc">gray process</string> <string name="str_desc">image description</string> </resources>(2) 布局文件:main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:id="@+id/btn_gray_process" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/str_proc"/> <ImageView android:id="@+id/image_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@string/str_proc"/> </LinearLayout>
(3) MainActivity.java
package com.iron.grayprocess; import org.opencv.android.BaseLoaderCallback; import org.opencv.android.LoaderCallbackInterface; import org.opencv.android.OpenCVLoader; import org.opencv.android.Utils; import org.opencv.core.Mat; import org.opencv.imgproc.Imgproc; import android.os.Bundle; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Bitmap.Config; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; public class MainActivity extends Activity implements OnClickListener{ private Button btnProc; private ImageView imageView; private Bitmap bmp; //OpenCV类库加载并初始化成功后的回调函数,在此我们不进行任何操纵 private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { @Override public void onManagerConnected(int status) { switch (status) { case LoaderCallbackInterface.SUCCESS:{ } break; default:{ super.onManagerConnected(status); } break; } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btnProc = (Button) findViewById(R.id.btn_gray_process); imageView = (ImageView) findViewById(R.id.image_view); //将lena图像加载程序中并进行表现 bmp = BitmapFactory.decodeResource(getResources(), R.drawable.lena); imageView.setImageBitmap(bmp); btnProc.setOnClickListener(this); } @Override public void onClick(View v) { Mat rgbMat = new Mat(); Mat grayMat = new Mat(); //获得lena黑色图像所对应的像素数据 Utils.bitmapToMat(bmp, rgbMat); //将黑色图像数据转换为灰度图像数据并存储到grayMat中 Imgproc.cvtColor(rgbMat, grayMat, Imgproc.COLOR_RGB2GRAY); //创建一个灰度图像 Bitmap grayBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Config.RGB_565); //将矩阵grayMat转换为灰度图像 Utils.matToBitmap(grayMat, grayBmp); imageView.setImageBitmap(grayBmp); } @Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存在于OpenCV安装包的apk目录中 OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback); } }
3.1.3 运行结果
应用 c++ API开发android:
创建工程
步调如工程一,创建新工程GrayProcess2,将lena.jpg添加到资源文件,并按上面所示将opencv类库添加到工程中。
编写下层代码(java)
(1)Stings.xml
<resources> <string name="app_name">GrayProcess2</string> <string name="hello_world">Hello world!</string> <string name="menu_settings">Settings</string> <string name="title_activity_main">GrayProcess2</string> <string name="str_proc">gray process</string> <string name="str_desc">image description</string> </resources>(2)main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:id="@+id/btn_gray_process" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/str_proc"/> <ImageView android:id="@+id/image_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@string/str_proc"/> </LinearLayout>
(3)MainActivity.java
package com.iron.grayprocess2; import org.opencv.android.BaseLoaderCallback; import org.opencv.android.LoaderCallbackInterface; import org.opencv.android.OpenCVLoader; import android.os.Bundle; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Bitmap.Config; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; public class MainActivity extends Activity implements OnClickListener{ private Button btnProc; private ImageView imageView; private Bitmap bmp; //OpenCV类库加载并初始化成功后的回调函数,在此我们不进行任何操纵 private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { @Override public void onManagerConnected(int status) { switch (status) { case LoaderCallbackInterface.SUCCESS:{ System.loadLibrary("image_proc"); } break; default:{ super.onManagerConnected(status); } break; } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btnProc = (Button) findViewById(R.id.btn_gray_process); imageView = (ImageView) findViewById(R.id.image_view); //将lena图像加载程序中并进行表现 bmp = BitmapFactory.decodeResource(getResources(), R.drawable.lena); imageView.setImageBitmap(bmp); btnProc.setOnClickListener(this); } @Override public void onClick(View v) { int w = bmp.getWidth(); int h = bmp.getHeight(); int[] pixels = new int[w*h]; bmp.getPixels(pixels, 0, w, 0, 0, w, h); int[] resultInt = ImageProc.grayProc(pixels, w, h); Bitmap resultImg = Bitmap.createBitmap(w, h, Config.ARGB_8888); resultImg.setPixels(resultInt, 0, w, 0, 0, w, h); imageView.setImageBitmap(resultImg); } @Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存在于OpenCV安装包的apk目录中 OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback); } }
代码第28行:System.loadLibrary("image_proc")用来当OpenCV类库初始化实现后加载类库image_proc。此类库由我们来生成,用于实现图像灰度处理的操纵,此部分将在下面中说明。
(4) ImageProc.java
package com.iron.grayprocess2; public class ImageProc { public static native int[] grayProc(int[] pixels, int w, int h); }
编写JNI及C相关代码
在项目中新建目录jni,在jni目录中分离添加文件Android.mk,Application.mk,ImageProc.h,ImageProc.cpp,这四个文件的内容分离如下所示。
(1) Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) include ../OpenCV-SDK/native/jni/OpenCV.mk LOCAL_SRC_FILES := ImageProc.cpp LOCAL_MODULE := image_proc include $(BUILD_SHARED_LIBRARY)
代码说明:
第一行:指明当前编译路径;
第二行:清空变量;
第三行:将OpenCV类库中的编译文件包含进来,如此一来在我们的工程中即可应用OpenCV类库;
第四行:指定须要编译的C++源文件;
第五行:指定编译生成的类库名称;
第六行:调用命令将源文件编译为静态库。
注:第三行指定的路径很关键,当opencv类库与工程路径相关位置产生改变时,此路径也要随之改变。
(2) Application.mk(配置文件)
APP_STL := gnustl_static APP_CPPFLAGS := -frtti -fexceptions APP_ABI := armeabi-v7a APP_PLATFORM := android-8
#include <ImageProc.h> #include <opencv2/core/core.hpp> #include <string> #include <vector> using namespace cv; using namespace std; JNIEXPORT jintArray JNICALL Java_com_iron_grayprocess2_ImageProc_grayProc(JNIEnv* env, jclass obj, jintArray buf, jint w, jint h){ jint *cbuf; cbuf = env->GetIntArrayElements(buf, 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; }
说明:
-
ImageProc.h头文件可以通过jdk提供的工具javah来生成,详细生成方法在下面
-
JNI中的定义的函数遵循必定的命名规则:Java_包名_类名_方法名,详细参考JNI编程相关知识;
-
ImageProc.cpp中利用黑色值转换为灰度值的计算公式,将lena.jpg图像的每一个像素转换为灰度值,并返回给应用层。须要注意的是对于 ARGB_8888类型的图像而言,其每一个像素值在int型数据中的存储序列为BGRA。还须要注 ImageProc.cpp 这个文件 第10行的函数名称Java_包名_类名_方法名 请修改成.h 文件生成的那个函数名
1.首先当年写完ImageProc.java 这个保存 当前 eclipse会自动帮你生成 java 的class文件
你可以再工程目录--》 bin --》classes -》com -------。。。。。 的文件里找到
比如我的 在E:\work\op\OpenCV-2.4.5-android-sdk\samples\Test2\bin\classes\com\test2\test2 这个路径下
如图
2.将classes文件拷贝到e盘根目录下
然后打开 cmd
e:
cd classes
javah com.test2.test2.ImageProc
然后就会在classes文件里找到一个 xxx.的头文件 如图
你可以将这个头文件改成任意名字 比如我们上面的ImageProc.h 然后放入工程目录的jni中
编译运行方法有两种
1 配置eclipse自动运行
第一步:转换工程。点击“文件 -> 新建 -> 其他”(快捷键:Ctrl+N)。选择“C/C++”下的“Convert to a C/C++ Project(Adds C/C++ Nature)”。进 入“下一步”。
第二步:选中你刚才建的“HelloJni”工程,下面左边选“Makefile project”右侧选“Cygwin GCC”。肯定后提示的“透视图”不清楚是什么,点击“是”即可。
第三步:在“HelloJni”工程上右键,选择“属性”。配置“C/C++ Build”和“C/C++ General -> Paths and Symbols”。
C/C++ Build:点击“C/C++ Build”,在右侧的“Builder Settings”中去掉默许勾选的“Use default build command”复选框。设置Build command为“
${NDKROOT}/ndk-build.cmd "
C/C++ General -> Paths and Symbols:在Includes下add新的GNU C依赖路径。此“HelloJni”工程须要“D:\Java\android-ndk-r8\platforms\android-8\arch-arm\usr\include”即可,当前根据不同项目选择不同的依赖库。
这里只要是你cpp文件里面文件包含目录
你可以直接在NDK 和opencv jni那个目录下搜索头文件名 然后看看在那个路径有
配置好后运行就行了
2.手动应用Cygwin 生成os 然后运行
由于程序中涉及到了JNI编程,因此须要用cygwin对其中的C/C++代码进行编译。打开cygwin,进入到工程的根目录中执行命令:$NDKROOT/ndk-build实现相关编译;当前在eclipse中刷新工程GrayProcess2,运行即可。编译及运行结果分离如下所示。
到这里两种方法都结束了!
有问题请留言
或者279291014@qq.com
文章结束给大家分享下程序员的一些笑话语录:
Borland说我很有前途,Sun笑了;Sun说我很有钱,IBM笑了;IBM说我很专业,Sybase笑了;Sybase说我数据库很牛,Oracle笑了;Oracle说我是开放的,Linux笑了;Linux说我要打败Unix,微软笑了;微软说我的系统很稳定,我们都笑了。