Android OpenCV(七十七):官方指南方式编译 OpenCV Android SDK.md

前言

众所周知😳, OpenCV 4.9.0 罕见的在 Android 平台上做出调整,具体更新内容请移步难得一见的 Android OpenCV ChangeLog。然而,近期笔者在查阅 OpenCV Github Wiki 时,又发现了新东西🤡,一篇名为 "Custom OpenCV Android SDK and AAR package build"的 Wiki。以前我们编译 SDK 采用的是CMake方式,具体可参考全网首发微信二维码引擎Android平台移植,而本篇新 Wiki 起草于 2023年11月23日,内容比较新,但是整体还是基于 CMake,只是采用 python 封装脚本方便执行而已,以前应该也可以采用这种方式执行,只是官方一直未正式发布指南。本文主要记录实践过。

环境准备

  • Ubuntu 20.04+(笔者版本 Ubuntu 20.04.6 LTS
  • Android Studio(笔者未使用)
  • OpenJDK 17
  • CMake
  • Ninja build tool
  • OpenCV source code (https://github.com/opencv/opencv)
  • (Optional) OpenCV contrib modules source code (https://github.com/opencv/opencv_contrib)
  • (Optional) OpenCV test data (https://github.com/opencv/opencv_extra)

步骤

1. 安装环境

  • 安装 OpenJDK 17

    sudo apt install openjdk-17-jdk openjdk-17-jre

  • 安装 CMake

    sudo apt install cmake

  • 安装 Ninja build tool

    sudo apt install ninja-build

  • 安装 build-tools、sdk和 ndk

    Install SDK 21.1.2 and NDK 18.1 using SDK manager in Android Studio (use checkbox “Show package details” to choose a version)

    文中的 21.1.2 应该指代的是 build-tools,因为 Android API级别向来都是大版本,ndk 版本则是 18.1.5063045,sdk 由于文中暂未明确指出,所以我们采用的是 Android 21

    sdkmanager "platforms;android-21"
    sdkmanager --install "ndk;18.1.5063045"
    sdkmanager --install "build-tools;21.1.2"
    
  • 安装 python3

    若 Ubuntu 系统默认未安装,需手动安装 sudo apt install python3

2. 下载源码

  • 下载 opencv 源码

    git clone https://github.com/opencv/opencv.git

  • (可选)下载 opencv_contrib 源码

    git clone https://github.com/opencv/opencv_contrib.git

  • (❌🚫)下载 opencv_extra 源码

    未发现使用的地方,暂时先不下载

笔者将二个源码文件夹放在同一层级目录,方便后续配置变量。

3. 配置编译目录和环境变量

  • 新建 build 目录

    笔者此处在二个源码文件夹同一层级目录下创建 build 文件夹

  • 配置环境变量

    笔者修改 .bashrc 文件,并在文档末尾追加如下内容

    export YOUR_OPENCV_SRC_FOLDER=/home/yi/opencv  # opencv 源码路径
    export YOUR_CONTRIB_SRC_FOLDER=/home/yi/opencv_contrib # opencv_contrib 源码路径
    export YOUR_OPENCV_BUILD_FOLDER=/home/yi/build # 构建目录
    export ANDROID_SDK=/home/yi/sdk   # Android SDK目录
    export ANDROID_NDK_HOME=/home/yi/sdk/ndk/18.1.5063045 # ndk目录
    

4. 编译 SDK

python3 $YOUR_OPENCV_SRC_FOLDER/platforms/android/build_sdk.py $YOUR_OPENCV_BUILD_FOLDER $YOUR_OPENCV_SRC_FOLDER --ndk_path $ANDROID_NDK_HOME --sdk_path $ANDROID_SDK --extra_modules_path $YOUR_CONTRIB_SRC_FOLDER/modules --config $YOUR_OPENCV_SRC_FOLDER/platforms/android/ndk-18-api-level-21.config.py

BUILD_ANDROID_PROJECTS="OFF"

ANDROID_PROJECTS_BUILD_TYPE="GRADLE"

libopencv_java4.so

配置 ANDROID_PROJECTS_BUILD_TYPE="GRADLE",可编译生成libopencv_java.so 与对应的 Java Wrapper 文件。由于使用的是 ndk-18-api-level-21.config.py配置文件,会生成 armeabi-v7a、arm64-v8a、x86_64、x86 四种架构的二进制共享库文件。

ABIs = [ABI("2", "armeabi-v7a", None, 21, cmake_vars=dict(ANDROID_ABI='armeabi-v7a with NEON')),ABI("3", "arm64-v8a",   None, 21),ABI("5", "x86_64",      None, 21),ABI("4", "x86",         None, 21),
]

如果只需要部分架构的 so 文件,调整文件留下对应的ABI变量即可。

cmake_vars 参数用来传递自定义 CMake 编译参数。例如:

  • arm64-v8a架构下不编译 G-API 和 DNN 模块
ABI("3", "arm64-v8a",   None, 21, cmake_vars=dict('BUILD_opencv_gapi': 'OFF', 'BUILD_opencv_dnn': 'OFF'))
  • 指定 OpenCV 部分构建工具的版本
ABI("3", "arm64-v8a",   None, 21, cmake_vars=dict('ANDROID_GRADLE_PLUGIN_VERSION': '7.3.1', 'GRADLE_VERSION': '7.5.1', 'KOTLIN_PLUGIN_VERSION': '1.5.20'))
  • 指定 CMake find_package 过程的外部库位置
ABI("3", "arm64-v8a",   None, 21, cmake_vars=dict('libavif_DIR': '<path to libavif library cross-compiled for Android arm-v8a>')

所以刚才我们提到的 BUILD_ANDROID_PROJECTS="OFF" 或者 ANDROID_PROJECTS_BUILD_TYPE="GRADLE" 均可以在这里配置。

比如,我们将 ndk-18-api-level-21.config.py 调整为

ABIs = [ABI("2", "armeabi-v7a", None, 21, cmake_vars=dict(ANDROID_ABI='armeabi-v7a with NEON', ANDROID_PROJECTS_BUILD_TYPE='GRADLE'))
]

则只会生成 armeabi-v7a 架构的 so 文件。

armeabi-v7a

5. 编译 AAR

python3 $YOUR_OPENCV_SRC_FOLDER/platforms/android/build_java_shared_aar.py $YOUR_OPENCV_BUILD_FOLDER/OpenCV-android-sdk

AAR

Maven AAR

6. 脚本参数与编译参数

build_sdk.py 举例如何查找脚本参数与编译参数,虽然脚本参数最后都会落脚到编译参数。

  • build_sdk.py 脚本参数
parser = argparse.ArgumentParser(description='Build OpenCV for Android SDK')
parser.add_argument("work_dir", nargs='?', default='.', help="Working directory (and output)")
parser.add_argument("opencv_dir", nargs='?', default=os.path.join(SCRIPT_DIR, '../..'), help="Path to OpenCV source dir")
parser.add_argument('--config', default='ndk-18-api-level-21.config.py', type=str, help="Package build configuration", )
parser.add_argument('--ndk_path', help="Path to Android NDK to use for build")
parser.add_argument('--sdk_path', help="Path to Android SDK to use for build")
parser.add_argument('--use_android_buildtools', action="store_true", help='Use cmake/ninja build tools from Android SDK')
parser.add_argument("--modules_list", help="List of  modules to include for build")
parser.add_argument("--extra_modules_path", help="Path to extra modules to use for build")
parser.add_argument('--sign_with', help="Certificate to sign the Manager apk")
parser.add_argument('--build_doc', action="store_true", help="Build javadoc")
parser.add_argument('--no_ccache', action="store_true", help="Do not use ccache during library build")
parser.add_argument('--force_copy', action="store_true", help="Do not use file move during library build (useful for debug)")
parser.add_argument('--force_opencv_toolchain', action="store_true", help="Do not use toolchain from Android NDK")
parser.add_argument('--debug', action="store_true", help="Build 'Debug' binaries (CMAKE_BUILD_TYPE=Debug)")
parser.add_argument('--debug_info', action="store_true", help="Build with debug information (useful for Release mode: BUILD_WITH_DEBUG_INFO=ON)")
parser.add_argument('--no_samples_build', action="store_true", help="Do not build samples (speeds up build)")
parser.add_argument('--opencl', action="store_true", help="Enable OpenCL support")
parser.add_argument('--no_kotlin', action="store_true", help="Disable Kotlin extensions")
parser.add_argument('--shared', action="store_true", help="Build shared libraries")
parser.add_argument('--no_media_ndk', action="store_true", help="Do not link Media NDK (required for video I/O support)")
args = parser.parse_args()
  • CMake 编译参数
cmake_vars = dict(CMAKE_TOOLCHAIN_FILE=self.get_toolchain_file(),INSTALL_CREATE_DISTRIB="ON",WITH_OPENCL="OFF",BUILD_KOTLIN_EXTENSIONS="ON",WITH_IPP=("ON" if abi.haveIPP() else "OFF"),WITH_TBB="ON",BUILD_EXAMPLES="OFF",BUILD_TESTS="OFF",BUILD_PERF_TESTS="OFF",BUILD_DOCS="OFF",BUILD_ANDROID_EXAMPLES=("OFF" if self.no_samples_build else "ON"),INSTALL_ANDROID_EXAMPLES=("OFF" if self.no_samples_build else "ON"),# BUILD_ANDROID_PROJECTS="OFF",# ANDROID_PROJECTS_BUILD_TYPE="GRADLE"
)

查找并理解编译参数,配合实践,应该可以编译出你想要的文件。

FAQ

❎❗️❗️Android SDK: Can’t build Android projects as requested by BUILD_ANDROID_PROJECTS=ON variable.

Question 1

✅**解决办法:**配置 BUILD_ANDROID_PROJECTS=”OFF“ 或者 ANDROID_PROJECTS_BUILD_TYPE="GRADLE" # 或者 ”ANT“。作为 Android 开发自然是配置 Gradle 嘛,不然颜面何在,当然我们也可以在 config 文件中配置

BUILD_ANDROID_PROJECTS=”OFF“

❎❗️❗️MainActivity.java:57: 错误: 找不到符号
mModelBuffer = loadFileFromResource(R.raw.mobilenet_iter_73000);
^
符号: 变量 raw
位置: 类 R
/home/yi/opencv/samples/android/mobilenet-objdetect/src/org/opencv/samples/opencv_mobilenet/MainActivity.java:58: 错误: 找不到符号
mConfigBuffer = loadFileFromResource(R.raw.deploy);
^
符号: 变量 raw
位置: 类 R

Question 2

✅**解决办法:**从官方 SDK 文件中手动复制。

❎❗️❗️gradle-7.6.3-all.zip 下载失败

✅**解决办法:**下载离线版本存放至 .gradle 对应目录下即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/337890.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【学习总结】地面路谱分析

本文仅用于记录自己的学习总结&#xff0c;包括个人理解。不保证内容严格正确。 0. 参考资料 [1] 国标GB/T 703-2005/ISO 8608:1995。[2] Bilibili-车辆考研-路面不平度统计特性[3] Bilibili-清华大学《汽车理论》[4] 网络参考文档.[5] 论文&#xff1a;高雄《路面不平度统计…

Scala入门到放弃—04—集合

文章目录 集合数组ListSetMapTuple其他 集合 数组 可变数组 package org.example object ArrayApp extends App{//继承App后直接直接调用函数&#xff0c;不需要main//println("hello")val a new Array[String](5)a(0)"hello"println(a(0))val b Array…

跟着我学Python进阶篇:02.面向对象(上)

往期文章 跟着我学Python基础篇&#xff1a;01.初露端倪 跟着我学Python基础篇&#xff1a;02.数字与字符串编程 跟着我学Python基础篇&#xff1a;03.选择结构 跟着我学Python基础篇&#xff1a;04.循环 跟着我学Python基础篇&#xff1a;05.函数 跟着我学Python基础篇&#…

免费运维工具测评——深入使用牧云主机管理助手

作为一名运维&#xff0c;宝塔&#xff0c;Nezha 监控面板&#xff0c;WinSCP&#xff0c;Termius 都用过了&#xff0c;谈一下自己的感受&#xff1a; 安装绑定 微信扫码可直接登录&#xff0c;主页简洁清晰&#xff0c;即使是个人体验版也没有任何广告。 只需要复制命令在服…

《More Effective C++》学习

条款1&#xff1a;仔细区别 pointers 和 references 引用应该被初始化&#xff0c;指针可以不被初始化。不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高。因为在使用引用之前不需要测试它的合法性。指针与引用的另一个重要的不同是指针可以被重新赋值…

【数据库原理】(11)SQL数据查询功能

基本格式 SELECT [ALL|DISTINCT]<目标列表达式>[,目标列表达式>]... FROM <表名或视图名>[,<表名或视图名>] ... [ WHERE <条件表达式>] [GROUP BY<列名 1>[HAVING <条件表达式>]] [ORDER BY <列名 2>[ASC DESC]];SELECT: 指定要…

《Linux C编程实战》笔记:线程私有数据

在多线程环境下&#xff0c;进程内的所有线程共享进程的数据空间&#xff0c;因此全局变量为所有线程共有。在程序设计中有时需要保存线程自己的全局变量&#xff0c;这种特殊的变量仅在某个线程内部有效。如常见的变量errno,它返回标准的出错代码。errno不应该是一个局部变量&…

冬日暖阳行走澳门探寻金沙度假区美食,游行全攻略

澳门金沙度假区是一个集度假、娱乐、购物、美食于一体的综合性旅游胜地。里面光酒店就有7家&#xff08;威尼斯人、巴黎人、四季、瑞吉、康莱德、假日、喜来登&#xff09;&#xff1b;大型购物中心4个&#xff08;四季名店、威尼斯人购物中心、巴黎人购物中心、金沙广场&#…

export default 和exprot

1.默认导入和默认导出 语法: export default {需要输出的内容} 接收: import 成员变量的名字 from 文件夹的路径 案例&#xff1a; a.mjs文件夹下默认导出 export default{a:10,b:20,show(){console.log(123);} } 在b.mjs文件中用成员变量进行接收 import AA from &q…

C语言之三子棋小游戏的应用

文章目录 前言一、前期准备模块化设计 二、框架搭建三、游戏实现打印棋盘代码优化玩家下棋电脑下棋判断输赢 四、结束 前言 三子棋是一种民间传统游戏&#xff0c;又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏分为双方对战&#xff0c;双方依次在9宫格棋盘上摆放棋子&#…

构建安全可靠的系统:第十六章到第二十章

第四部分&#xff1a;维护系统 原文&#xff1a;Part IV. Maintaining Systems 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 准备应对不舒适情况的组织有更好的机会处理关键事件。 尽管不可能为可能扰乱您组织的每种情况制定计划&#xff0c;但作为综合灾难规划策略…

dubbo的springboot集成

1.什么是dubbo&#xff1f; Apache Dubbo 是一款 RPC 服务开发框架&#xff0c;用于解决微服务架构下的服务治理与通信问题&#xff0c;官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力&#xff0c; 利用 Dubbo …