# build_android_opencv **Repository Path**: leesonzhong/build_android_opencv ## Basic Information - **Project Name**: build_android_opencv - **Description**: 编译android版本的opencv和opencv_contrib - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2021-02-04 - **Last Updated**: 2022-05-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 下载编译脚本、opencv库、opencv_contrib库、ndk编译工具 - 从github下载别人弄好的脚本https://github.com/tzutalin/build-opencv-for-android - 从gitee下载opencv库https://gitee.com/leesonzhong/opencv,下载版本3.4.8,git clone xxxx --branch 3.4.8 - 从gitee下载opencv_contrib库https://gitee.com/leesonzhong/opencv_contrib,opencv_contrib库是opencv的额外模块库 - 从安卓开发者网站下载ndk工具https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip?hl=zh_cn - 也可以使用下载的脚本来下载opencv、opencv_contrib和ndk,在linux命令行下,切换到脚本目录,运行setup.sh脚本,3.4.8是分支版本号,去掉版本号默认是最新版本 ``` /setup.sh 3.4.8 ``` # 准备工作 - 新建用于编译的文件夹,比如build_opencv,把下载的opencv库和opencv_contrib库拷贝到目录下,ndk工具包解压放到目录下,注意库的文件夹名称必须是opencv和opencv_contrib。 - 把下载的脚本build-android-opencv.sh拷贝到目录。查看脚本,可以知道脚本下载https://github.com/taka-no-me/android-cmake.git,通过android.toolchain.cmake会调用cmake和ndk进行编译,所以要注意系统已经安装cmake (\>=2.8) - 在linux命令行下,设置ndk路径(可以用pwd查看路径),比如ndk目录为/mnt/d/linux/android-ndk-r14b ``` export NDK_ROOT=/mnt/d/linux/android-ndk-r14b ``` - 在linux命令行下,切换到编译的目录下,运行脚本 ``` ./build-android-opencv.sh ``` - 如果运行脚本出现$'\r': command not found这样的错误,这是因为在windows下载脚本的原因。使用vim打开脚本进行编辑 ``` vim build-android-opencv.sh :set ff=unix :wq ``` - 如果运行脚本出现错误 ``` CMake Deprecation Warning at /usr/share/cmake-3.10/Modules/CMakeForceCompiler.cmake:83 (message): The CMAKE_FORCE_CXX_COMPILER macro is deprecated. Instead just set CMAKE_CXX_COMPILER and allow CMake to identify the compiler. Call Stack (most recent call first): /mnt/d/linux/build_opencv/android-cmake/android.toolchain.cmake:1140 (CMAKE_FORCE_CXX_COMPILER) /usr/share/cmake-3.10/Modules/CMakeDetermineSystem.cmake:94 (include) CMakeLists.txt:106 (enable_language) CMake Error: CMake was unable to find a build program corresponding to "Unix Makefiles". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool. -- Configuring incomplete, errors occurred! See also "/mnt/d/linux/build_opencv/opencv/platforms/build_android_mips64/CMakeFiles/CMakeOutput.log". make: *** No targets specified and no makefile found. Stop. make: *** No rule to make target 'install/strip'. Stop. ``` cmake版本不对,版本是3.10,安装低版本cmake2.8.9后运行脚本会提示CMake 2.8.12.2 or higher is required. You are running version 2.8.9,我重新下载3.2.0的opencv,可以成功编译。所以下载opencv最好是3.0到3.4之间,cmake版本大于2.8,最好不要大于3.0,要自己尝试 ``` git clone https://gitee.com/johnroot/CMake.git --branch v2.8.9 sudo apt-get autoremove cmake cd Cmake ./bootstrap && make sudo make install ``` 3.2.0版本会提示下载ippicv_linux_20151201.tgz失败,网上百度下载后放到对应文件夹中,根据出差信息进行判断 ``` for file: [/mnt/d/linux/build_opencv/build-opencv-for-android/opencv/3rdparty/ippicv/downloads/linux-808b791a6eac9ed78d32a7666804320e/ippicv_linux_20151201.tgz] ``` 发现还是会遇到不少错,决定从新下载cmake2.8.12.2,opencv3.4.8,opencv_contrib3.4.8 Android SDK: specify path to Android SDK via ANDROID_SDK_ROOT / ANDROID_HOME / ANDROID_SDK variables,系统没有安装sdk并设置ANDROID_SDK环境变量,下载http://dl.google.com/android/android-sdk_r24.4.1-linux.tgz, ``` export ANDROID_SDK=/mnt/d/linux/build_opencv/android-sdk-linux ``` 设置ANDROID_SDK环境变量后,执行脚本出现错误Android SDK Build Tools: directory doesn't exist,这是因为下载的linux版本的android sdk没有Android SDK Platform-tools,在Linux命令下执行命令下载 ``` cd /mnt/d/linux/build_opencv/android-sdk-linux tools/android update sdk --no-ui ``` 更新android sdk发现无法找到java,安装jdk或jre。找到java的安装路径,设置JAVA_HOME=路径,比如JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java",然后加载环境变量,可以用echo输出看环境变量设置结果 ``` sudo apt install openjdk-8-jdk sudo update-alternatives --config java sudo vim /etc/environment source /etc/environment echo $JAVA_HOME ``` 安装Android SDK Platform-tools后,重新运行编译脚本,报错:Android SDK: Can't build Android projects as requested by BUILD_ANDROID_PROJECTS=ON variable。在opencv/cmake/android/OpenCVDetectAndroidSDK.cmake第一行添加代码 ``` set(BUILD_ANDROID_PROJECTS OFF) ``` 运行脚本编译,编译时报错opencv_contrib/modules/xfeatures2d/src/boostdesc.cpp:653:20: fatal error: 'boostdesc_bgm.i' file not found,下载boostdesc_xxxx和vgg_generated_xxxx并放进目录中opencv_contrib/modules/xfeatures2d/src ``` git clone https://gitee.com/leesonzhong/boostdesc_bgm_files_build_opencv_contrib_needed.git ``` 运行脚本编译,编译时报错matchers.hpp:52:42: fatal error: opencv2/xfeatures2d/cuda.hpp: No such file or directory。opencv/modules/stitching/CMakeLists.txt文件中加入一条语句使其include opencv_contrib/modules/xfeatures2d/include,可以使用绝对路径或相对路径,OPENCV_EXTRA_MODULES_PATH是编译脚本build-android-opencv.sh有设置 ``` INCLUDE_DIRECTORIES("${OPENCV_EXTRA_MODULES_PATH}/xfeatures2d/include") ``` # 最终编译的库和对应版本 - 脚本build-opencv-for-android.sh,如果是windows平台下载的,需要用vim打开,使用set ff=unix进行转换,脚本我修改只编译"arm64-v8a"和"armeabi-v7a",编译其它架构应该也没问题。 - opencv库版本3.4.8 - opencv_contrib库版本3.4.8 - python2.7.17 - android-ndk-r14b,export NDK_ROOT=ndk根目录,也可以在调用脚本命令后面加上ndk路径 - cmake版本2.8.12.2 - openjdk-8-jdk,配置JAVA_HOME - android-sdk_r24.4.1-linux,使用tools/android update sdk --no-ui下载Platform-tools,export ANDROID_SDK=sdk根目录 - opencv/cmake/android/OpenCVDetectAndroidSDK.cmake第一行添加代码set(BUILD_ANDROID_PROJECTS OFF) - 下载boostdesc和vgg文件放到opencv_contrib/modules/xfeatures2d/src - opencv/modules/stitching/CMakeLists.txt添加INCLUDE_DIRECTORIES("${OPENCV_EXTRA_MODULES_PATH}/xfeatures2d/include") # 使用编译的opencv静态库 - 头文件在编译目录/android_opencv/opencv/sdk/native/jni/include,拷贝放到app/src/main/cpp/include - 静态库在编译目录/android_opencv/opencv/sdk/native/staticlibs,拷贝放到app/src/main/jniLibs - 第三方静态库在编译目录/android_opencv/opencv/sdk/native/3rdparty/libs,拷贝放到app/src/main/jniLibs - opencv的静态库依赖第三方静态库,所以第三方静态库也要导入到工程 - 默认情况下要求被依赖的库放在依赖它的库后面,当一个程序或共享库依赖的静态库较多时,可能会陷入解决链接问题的坑中,ld为此提供了start-group和end-group两个选项,让包含在这两者间的静态库顺序可以随意 - 静态库还依赖zlib,所以在添加 link_libraries(z),要在 add_library () 引入cpp 文件的之前添加 - 可以使用 file(GLOB OPENCVLIB "${lib_src_DIR}/lib*.a") 集合多个静态库,通过通配符匹配,使用时${OPENCVLIB} - app/src/main/cpp有CMakeLists.txt,大致内容和下面类似,只是多了ffmpeg的动态库 ``` # For more information about using CMake with Android Studio, read the # documentation: https://d.android.com/studio/projects/add-native-code.html # Sets the minimum version of CMake required to build the native library. cmake_minimum_required(VERSION 3.4.1) #设置include头文件的路径 include_directories( ${CMAKE_SOURCE_DIR}/include ) #设置lib_src_DIR指向jniLibs的对应架构目录 set(lib_src_DIR ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}) #导入libavcodec.so,库名为avcodec-lib add_library(avcodec-lib SHARED IMPORTED) set_target_properties(avcodec-lib PROPERTIES IMPORTED_LOCATION ${lib_src_DIR}/libavcodec.so) #导入libavfilter.so,库名为avfilter-lib add_library(avfilter-lib SHARED IMPORTED) set_target_properties(avfilter-lib PROPERTIES IMPORTED_LOCATION ${lib_src_DIR}/libavfilter.so) #导入libavformat.so,库名为avformat-lib add_library(avformat-lib SHARED IMPORTED) set_target_properties(avformat-lib PROPERTIES IMPORTED_LOCATION ${lib_src_DIR}/libavformat.so) #导入libavutil.so,库名为avutil-lib add_library(avutil-lib SHARED IMPORTED) set_target_properties(avutil-lib PROPERTIES IMPORTED_LOCATION ${lib_src_DIR}/libavutil.so) #导入libpostproc.so,库名为postproc-lib add_library(postproc-lib SHARED IMPORTED) set_target_properties(postproc-lib PROPERTIES IMPORTED_LOCATION ${lib_src_DIR}/libpostproc.so) #导入libswresample.so,库名为swresample-lib add_library(swresample-lib SHARED IMPORTED) set_target_properties(swresample-lib PROPERTIES IMPORTED_LOCATION ${lib_src_DIR}/libswresample.so) #导入libswscale.so,库名为swscale-lib add_library(swscale-lib SHARED IMPORTED) set_target_properties(swscale-lib PROPERTIES IMPORTED_LOCATION ${lib_src_DIR}/libswscale.so) #把多个opencv静态库和第三方静态库集成并命名为OPENCVLIB file(GLOB OPENCVLIB "${lib_src_DIR}/lib*.a") # Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by # default, you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build. link_libraries(z) find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log ) add_library( # Sets the name of the library. ffmpeg-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). ffmpeg-lib.cpp opengles_render.cpp opengles_render_caas.cpp FaceDetectUtil.cpp ) target_link_libraries( # Specifies the target library. ffmpeg-lib # Links the target library to the log library # included in the NDK. -landroid GLESv1_CM GLESv2 ${log-lib} avcodec-lib avfilter-lib avformat-lib avutil-lib postproc-lib swresample-lib swscale-lib -Wl,--start-group ${OPENCVLIB} -Wl,--end-group) ``` - app的build.gradle主要是添加cmake编译的设置,比如cppFlags和abiFilters,还要设置cmake编译脚本的地址和版本 ``` android { compileSdkVersion 28 defaultConfig { applicationId "com.octant.panchip" minSdkVersion 21 targetSdkVersion 28 versionCode 3 versionName "0.0.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { cppFlags "-std=c++11 -frtti -fexceptions" // arguments '-DANDROID_STL=gnustl_static' abiFilters "armeabi-v7a" , "arm64-v8a" } } } externalNativeBuild { cmake { path "src/main/cpp/CMakeLists.txt" version "3.10.2" } } ```