按照使用语言角度,在Android下使用OpenCV有以下几种方式:

完全使用Java语言

完全使用C++语言

混合使用Java和C++语言

下面分别讲一下怎么做,并说明这样做可能需要注意的问题。

完全使用Java语言

开始我是希望完全用Java语言开发的(也就是使用OpenCV4Android),主要好处是:

开发效率高,我指的是Java比C++生产代码的速度要快一些,至少在我的团队是这样

编译环境搭建比较简单,尤其是通过async initialization的情况下

但是,有得就有失,OpenCV是C++写的,虽然OpenCV组织也推出了供开发者使用的OpenCV4Android,但并不是所有的OpenCV C++功能都能在OpenCV4Android中找到。这也挺好理解的,人家是先写出C++的功能,然后再考虑在OpenCV4Android中实现。

所以,使用OpenCV4Android的问题是有些功能OpenCV里有,但它没有。

另外一个问题是,需要在架构上避免频繁的JNI操作,这样对性能不利。如下图:

实际上,OpenCV4Android只是在原来C++本地库的基础上做了个Java/JNI的包装(wrapper)。

在开发上,又有两种加载OpenCV4Android的方式:

async initialization,这是官方文档里推荐的,你都不需要在自己Android项目里加入OpenCV的本地库,OpenCV提供了一个可在Google Play上下载的App,你只需要将OpenCV4Android的Android库项目(libraray project)加入到你Android项目中即可,官方文档说明了这个配置过程

static initialization,官方文档建议只在开发阶段使用,和前者的不同在于,你需要将相关的本地库(so文件)部署到项目中来

如果我来选择,我可能希望正式环境下也使用static initialization的方式,原因是:

国内Android设备使用Google Play的并不多,虽然可以指定下载链接,但是增加了用户操作,不方便

可能存在这样的问题,通过Google Play下载的版本和开发使用的OpenCV4Android Java库版本不匹配

TODO: 提供一个这样的github项目示例

完全使用C++

在前一阶段的开发,我们使用的是这种方式。

希望能尽量减少混合编程带来的复杂性。借图说明:

但是,项目中业务的复杂性,需要考虑面向对象和它们的生命周期,这样可以让架构简明,而使用纯粹的C++解决方案,Java无法管理到OpenCV的对象,比如矩阵(Mat)。我们对C++的控制能力有限,担心如果设计复杂的对象和生命周期的结构,会带来错误和调试上的效率问题。

TODO: 提供github项目示例

混合使用Java和C++语言

使用上,用矩阵(Mat)的操作举例。

Java创建矩阵

创建矩阵,将Android api中的Bitmap转为矩阵:

1

2Mat bitmapMat = new Mat();

Utils.bitmapToMat(bitmap, bitmapMat);

如何将Java创建矩阵对象传递到C++

将矩阵对象传递给C++代码,实际上Mat就是C++在内存中生成的对象,Java只需传递该对象的地址就行了。

1long address=bitmapMat.getNativeObjAddr();

然后Java本地方法类似这样:

1private native long generateHistogram(long bitmap);

那么通过javah生成的头文件中方法类似这样:

1

2JNIEXPORT void JNICALL Java_marshal_opencvproto_Detector_detect(JNIEnv *env,

jobject thiz, jlong matPtr);

在C++代码中这样生成Mat对象:

1Mat *bitmpaMat = (Mat*) bitmapMatPtr;ddd

如何将C++的矩阵对象传递给Java

要根据生命周期来分析,可以有两种方式:

可在Java中创建,然后传递到C++中做处理,不需要作为返回值,因为引用的是同一个对象

在C++中创建,然后作为方法的返回值

对于后者,在C++中只需要做一次强制转型就可将矩阵对象指针传递回Java:

1

2

3

4

5Mat *hist = new Mat();

// ...

return (jlong) hist;

回传到Java需要做的处理:

1

2long address = generateHistogram(bitmapMat.nativeObj);

Mat histogram = new Mat(address);

即,直接用地址的long值创建矩阵对象即可。

C++和Java混合编程需要注意的问题

环境搭建

环境搭建中的步骤类似官方文档中static initialization的步骤。

要使用文档中说的有JNI部分的方式,而不是简单的复制本地库到libs目录下。所以重点是配置Android.mk文件,以下是我的:

1

2

3

4

5

6

7

8

9

10

11

12

13

14LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

OPENCV_INSTALL_MODULES:=on

include /opt/OpenCV-2.4.6-android-sdk/sdk/native/jni/OpenCV.mk

LOCAL_MODULE := Detector

LOCAL_SRC_FILES := Detector.cpp

LOCAL_LDLIBS :=-llog

include $(BUILD_SHARED_LIBRARY)

如何加载OpenCV库

加载OpenCV库,如果按照官方文档,也就是这样:

1OpenCVLoader.initDebug();

会有一个error日志,不过不影响使用:

1OpenCV error: Cannot load info library for OpenCV

查了一下OpenCV源代码,是加载opencv_info.so出错造成的,我没来得及看如何在Android.mk中设置将它加进来。

但可以直接这样直白的加载OpenCV库:

1system.loadLibrary("opencv_java");

就没有问题了。

使用OpenCVLoader.initDebug()加载的好处是,日志会显示很详细的OpenCV加载信息,便于你排查问题。

未解决的问题

目前有一个,就是怎样在Java中保存矩阵对象数据,以后还能根据这个数据恢复矩阵对象。

OpenCV提供了写入文件的办法,使用YAML格式,但是在Android环境下,未提供相应的wrapper API。

opencv生成日志_OpenCV在Android环境下的使用方法相关推荐

  1. opencv生成日志_opencv数据写入txt文件

    {"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],&q ...

  2. 服务器宝塔怎么开启php5.4伪静态,WeCenter在宝塔面板LNMP环境下开启伪静态方法

    WeCenter这款程序相信很多站长都使用过,风格类似于知乎社区,是一款体验很不错的程序.正好博主想要搭建一个论坛,用过DZ程序,还用过很多的轻论坛程序,最后博主想要试下WeCenter程序.在搭建的 ...

  3. android登录加密传输,android环境下两种md5加密方式(示例代码)

    在平时开发过程中,MD5加密是一个比較经常使用的算法,最常见的使用场景就是在帐号注冊时,用户输入的password经md5加密后,传输至server保存起来.尽管md5加密经经常使用.可是md5的加密 ...

  4. 【积沙成塔】Android 环境下编译后出现乱码错误的情况

    如果在Android Studio下,编译有中文备注或者含中文的程序时,会出现包含有UTF-8的看不懂的乱码错误,原因是Android Studio编码问题,在file -> setting - ...

  5. 基于Android环境下象棋的设计程序,基于Android平台的中国象棋设计与实现

    摘要: 近年,随着第三代数字通信技术的发展,数字信息产品如手机,IPad,PDA等开始获得用户的广泛接受和良好的体验.作为移动终端设备的数字信息产品己经从仅仅将通信作为唯一目标的模式演变成了具有更多市 ...

  6. opencv 调整窗口大小_opencv改变imshow窗口大小,窗口位置的方法

    opencv改变imshow窗口大小,窗口位置的方法 如下所示: cv2.HoughLinesP cv2.namedWindow("enhanced",0); cv2.resize ...

  7. Linux环境下Swap配置方法

    2019独角兽企业重金招聘Python工程师标准>>> 在Unix/Linux环境下,Swap是比较重要的空间配置内容.Swap出现的背景源于对物理内存的使用特性.相对于外存储器(硬 ...

  8. freebsd mysql5.7_FreeBSD 环境下Mysql问题解决方法集锦

    整理了一些FreeBSD 环境下Mysql问题的解决方法,供大家参考!1 修改root用户的密码时出现错误:# mysqladmin -uroot -p password 整理了一些FreeBSD 环 ...

  9. Android环境下生成PDF文件

    一.背景 公司需要一个从本地选择图片生成pdf文件并上传的功能,由于Android本身并没有对pdf的支持,这里选择使用一个第三方的库来达成需求. 二.库的选择 2.1 当前主流的库 在众多Java语 ...

最新文章

  1. 31岁成为博导!从小乡村走出的985高校教授坦言:读书这条路最简单...
  2. Windows Server 排错和发帖求助必读
  3. Linux Shell -- 无网不利
  4. Python实现网页截图
  5. vs 没有足够的内存继续执行程序_科赋内存条:韩国和台湾产的有不同?
  6. android学习资料_5G到来未来五年,纯应用的安卓开发者如何学习通过音视频破局?...
  7. 动态路由协议的分类、动静态路由优缺点、RIP简介、组播单播广播详解(附图)
  8. 在Asp.net中弹出对话框,确定后跳转到其他页面
  9. 拓端tecdat|Python用ARIMA和SARIMA模型预测销量时间序列数据
  10. 实用小工具-动软代码生成器
  11. 【数理逻辑三】命题逻辑及形式系统【下】
  12. uva12489 Combating cancer(树同构)
  13. Jenkins--创建自己的第一个Jenkins任务
  14. vs2017\vs2019 VGG19处理cifar-10数据集的TensorFlow实现
  15. 开源神器:可快速将真实物件复制粘贴到电脑上!
  16. 读书笔记---阶级逆袭——三代人的卵巢彩票
  17. java 游戏 protobuf,Unity 3D Protobuf的使用 信息的简单发送 并在Java服务器上接受显示...
  18. 4. DBSCAN方法及其应用
  19. 邻接矩阵的定义和例子
  20. 微信公众 mysql回复图片_微信公众号开发之微信公共平台消息回复类实例

热门文章

  1. java 无锁框架_高性能无锁并发框架 Disruptor,太强了!
  2. java for(o t :object) 获取顺序号_JAVA泛型通配符T,E,K,V区别 瞬间豁然开朗
  3. ArcGIS 10.2.2利用Anaconda集成scipy和pandas
  4. 开源备份web_13个开源备份解决方案
  5. 分布式 开源_3个开源分布式跟踪工具
  6. dropbox_Dropbox的5种开源替代品
  7. linux ansible_使用Ansible在Raspberry Pi上构建基于Linux的HPC系统
  8. 网络监控工具 开源_在不到一个月的时间内,我如何使用开源工具成为网络漫画家
  9. 周末总是被工作打扰_如何在不打扰任何人的情况下问为什么在工作中
  10. 高性能滚动scroll(防抖和节流)