Android Studio配置并运行OpenCV4Android的face-detection

来源:互联网 发布:js怎么让div隐藏 编辑:程序博客网 时间:2024/06/14 00:20

0. 开发环境

之前一直是用ADT bundle自带的Eclipse来做OpenCV4Android的开发,其实AS(Android Studio)经过几年的发展已经逐渐完善,对Android开发的支持也好过Eclipse,所以痛下决心,这一次就花点时间把OpenCV4Android在AS中配置好。我会尽量把配置过程写得详细点,因为自己在配置过程中也遇到了很多坑。

为什么要选择face-detection这个project呢?相信熟悉OpenCV4Android的同学都知道fd的人脸识别模块调用的是jni的库,所以正好在借这个机会把jni在Android Studio里面的配置也搞清楚。

下面是我的开发环境清单:

  • 操作系统: Win7
  • Android Studio 2.2.2
  • JDK&JRE: 1.8
  • OpenCV4Android-2.4.10
  • NDK: android-ndk-r10d

1. 导入eclipse程序

1.1 确定SdkVersion

在导入程序之前,我们需要先确定待会的OpenCv工程中的一些和SdkVersion有关的配置,最好的办法就是先用AS建一个HelloWorld,也可以顺便熟悉一下Android Studio的开发流程。在工程中打开build.gradle,可以得到我们需要的信息:

#这两个很重要compileSdkVersion 25buildToolsVersion "25.0.2"#这个随意,和开发的APP的兼容性有关minSdkVersion 21targetSdkVersion 25

1.2 导入samples\face-detection

在Android Studio的界面上,选择File->New->Import Project:
这里写图片描述
在弹出的框里面选择OpenCV-2.4.10-android-sdk下的samples\face-detection,点击OK:
这里写图片描述

选择Next:
这里写图片描述

下一步请按下图勾选,然后点击Finish:
这里写图片描述

此时Android Studio会新打开一个窗口实例来导入工程,不出意外会出现如下错误:
这里写图片描述

此时,我们在AS左侧的Project窗口的打开如下的配置文件:
openCVSamplefacedetection->src->build.gradle
这里写图片描述

修改如下4个配置信息:

compileSdkVersion 14buildToolsVersion "25.0.2"minSdkVersion 8targetSdkVersion 8

按照之前的HelloWorld工程里的配置进行修改:
这里写图片描述

在修改完成之后,需要重新进行”Gradle project sync”,点击Tools->Android->Sync Project with Gradle Files:
这里写图片描述

Oops,貌似又报错了:

Error:Failed to find target with hash string 'android-14' in: D:\develop\Android_Studio\sdk<a href="install.android.platform">Install missing platform(s) and sync project</a>

原因在于,工程openCVSamplefacedetection依赖于库工程openCVLibrary2410,而库工程openCVLibrary2410的build.gradle配置也需要修改。这里不再赘述,找到openCVLibrary2410下的build.gradle进行修改即可。

修改完成后再次进行”Gradle project sync”,这一次”Gradle Sync”没有报错,随后AS会进行”Gradle build”,也顺利完成。

接下来我们尝试进行工程构建,点击工具栏中的“锤子”图案进行构建:
这里写图片描述

这一次出现以下错误,分析可以知道是fd工程的jni C++部分没有被正确编译。

FAILURE: Build failed with an exception.* What went wrong:Execution failed for task ':openCVSamplefacedetection:compileDebugNdk'.> Error: Your project contains C++ files but it is not using a supported native build system.

1.3 jni的配置

怎样解决上面出现的问题?
首先,我们需要先配置NDK的路径,点击File->Project Structure,在如下的界面上配置NDK的路径。
这里写图片描述

然后,在左侧的项目窗口中选中openCVSamplefacedetection,右键点击”Link C++ Project with Gradle”,在弹出的窗口中按照下图选择,点击”OK”。
这里写图片描述

接下来,在左右的项目窗口中的“External Build Files”下,选择Android.mk,修改OpenCV.mk的路径:

include ../../sdk/native/jni/OpenCV.mk

修改后的路径为,当然你需要根据自己电脑上的OpenCV4Android路径进行配置:

include D:\develop\OpenCV-2.4.10-android-sdk\sdk\native\jni\OpenCV.mk

最后一个需要修改的地方,修改对应于当前module(openCVSamplefacedetection)的build.gradle:
这里写图片描述

在第12行的ndk部分加入以下的声明:

abiFilters "armeabi-v7a"

最终得到:

ndk {    abiFilters "armeabi-v7a"    moduleName "detection_based_tracker"}

至此,整个jni部分的配置就全部完成,这时再点击”构建“,可以发现已经可以生成成功。

BUILD SUCCESSFUL

2. 剔除OpenCV Manager依赖

在上一小节中,我们已经可以成功地配置fd工程,并且编译生成都成功,此时我们可以将apk部署到手机上进行运行。但是等等,你还想被OpenCV Manager所困扰吗?说实话,每次我想要找到适合自己手机的OpenCV Manager,都要上网查一大堆资料,费时又费劲。

那么接下来我就基于face-detection工程,给大家分享一个去掉OpenCV Manager依赖的方法。

找到mainActivity,在我们这里是FdActivity,如下两段代码是载入OpenCV Manager的核心代码:

private BaseLoaderCallback  mLoaderCallback = new BaseLoaderCallback(this) {    @Override    public void onManagerConnected(int status) {        switch (status) {            case LoaderCallbackInterface.SUCCESS:            {                Log.i(TAG, "OpenCV loaded successfully");                // Load native library after(!) OpenCV initialization                System.loadLibrary("detection_based_tracker");                try {                    // load cascade file from application resources                    InputStream is = getResources().openRawResource(R.raw.lbpcascade_frontalface);                    File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);                    mCascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");                    FileOutputStream os = new FileOutputStream(mCascadeFile);                    byte[] buffer = new byte[4096];                    int bytesRead;                    while ((bytesRead = is.read(buffer)) != -1) {                        os.write(buffer, 0, bytesRead);                    }                    is.close();                    os.close();                    mJavaDetector = new CascadeClassifier(mCascadeFile.getAbsolutePath());                    if (mJavaDetector.empty()) {                        Log.e(TAG, "Failed to load cascade classifier");                        mJavaDetector = null;                    } else                        Log.i(TAG, "Loaded cascade classifier from " + mCascadeFile.getAbsolutePath());                    mNativeDetector = new DetectionBasedTracker(mCascadeFile.getAbsolutePath(), 0);                    cascadeDir.delete();                } catch (IOException e) {                    e.printStackTrace();                    Log.e(TAG, "Failed to load cascade. Exception thrown: " + e);                }                mOpenCvCameraView.enableView();            } break;            default:            {                super.onManagerConnected(status);            } break;        }    }};
@Overridepublic void onResume(){    super.onResume();    OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);}

在onResume method中进行OpenCVLoader的初始化,然后在回调函数onManagerConnected中,当OpenCV Manager载入成功,则进行后续的初始化。

要完全剔除OpenCV Manager的依赖,我们在编译构建apk时就选择将当前依赖的.so库进行静态链接,而不是动态地在app运行时再动态链接。

首先,将OpenCV-2.4.10-android-sdk\sdk\native下的libs文件夹拷贝至face-detection\openCVSamplefacedetection\src\main,并且重新命名为jniLibs;

然后修改代码,移除前面两段代码,在当前的activity中加入如下的静态声明:

static{     System.loadLibrary("opencv_java"); }

将下面这段代码搬移到onCreate函数的最后部分。

// Load native library after(!) OpenCV initializationSystem.loadLibrary("detection_based_tracker");try {    // load cascade file from application resources    InputStream is = getResources().openRawResource(R.raw.lbpcascade_frontalface);    File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);    mCascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");    FileOutputStream os = new FileOutputStream(mCascadeFile);    byte[] buffer = new byte[4096];    int bytesRead;    while ((bytesRead = is.read(buffer)) != -1) {        os.write(buffer, 0, bytesRead);    }    is.close();    os.close();    mJavaDetector = new CascadeClassifier(mCascadeFile.getAbsolutePath());    if (mJavaDetector.empty()) {        Log.e(TAG, "Failed to load cascade classifier");        mJavaDetector = null;    } else        Log.i(TAG, "Loaded cascade classifier from " + mCascadeFile.getAbsolutePath());    mNativeDetector = new DetectionBasedTracker(mCascadeFile.getAbsolutePath(), 0);    cascadeDir.delete();} catch (IOException e) {    e.printStackTrace();    Log.e(TAG, "Failed to load cascade. Exception thrown: " + e);}mOpenCvCameraView.enableView();

这时,我们可以惊喜地发现,在手机上没有安装OpenCV Manager的情况下,face-detection也可以顺利运行。

3. 运行效果

在手机上实测的人脸识别效果如下所示:
这里写图片描述

原创粉丝点击