记录如何编译使用 OpenCV Contrib for Android SDK

好久好久没写 blog 了,上次写还是 2019 年,真是漫长的一段时间。

今天想记录一下如何编译 OpenCV Contrib for Android SDK。

作为一个对 NDK 和 C/C++ 几乎完全不懂的人 最近在研究如何做一个很简单的事情 说起来就由公司研究 OpenCV 的同事写一段 C++ 的函数 调用 opencv 来实现某个功能 而我在 Android 和 iOS 端分别写一个 C 函数来调用同事写的代码 打包为库 最后由 kotlin/swift 调用我自己的这个函数。

如何编译最简单的 so 库

这里需要用到 NDK 和 JNI。
这里简单记录一下文件构成。

Android.mk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_CPPFLAGS += -frtti -fexception
LOCAL_CPP_FEATURES := rtti exceptions

OPENCV_LIB_TYPE:=STATIC
OPENCV_INSTALL_MODULES:=on
include ../../../libs/sdk/native/jni/OpenCV.mk

LOCAL_MODULE := version
LOCAL_SRC_FILES := version.cpp main.c

include $(BUILD_SHARED_LIBRARY)

Application.mk

1
2
3
4
5
APP_ABI := all
APP_PLATFORM := android-19
APP_STL := c++_shared
APP_CPPFLAGS += -fexceptions -frtti
APP_CPP_FEATURES := exceptions rtti

main.c

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jni.h>

extern const char* getOpenCVVersion();

JNIEXPORT jstring JNICALL
Java_com_example_cppcp_OpencvUtils_getOpenCVVersion(JNIEnv *env, jobject thiz) {
const char* version = getOpenCVVersion();
return (*env)->NewStringUTF(env, version);
}

version.cpp

1
2
3
4
5
6
7
8
#include <opencv2/opencv.hpp>
#include <iostream>

extern "C" {
const char* getOpenCVVersion() {
return CV_VERSION;
}
}

这些文件都是在 app/src/main/jni 中,ndk-build 来编译,当然不要忘记在 build.gradle 中添加 jni sorceSet

1
2
3
4
5
sourceSets {
main {
jniLibs.srcDirs = ['src/main/libs']
}
}

这里是最简单的输出 OpenCV ncv version 的例子。
但是同事用到了 SURF 算法等相关,即需要调用 xfeatures2d 相关内容。
但是官网下载的OpenCV是没有SIFT和SURF算法的,因为这些算法是受专利保护的,所以并没有被包含在预编译库中,所以如果想要使用SIFT和SURF算法,需要自己来编译OpenCV Android SDK。

如何编译

其实 OpenCV 的 SDK 中是含有编译脚本的 我们不再需要使用 CMake 来自己编译 只是我们需要加入参数来进行编译 这里对命令做一个简单记录。

需要下载 OpenCV 的源码 而不是官网编译好的 Android SDK。

在下载的内容中 在 platforms/android 目录下 可以找到 build_sdk.py 这就是编译脚本。

以下是我调用的命令

1
2
3
python3 Downloads/opencv-4.7.0/platforms/android/build_sdk.py \
--extra_modules_path workspaces/opencv_contrib/modules/ \
--config Downloads/opencv-4.7.0/platforms/android/ndk-25.config.py

非常简单的命令。

首先是 extra_modules_path 这是需要额外编译进去的 module 的路径 我们从 GitHub 下载 opencv_contrib 的源码 extra_modules_path 也就是 opencv_contrib 目录下的 modules目录。

然后是需要选择 config 这里是需要选择跟我们 NDK 版本对应的 config.py 我这里是 NDK-25 版本 所以我们选择了 ndk-25.config.py

然后执行编译就行了 我的 M1 pro 大概花了十几分钟的样子。

最后在编译成功的 SDK 目录下可以发现我们需要的 xfeatures 文件 也就是编译成功了。

目前这里是 Android 编译 OpenCV Contrib SDK 的方法和使用。iOS 的还没研究 研究完后将再次写文章以记录 以免日后忘记。