前言
SDK下载地址
这里使用4.8.1版本
在 Android 中使用 OpenCV 主要涉及 集成 OpenCV 库、加载原生库、调用图像处理接口 三大步骤。
下载 OpenCV
- 官网地址:https://opencv.org/releases/
- 下载 OpenCV for Android(如
opencv-4.8.1-android-sdk.zip) - 解压后得到
OpenCV-android-sdk文件夹
注意:
不要直接使用 GitHub 上的源码,要用官方发布的 SDK 包。
集成方式
这是最稳定、兼容性最好的方式。
集成代码
复制 OpenCV SDK 到项目
- 将
OpenCV-android-sdk/sdk/java文件夹重命名为opencv - 放入你的 Android 项目根目录下(与
app同级) - 删除
javadoc文件夹 src下创建main/java文件夹,把org文件夹复制进来- 把
res和AndroidManifest.xml移动到src/main下
创建一个类
1 | package org.opencv; |
修改 opencv/build.gradle
1 | plugins { |
在主项目 settings.gradle.kts 中包含 opencv 模块
1 | include(":opencv") |
在 app/build.gradle.kts 中添加依赖
1 | dependencies { |
集成原生库
查看架构
注意
原生库不同的 CPU 架构有不同的 ABI,我们不要全都复制,按照实际的情况复制对应架构的就行。
查看架构
1 | adb shell getprop ro.product.cpu.abi |
输出可能是:
arm64-v8a→ 你需要提供arm64-v8a/libopencv_java4.sox86_64→ 模拟器,需要x86_64/libopencv_java4.so
确保你的设备 CPU 架构与 .so 文件匹配。
常见的 ABI 有:
arm64-v8a(主流 64 位 ARM)armeabi-v7a(32 位 ARM,兼容性好)x86/x86_64(模拟器)
原生库ABI选择原则
要考虑实际的运行环境:
如果只在现代设置上运行只选
arm64-v8a就行了。如果要兼容早期的手机再添加上
armeabi-v7a。如果要在模拟器上运行再添加上
x86_64,现在基本上都是64位的模拟器了。
复制原生库
复制OpenCV库
- 将
OpenCV-android-sdk/sdk/native/libs文件夹内需要的ABI复制出来 - 复制到
app/src/main/jniLibs/(若无此目录则新建) - 最终路径:
app/src/main/jniLibs/arm64-v8a/libopencv_java4.so等
复制OpenCV依赖库
OpenCV 4.8.1 是使用 Android NDK 编译的,依赖libc++_shared.so,而 libc++_shared.so 并不是 OpenCV 自带的,而是 NDK 提供的标准 C++ 共享库。
因此,你需要从你本地安装的 Android NDK 目录中获取它。
复制libc++_shared.so文件
查找NDK位置
File => Settings => Language & Frameworks => Android SDK
里面可以看到SDK的路径找到NDK下的
D:\Tools\AndroidSDK\ndk\25.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\sysroot\usr\lib
如图
设置ABI过滤(非必要)
ABI(Application Binary Interface,应用二进制接口)定义了应用程序与系统之间在底层(如寄存器使用、调用约定、数据对齐等)如何交互。
不同的 CPU 架构有不同的 ABI,例如:
armeabi-v7a:32 位 ARM 架构(较旧的 Android 设备)arm64-v8a:64 位 ARM 架构(现代主流 Android 设备)x86:32 位 Intel/AMD 架构(部分模拟器或老旧设备)x86_64:64 位 Intel/AMD 架构(部分模拟器或 Chromebook)
abiFilters 的作用
当你使用 NDK(Native Development Kit) 编写 C/C++ 代码并编译成 .so 动态库时,这些库必须为特定的 ABI 编译。
abiFilters 告诉 Gradle 只打包指定 ABI 的原生库到最终 APK 或 AAB 中。
1 | android { |
设置原生库路径(非必要)
注意这个配置不是必要的
如果把 .so 文件放在 默认路径 src/main/jniLibs/ 下,不需要额外配置 sourceSets,Android Gradle Plugin(AGP)会自动识别并打包这些 native 库。
1 | android { |
验证是否生效
你可以通过以下方式确认 .so 是否被打包进 APK:
- 构建 APK 后,用 Android Studio → Build > Analyze APK… 打开它;
- 查看
lib/arm64-v8a/等目录下是否有libopencv_java4.so。
项目结构示意
1 | MyApp/ |
初始化 OpenCV
初始化 OpenCV(必须)
OpenCV 需要加载原生库才能使用。不能直接调用 Mat 等类!
推荐方式:使用 OpenCVLoader.initDebug()
1 | class MainActivity : ComponentActivity() { |
注意:
initDebug()适用于开发;发布时建议用initAsync()避免 ANR。- 如果你只在特定功能中使用 OpenCV,可在该 Activity 或 Fragment 中初始化。
示例
示例:从相册选图 → 转灰度 → 显示
1 | // 1. 从资源或文件加载 Bitmap |
🔧 常用模块:
Imgproc:图像处理(滤波、边缘、变换等)Core:矩阵运算Imgcodecs:读写图像文件(注意:Android 中通常用Bitmap代替)Features2d:特征点检测(SIFT、ORB 等)
常见问题解决
| 问题 | 解决方案 |
|---|---|
UnsatisfiedLinkError |
确保 jniLibs 中有对应 ABI 的 .so 文件 |
| 图像方向错误 | Android Bitmap 是 RGBA,OpenCV 默认 BGR,注意颜色空间转换 |
| 内存泄漏 | 使用完 Mat 后调用 mat.release() |
| APK 体积过大 | 参考上一问:裁剪 ABI 或使用精简版 OpenCV |
进阶建议
- 异步处理:图像操作放在
AsyncTask或Coroutine中,避免卡 UI。 - 内存优化:复用
Mat对象,及时release()。 - 自动检测文档四角:结合
Canny + findContours + approxPolyDP实现扫描仪效果。 - 替代方案:如果只需简单处理(缩放、旋转),可考虑纯 Java/Kotlin 实现,避免引入 OpenCV。
图形校正
1 | import android.graphics.Bitmap |