[TOC]
本文的实现思路是基于OpenCV库实现人脸检测,首先集成底层so动态库及头文件等,然后集成OpenCV的Java模块,当做lib库使用,实现的效果也是Samples文件中的,对于手机而言,没有旋转,甚是别扭。项目中goto detect按键实现的就是这种效果。本文正文介绍的也是这种方式。
然后想实现正常的预览视角,抛弃OpenCV的Java模块,此时遇到的问题主要有预览视图的旋转设置,回调后buffer数据的旋转,然后摄像头NV21数据格式转成RGB格式,流数据格式转Mat,调用人脸识别,画人脸矩形框,将带人脸框的数据渲染到SurfaceView等等。此种方式本文有实现,此种方式1.2.2和1.2.7便无需再参考了。
这里各种数据格式的转换是参考别人网上找的算法,然后实现RGB与YUV之间的转换还可以借助libyuv这个库(我自己目前还没有实践,有空了要试一下),官网地址为:https://chromium.googlesource.com/libyuv/libyuv
但是因为是Google的库,需要翻墙,这里可以曲线救国,从GitHub上下载:https://github.com/lemenkov/libyuv
可以参考Android音视频——Libyuv使用实战。
先来个效果图一睹为快吧:
去 OpenCV官网 下载合适的 Android 版本并解压,这里以OpenCV-4.1.2为例。
新建带有C++库的Android项目,在app/src/main/目录下新建jniLibs目录,并将OpenCV-android-sdk/sdk/native/libs/下的armeabi-v7a目录拷贝到jniLibs目录中。 在app下的build.gradle中的defaultConfig中添加:
ndk {
abiFilters 'armeabi-v7a'
}将OpenCV-android-sdk/sdk/native/jni/下的include目录拷贝到app/src/main/cpp/目录下,然后修改该目录下的CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.4.1)
#指定头文件查找路径
include_directories(include)
#指定库的查找路径
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")
add_library( # Sets the name of the library.
native-lib
SHARED
native-lib.cpp)
target_link_libraries( # Specifies the target library.
native-lib
opencv_java4
log)将OpenCV-android-sdk/samples/face-detection/res/下的raw目录拷贝到我们自己项目中的app/src/main/res/目录下,这个是人脸识别的模型对比文件。
在项目中建立名为org.opencv.samples.facedetect的包,然后将``OpenCV-android-sdk/samples/face-detection/src/org/opencv/samples/facedetect/目录下的DetectionBasedTracker.java`和`FdActivity.java`文件复制到该包下,然后将`FdActivity`加入到`AndroidManifest.xml`中;将`OpenCV-android-sdk/samples/face-detection/res/layout/`下的`face_detect_surface_view.xml`拷贝到`app/src/main/res/layout/`目录下。
将OpenCV-android-sdk/samples/face-detection/jni/目录下的DetectionBasedTracker_jni.cpp和DetectionBasedTracker_jni.h文件复制到app/src/main/cpp/目录下,然后修改CMakeLists.txt文件:
add_library( # Sets the name of the library.
native-lib
SHARED
DetectionBasedTracker_jni.cpp) #这里之前为 native-lib.cpp,现修改为 DetectionBasedTracker_jni.cpp修改FdActivity.java中的BaseLoaderCallback监听中的加载库:
System.loadLibrary("native-lib");AndroidManifest.xml文件中添加权限:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>File->New->Import Module...选择将OpenCV-android-sdk/sdk/下的java目录导入项目,然后修改该Module中src目录下的build.gradle文件:
//apply plugin: 'com.android.application'
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
defaultConfig {
// applicationId "org.opencv"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}然后在“项目结构视图”中将该库作用app的依赖。
OpenCV提供的人脸识别默认采用的是后置摄像头,可以在onCreate()方法中添加如下代码,即可实现前置摄像头的使用:
//0:后置摄像头 1:前置摄像头
mOpenCvCameraView.setCameraIndex(1);
mOpenCvCameraView.enableView();警告信息如下:
To make sure the C++ compiler uses unmodified names when calling functions in your C code,list your C functions in your C++ code usinng extern "C".解决方案:
如警告所建议,在方法前添加extern "C"。
运行显示提示框:
OpenCV Manager package was not found! Try to install it?原因:动态库没有真正生成。
解决方案: 修改app目录下的gradle文件
defaultConfig {
applicationId "com.sty.opencv.facedetection.android"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
//OpenCV 4.x+ requires enabled C++11 support
cppFlags "-std=c++11"
abiFilters "armeabi-v7a"
arguments "-DANDROID_STL=c++_shared"
}
}
ndk {
abiFilters 'armeabi-v7a'
}
}