深入OpenCV Android应用开发 中文版 – 第三章代码更新

book

本书中文版链接:

亚马逊  京东  当当

英文原版链接:

亚马逊《Mastering OpenCV Android Application Programming》


        原书所给代码以章为单位,针对的Android版本从API 19到API 21不等,同时使用的OpenCV库版本也有2.4.9和2.4.10两种。本文给出的代码是在原书代码的基础上,针对Android 6.0(API 23)与OpenCV 3.1进行了修改,适当地增加了一些预处理等操作,以使代码整体上更合理。

        原书的完整代码可以在这里获取:https://www.packtpub.com/lcode_download/22299

        关于在Android Studio上配置OpenCV 3.1开发环境的方法,请参考《在Android Studio上进行OpenCV 3.1开发》

        关于在Android Studio上利用NDK配置OpenCV 3.1开发环境的方法,请参考《Android Studio 2上利用NDK进行OpenCV 3.1开发》

        本章介绍如何在Android Studio 2上利用OpenCV 3.1的Java API和Native API,并通过Android NDK r12b开发一个图像匹配应用,涉及的算法有SIFT,SURF,ORB,BRISK和FREAK。关于以上各算法的原理可以参考《深入OpenCV Android应用开发》第三章。

        本书中文版在62页介绍了向Android项目添加nonfree模块的方法,但对于OpenCV 3.1是不适用的。首先,在OpenCV 3.1中,SIFT等匹配算法被转移到了opencv_contrib项目的xfeatures2d模块中。其次,即使在项目的Android.mk中添加所需的源码文件,由于OpenCV 3.1本身的一个BUG,来自源码的features2d_manual.hpp文件中是没有声明相应的C++接口的。所以就需要自己来编译支持SIFT等匹配算法的OpenCV Android SDK,并生成相应的OpenCV Manager安装包。所以,本文所给的代码与原书相比变化较大。

        此外,由于涉及的目标匹配算法计算量都比较大,所以本章引入了Android多线程编程技巧,利用AsyncTask执行核心计算,以避免阻塞主UI进程。具体细节请参考下文代码。


开发环境:

        Ubuntu 16.04 x64(Windows 7 x64旗舰版以及 Windows 10 x64专业版也测试通过)

        Android Studio 2.1.2(Gradle 2.10,Android Plugin 2.1.2)

        Android 6.0(API 23)

        OpenJDK 1.8.0(对于一般Android开发来说,与Oracle JDK并无差别)

        OpenCV 3.1.0 Android SDK dev(需要自己编译)


编译OpenCV Android SDK:

        请参考《Ubuntu 16.04下为Android编译OpenCV 3.1.0 Manager》的过程为该项目编译一个支持SIFT,SURF和FREAK算法的OpenCV Android SDK,并将编译产生的OpenCV-android-sdk文件夹拷贝到某个位置,比如/home/john/Android/OpenCV-contrib-android-sdk(我把自己编译的OpenCV Android SDK重命名为OpenCV-contrib-android-sdk以区分官方的预编译库)。

        我的Android SDK目录为/home/john/Android/Sdk,Android NDK目录为/home/john/Android/Sdk/ndk-bundle。

opencv-contrib-android-sdk

        向Android项目导入自己编译的OpenCV Android SDK时,显示的名称为openCVLibrary310dev,而且在项目结构视图里会出现两个模块,分别为openCVLibrary310openCVLibrary310dev,其中openCVLibrary310dev需要加入app的Dependencies。

project-structure


代码及简略解释:

        1.创建Android Studio项目,包命名为net.johnhany.moaap_chp3

        2.在app\src\main\java目录中找到net.johnhany.moaap_chp3包,为MainActivity.java添加如下代码:

        与原书的代码相比,变化主要有:

        (1)去掉了一些无用的import,增加了一些必要的import;

        (2)在onCreate()中增加了动态申请外部存储读取权限的机制,并增加了相应变量REQUEST_READ_EXTERNAL_STORAGEread_external_storage_granted;在需要保存输出图像的代码之前增加了申请外部存储写入权限的代码,并增加了相应变量REQUEST_WRITE_EXTERNAL_STORAGEwrite_external_storage_granted

        (3)将部分Log.d()替换为Log.i(),便于查看调试信息;

        (4)更新了OpenCV的版本,OPENCV_VERSION_2_4_9改为OPENCV_VERSION_3_1_0

        (5)把jni模块nonfree重命名为xfeatures2d

        3.在app\src\main\java目录中添加一个名为HomeActivity.java的文件,其内容如下:

        4.在app\src\main中添加一个名为jni的文件夹,在这个文件夹里添加一个名为Android.mk的文件,内容如下:

        其中/home/john/Android/OpenCV-contrib-android-sdk/sdk/native/jni/OpenCV.mk要替换为你编译得到的OpenCV Android SDK目录下的对应路径。

        5.在app\src\main\jni文件夹中添加Application.mk文件,内容如下:

        6.把/home/john/Downloads/opencv-master/opencv_contrib/modules/xfeatures2d/src目录下的freak.cppprecomp.hppsift.cppsurf.cppsurf.hppxfeatures2d_init.cpp共6个文件拷贝到app\src\main\jni文件夹中。其中,precomp.hpp文件需要做如下修改:

        注释掉第52-53行的

        再注释掉第66行的

        7.修改app/src/main/res/layout/activity_main.xml文件内容为:

        8.在app/src/main/res/layout目录中添加activity_home.xml文件,其内容如下:

        9.在app/src/main/res目录下新建一个名为menu的文件夹,在其中添加一个menu_main.xml文件,内容如下:

        10.修改app/src/main/res/values/strings.xml文件,内容为:

        11.修改app/src/main/AndroidManifest.xml文件为如下内容:

        12.修改app/build.gradle文件为:

        注意倒数第二行的依赖库名称为openCVLibrary310dev,而不是默认的openCVLibrary310

        13.修改openCVLibrary310dev项目下的build.gradle文件为:

        14.确认一下项目根目录下的build.gradle文件是否为:


运行效果:

Screenshot_20160729

共有32条评论

  1. 請問我得到這個錯誤是哪裡有錯嗎? 照著上面的步驟做

    java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN2cv3hal6exp32fEPKfPfi" referenced by "libxfeatures2d.so"

    1. 對了~ 關於 把/home/john/Downloads/opencv-master/opencv_contrib/modules/xfeatures2d/src目录下的freak.cpp,precomp.hpp,sift.cpp,surf.cpp,surf.hpp,xfeatures2d_init.cpp共6个文件拷贝到app\src\main\jni文件夹中。其中,precomp.hpp文件需要做如下修改:

      這六個文件 我是網路上google 載的 不知道有沒有差!!

    2. 整個錯誤訊息是

      E/art: dlopen("/data/app/com.example.yantingchen.testopencv3-2/lib/arm/libxfeatures2d.so", RTLD_LAZY) failed: dlopen failed: cannot locate symbol "_ZN2cv3hal6exp32fEPKfPfi" referenced by "libxfeatures2d.so"…
      E/AndroidRuntime: FATAL EXCEPTION: main
                        Process: com.example.yantingchen.testopencv3, PID: 13942
                        java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN2cv3hal6exp32fEPKfPfi" referenced by "libxfeatures2d.so"…
                            at java.lang.Runtime.loadLibrary(Runtime.java:371)
                            at java.lang.System.loadLibrary(System.java:989)
                            at com.example.yantingchen.testopencv3.MainActivity$1.onManagerConnected(MainActivity.java:68)
                            at org.opencv.android.AsyncServiceHelper$3.onServiceConnected(AsyncServiceHelper.java:319)
                            at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1314)
                            at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1331)
                            at android.os.Handler.handleCallback(Handler.java:739)
                            at android.os.Handler.dispatchMessage(Handler.java:95)
                            at android.os.Looper.loop(Looper.java:155)
                            at android.app.ActivityThread.main(ActivityThread.java:5696)
                            at java.lang.reflect.Method.invoke(Native Method)
                            at java.lang.reflect.Method.invoke(Method.java:372)
                            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
                            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)

       

  2. 請問如何使用openCV 3.1 去支援 android api level 18的版本

    因為專案的minSdkVersion 是18  

    所以不知道有沒有方法是可以支援到18的

    1. 应该是可以的,除了要把compileSdkVersion和targetSdkVersion改为18之外,一些动态申请权限的代码也要去掉。另外可能还有需要修改的地方,我要试验一下才能得知。

  3. 《深入OpenCV Android应用开发》这本书我买了,刚开始学习。请问其他章节的代码有更新计划吗?

      1. 博主真的好棒啊。我是刚刚接触as opencv,你简直是我的大救星啊!!!期待后面的内容~~~

  4. 你好,第6步的opencv_contrib,我下载了github上的6个文件,并注释了precomp.hpp的52-53,66行,OpenCV的sdk也是用你编译的,编译报错:Error:(46, 40) opencv2/xfeatures2d/cuda.hpp: No such file or directory

    然后我把46和48行注释了,还是报错:

    Error:(48, 4) error: #error this is a private header which should not be used from outside of the OpenCV library
    Error:(52, 22) cvconfig.h: No such file or directory

    请问这是什么原因呢,能提供一下你的freak.cpp,precomp.hpp,sift.cpp,surf.cpp,surf.hpp,xfeatures2d_init.cpp文件吗

    1. 好像是我理解错了,我以为http://pullrequest.opencv.org/buildbot/export/opencv_releases/precommit_pack_android/20160723-073613_116/

      这个路径的包是你编译的。能分享一下你编译的OpenCV Android SDK吗?我没有Ubuntu环境,windows环境下不知道怎么编译

        1. 你好,我下载了您编译的SDK,在java\src\org\opencv 发现比官方的标准库多了bioinspired和structured_light 这两个原本属于opencv_contrib 的模块,请问这两个是您自己编译的吗? 如果是的话,方便告知如何编译吗? 在此谢过。

          1. 学长你好,你的sdk中其实把opencv_contrib/modules/xfeatures2d/src目录下的的6个cpp编译进去了对吗?我没有用你给的library,也没有manager.apk,我只用你编译的sdk成功提取到图片的surf特征值。

          2. 主要工作是这样,而且还要修改一下features2d_manual.hpp文件里面对这几个类的声明。有cpp文件的实现,和hpp文件中的声明,新模块就加进来了!

          3. 嗯,我就说我直接引入头文件后编写c++代码然后就可以直接使用了哈,谢谢学长。

  5. 博主你好,你那有用Cmake编译的opencv2.4.10的库吗?有的话能不能分享一下,我的邮箱1219493801@qq.com

    1. 多谢,多谢!《深入OpenCV Android应用开发》系列的代码是把原书中的代码针对新平台和工具修改了一下,其他文章的基本都是兴趣使然了,毕竟做项目的代码还涉及版权之类的问题;)

发表评论

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