Windows下编译OpenCV+OpenCV_Contrib的Android模块

此文可以给你节省24个小时。

因为公司的项目需要,需要在Android上实现一些较为复杂的图像处理任务。我们计划采用流行的开源图像处理库OpenCV作为相应算法实现的基础。

OpenCV整套代码是基于C和C++实现的,在Android上调用存在两种方式:

  • Java Native代码实现
  • C++ NDK代码实现

其中Java Native代码实现是直接通过Java OpenCV API编写算法实现部分,相对应的特点在于:

  • 环境搭建简单:直接引入官方OpenCV-for-Android的对应jar包即可
  • 代码维护繁琐:由于OpenCV-for-Android的Java API与C++不完全相同,任何算法的更新都需要重写 => 在存在Windows、iOS等多平台更新时比较麻烦
  • 运行效率低:Java代码会在内部进行C++翻译,运行时性能损耗较大

而直接采用C++代码导入的方式的特点在于:

  • 环境搭建复杂:往往需要现自行编译对应的库,再进行NDK、Cmakelists和build.gradle的配置
  • 代码维护简单:由于直接采用C++实现算法部分,与其他平台的兼容性极好,能与Android程序员分离开发 => 算法升级时替换对应的算法库文件即可
  • 运行效率高:不存在内部执行时的代码转换问题,性能最好

总结来看,Java Native代码实现是爽一时但是后面会不爽很久,对于有时间精力且要求较高的开发任务,强烈建议多花点时间搭建C++ NDK方式。

这不,我就被折腾了3天时间才完成Opencv+contrib for Andorid的环境搭建。当然,这里面最为麻烦的时opencv_contrib实在缺乏相关的经验参考,都是自行摸索出来的。

前言

如果你仅需要做一些基础的图像处理任务,比如操作像素、滤波、分割等,OpenCV主体库能完成这些所有需求。这一块有非常多的资料可以借鉴,会有很多比我介绍更加完善的博文。

而如果你需要使用诸如 特征提取机器学习 等诸多高级或者带有专利的功能时,就需要额外的OpenCV_contrib库了。而这个库并没有很好的与Android打通,需要一些我们额外的工作。这一块网上就应该没什么资料了。

编译环境准备

  1. OpenCV 3.1.0源码(假定目录为<opencv-souce>)
  2. OpenCV_contrib 3.1.0源码(假定目录为<opencv-contrib>)
  3. cmake-gui 3.8.2 cmake的GUI工具
  4. Mingw 编译工具(假定目录为<mingw-dir>)
  5. Android NDK r12b 或者最新(假定目录为<ndk-dir>)
  6. Android SDK >=19(假定目录为<sdk-dir>)
  7. Android Studio
  8. Java ANT 1.9.9(假定目录为<ant-dir>)

以上你是需要准备编译的基础环境,下面分别讲解一下:
1.OpenCV源码

1
2
3
cd <opencv-source>;
git clone https://github.com/opencv/opencv.git
git checkout -b "3.1.0" "3.1.0"

2.OpenCV_contrib源码

1
2
3
cd <opencv-contrib>;
git clone https://github.com/opencv/opencv-contrib.git
git checkout -b "3.1.0" "3.1.0"

PS> 注意我们看到这里我采用的是opencv和opencv_contrib的3.1.0版本,主要的原因是opencv3.0.0和
3.2.0在实践中会遇到各种莫名其妙的原因,很难进行下去(比如opencv3.2.0目前还很难用mingw编译),这一块的摸索花了我大量的时间,所以我建议你也统一使用3.1.0版本。

3.cmake-gui工具
去到cmake官网下载3.8.2版本的cmake-64位工具:https://cmake.org/files/v3.8/cmake-3.8.2-win64-x64.msi

4.MinGW
MinGW是Windows下的GCC编译工具,去到Sourceforge下载MinGW的管理工具mingw-get-setup.exe。配置mingw的目录为<mingw-dir>,并将<mingw-dir/bin>添加进系统变量。

PS> 注意你可以选择mingw32或者mingw64都是可以的。我后续采用的是mingw32。也就是安装选项中的:
mingw32

5.Android NDK
NDK的官方介绍是:

Android NDK 是一套允许您使用原生代码语言(例如 C 和 C++)实现部分应用的工具集。在开发某些类型应用时,这有助于您重复使用以这些语言编写的代码库。

你可以去下载最新64位稳定版本:android-ndk-r14b-windows-x86_64.zip

当然由于历史原因我选择的是android-ndk-r12b-windows-x86_64.zip

下载后解压开即可。解压目录为<ndk-dir>。

6&7. Android SDK和Android Studio就不必说了,注意SDK的版本安装全一点,从API_LEVEL=19以上的都下了最好。其中SDK的目录为<sdk-dir>。

8.JAVA ANT 1.9.9
在编译OpenCV for JAVA起到关键作用。下载地址:http://apache.fayea.com//ant/binaries/apache-ant-1.9.9-bin.zip。 相应解压目录为<ant-dir>。

编译配置

  1. 去到 <opencv-source> 中,创建<opencv-source>/platforms/android_arm
  2. 双击打开”cmake-gui.exe”
  3. 在”where is th source code”填入<opencv-source>目录
  4. 在”where to build the binaries”填入<opencv-source>/platforms/android_arm
  5. 点击”Add Entry”,添加”ANDROID_NDK”,并设定为”PATH”类目,对应目录为<nkd-dir>,在我的电脑上就是”F:\Android\android-ndk-r10e”
    android-ndk-setting
  6. 点击”Add Entry”,添加”ANDROID_NDK_HOST_X64”,并设定为”BOOL”类目,点击勾选。这是因为我们的NDK是64位版本的,如果你的NDK是32位的,则不需要勾选
    android-ndk-setting-2
  7. 点击”Add Entry”,添加”CMAKE_TOOLCHAIN_FILE”,并设定为”FILEPATH”类目,设置路径为<opencv-source>/platforms/android/android.toolchain.cmake
    android-ndk-setting-3
  8. 点击”Add Entry”,添加”CMAKE_BUILD_WITH_INSTALL_RPATH”,并设定为”BOOL”类目,点击勾选
  9. 点击”Add Entry”,添加”ANDROID_SDK”,并设定为”path”类目,设置路径为<sdk-path>
  10. 点击”Add Entry”,添加”ANDROID_ABI”,并设定为”string”类目,设置值为armeabi-v7a。这里的选项也即你需要编译的库类型,如果你想要编译armeabi或者X86都在这个值上修改。我们可以先编译armeabi-v7a
    android-ndk-setting-4
  11. 点击”Add Entry”,添加”ANDROID_NATIVE_API_LEVEL”,并设定为”string”类目,设置值为19。这里的选项也即你需要编译的API-LEVEL,我定的是19,你也可以用20或者21
  12. 点击”Configure”,选择”MinGW Makefile”作为编译选项,并在接下来的选项中选择”Specify toolchain file for cross-compiling”,点击”Next”,对应的路径选择<opencv-source>/platforms/android/android.toolchain.cmake,点击”Finish”

MinGW交叉编译配置
MinGW交叉编译配置

等待configure完成,如下图所示:
cmake-configure-1

我们接着添加opencv-contrib模块,搜索extra,在OPENCV_EXTRA_MODULES_PATH添加路径<opencv-contrib>/modules后,再点击configure。此时会报错:
cmake-error

不解??前面不是配过了么?怎么又来一次?
于是就再来一次吧:
点击”Add Entry”,添加”ANDROID_NDK”,并设定为”PATH”类目,对应目录为<nkd-dir>

再次configure就没什么问题了,至于出现的warnings就不管了。

Configuring done完成后我们还需要进行一些调整:

  1. WITH_CUDA=OFF
  2. WITH_MATLAB=OFF
  3. BUILD_DOCS=OFF
  4. BUILD_PERF_TESTS=OFF
  5. BUILD_TESTS=OFF
  6. WITH_TIFF=OFF
  7. BUILD_opencv_bioinspired=OFF
  8. BUILD_opencv_dnn=OFF(如果你用不到这个的话,建议你禁掉)
  9. BUILD_opencv_structured_light=OFF(我当时添加这个模块时出现了错误,建议你也禁掉)
  10. BUILD_opencv_ximgproc=OFF(我当时添加这个模块时出现了错误,建议你也禁掉)
  11. BUILD_opencv_world:BOOL=OFF (不用尝试编译opencv_world了,从我的经验来看是编译不出来)
  12. BUILD_opencv_contrib_world:BOOL=OFF (同上)
  13. ANT_EXECUTABLE=<ant-dir>/bin/ant.bat

上述调整好后,还必须去修改opencv-contrib的对应CMakeLists.txt。这是因为Java在调用OpenCV时,需要对应的Java Wrapper。默认opencv-contrib是不编译生成Java Wrapper的。具体操作为,进入<opencv-contrib>/modules每一个子目录中,在CMakeLists.txt文件中的

1
2
ocv_define_module(******)
ocv_define_module(****** WRAP python)

语句都统一改成

1
ocv_define_module(****** WRAP python java)

也即在ocv_define_module没有WRAP或者有WRAP但没有包括java的,都统计更改为包含WRAP Java
如在原来的xfeatures2d中的CMakeLists.txt

1
2
set(the_description "Contributed/Experimental Algorithms for Salient 2D Features Detection")
ocv_define_module(xfeatures2d opencv_core opencv_imgproc opencv_features2d opencv_calib3d opencv_shape opencv_highgui opencv_videoio opencv_ml OPTIONAL opencv_cudaarithm WRAP python)

都要改成

1
2
3
set(the_description "Contributed/Experimental Algorithms for Salient 2D Features Detection")
ocv_define_module(xfeatures2d opencv_core opencv_imgproc opencv_features2d opencv_calib3d opencv_shape opencv_highgui opencv_videoio opencv_ml
OPTIONAL opencv_cudaarithm WRAP python java)

上诉设定调整好后,再次点击configure后再点击generate,显示:

Configuring done
Generating done

执行编译

在上述编译配置完成后,通过命令行工具进入<opencv-source>/platforms/android_arm目录,执行

1
mingw32-make -j4

即可开始编译
building

但是执行到快要结束的时候会发生多个错误:

错误1

1
2
3
4
fatal error: opencv2/reg.hpp: No such file or directory
#include "opencv2/reg.hpp"
^
compilation terminated.

解决方案:进入<opencv-source>/platforms/android_arm/modules/java/reg.cpp
注释掉

1
#include "opencv2/reg.hpp"

然后执行mingw32-make install

PS. 注意这里千万别执行mingw32-make -j4不然仍然会出现这个错误。

错误2

1
2
3
4
fatal error: opencv2/datasets.hpp: No such file or directory
#include "opencv2/datasets.hpp"
^
compilation terminated.

解决方案:进入<opencv-source>/platforms/android_arm/modules/java/datasets.cpp
注释掉

1
#include "opencv2/datasets.hpp"

然后执行mingw32-make install

PS. 注意这里千万别执行mingw32-make -j4不然仍然会出现这个错误。


一般而言,都会出现上面的错误,所以执行了mingw32-make install之后,如果类似下面的图片的话,整个编译库就编译和安装了:
buiding-success

相关的安装库在<opencv-source>/platforms/android_arm/install/sdk中

Android Studio 导入

关于Android Studio如何使用OpenCV编译库的问题,网上已经有很多文章阐述得很详细了,例如
Android Studio 集成 OpenCV

我就不再赘述了。唯一提醒的细节就是,在Android Studio引入OpenCVLiberary310模块时,在模块build.gradle

  • 替换掉’apply plugin: com.android.application’ 为 ‘apply plugin: com.android.library’
  • 删除 ‘applicationId “org.opencv”‘

ENJOY!!