Build OpenCV Android SDK from source, plus contrib modules

3839 ワード

The official OpenCV Android SDK does not contain the contrib modules, which include good features like SIFT and SURF, etc. To generate Android library (.so) from source (with OpenCV contrib modules possibly), one still uses cmake, with appending values for the following cmake Android variables:
DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake

$ANDROID_NDK is the path to your Android ndk-bundle directory.
DANDROID_STL=c++_static

One can choose c++_static (tested) or c++_shared runtimes. Caveat: The official OpenCV Android SDK provided online was compiled with gnustl runtime for C++ STL library. You need to make STL runtime here compatible with other places in your project. More elaboration at the end of the article.
DANDROID_NATIVE_API_LEVEL=android-16

Minimum native api level.
DANDROID_ABI=arm64-v8a

Target platform. For mobile applications, mostly choose either arm64-v8a (tested) or armeabi-v7a (tested). One may also choose other platforms, see https://developer.android.com/ndk/guides/abis#android-platform-abi-support.
DBUILD_ANDROID_PROJECTS=OFF

You only build libraries, not projects. So set this to be OFF.
DBUILD_SHARED_LIBS=ON

By default, its value is OFF. If so, it only generates .a static libraries. If sets ON, it generates .so dynamic libraries.
DBUILD_opencv_world=ON

By default, its value is OFF, hence a separate .a/.so file is generated for each module. For simplicity, we generate an aggregated module for easy linking with other libraries using OpenCV.
DBUILD_ANDROID_EXAMPLES=OFF

This is to speed up the make process.
We test it successfully on OpenCV 3.4.1 with ndk version 16.0.4442984. The script is as follows (suppose we are in the opencv-3.4.1 root directory):
mkdir build && cd build
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_STL=c++_static \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_NATIVE_API_LEVEL=android-16 \
-DANDROID_ABI=arm64-v8a \
-DBUILD_ANDROID_PROJECTS=OFF \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_opencv_world=ON \
-DBUILD_ANDROID_EXAMPLES=OFF ..
make -j5 && make install

The installed libraries and include files are in/build/install/sdk/native. The OpenCV aggregated library has name "libopencv_world.so".
Adding contrib modules are easy then:
mkdir build && cd build
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_STL=c++_static \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_NATIVE_API_LEVEL=android-16 \
-DANDROID_ABI=arm64-v8a \
-DBUILD_ANDROID_PROJECTS=OFF \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_opencv_world=ON \
-DBUILD_ANDROID_EXAMPLES=OFF \
-DOPENCV_EXTRA_MODULES_PATH=/modules ..
make -j5 && make install

C++ STL runtime issue in Android NDK
There are two places in building/calling Android NDK libraries where you need to specify C++ STL runtime:
  • In Application.mk, where it is to generate various .so libraries to be called by JNI.
  • In build.gradle in Android Studios, where it specifies various compilation flags for ndk and cmake.

  • In both places, the STL runtimes must be the same. Otherwise you will see "Reference undefined"type of errors. In earlier versions of Android SDKs, gnustl is the mainstream STL runtime (including the official OpenCV Android SDK). But now Android SDKs are fully shifted to c++_static/c++_shared runtimes. So you need to re-compile OpenCV from source to generate Android SDKs with c++_static/shared STL runtimes.