Ubuntu 16.04下为Android编译OpenCV 3.1.0 Manager

        最近想在Android上尝试一下SIFT和SURF匹配算法,但考虑到这些算法都是专利保护的,并没有被包含在预编译库中,所以还需要自己来动手编译OpenCV Android SDK。在OpenCV 2.4.x版本中,这些算法被包含在nonfree模块中;从3.0版本开始,用于图像特征匹配的一些算法(比如SIFT,SURF,BRIEF,FREAK等)被转移到了opencv_contrib项目的xfeatures2d模块中。在PC环境下,为C++编译opencv+contrib库是很方便的,不过为Android平台的编译过程就有些麻烦了。

        我在编译的过程中也遇到了一些问题,在网络上搜索相应解决方案时也发现很多人都在尝试为OpenCV Android SDK添加contrib(nonfree)支持,某些遇到难以解决的问题最后只能绕路而行,比如这里这里。我找到相应解决办法后回应了他们,但愿对别人会有所帮助吧!

        本文要介绍的内容就是如何在Ubuntu 16.04环境下利用最新的OpenCV和opencv_contrib为Android平台编译一个可用的OpenCV Android SDK,并生成相应的OpenCV Manager。

        我的开发环境如下:

                Ubuntu 16.04 LTS (x64)

                GCC 5.4.0

                CMAKE 3.5.1

                OpenCV 3.1.0

                Android SDK API 23(Android 6.0)

                Androird NDK r12b(12.1.2977051)

                Python 2.7.12

        当然在编译过程中还会用到很多其他工具和软件包,比如Ninja,Ant等,我会在文中需要的时候给出它们的版本和安装方法。

        关于GCC,CMAKE和Python的安装过程本文就不详述了,一是因为这些工具的安装过程很容易,网络上的介绍都很详细,二是因为之前刚刚配置好TensorFlow,安装了一大堆软件包,我也不清楚本文的内容究竟会涉及哪些依赖库,我会尽量把我在编译过程中所需的工具和库标记出来。

        同样,Android SDK和NDK的安装方法这里也不会作过多介绍。我是通过Android Studio 2.1.2提供的SDK Manager下载的Android SDK和Android NDK,在Android Studio中下载Android SDK和Android NDK的方法可以参考《Android Studio 2上利用NDK进行OpenCV 3.1开发》,虽然开发平台不同,但在软件界面中的操作过程是相似的。我的Android SDK路径是/home/john/Android/Sdk,Android NDK的路径是/home/john/Android/Sdk/ndk-bundle。


下载源码

        在opencv的master分支下载最新的opencv源码,解压到一个有读写权限的目录下,比如/home/john/Downloads/opencv-master。在这里下载最新的opencv-contrib源码,解压到某个目录下,个人习惯是解压到OpenCV的源码根目录下,使得opencv-contrib/modules目录的路径如/home/john/Downloads/opencv-master/opencv_contrib/modules,这个路径后面会用到。

        如果你的机器上已经有了一份opencv源码,但不想花时间去下载最新版本,至少要保证你的opencv源码是在16年5月份之后下载的(具体来讲,至少要包含该Pull Request:Added –extra_modules_path to build_sdk.py #6460,这样你的build_sdk.py才会包含后面要用到的extra_modules_path)。

        仅仅下载好源码还不够,还要对源码做一些修改,具体如下:

        1.把/home/john/Downloads/opencv-master/opencv_contrib/modules/xfeatures2d/include/opencv2目录下的xfeatures2d.hpp文件和xfeatures2d文件夹复制到/home/john/Downloads/opencv-master/modules/features2d/include/opencv2目录下。此时,该目录包含的文件应该如下图所示:

features2d-include        2.找到/home/john/Downloads/opencv-master/modules/features2d/misc/java/src/cpp目录,打开features2d_manual.hpp文件,做以下修改:

        在第8行增加一个头文件opencv2/xfeatures2d.hpp,即把

改为

        把第120-125行的

改为

        把第352-357行的

改为

        把第367-359行的

改为


编译OpenCV Android SDK

        找到/home/john/Downloads/opencv-master/platforms/android目录,在该目录下会发现build_sdk.py文件,这个文件就是用来编译OpenCV Android SDK的Python脚本文件。

        首先做一些检查工作:

        1.在第78行的ABIs定义了需要编译的ABI目标以及相应的NDK工具链。保险起见,可以先在/home/john/Android/Sdk/ndk-bundle/toolchains中查看一下你的NDK工具链版本,如果版本号有所不同,就要修改build_sdk.py中对应ABI工具链的版本,如下图所示:

ndk-toolchains        mips和mips64两行被注释掉的原因是,在我的机器上编译时,由于依赖库之一Google Protobuf的编译错误,无法为这两个架构成功编译OpenCV Android SDK。不过我手边并没有采用该架构的Android设备,而且我暂时还不需要考虑短期内编写的代码有太好的兼容性,所以干脆放弃对这两种架构进行编译。如果感兴趣,你可以试着为mips编译一下:)

        2.安装Ninja。打开终端,输入:

        另外,我在编译之前参考这里又安装了几个用于交叉编译的库,不确定是否必要,但还是贴出来吧:

        其中版本号4.9根据你的NDK工具链的版本来修改。

        3.安装Ant。在终端输入:

        如果不安装Ant,在编译过程中CMAKE关于Java的输出信息全是NO,而且后面还会出现unknown target 'opencv_engine'的错误。

        4.build_sdk.py里还有很多可以根据需要来修改的地方,比如-DANDROID_NATIVE_API_LEVEL可以适当地提高,可以选择开启-DBUILD_EXAMPLES-DBUILD_TESTS等等。这里为了演示的目的,除了前文提到的,其他地方全部保持默认,不做修改。

        5.在终端中输入:

        注意命令是一行的,中间没有换行符。

        根据build_sdk.py文件中第252行的说明,其采用的参数按照以下格式:

        其中,<output-dir>是保存编译中间结果和最终结果的目录(也叫工作目录),<android-sdk-path>指向OpenCV源码目录,<android-sdk-path>为Android SDK目录,<ndk-path>为Android NDK目录,<opencv-contrib-path>为opencv_contrib/modules所在的路径。


结果

        最终,在/home/john/Downloads/opencv-master/build目录中会得到一个名为OpenCV-android-sdk的文件夹,这就是你编译得到的OpenCV Android SDK。和官方预编译库一样,在apk子文件夹中是OpenCV Manager的安装包,在sdk/java文件夹中是OpenCV的Java接口,sdk/native是OpenCV的Native接口。

        在新项目中使用自己编译的OpenCV Android SDK时,要注意需要在设备上重新安装OpenCV Manager,还要修改Android.mk中指向OpenCV.mk的路径。

opencv-manager-apk

        如果需要调用SIFT,SURF等匹配算法,还要把相应的源码文件(位于/home/john/Downloads/opencv-master/opencv_contrib/modules/xfeatures2d/src)拷贝到项目jni文件夹中,然后在Android.mk中为LOCAL_SRC_FILES添加对应的源码文件。

        在编译的过程中如果发现有错误或异常出现,可以首先比较一下OpenCV官方BuildBot的输出信息,便于分析自己的问题原因。最新编译结果的链接为:http://pullrequest.opencv.org/buildbot/one_line_per_build。一次编译成功的输出结果为precommit_pack_android Build Log #116。如果你的网络比较好,甚至可以把网站上生成的压缩包下载下来(比如这里)!

        另外附上一篇在Android上利用SIFT,SURF和FREAK进行目标匹配的教程:《深入OpenCV Android应用开发 中文版 – 第三章代码更新》


参考资料

[1] http://stackoverflow.com/questions/30657774/surf-and-sift-algorithms-doesnt-work-in-opencv-3-0-java

[2] https://github.com/opencv/opencv/issues/5561

[3] https://github.com/opencv/opencv/issues/6215

[4] http://answers.opencv.org/question/73863/how-to-run-build_sdkpy-for-android-sdk/

共有6条评论

  1. 第二步修改源码的目的是因为楼主要用到sift和surf,现在我想用contrib里的tracking,是不是就不用修改了?谢谢楼主~

  2. 学长你好,我也是电子科大的,能看到你的博客真的很高兴。我是一名初级android开发人员对jni与opencv不是很懂,最近项目需要在android本地端实现surf,你的取灰度图工程我跑通了,但是contrib加入opencv编译无法通过,不知道学长你能共享一下你编译成功的sdk吗?万分感谢,我的邮箱是:qwer673055793@163.com。

  3. 你好 我想问下 第二步那些代码的修改的目的是什么?  我想用contrib中的bgsegm和xphoto  请问也需要这样修改代码吗?

    1. 你好,你把contrib加入opencv编译通过了吗?我需要用到surf,不知道朋友你能共享下你编译成功的sdk吗?

    2. 层主后来试了么?那些修改的代码怎么回事,不用到特征检测就不用改对吧?只关心contrib里自己需要的东西?

发表评论

电子邮件地址不会被公开。 必填项已用*标注