OpenCV4Android开发之旅(一)----OpenCV2.4简介及 app通过Java接口调用OpenCV的示例

2023-11-02

开发环境: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,下面贴源码:
布局文件:
<RelativeLayout xmlns: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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:text="@string/wellcome_words" />
    <ImageView 
        android:id="@+id/img_huaishi"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/nanhuaijin"
        android:layout_centerInParent="true"/>
    <Button
        android:id="@+id/btn_gray_process"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/img_huaishi"
        android:layout_centerHorizontal="true"
        android:text="灰度化"/>"

</RelativeLayout>
java文件:
package com.example.grayprocess;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {

	Button btnProcess;
	Bitmap srcBitmap;
	Bitmap grayBitmap;
	ImageView imgHuaishi;
	private static boolean flag = true; 
	private static boolean isFirst = true; 
	private static final String TAG = "MainActivity";

	//OpenCV库加载并初始化成功后的回调函数
	private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {

		@Override
		public void onManagerConnected(int status) {
			// TODO Auto-generated method stub
			switch (status){
			case BaseLoaderCallback.SUCCESS:
				Log.i(TAG, "成功加载");
				break;
			default:
				super.onManagerConnected(status);
				Log.i(TAG, "加载失败");
				break;
			}
			
		}
	};
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initUI();
	
		btnProcess.setOnClickListener(new ProcessClickListener());
	}


	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	public void initUI(){
		btnProcess = (Button)findViewById(R.id.btn_gray_process);
		imgHuaishi = (ImageView)findViewById(R.id.img_huaishi);
		Log.i(TAG, "initUI sucess...");

	}

	public void procSrc2Gray(){
		Mat rgbMat = new Mat();
		Mat grayMat = new Mat();
		srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.nanhuaijin);
		grayBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), Config.RGB_565);
		Utils.bitmapToMat(srcBitmap, rgbMat);//convert original bitmap to Mat, R G B.
		Imgproc.cvtColor(rgbMat, grayMat, Imgproc.COLOR_RGB2GRAY);//rgbMat to gray grayMat
		Utils.matToBitmap(grayMat, grayBitmap); //convert mat to bitmap
		Log.i(TAG, "procSrc2Gray sucess...");
	}

	private class ProcessClickListener implements OnClickListener{
		
		@Override
		public void onClick(View v) {
			// TODO Auto-generated method stub
			if(isFirst)
			{
				procSrc2Gray();
				isFirst = false;
			}
			if(flag){
				imgHuaishi.setImageBitmap(grayBitmap);
				btnProcess.setText("查看原图");
				flag = false;
			}
			else{
				imgHuaishi.setImageBitmap(srcBitmap);
				btnProcess.setText("灰度化");
				flag = true;
			}
		}

	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		//load OpenCV engine and init OpenCV library
		OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_4, getApplicationContext(), mLoaderCallback);
		Log.i(TAG, "onResume sucess load OpenCV...");
//		new Handler().postDelayed(new Runnable(){
//
//			@Override
//			public void run() {
//				// TODO Auto-generated method stub
//				procSrc2Gray();
//			}
//			
//		}, 1000);
		
	}
	
	
	

}
功能很简单,就是将一个图片灰度化,然后再次点击恢复成原来的。里面有几个需要注意的事项:
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()依旧不行。除了上面代码里的方法外,还可以用一个延迟,默认等加载完包初始化后,再进行图像处理的操作:
		new Handler().postDelayed(new Runnable(){

			@Override
			public void run() {
				// TODO Auto-generated method stub
				procSrc2Gray();
			}
			
		}, 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开发融合。
-------本文系原创,转载请注明作者yanzi1225627,欢迎大家加入OpenCV4Android开发联盟群:66320324,备注yanzi
示例中的代码下载:http://download.csdn.net/detail/yanzi1225627/6602691


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCV4Android开发之旅(一)----OpenCV2.4简介及 app通过Java接口调用OpenCV的示例 的相关文章

随机推荐

  • 认识 Java 中的异常 看这篇

    目录 1 初始异常 2 防御式编程 3 异常的基本用法 3 1 基本语法 3 2 为什么要处理异常 3 3 关于异常的处理方式 3 4 异常处理流程 3 5 捕获异常的注意点 3 6 抛出异常 3 7 关于finally 4 Java 异常
  • 拦截召唤神龙云文件,运行本地文件(侵删)

    第一步进入网址 https www mutegame com 170 第二步打开开发者工具 第三步找到一个叫 index 3786c js 文件右键复制网址 第四步拷贝js源码 记住上面的网址 第五步创建一个文件夹 和一个文件 第6步打开v
  • matlab练习程序(旋转矩阵、欧拉角、四元数互转)

    欧拉角转旋转矩阵公式 旋转矩阵转欧拉角公式 旋转矩阵转四元数公式 其中1 r11 r22 r33 gt 0 四元数转旋转矩阵公式 q0 2 q1 2 q2 2 q3 2 1 欧拉角转四元数公式 四元数转欧拉角公式 matlab代码如下 cl
  • 求最大公约数和最小公倍数的几种算法

    对于求解这两道道例题有很多种不同的解法 比如辗转相除法 穷举法 等等 这次简单介绍一下 求最大公约数 1 辗转相除法 辗转相除法 又名欧几里德算法 Euclidean algorithm 它的具体做法是 用较小数除较大数 再用出现的余数 第
  • asm常用命令汇总

    在Oracle 环境下 使用grid帐号执行 运行asmcmd进入asm命令模式 如 grid oradb node1 asmcmd ASMCMD gt ASMCMD gt du 显示指定的ASM目录下ASM文件占用的所有磁盘空间 ASMC
  • ecw2c理解元数据:使用BigQuery k-means将4,000个堆栈溢出标签聚类

    您如何将超过4 000个活动的Stack Overflow标签分组为有意义的组 对于无监督学习和k均值聚类来说 这是一项完美的任务 现在您可以在BigQuery中完成所有这些工作 让我们找出方法 Visualizing a universe
  • install cuda in a new Ubuntu 20.4 LTS for Geforce rtx 2080Ti

    Install cuda 11 6 2 1 download cuda 11 6 2 CUDA Toolkit Archive NVIDIA Developer 2 install cuda toolkits reference to In
  • 前端甘特图组件开发(一)

    背景 工作中需要在网页上实现甘特图 以展示进度数据 通过网上调研相关项目 找到一款 dhtmlx gantt 组件 在低程度上满足项目需求 但在部分定制功能 如时间轴自定义 编辑弹窗样式风格等 并不能完全满足项目需求 此外 使用此类开源项目
  • Rumor CodeForces - 893C(并查集基本操作:维护连通块最值)

    题目链接 PS 这题也可以用dfs搜连通块 一遍搜一遍记录连通块的最值 AC代码 include
  • 在浏览器中使用VLC插件实现播放RTSP流视频

    在浏览器中使用VLC插件实现播放RTSP流视频 一 安装VLC插件 二 编写测试html文件 三 生成一个测试用RTSP流视频 四 在浏览器中播放RTSP流视频 五 VLC插件知识扩展 1 VLC插件就是axvlc dll 2 如何手动安装
  • 【转】PL/SQL Developer 设置快捷键

    转自 http www cnblogs com SingleCat archive 2010 06 16 1759010 html 1 登录后默认自动选中My Objects 默认情况下 PLSQL Developer登录后 Brower里
  • LeetCode 刷题 14. 最长公共前缀

    LeetCode 刷题 14 最长公共前缀 题目链接点此 class Solution def longestCommonPrefix self strs List str gt str strs sort re for i j in zi
  • 制造业企业为什么都纷纷上MES系统?

    什么是MES系统 MES管理系统是一套面向制造企业车间执行层的生产信息化管理系统 它可以为企业打造一个扎实 可靠 全面 可行的制造协同管理平台 作为企业车间信息化管理技术的系统 制造执行系统MES在实现生产过程的自动化 智能化 网络化等方面
  • 用IDEA测试代码覆盖度

    IDEA自身就带有代码覆盖度测试工具 无需下载或安装其他任何工具 以下我们以P1 Graph为例讲一讲怎么用IDEA测试代码覆盖度 1 右键单击P1 Graph 2 点击Run Tests in P1 Graph 3 运行测试结束后再次右键
  • 出现windows启动服务失败(无法从命令行或调试器启动,需要安装InstallUtil.exe)的解决办法...

    两种方法1 从命令行安装2 选择项目 视图 自定义操作 然后将 安装 提交 回滚 卸载分别加入自定义操作 注意InstallClass属性为true 转载于 https www cnblogs com lovezhaolei p 38178
  • simclrv2框架

    机器学习 Machine Learning Huge Self Supervised Models are Strong Semi Supervised learners 巨大的自我监督模型是强大的半监督学习者 目录 Table of Co
  • 斐波那契(Fibonacci)查找算法

    一 黄金分割和斐波那契数列 二者的关系 黄金分割 这个词经常出现在一些建筑物的设计 黄金分割的近似值是0 618 斐波那契数列又称黄金比例数列 指的是这样的数列 1 1 2 3 5 8 13 21 34 这个数列从第三项开始 每一项都等于前
  • WebSocket协议介绍

    文章目录 前言 一 WebSocket是什么 二 WebSocket出现之前的实时技术 三 WebSocket应用场景 四 WebSocket协议栈 五 WebSocket与HTTP的区别 六 WebSocket握手过程 七 WebSock
  • 使用win10专业版自带远程桌面公司内网电脑

    在现代社会中 各类电子硬件已经遍布我们身边 除了应用在个人娱乐场景的消费类电子产品外 各项工作也离不开电脑的帮助 特别是涉及到数据采集和储存的场景 如安保监控 自动化流程等等 更是离不开电脑 在一般情况下 这些数据采集和记录的电脑会自成一个
  • OpenCV4Android开发之旅(一)----OpenCV2.4简介及 app通过Java接口调用OpenCV的示例

    开发环境 windows ADT Bundle CDT OpenCV 2 4 4 android sdk 一 OpenCV2 4简介 OpenCV近年来发展迅猛 随着Android智能终端的发展 越来越多的传统科研平台都转向Android移