当前最新版SDK地址
其实整个SDK里面只用到三个核心文件、三个util脚本,当然如果不想自己创建工程,它里面有一个demo是可以直接跑的。
SDK包含三个核心文件:
两个.aar
文件位于:~\MegviiFacepp_Android_0.5.2\Android-Demo\Android-Demo\faceppdemo\libs
,将它们拷贝到YourProject\app\libs
;模型文件位于~\MegviiFacepp_Android_0.5.2\Android-Demo\Android-Demo\faceppdemo\src\main\res\raw
,将其拷贝到YourProject\app\src\main\res\raw
(文件夹raw
可能并不存在,手动创建就好)。
在 AS 中修改module
的配置文件build.gradle
:在dependencies
结构中添加如下两行
compile(name: 'MGLicenseManagerSDK-0.3.1', ext: 'aar')
compile(name: 'MGFaceppSDK-0.5.2', ext: 'aar')
在android
结构中添加如下代码
repositories {
flatDir {
dirs 'libs'
}
}
注意:官方文档给出的是compile
命令,在最新的Android框架中可能会提示使用implementation
去替代;name
需要跟你使用的SDK版本保持一致,否则会报错。接下来重新编译工程即可:菜单栏Build -> Clean Project-> Rebuild Project
。成功之后可以在工程中使用如下命令导入和使用SDK:
import com.megvii.facepp.sdk.Facepp;
import com.megvii.licensemanager.sdk.LicenseManager;
这三个脚本其实并不是必需的,但是确实是要用到里面的一些方法,那既然官方写好了那我们直接用就好。
直接将这三个文件拷贝到YourProject\app\src\main\java\com\**\**\util
下面,然后修改每个文件头部的package
,修改Util.java
的key
值为你自己就好。key
值需要到官网注册账号,然后新建API,绑定Bundle(在“应用管理”中可以看到),Bundle的ID最好是跟项目的applicationId
保持一致(我试过不一样也能用好像~)。
SDK分为离线授权和联网授权两种,离线授权就是你买它的SDK,他给你的时候就把权限写在SDK里面了;联网授权一般是在免费使用版本中,每一次使用SDK的时候需要通过网络访问来获取权限,这里以联网授权的版本为例。
INTERNET
,ACCESS_NETWORK_STATE
,然后还有关于图像数据的读写、相机权限等需要自己添加,最好是动态授权。联网授权最关键的代码部分:
private void network() {
// 获取联网授权类型
int type = Facepp.getSDKAuthType(ConUtil.getFileContent(this, R.raw.megviifacepp_0_5_2_model));
if ( type == 2) {// 非联网授权
authState(true,0,"");
return;
}
// 开始联网授权
final LicenseManager licenseManager = new LicenseManager(this);
String uuid = ConUtil.getUUIDString(this); // 手机唯一序列号
long apiName = Facepp.getApiName(); // 大概是SDK的版本名称,API自己获取不用管
licenseManager.setAuthTimeBufferMillis(0); // 设置时间缓冲,猜测可能跟SDK的License期限有关
// 回调
licenseManager.takeLicenseFromNetwork(
Util.CN_LICENSE_URL, // 联网授权地址
uuid,
Util.API_KEY,
Util.API_SECRET,
apiName,
"1", // 使用期限,试用版本只能是1天
new LicenseManager.TakeLicenseCallback() {
@Override
public void onSuccess() {
authState(true,0,"");
}
@Override
public void onFailed(int i, byte[] bytes) {
if (TextUtils.isEmpty(Util.API_KEY)||TextUtils.isEmpty(Util.API_SECRET)) {
if (!ConUtil.isReadKey(MainActivity.this)) {
authState(false,1001,"");
}else{
authState(false,1001,"");
}
}else{
String msg="";
if (bytes!=null&&bytes.length>0){
msg= new String(bytes);
}
authState(false,i,msg);
}
}
});
}
private void authState(boolean isSuccess,int code,String msg) {
if (isSuccess) { // 联网授权成功
Log.d("联网授权", "成功");
Intent intent = new Intent();
intent.setClass(this, FaceActionActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
} else { // 联网授权失败
Log.d(code, msg);
}
}
最为关键的就是licenseManager.takeLicenseFromNetwork
,它里面重写了onSuccess
、onFailed
函数,分别会在授权成功/失败时调用。授权成功的话我们会让它跳转至FaceActionActivity.class
,同时销毁当前的MainActivity
,然后在FaceActionActivity
里进行人脸关键点的检测,这样做的原因是:联网授权的network
(其实就是里面的licenseManager.takeLicenseFromNetwork
)是一个异步事件,需要在它的OnSuccess
里面做检测,如果在这之后做检测可能会有问题。
官方给出的一些说明好像跟实际应用开发并不一致,比如关于权限次数:官方文档写明一个API_Key一天有五次机会,也就是说如果你把当前的API_Key删除,重新创建一个API_Key会拥有新的五次机会,但实践证明不会。可以能会得到以下的返回错误:
(1)初始化实例,然后加载模型
Facepp facepp = new Facepp();
String errorCode = facepp.init(this, ConUtil.getFileContent(this, R.raw.megviifacepp_0_5_2_model), 1);
这里可能会存在R.raw
不存在的问题,关掉项目重新打开一下就好;最后一个参数表示是否只检测单个人脸,0表示否,1表示是。一般如果联网授权没问题,这里的errorCode
返回值是null
,否则会返回具体的错误信息。
(2)检测参数设置
// 设置检测器参数(这里只列出一部分)
Facepp.FaceppConfig faceppConfig = new Facepp.FaceppConfig();
faceppConfig.detectionMode = Facepp.FaceppConfig.DETECTION_MODE_TRACKING_FAST; // 检测模式:FAST,ROUBUST
faceppConfig.minFaceSize = 1; // 最小人脸尺寸
faceppConfig.roi_right = w; // 感兴趣区域
faceppConfig.roi_bottom = h;
facepp.setFaceppConfig(faceppConfig);
(3)人脸检测,获取数据
// 检测人脸,最后一个参数是输入图像的格式
final Facepp.Face[] faces = facepp.detect(imgData, w, h, Facepp.IMAGEMODE_NV21);
// 获取人脸数据
facepp.getLandmarkRaw(faces[0], Facepp.FPP_GET_LANDMARK106);
facepp.get3DPose(faces[0]);
检测人脸的时候输入数据类型是byte[]
,官方给出支持 NV21、BGR 格式的检测(就是detect方法的最后一个参数),但是亲测好像只支持NV21,所以最好是将图像转成 NV21 格式的byte[]
;如果把BGR数据送进去,最后检测到的人脸数量为0。
关于SDK能够获取到的数据可以看官方文档,基本上就是关键点、头部3D-pose、人脸属性等,有些事收费才能获取的,但是关键点和头部3D-pose是免费的。