Opencv4Android环境搭建及第一个例子

本文是基于网上一大牛的博客写的,大体的东西是类似的:

http://blog.csdn.net/yanzi1225627/article/details/16917961

首先是Android环境,网上很多的教程环境的配置比较的麻烦,因为多数是Android的早期版本的环境配置方法。

不知道Android在什么时候已经提供了现成的开发环境(sdk+Eclipse+ide)。现在Android的官方网站可以下载到最新的Android的开发环境,再在电脑上安装Java环境。解压Android的下载包可以就可以直接使用了。

Android开发环境下载:http://developer.android.com/sdk/index.html

jdk下载:http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javase6-419409.html#jdk-6u45-oth-JPR

下载OpenCV-x.x.x-android-sdk:http://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.4.9/OpenCV-2.4.9-android-sdk.zip/download

开发环境:windows+ADT Bundle+CDT+OpenCV-2.4.4-android-sdk

一、OpenCV2.4简介

OpenCV近年来发展迅猛,随着Android智能终端的发展,越来越多的传统科研平台都转向Android移动终端。记得2010年人们还不大知道Android,当时第一次用OpenCV还是用的1.0.2版本在VC6.0上。早期的OpenCV只提供C语言接口,你要申请个矩阵还得CvMat *mat  = cvCreateMat(...)写一大串,这样做是为了保证程序的运行效率,带来的不便是要开发者手动管理内存分配,稍有不慎内存泄漏那是常有的事。在OpenCV的发展历程上,第一次飞跃是2009年10月1日发布的2.0版本,该版本支持C++接口
了,是直接从1.2版本跳到2.0。不久又推出了2.1,自此后想要移植OpenCV至嵌入式系统,在编译时必须借助CMake工具,而以往的不用。

第二次飞跃是在2010年6月发布的2.3、2.3.1版本,除提供C++接口向下兼容C接口外,新增了Java接口,且是对准Android平台。更重要的是以前官方不支持ndk-build,这次终于一统JNI接口调用方式,方便在Android上开发使用。2012年4月2日发布了2.4版本,支持windows/Linux、Mac/Android/IOS四大系统。

最新的版本是2013年11月11日发布的2.7版本。我电脑上配置的是2.4.4版本。

从2.4之后,为了和Android的系统架构保持同步,准确说是吸收Android框架层的优点,引入了OpenCV Manager的概念,其本质就是一个Service,用来管理OpenCV动态链接库。它工作在APP和OpenCV的动态链接库之间。OpenCV Manager的结构就是模仿Android的Binder机制。其架构图如下:

APP在运行时会首先检查OpenCV Manager存在不,如果不存在则会提示安装。如果存在,就会连接这个服务,进一步初始化加载OpenCV库。流程如下:

对于开发者而言,了解即可。从应用层面讲,将OpenCV-2.4.4-android-sdk解压后,会看到如下文件夹:

其中sdk就是开包时要用到的包,samples是自带的示例,doc是说明文档,apk则就是OpenCV Manager。手机想要运行基于OpenCV的Java接口的程序,就必须先安OpenCV Manager。

不同的手机选择不同的版本,如果是英特尔平台就选那个带x86的。比较老的手机不支持ARMv7的选第三个。根据android的版本选择前两个。我手机支持的是第一种。安装后即可。

二、Android APP通过Java接口调OpenCV

1、配置

配置其实比较简单,比之前的用JNI接口调OpenCV要简单很多,不过为了保持同步,也即以后的开发中可以随意混用Java接口和JNI接口,我们仍将压缩包解压到跟工作空间平级的目录。然后将解压后的sdk文件夹命名为OpenCV4Android-sdk,拷贝到新建的工作空间中。假设新建的工作空间名为OpenCV4Android。

【备注:这里让它两平级是为了以后JNI调用时无需修改mk文件。注意解压后会嵌套一个目录,把它拷到最外层。sdk文件夹命名和拷贝到新的工作空间都不是必须的。】

打开Eclipse切换到这个新的工作空间,右键import---General---Existing Projects into workspaces,选择OpenCV解压后的那个sdk包。导入后看是否有错误,我的是提示找不到java.util.List这个包,原来是没有加载进来Android的SDK。选中项目,按快捷键Alter
+ Enter,点Android,选中一个SDK,要求3.0以上。然后clean一下,看bin文件夹下的opencv library - 2.4.4.jar是否生成,如果它生成了就表示已经导入成功。

2、新建项目并引入上面的jar包

任意新建一个Android Application Project,然后选中该项目快捷键Alter + Enter,在下面的加库区域点Add,将导入工作空间的opencv sdk选中:

可以看到在Android Dependencies中将刚到导包bin目录下生成的jar文件导进去了。之后就可以使用opencv的API了。

【备注:说白了就是为了把这个jar包导进来。在生成这个jar包后可以把它拷出来,新建一个user library参见导原生camera到eclipse这篇
之后将包加进来是一样的。这个包只有200多kb,也可以将其直接拷贝到工程目录下的libs文件夹,也是ok的。但是这样做后,就看不到jar包里具体的子包了,如org.opencv.ml这些。】

3、一个完成的demo:将一个图片灰度化

项目名字为GrayProcess,下面贴源码:

布局文件:

[html] view
plain
copyprint?

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:paddingBottom="@dimen/activity_vertical_margin"
  6. android:paddingLeft="@dimen/activity_horizontal_margin"
  7. android:paddingRight="@dimen/activity_horizontal_margin"
  8. android:paddingTop="@dimen/activity_vertical_margin"
  9. tools:context=".MainActivity" >
  10. <TextView
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:layout_alignParentTop="true"
  14. android:text="@string/wellcome_words" />
  15. <ImageView
  16. android:id="@+id/img_huaishi"
  17. android:layout_width="wrap_content"
  18. android:layout_height="wrap_content"
  19. android:background="@drawable/nanhuaijin"
  20. android:layout_centerInParent="true"/>
  21. <Button
  22. android:id="@+id/btn_gray_process"
  23. android:layout_width="wrap_content"
  24. android:layout_height="wrap_content"
  25. android:layout_below="@id/img_huaishi"
  26. android:layout_centerHorizontal="true"
  27. android:text="灰度化"/>"
  28. </RelativeLayout>

java文件:

[java] view
plain
copyprint?

  1. package com.example.grayprocess;
  2. import org.opencv.android.BaseLoaderCallback;
  3. import org.opencv.android.OpenCVLoader;
  4. import org.opencv.android.Utils;
  5. import org.opencv.core.Mat;
  6. import org.opencv.imgproc.Imgproc;
  7. import android.app.Activity;
  8. import android.graphics.Bitmap;
  9. import android.graphics.Bitmap.Config;
  10. import android.graphics.BitmapFactory;
  11. import android.os.Bundle;
  12. import android.os.Handler;
  13. import android.util.Log;
  14. import android.view.Menu;
  15. import android.view.View;
  16. import android.view.View.OnClickListener;
  17. import android.widget.Button;
  18. import android.widget.ImageView;
  19. public class MainActivity extends Activity {
  20. Button btnProcess;
  21. Bitmap srcBitmap;
  22. Bitmap grayBitmap;
  23. ImageView imgHuaishi;
  24. private static boolean flag = true;
  25. private static boolean isFirst = true;
  26. private static final String TAG = "MainActivity";
  27. //OpenCV库加载并初始化成功后的回调函数
  28. private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
  29. @Override
  30. public void onManagerConnected(int status) {
  31. // TODO Auto-generated method stub
  32. switch (status){
  33. case BaseLoaderCallback.SUCCESS:
  34. Log.i(TAG, "成功加载");
  35. break;
  36. default:
  37. super.onManagerConnected(status);
  38. Log.i(TAG, "加载失败");
  39. break;
  40. }
  41. }
  42. };
  43. @Override
  44. protected void onCreate(Bundle savedInstanceState) {
  45. super.onCreate(savedInstanceState);
  46. setContentView(R.layout.activity_main);
  47. initUI();
  48. btnProcess.setOnClickListener(new ProcessClickListener());
  49. }
  50. @Override
  51. public boolean onCreateOptionsMenu(Menu menu) {
  52. // Inflate the menu; this adds items to the action bar if it is present.
  53. getMenuInflater().inflate(R.menu.main, menu);
  54. return true;
  55. }
  56. public void initUI(){
  57. btnProcess = (Button)findViewById(R.id.btn_gray_process);
  58. imgHuaishi = (ImageView)findViewById(R.id.img_huaishi);
  59. Log.i(TAG, "initUI sucess...");
  60. }
  61. public void procSrc2Gray(){
  62. Mat rgbMat = new Mat();
  63. Mat grayMat = new Mat();
  64. srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.nanhuaijin);
  65. grayBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), Config.RGB_565);
  66. Utils.bitmapToMat(srcBitmap, rgbMat);//convert original bitmap to Mat, R G B.
  67. Imgproc.cvtColor(rgbMat, grayMat, Imgproc.COLOR_RGB2GRAY);//rgbMat to gray grayMat
  68. Utils.matToBitmap(grayMat, grayBitmap); //convert mat to bitmap
  69. Log.i(TAG, "procSrc2Gray sucess...");
  70. }
  71. private class ProcessClickListener implements OnClickListener{
  72. @Override
  73. public void onClick(View v) {
  74. // TODO Auto-generated method stub
  75. if(isFirst)
  76. {
  77. procSrc2Gray();
  78. isFirst = false;
  79. }
  80. if(flag){
  81. imgHuaishi.setImageBitmap(grayBitmap);
  82. btnProcess.setText("查看原图");
  83. flag = false;
  84. }
  85. else{
  86. imgHuaishi.setImageBitmap(srcBitmap);
  87. btnProcess.setText("灰度化");
  88. flag = true;
  89. }
  90. }
  91. }
  92. @Override
  93. protected void onResume() {
  94. // TODO Auto-generated method stub
  95. super.onResume();
  96. //load OpenCV engine and init OpenCV library
  97. OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_4, getApplicationContext(), mLoaderCallback);
  98. Log.i(TAG, "onResume sucess load OpenCV...");
  99. //      new Handler().postDelayed(new Runnable(){
  100. //
  101. //          @Override
  102. //          public void run() {
  103. //              // TODO Auto-generated method stub
  104. //              procSrc2Gray();
  105. //          }
  106. //
  107. //      }, 1000);
  108. }
  109. }

功能很简单,就是将一个图片灰度化,然后再次点击恢复成原来的。里面有几个需要注意的事项:

a、Bitmap和Mat互相转换:Utils.bitmapToMat  Utils.matToBitmap

b、加载一个图片到Bitmap:BitmapFactory.decodeResource(getResources(), R.drawable.nanhuaijin);

c、颜色转换:Imgproc.cvtColor(rgbMat, grayMat, Imgproc.COLOR_RGB2GRAY);

d、grayBitmap的格式Config.ARGB_8888和Config.RGB_565都是可以的

e、最重要的一点:app在找OpenCV里的一些包时必须在onResume函数OpenCVLoader.initAsync()之后,否则会找不到库。最初我将procSrc2Gray();放在initUI()之后直接挂掉,后来放到OpenCVLoader.initAsync()依旧不行。除了上面代码里的方法外,还可以用一个延迟,默认等加载完包初始化后,再进行图像处理的操作:

[java] view
plain
copyprint?

  1. new Handler().postDelayed(new Runnable(){
  2. @Override
  3. public void run() {
  4. // TODO Auto-generated method stub
  5. procSrc2Gray();
  6. }
  7. }, 1000);

这样就ok了,在按键监听里无需在判断是否是第一次了。程序运行结果:

最后解释下OpenCV4Android的4应该是for的意思。另外,近年来还流行个词叫JavaCV。它和OpenCV4Android完全补一个概念,但都是java接口调用OpenCv。后文会撰文介绍其搭建方式和使用。通过JNI的方式调用OpenCV参见:http://blog.csdn.net/yanzi1225627/article/details/8525720

三、OpenCV网站导航

1、http://opencv.org/ 这是OpenCV的官方网站

2、http://wiki.opencv.org.cn/index.php/ 这是国内的官网老版

3、http://www.opencv.org.cn/ 国内的官网新版

鉴于自OpenCV新增C++接口后,国内的书籍就很少,几乎没有。尤其是增加OpenCV4Android Java接口后就更少了。后续将以专栏围绕翻译OpenCV4Android Java/C++ API,及介绍如何将数字图像处理与Android APP开发融合。

时间: 2024-11-07 22:03:50

Opencv4Android环境搭建及第一个例子的相关文章

ArcGIS API for JavaScript开发环境搭建及第一个实例demo

原文:ArcGIS API for JavaScript开发环境搭建及第一个实例demo ESRI公司截止到目前已经发布了最新的ArcGIS Server for JavaScript API v3.9,它提供了更为丰富而又强大的功能.     一.安装前准备 1.ArcGIS Server for JavaScript API各版本下载地址:http://support.esrichina-bj.cn/2011/0223/960.html,我们选择下载最新的"ArcGIS API for Ja

scala 入门Eclipse环境搭建及第一个入门经典程序HelloWorld

IDE选择并下载: scala for eclipse 下载: http://scala-ide.org/download/sdk.html 根据自己的机器配置选择合适的IDE: 我这里选择For scala2.11 版本的Windows 32 bit的IDE,单击即下载. scala安装: 安装包下载地址,进入官网:http://www.scala-lang.org/ 进入DOWNLOAD下,选择scala 2.11 版本,单击下载: Windows上安装scala 2.11: 单击运行sca

windows下python环境搭建及第一个hello world

下为windows环境下的搭建过程,闲着无事记录一下,以备后用,也可以给新入门的做个参考.主要包括Python开发环境下载.安装.测试:IDE(我这里选择的是pycharm)下载.安装.配置,以及第一个hello world的运行,具体如下: 1:访问Python官网,地址:http://www.python.org/download/,下载最新的python版本. 2:安装下载包:运行下载的python安装包,然后确认JDK已安装并配置好. 3:配置环境变量:把python的安装目录添加到pt

Java程序设计基础--环境搭建及第一个java程序--Windows开发环境

一.下载jdk(建议直接选择最新的) 输入https://www.oracle.com/index.html 二.安装jdk 三.设置环境变量 JDK需要两个环境变量,分别是: CLASSPATH , PATH PATH :告诉操作系统应该在哪里找到jdk CLASSPATH:告诉jvm在哪里找到我们需要的.class文件 直接选择我的电脑--右键选择属性 建议直接建立一个“JAVA_HOME”的环境变量 PATH变量名就在后面新加否则新建此变量名输入 ;%JAVA_HOME%\bin;%JAV

SpringBoot环境搭建及第一个程序运行(详细!)

前言 SpringBoot早就想好好学习一下了,奈何自己水平不够在ssm卡了很久,好在前几天写完了一个SSM项目发到阿里云上了,网址在这贴一下,觉得还可以就往下学新的框架了,其实有了SpringMVC的底子学习过程还是很快的,记录一下学习的全过程,这样以后忘了的知识点也方便查缺补漏,话不多说直接上干货. spring boot简介 spring boot框架抛弃了繁琐的xml配置过程,采用大量的默认配置简化我们的开发过程. 所以采用Spring boot可以非常容易和快速地创建基于Spring

SpringMVC+Spring3+hibernate4 开发环境搭建以及一个开发实例教程

刚刚接触了SpringMVC这个框架,因此有必要把它拿过来同hibernate.Spring框架进行集成和开发一个实例,在真正企业从头开发的项目中往往一个稳定的开发环境至关重要,开发一个项目选择什么样的搭建平台也需要有经验才可以,并不是说你会搭建一个开发平台然后公司就会用你搭建的开发平台,一个项目或者一个公司看中的也不是你可以搭出框架,而是在这个框架使用过程中出现的各种问题你可以解决掉. 也就是说呢,无论开发什么项目要做到稳定.环境稳定.开发成本稳定.技术稳定.换句话说就是"风险可控"

Android adt bundle 开发环境配置及第一个“Hello world”程序运行

    最近在学习Android 顺便记录下学习过程当作复习吧,这是写的第一篇正式博客.  一.jdk环境配置     二.android adt bundle 下载     三.安装SDK     四.模拟器及真机调试     五.第一个程序 Hello world!     六.总结 一.jdk环境配置 jdk下载地址 选中"Accept License Agreement"之后才能下载,如下图: 下载之后 点击安装,一路next 之后配置环境变量 JAVA_HOME,找到jdk安

Android开发环境搭建&amp;第一个Android工程建立

我本人对安装开发环境花费的时间比较注意,一般不会很久,能满足自己当前眼下用就可以了,而不会把所有的资源全部配置上去,这样我会感觉十分浪费时间,然后全部搭建还会出现这样那样的不知所云的问题,看似一个一个解决掉对自己能力有一定的提升,然后对我来说这并没有什么卵用,我用这段时间,基本可以做到Android入门了,而有些人还在琢磨这eclipse怎么配置sdk路径的问题,百度谷歌了一大堆.下面是如何快速搭建Android开发环境,并写出第一个Android应用程序,我从来不写hello world,因为

appium环境配置和一个例子

最近觉得appium挺火的,看了一些资料,本来想使用npm在线安装,遇见各种问题,先简单说一下: 在cmd窗口中使用命令:npm install -g appium安装,报无python的error,好吧,下载python(环境变量自动配置),我下载的是3.3,又提示python版本不对,根据提示,需要2.5到3.0的版本,下载了python2.7,OK了,一直没有提示error,哈哈,正开心的时候,报了下面的错误: 看样子是需要C++编译器,网上查了一下资料,Windows7&Windows8