前言
最近完成了Android上使用OpenCV进行图像拼接的功能,通过导入OpenCV的.so或.a库,JNI封装C++代码供Java层调用,同时在CMakeLists中指定自己需要的.a库以减少库的大小,毕竟我只用了拼接功能,其它诸如dnn、video等模块我都没用到。
在开始之前当然要把OpenCV Android SDK下载下来,推荐去GitHub下载,在OpenCV官网下载真是龟速,链接。
环境:OpenCV 3.3.1 、Android Studio 3.0
步骤
1.添加OpenCV-android-sdk
将OpenCV-android-sdk\sdk\native文件夹添加到项目中,这里我把native重命名为opencv,如下图:
其中3rdparty包含opencv使用的第三方库,jni/include包含opencv的头文件
,libs包含opencv编译好的动态库与静态库。
2.修改build.gradle
如图,添加红框中的内容,其中abiFilters 'armeabi'表示只生成armeabi架构的包,若不指定则会生成全部架构。
注意:确保你当前的工程已启用C++支持,如果没有就重新建一个项目并勾选Include C++ Support,我也尝试过创建普通Android工程,是build不过的,想启用C++支持也没找到方法,只好重新建一个包含C++支持的项目了。
3.修改CMakeLists.txt
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# 包含opencv的头文件
include_directories(opencv/jni/include)
# 静态方式导入库
add_library(opencv_calib3d STATIC IMPORTED)
add_library(opencv_core STATIC IMPORTED)
add_library(opencv_features2d STATIC IMPORTED)
add_library(opencv_flann STATIC IMPORTED)
add_library(opencv_imgcodecs STATIC IMPORTED)
add_library(opencv_imgproc STATIC IMPORTED)
add_library(opencv_stitching STATIC IMPORTED)
add_library(cpufeatures STATIC IMPORTED)
add_library(IlmImf STATIC IMPORTED)
add_library(libjasper STATIC IMPORTED)
add_library(libjpeg STATIC IMPORTED)
add_library(libpng STATIC IMPORTED)
#add_library(libprotobuf STATIC IMPORTED)
add_library(libtiff STATIC IMPORTED)
add_library(libwebp STATIC IMPORTED)
add_library(tbb STATIC IMPORTED)
add_library(tegra_hal STATIC IMPORTED)
# 设置库路径
set_target_properties(opencv_calib3d PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/libs/${ANDROID_ABI}/libopencv_calib3d.a)
set_target_properties(opencv_core PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/libs/${ANDROID_ABI}/libopencv_core.a)
set_target_properties(opencv_features2d PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/libs/${ANDROID_ABI}/libopencv_features2d.a)
set_target_properties(opencv_flann PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/libs/${ANDROID_ABI}/libopencv_flann.a)
set_target_properties(opencv_imgcodecs PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/libs/${ANDROID_ABI}/libopencv_imgcodecs.a)
set_target_properties(opencv_imgproc PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/libs/${ANDROID_ABI}/libopencv_imgproc.a)
set_target_properties(opencv_stitching PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/libs/${ANDROID_ABI}/libopencv_stitching.a)
set_target_properties(cpufeatures PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/3rdparty/libs/${ANDROID_ABI}/libcpufeatures.a)
set_target_properties(IlmImf PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/3rdparty/libs/${ANDROID_ABI}/libIlmImf.a)
set_target_properties(libjasper PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/3rdparty/libs/${ANDROID_ABI}/liblibjasper.a)
set_target_properties(libjpeg PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/3rdparty/libs/${ANDROID_ABI}/liblibjpeg.a)
set_target_properties(libpng PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/3rdparty/libs/${ANDROID_ABI}/liblibpng.a)
#set_target_properties(libprotobuf PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/3rdparty/libs/${ANDROID_ABI}/liblibprotobuf.a)
set_target_properties(libtiff PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/3rdparty/libs/${ANDROID_ABI}/liblibtiff.a)
set_target_properties(libwebp PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/3rdparty/libs/${ANDROID_ABI}/liblibwebp.a)
set_target_properties(tbb PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/3rdparty/libs/${ANDROID_ABI}/libtbb.a)
set_target_properties(tegra_hal PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/opencv/3rdparty/libs/${ANDROID_ABI}/libtegra_hal.a)
set(SRC_DIR src/main/cpp)
file(GLOB_RECURSE CPP_SRCS "${SRC_DIR}/*.cpp") #指定当前目录下的所有.cpp文件(包括子目录)
add_library( # Sets the name of the library.
MyStitch
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
${CPP_SRCS} )
# 链接库,注意被依赖的库放后面
target_link_libraries( # Specifies the target library.
MyStitch
opencv_stitching
opencv_features2d
opencv_flann
opencv_imgcodecs
opencv_imgproc
opencv_core
opencv_calib3d
IlmImf
cpufeatures
libjasper
libjpeg
libpng
#libprotobuf
libtiff
libwebp
tbb
tegra_hal
# included in the NDK.
jnigraphics
log )
这些库都是拼接所必需的,自己尝试了好多次才成功。其实思路很简单,用add_library和set_target_properties导入需要的库,最后在target_link_libraries中全部链接,值得注意的是最终链接库时被依赖的库要放后面,顺序不能搞错了。
如果要使用opencv全部的功能,官方也已经为我们制作了libopencv_java3.so库,只用导入这一个就行了。
4.调用opencv
在cpp文件夹下添加你自己的代码文件,就可以用C++调用opencv了,话说用AS写C++体验还是蛮好的。之后你还需要用JNI封装C++方法,以供Java层调用,不过这不在本文的讨论范围之内。
后记
完成后我得到的aar包大小为2.5MB,包含全部功能的libopencv_java3.so为10MB多,Mission Completed!