Android Studio配置OpenCV记录

前言

在上一篇文章中简单记录了关于Qt配置Android开发环境的内容,也包括配置OpenCV的部分,这篇文章则是记录在Android Studio上配置OpenCV的方法。由于OpenCV提供的Android开发工具包即包括C++ API也包括Java API,同时Android Studio也支持NDK的开发,故用户可选择使用纯Java完成整个应用的开发,也可以借助JNI和NDK,使用Java和C++混合编程完成应用的开发。Android Studio配置OpenCV包含两个部分,一是OpenCV Java 库的配置,二是C++库的配置,在本文中都会有简单记录。实际上关于Android Studio配置OpenCV的文章已经很多,但问题在于大部分使用的Android Studio版本都比较老,导致我在按照他们的教程配置的时候均出现了一些问题。为方便自己以后复习,我觉得有必要自己记录一下最新版本Android Studio的OpenCV配置方法,比较完整的教程可参考OpenCV On Android最佳环境配置指南。

OpenCV配置方法

在配置OpenCV之前,需要先完成Android Studio的开发环境配置,即确保在Android Studio上已经可以正常构建简单的应用程序。接着根据需要的版本在OpenCV官网下载Android开发工具包。我PC上安装的Android Studio版本是4.1.1,SDK和NDK是最新版本,安卓版本是29,OpenCV版本是4.4.0。

OpenCV Java库配置

打开一个Android Studio Native C++工程,依次点击File->New->Import Module,在弹出的窗口中选择下载的OpenCV Android SDK安装目录下的sdk\java目录,如下图所示:
Android Studio配置OpenCV记录_第1张图片
输入路径后点击Next->Finish即可。在老版Android Studio中,Import Module时可以设置Module的名字,但在最新版中没有这个选项,需要在Import后右键点击左侧Module根目录,选择Refactor->Rename,在弹出的窗口中选择Rename module进行更名,本例中更名为opencv,更名后如下所示:
Android Studio配置OpenCV记录_第2张图片
由于opencv模块的build.gradle文件内容与app模块的build.gradle不同,且Android Studio不支持同时有两个模块配置为com.android.application,因此需要对opencv的build.gradle文件进行修改,修改的内容如下:

  • 修改apply plugin: 'com.android.application'apply plugin: 'com.android.library'
  • 删除defaultConfig中的applicationId "com.example.xxx"字段
  • 设置compileSdkVersion,内容与app模块的build.gradle文件保持一致

老版Android Studio可在File->Project Structure->Dependencies中设置app模块的依赖选项,但新版无法直接添加,需要在app模块的build.gradle文件中的dependencies处手动添加一行implementation project(":opencv")

完成上面的配置后,还需配置OpenCV Java的运行库,不然在程序运行时会提示需要安装OpenCV Manager。配置的方法如下:

  • 复制OpenCV Android SDK目录sdk\native\libs\下的文件夹到Android Studio工程app\libs目录下,可根据需要,仅复制目标设备的运行库,通常复制armeabi-v7a和arm64-v8a即可,如下图所示:
    Android Studio配置OpenCV记录_第3张图片
  • 修改app模块的build.gradle文件,在android字段添加如下:
sourceSets {
	main {
		jniLibs.srcDirs = ["libs"];
	}
}
  • 修改app模块的build.gradle文件,在defaultConfig -> externalNativeBuild -> cmake字段中添加如下:
arguments "-DANDROID_STL=c++_shared"

添加后如下所示:
Android Studio配置OpenCV记录_第4张图片
完成上面的配置后,在打包apk时会将libopencv_java4.soc++_shared.so自动包括进去,注意需要是Native C++工程,其他类型的工程可能需要手动添加c++_shared.so到apk中。需要吐槽的是,即使包括了OpenCV运行库,在应用程序运行时依旧会提示需要安装OpenCV Manager,需要做点处理避开OpenCV Manager的初始化,具体可以参考OpenCV使用DNN模块加载SDD模型Android示例

OpenCV C++库配置

比较简单的方法是创建Native C++工程,Android Studio会自动生成cpp相关的文件,包括.cpp源码和CMakeLists.txt,接着用CMake的配置方式在CMakeLists.txt中配置OpenCV即可,配置的内容如下:

set(OpenCV_DIR D:/OpenCV/opencv-4.4.0-android/OpenCV-android-sdk/sdk/native/jni)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(native-lib ${OpenCV_LIBS})

添加配置后,还需在MainActivity中加载native-lib库,如果是Native C++工程,Android Studio会自动生成加载的代码如下:

static {
	System.loadLibrary("native-lib");
}

在需要C++处理时,可在Java类中声明native函数,并在.cpp文件中具体实现,native函数的形式与普通函数一致,不同的是需要在函数前添加native关键字。举例就是:假设Java包名为com.example.opencv.MainActivity,我们需要一个使用C++代码处理帧的函数processFrameJNI,那么在MainActivity中可声明函数如下:

native void processFrameJNI(Object frame);

在.cpp文件中对应的代码如下:

#include 
#include 
#include 
#include 

extern "C" JNIEXPORT void JNICALL
Java_com_example_opencv_MainActivity_processFrameJNI(
        JNIEnv* env,
        jobject /* this */,
        jobject frame) {
    AndroidBitmapInfo info;
    AndroidBitmap_getInfo(env, frame, &info);
    void* pdata{nullptr};
    AndroidBitmap_lockPixels(env, frame, &pdata);
    if (pdata && info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
        cv::Mat image(info.height, info.width, CV_8UC4, pdata);
        cv::cvtColor(image, image, CV_RGBA2BGR);
        
        /* process the image here ... */
        
        cv::cvtColor(image, image, CV_BGR2RGBA);
    }
    AndroidBitmap_unlockPixels(env, frame);
}

注意.cpp文件中函数名形式必须与Java包名一致,如使用到NDK的图形库如Bitmap,还需在CMakeLists.txt中添加相关的运行库如下:

target_link_libraries(native-lib jnigraphics)

结语

在写Windows下Qt编写Android应用程序的环境搭建记录的时候我说如果避不开Java的话,还是在Android Studio上编写Java和C++的混合代码要更为便捷一些。当然,有些熟悉Qt的开发人员可能更倾向于在Qt上开发,这个因人而异。就我自己来说,是更倾向于Android Studio的。不得不说JNI是个好东西,经由它可以使得应用程序开发即能享受Java成熟的UI设计,同时也能享受C++带来的性能提升,相信在以后写APP时会是我的首选。

你可能感兴趣的:(android,java,c++,opencv)