1. 概述

人脸识别技术(Automatic Face Recognition),简称AFR,是生物识别技术的一种,通过人的面部特征,进行身份鉴别。

本文档旨在讲解如何快速地集成灵云AFR功能到开发者应用中。关于各服务接口更详细的说明,请参考灵云SDK开发手册。在集成过程中如有疑问,可登录灵云开发者论坛,查找答案或与其他开发者交流。

1.1 概念解释

对指南中涉及的名词作简要描述,使开发者在阅读开发指南时,对此有一些大致的了解和预备知识的了解。 如:

名称 说明
Session Session用来标记一个能力运行过程的上下文。一个应用最多可同时创建的Session数受到授权的限制
云端识别 由云端服务器提供识别结果的方式。使用云端能力需要加上hci_afr_cloud_recog模块
本地识别 通过本地运算来得到识别结果的方式。使用本地能力需要加上hci_afr_local_recog模块和本地资源文件
人脸检测 通过对会话图像进行检测,提取其中的人脸特征。通过hci_afr_detect函数实现
人脸注册 通过对人脸模型进行多次训练,达到提高识别速度和正确率的目的。通过hci_afr_enroll函数实现
人脸确认 使用人脸ID与已注册的用户ID的特征进行匹配性确认。通过hci_afr_verify函数实现
人脸辨识 在一组用户中进行指定人脸ID的用户辨识。通过hci_afr_identify函数实现

1.2 能力定义(capkey)

AFR 支持多种能力,通过 capkey 区分不同能力的调用和配置。其中常用 capkey 如下所示:

capkey 所需本地资源文件
afr.cloud.recog
afr.local.recog FRAttr.bin
FRComp.bin
FRDetect.bin
FRFeat.bin
AFR.conf

1.3 识别流程

2. 能力使用说明

2.1 准备工作

下载人脸识别SDK并解压缩。

如果需要使用本地人脸识别,请下载相应资源包并解压缩。

2.2 使用Android版SDK

  • 必选模块

    • libhci_curl.so
    • libhci_sys.so
    • libhci_sys_jni.so
    • libstlport_shared.so
    • libhci_afr.so
    • libhci_afr_jni.so
  • 云端识别

    • libhci_afr_cloud_recog.so
  • 本地识别

    • libhci_afr_local_recog.so

2.3 使用C++版SDK

  • 必选模块

    • hci_sys.dll
    • libhci_curl.dll
    • hci_afr.dll
  • 云端识别

    • hci_afr_cloud_recog.dll
  • 本地识别

    • AFREngine.dll
    • hci_afr_local_recog.dll
    • mkl_avx.dll
    • mkl_avx2.dll
    • mkl_core.dll
    • mkl_intel_thread.dll
    • mkl_p4.dll
    • mkl_p4m.dll
    • mkl_p4m3.dll
    • mkl_p4p.dll
    • mkl_rt.dll
    • mkl_sequential.dll
    • mkl_vml_avx.dll
    • mkl_vml_avx2.dll
    • mkl_vml_cmpt.dll
    • mkl_vml_ia.dll
    • mkl_vml_p4.dll
    • mkl_vml_p4m.dll
    • mkl_vml_p4m2.dll
    • mkl_vml_p4m3.dll
    • mkl_vml_p4p.dll

2.4 使用iOS版SDK

  • 必选模块

    • libcurl_device_simulator_iOS5.1.1.a
    • libhci_sys_device_simulator_iOS5.1.1.a
    • libhci_afr_device_simulator_iOS5.1.1.a
  • 云端识别

    • libhci_afr_cloud_recog_device_simulator_iOS5.1.1.a
  • 本地识别

    • libhci_afr_local_recog_device_simulator_iOS5.1.1.a
  • 适配器选择(只选其一)

    • libhci_afr_only_cloud_adapter_device_simulator_iOS5.1.1.a(只使用云端能力)
    • libhci_afr_only_local_adapter_device_simulator_iOS5.1.1.a(只使用本地能力)
    • libhci_afr_cloud_local_adapter_device_simulator_iOS5.1.1.a(既使用云端能力,又使用本地能力)

PS:

在集成灵云的iOS版本SDK时,静态库目录中会提供一种名称中包含adapter的静态库文件。值得说明一点的是,包含adapter名称的静态库文件是作为适配器使用的,所谓适配器是指开发者使用的灵云能力,即capkey是云端能力、本地能力,亦或者是云+端能力,所以适配器文件也还会对应以上的能力范围。当开发者集成时,适配器静态库在集成到工程中,有且只能有一个适配器静态库被添加到Link目录中,如开发者使用ASR的本地自由说能力,则适配器只需要选择libhci_asr_only_local_adapter_device_simulator_iOS7.1.1.a即可。

3. 能力集成说明

在调用AFR能力之前,需要初始化灵云SDK的SYS通用模块。详见灵云SDK开发手册

3.1 通用模块初始化

Android示例代码

// 创建初始化参数辅助类
InitParam initparam = new InitParam();
// 授权文件所在路径,此项必填
String authDirPath = context.getFilesDir().getAbsolutePath();;
initparam.addParam(InitParam.AuthParam.PARAM_KEY_AUTH_PATH, authDirPath);
// 灵云云服务的接口地址,此项必填
initparam.addParam(InitParam.AuthParam.PARAM_KEY_CLOUD_URL, "http://api.hcicloud.com:8888");
// 开发者密钥,此项必填,由捷通华声提供
initparam.addParam(InitParam.AuthParam.PARAM_KEY_DEVELOPER_KEY, "01234567890");
// 应用程序序号,此项必填,由捷通华声提供
initparam.addParam(InitParam.AuthParam.PARAM_KEY_APP_KEY, "1234abcd");
// 日志的路径,可选,如果不传或者为空则不生成日志
String logDirPath = "/storage/emulated/0/sinovoice/com.sinovoice.example/log";
initparam.addParam(InitParam.LogParam.PARAM_KEY_LOG_FILE_PATH, logDirPath);
//日志等级,0=无,1=错误,2=警告,3=信息,4=细节,5=调试
//SDK将输出小于等于logLevel的日志信息
initparam.addParam(InitParam.LogParam.PARAM_KEY_LOG_LEVEL, "5");
// 灵云系统初始化
// 第二个参数在Android平台下,必须为当前的Context
int errCode = HciCloudSys.hciInit(initparam.getStringConfig(), this);
if(errCode != HciErrorCode.HCI_ERR_NONE) {
    // "系统初始化失败"
    return;
}

C++示例代码

HCI_ERR_CODE err_code = HCI_ERR_NONE;
//配置串是由"字段=值"的形式给出的一个字符串,多个字段之间以','隔开。字段名不分大小写。
string init_config = "";
//灵云应用序号
init_config += "appKey=1234abcd";
//灵云开发者密钥
init_config += ",developerKey=1234567890";
//灵云云服务的接口地址
init_config += ",cloudUrl=http://api.hcicloud.com:8888";
//授权文件所在路径,保证可写
init_config += ",authpath=../../bin";
//日志的路径
init_config += ",logfilepath=../../bin";
//日志的等级
init_config += ",loglevel=5";
//日志文件的大小
init_config += ",logfilesize=512";
//其他配置使用默认值,不再添加,如果想设置可以参考开发手册
err_code = hci_init( init_config.c_str() );

iOS示例代码

HCI_ERR_CODE errCode = HCI_ERR_NONE;
// appkey, developerKey, cloudUrl, authPath为必填项。
// 其他可配置信息请查询灵云SDK开发手册hci_init函数说明。
NSString *appkey = @"";           //开发者社区申请所得
NSString *developerKey = @"";     //开发者社区申请所得
NSString *cloudUrl = @"";         //开发者社区申请所得
NSString *authPath = @"";         //授权文件所在路径,一般设置为沙盒Document路径
NSString *config = [NSString stringWithFormat:@"appkey=%@,
                                                developerKey=%@,
                                                cloudUrl=%@,
                                                authPath=%@",
                                                appkey,
                                                developerKey,
                                                cloudUrl, 
                                                authPath];
errCode = hci_init(config.UTF8String);
if (errCode != HCI_ERR_NONE && errCode != HCI_ERR_SYS_ALREADY_INIT) {
    NSLog(@"hci_init failed, error: %d", errCode);
} else {
     NSLog(@"hci_init success");
}

常见errcode,详见灵云SDK开发手册

3.2 授权检测

在初始化灵云SDK的通用模块后,还需要调用授权检测函数获取云端授权。

Android示例代码

// 获取授权
private int checkAuthAndUpdateAuth() {
    // 获取系统授权到期时间
    int initResult;
    AuthExpireTime objExpireTime = new AuthExpireTime();
    initResult = HciCloudSys.hciGetAuthExpireTime(objExpireTime);
    if (initResult == HciErrorCode.HCI_ERR_NONE) {
        // 显示授权日期,如用户不需要关注该值,此处代码可忽略
        Date date = new Date(objExpireTime.getExpireTime() * 1000);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd",Locale.CHINA);
        Log.i(TAG, "expire time: " + sdf.format(date));

        if (objExpireTime.getExpireTime() * 1000 > System.currentTimeMillis()) {
            Log.i(TAG, "checkAuth success");
            return initResult;
        }
    }

    // 获取过期时间失败或者已经过期
    initResult = HciCloudSys.hciCheckAuth();
    if (initResult == HciErrorCode.HCI_ERR_NONE) {
        Log.i(TAG, "checkAuth success");
        return initResult;
    } else {
        Log.e(TAG, "checkAuth failed: " + initResult);
        return initResult;
    }
}

C++示例代码

//获取过期时间
int64 expire_time;
int64 current_time = (int64)time( NULL );
HCI_ERR_CODE err_code = hci_get_auth_expire_time( &expire_time );
if( err_code == HCI_ERR_NONE )
{
    //获取成功则判断是否过期
    if( expire_time > current_time )
    {
        //没有过期
        printf( "auth can use continue\n" );
        return true;
    }
}
//获取过期时间失败或已经过期
//手动调用更新授权
err_code = hci_check_auth();
if( err_code == HCI_ERR_NONE )
{
    //更新成功
    printf( "check auth success \n" );
    return true;
}
else
{
    //更新失败
    printf( "check auth return (%d)\n", err_code);
    return false;
}

iOS示例代码

//获取过期时间
int64 expireTime;
int64 currentTime = (int64)time(NULL);
HCI_ERR_CODE errCode = hci_get_auth_expire_time(&expireTime);
if (errCode == HCI_ERR_NONE) {
    if (expireTime < currentTime) {
        errCode = hci_check_auth();
        if(errCode == HCI_ERR_NONE){
            NSLog(@"check auth success");
            return YES;
        }else{
            NSLog(@"check auth failed, error: %@", errCode);
            return NO;
        }
    }else{
        //没有过期
        NSLog(@"auth can use continue");
        return YES;
    }
}
//读取授权文件出现错误
else if(errCode == HCI_ERR_SYS_AUTHFILE_INVALID){
    errCode = hci_check_auth();
    if(errCode == HCI_ERR_NONE){
        NSLog(@"check auth success");
        return YES;
    }else{
        NSLog(@"check auth failed, error: %@", errCode);
        return NO;
    }
}else{
    NSLog(@"check auth failed, error: %@", errCode);
    return NO;
}

3.3 AFR初始化

Android示例代码

AfrInitParam initParam = new AfrInitParam();
// 获取App应用中的lib的路径,放置能力所需资源文件。
String dataPath = Environment.getExternalStorageDirectory().getAbsolutePath()+ 
                File.separator + "sinovoice" + 
                File.separator + this.getPackageName() + 
                File.separator + "data";


initParam.addParam(AfrInitParam.PARAM_KEY_DATA_PATH, dataPath);
initParam.addParam(AfrInitParam.PARAM_KEY_INIT_CAP_KEYS, capkey);
int errCode = HciCloudAfr.hciAfrInit(initParam.getStringConfig());
if (errCode != HciErrorCode.HCI_ERR_NONE) {
    ShowMessage("HciAfrInit error:"+ HciCloudSys.hciGetErrorInfo(errCode));
    return;
}else{
    ShowMessage("HciAfrInit Success");
}

C++示例代码

//AFR 初始化
string afr_init_config = "dataPath=";
afr_init_config += data_path;
afr_init_config += ",initCapkeys=";
afr_init_config += capkey;
errCode = hci_afr_init(afr_init_config.c_str());
if (errCode != HCI_ERR_NONE)
{
    printf("hci_afr_init return (%d) \n",errCode);
    return;
}

iOS示例代码

//本地能力所需本地资源所在路径
NSString *dataPath = [[NSBundle mainBundle] pathForResource:@"data" ofType:Nil];  
//initCapKeys为必填项。其他可配置信息请查询开发手册hci_afr_init函数说明。
NSString *initCapKeys = @"afr.local.recog";
NSString *config = [NSString stringWithFormat:@"initCapKeys = %@,dataPath = %@", 
                    initCapKeys,dataPath];
HCI_ERR_CODE errCode = HCI_ERR_NONE;
errCode = hci_afr_init(config.UTF8String);
if (errCode != HCI_ERR_NONE){
    NSLog(@"hci_afr_init failed, error:%@", errCode);
    eturn NO;
}
NSLog(@"hci_afr_init success");
return YES;

对于使用本地多能力时,可以使用initCapKeys传入需要使用的所有能力,以';'隔开。 initCapKeys的作用是告知SDK,需要预先准备哪些能力并提前加载对应的库资源,提高执行效率。

以HWR能力为例:

Android示例代码

initParam.addParam(HwrInitParam.PARAM_KEY_INIT_CAP_KEYS, 
                   "hwr.local.letter;hwr.local.freestylus;hwr.local.associateword");

C++示例代码

//HWR 初始化
string hwr_init_config = "dataPath=";
hwr_init_config += data_path;
hwr_init_config += ",initCapkeys=";
hwr_init_config += "hwr.local.letter;hwr.local.freestylus;hwr.local.associateword";

iOS示例代码

//本地能力所需本地资源所在路径
NSString *dataPath = [[NSBundle mainBundle] pathForResource:@"data" ofType:Nil];  
//initCapKeys为必填项。其他可配置信息请查询开发手册hci_hwr_init函数说明。
NSString *initCapKeys = @"hwr.local.letter;hwr.local.freestylus;hwr.local.associateword";
NSString *config = [NSString stringWithFormat:@"initCapKeys = %@,dataPath = %@", 
                    initCapKeys,dataPath];

常见errcode,详见灵云SDK开发手册

3.4 开启会话(session)

AFR 是通过会话(session)来管理识别过程的。在AFR能力初始化成功之后,需要通过开启识别会话来完成识别。详见灵云SDK开发手册

Android示例代码

// 开始会话
AfrConfig sessionConfig = new AfrConfig();
sessionConfig.addParam(AfrConfig.SessionConfig.PARAM_KEY_CAP_KEY, capkey);
ShowMessage("hciAfrSessionStart config: " + sessionConfig.getStringConfig());
Session session = new Session();
int errCode = HciCloudAfr.hciAfrSessionStart(sessionConfig.getStringConfig(), 
                                             session);
if (HciErrorCode.HCI_ERR_NONE != errCode) {
    ShowMessage("hciAfrSessionStart return " + errCode);
    return false;
}
ShowMessage("hciAfrSessionStart Success");

C++示例代码

int session_id = -1;
//用户模型路径,默认是授权文件路径
string session_config = "capkey=afr.local.recog,usermodelpath=e://";
HCI_ERR_CODE err_code = hci_afr_session_start(session_config.c_str(), 
                                              &session_id);
if( err_code != HCI_ERR_NONE )
{
    printf("hci_afr_session_start return (%d) \n",err_code);
    return;
}
printf( "hci_afr_session_start success\n" );

iOS示例代码

// 开启session
HCI_ERR_CODE errCode = HCI_ERR_NONE;
NSString *config = @"capKey=afr.local.recog";
int sessionID;            // 开启会话成功后,会返回的会话ID
errCode = hci_afr_session_start(config.UTF8String, &sessionID);
if (errCode != HCI_ERR_NONE){
    NSLog(@"hci_afr_session_start failed, error:%@", errCode);
    return NO;
}
NSLog(@"hci_afr_session_start success");
return YES;

3.5 人脸注册

在启动会话(session)成功后,即可可以进行 AFR的人脸注册。配置参数详见灵云SDK开发手册

Android示例代码

//设置检测图像
//buffer中为图像数据
errCode = HciCloudAfr.hciAfrSetImageBuffer(session, buffer);
if (HciErrorCode.HCI_ERR_NONE != errCode) {
    HciCloudAfr.hciAfrSessionStop(session);
    ShowMessage("hciAfrSetImageBuffer error.");
    return false;
}
// AFR检测
String detectConfig = "";
ArrayList<String> faceIds = new ArrayList<String>();
AfrDetectResult detectResult = new AfrDetectResult();
errCode = HciCloudAfr.hciAfrDetect(session, detectConfig, detectResult);
if (HciErrorCode.HCI_ERR_NONE != errCode) {
    ShowMessage("face detect error");
    return false;
}
for (AfrDetectFace face : detectResult.getFaceList()) {
    faceIds.add(face.getFaceId());
}

if (faceIds.size() > 0)
{
    //选择注册的faceid
    enrollConfig.addParam("faceid", faceIds.get(0));
    ShowMessage("faceid = "+faceIds.get(0));
}
//AFR注册
AfrEnrollResult result = new AfrEnrollResult();
errCode = HciCloudAfr.hciAfrEnroll(session,
        enrollConfig.getStringConfig(), result);
if (HciErrorCode.HCI_ERR_NONE != errCode) {
    HciCloudAfr.hciAfrSessionStop(session);
    ShowMessage("hciAfrEnroll return " + errCode);
    return false;
}

//释放检测结果
HciCloudAfr.hciAfrFreeDetectResult(detectResult);

C++示例代码

//AFR人脸检测
errCode = hci_afr_set_image_buffer(sessionId, file.buff_, file.buff_len_);
if (errCode != HCI_ERR_NONE)
{
    printf("failed to set image.\n");
    return errCode;
}
errCode = hci_afr_detect(sessionId, sessionConfig.c_str(), &detectResult);
if (errCode != HCI_ERR_NONE)
{
    printf("failed to detect face from image.\n");
    return errCode;
}
else
{
    PrintDetectResult(detectResult);
}
// 保存人脸检测结果用户ID列表。
for (int i = 0; i < detectResult.nFaceCount; i++)
{
    faceIds.push_back(detectResult.pFaceList[i].pszFaceId);
    printf("detect face id = %s\n", detectResult.pFaceList[i].pszFaceId);
}
//AFR 人脸注册
string enrollConfig;
enrollConfig += ",faceId=" + faceIds[0];
if (userId != "")
{
    enrollConfig += ",userId=" + userId;
}
printf("hci_afr_enroll config [%s]\n", enrollConfig.c_str());
AFR_ENROLL_RESULT enrollResult;
errCode = hci_afr_enroll(sessionId,enrollConfig.c_str(),&enrollResult);
if (errCode != HCI_ERR_NONE)
{
    printf("hci_afr_enroll return (%d) \n",errCode);
    return errCode;
}
userId = enrollResult.pszUserId;
hci_afr_free_enroll_result(&enrollResult);
// 释放人脸检测结果。
hci_afr_free_detect_result(&detectResult);

iOS示例代码

//设置检测的图像
NSString *fileName = @"face.jpg";       //待检测的图片地址
errCode = hci_afr_set_image_file(sessionID,fileName.UTF8String);
if (errCode != HCI_ERR_NONE){
    NSLog(@"failed to set image.");
    return;
}

//人脸检测
AFR_DETECT_RESULT result;
errCode = hci_afr_detect(sessionID,config.UTF8String,&result);
if (errCode != HCI_ERR_NONE){
    NSLog(@"failed to detect face from image.");
    return;
}

NSMutableArray *faceIds = [NSMutableArray array];
// 保存人脸检测结果用户ID列表。
for (int i = 0; i < result.nFaceCount; i++){
    NSString *faceId = [NSString stringWithFormat:@"%s",
                        result.pFaceList[i].pszFaceId];
    [faceIds addObject:faceId];    
    NSLog(@"detect face id = %s", result.pFaceList[i].pszFaceId);
}

if (!faceIds.count){
    NSLog(@"fail to detect face from image.");
    hci_afr_session_stop(sessionID);
    return;
}

hci_afr_free_detect_result(&result);

//人脸注册
//人脸ID必填,通过检测接口获取,多个faceid之间使用分号隔开,如123;456。
//目前支持使用1至3个人脸进行训练。
/*用户ID可选,字符串,最多64个字符,如abc123。注册成功时,结果返回userid;
若指定此参数,将覆盖该userid已存在的模型。*/
NSString *enrollConfig =  [NSString stringWithFormat:@"faceid=%@",faceIds[0]]; 
AFR_ENROLL_RESULT enrollResult;
errCode = hci_afr_enroll(sessionID,enrollConfig.UTF8String,&enrollResult);
if (errCode != HCI_ERR_NONE){
    NSLog(@"hci_afr_enroll return(%d)",errCode);
    hci_afr_session_stop(sessionID);
    return;
}
hci_afr_free_enroll_result(&enrollResult);

常见errcode,详见灵云SDK开发手册

3.6 人脸确认

Android示例代码

ArrayList<String> faceIds = new ArrayList<String>();
//加载人脸图片
byte[] buffer = HciCloudHelper.getAssetFileData(filename);
if (buffer.length == 0) {
    ShowMessage("Open input iamge file" + filename + "error!");
    return false;
}
//设置检测图像
errCode = HciCloudAfr.hciAfrSetImageBuffer(session, buffer);
if (HciErrorCode.HCI_ERR_NONE != errCode) {
    HciCloudAfr.hciAfrSessionStop(session);
    ShowMessage("hciAfrSetImageBuffer error.");
    return false;
}
//AFR检测
String detectConfig = "";
AfrDetectResult detectResult = new AfrDetectResult();
errCode = HciCloudAfr.hciAfrDetect(session, detectConfig, detectResult);
if (HciErrorCode.HCI_ERR_NONE != errCode) {
    ShowMessage("face detect error");
    return false;
}
printDetectResult(detectConfig,detectResult);
for (AfrDetectFace face : detectResult.getFaceList()) {
    faceIds.add(face.getFaceId());
}

if (faceIds.size() > 0)
{
    //选择验证的faceid
    verifyConfig.addParam("faceid", faceIds.get(0));
}
// 开始确认
ShowMessage("hciAfrVerify config:" + verifyConfig.getStringConfig());
errCode = HciCloudAfr.hciAfrVerify(session,
        verifyConfig.getStringConfig(), result);
if (HciErrorCode.HCI_ERR_NONE != errCode) {
    ShowMessage("Hciafr hciAfrVerify return " + errCode);
    HciCloudAfr.hciAfrSessionStop(session);
    return false;
}
ShowMessage("hciAfrVerify Success");
if (result.getStatus() == AfrVerifyResult.AFR_VERIFY_STATUS_MATCH) {
    ShowMessage("face data matches with user_id !");
} else {
    ShowMessage("face data doesn't match with user_id !");
}

// 释放检测结果。
HciCloudAfr.hciAfrFreeDetectResult(detectResult);

C++示例代码

// AFR人脸检测
err_code = hci_afr_set_image_buffer(sessionId, file.buff_, file.buff_len_);
if (err_code != HCI_ERR_NONE)
{
    printf("failed to set image.\n");
    break;
}
err_code = hci_afr_detect(sessionId, sessionConfig.c_str(), &detectResult);
if (err_code != HCI_ERR_NONE)
{
    printf("failed to detect face from image.\n");
    break;
}
else
{
    PrintDetectResult(detectResult);
}
//保存人脸检测结果用户ID列表。
for (int i = 0; i < detectResult.nFaceCount; i++)
{
    faceIds.push_back(detectResult.pFaceList[i].pszFaceId);
}

//Verify
string verifyConfig = "userid=" + userId;
verifyConfig += ",faceId=" + faceIds[0];
printf("hci_afr_verify config [%s]\n", verifyConfig.c_str());
AFR_VERIFY_RESULT verifyResult;
err_code = hci_afr_verify(sessionId, verifyConfig.c_str(), &verifyResult);
if( err_code != HCI_ERR_NONE )
{
    printf("hci_afr_verify return (%d) \n",err_code);
    break;
}
printf( "hci_afr_verify success\n" );
verifySuccess = true;
if (verifyResult.eStatus == AFR_VERIFY_STATUS_MATCH)
{
    printf( "face matches with user id:%s\n",userId.c_str() );
    printf("the result score is :%d\n",verifyResult.uiScore);
}
else
{
    printf("voice data doesn't match with user id:%s !\n",userId.c_str());
}    
isUserFace = verifyResult.eStatus == AFR_VERIFY_STATUS_MATCH;
hci_afr_free_verify_result(&verifyResult);

//释放人脸检测结果。
hci_afr_free_detect_result(&detectResult);

iOS示例代码

//设置检测的图像
NSString *fileName = @"face.jpg";       //待检测的图片地址
errCode = hci_afr_set_image_file(sessionID,fileName.UTF8String);
if (errCode != HCI_ERR_NONE){
    NSLog(@"failed to set image.");
    return;
}

//人脸检测
AFR_DETECT_RESULT result;
errCode = hci_afr_detect(sessionID,config.UTF8String,&result);
if (errCode != HCI_ERR_NONE){
    NSLog(@"failed to detect face from image.");
    return;
}

NSMutableArray *faceIds = [NSMutableArray array];
// 保存人脸检测结果用户ID列表。
for (int i = 0; i < detectResult.nFaceCount; i++){
    NSString *faceId = [NSString stringWithFormat:@"%s",
        detectResult.pFaceList[i].pszFaceId];
    [faceIds addObject:faceId];    
    NSLog(@"detect face id = %s", detectResult.pFaceList[i].pszFaceId);
}

if (!faceIds.count){
    NSLog(@"fail to detect face from image.");
    hci_afr_session_stop(sessionID);
    return;
}

//人脸确认
NSString *userId = @"abc123";
NSString *verifyConfig =  [NSString stringWithFormat:@"userId=%@,
    faceid=%@",userId,faceIds[0]]; 
AFR_VERIFY_RESULT verifyResult;
errCode = hci_afr_verify(sessionID, verifyConfig.UTF8String, &verifyResult);
if (errCode != HCI_ERR_NONE){
    NSLog(@"hci_afr_verify return(%d)",errCode);
    hci_afr_session_stop(sessionID);
    return;
}

if (verifyResult.eStatus == AFR_VERIFY_STATUS_MATCH){
    NSLog(@"face matches with user id:%@",userId );
    NSLog(@"the result score is :%d",verifyResult.uiScore);
}else{
    NSLog(@"voice data doesn't match with user id:%@ !",userId);
}

hci_afr_free_verify_result(&verifyResult);

常见errcode,详见灵云SDK开发手册

3.7 人脸辨识

Android示例代码

ArrayList<String> faceIds = new ArrayList<String>();

//加载人脸图片
byte[] buffer = HciCloudHelper.getAssetFileData(filename);
if (buffer.length == 0) {
    ShowMessage("Open input iamge file" + filename + "error!");
    return false;
}
//设置检测图像
errCode = HciCloudAfr.hciAfrSetImageBuffer(session, buffer);
if (HciErrorCode.HCI_ERR_NONE != errCode) {
    HciCloudAfr.hciAfrSessionStop(session);
    ShowMessage("hciAfrSetImageBuffer error.");
    return false;
}
//AFR检测
String detectConfig = "";
AfrDetectResult detectResult = new AfrDetectResult();
errCode = HciCloudAfr.hciAfrDetect(session, detectConfig, detectResult);
if (HciErrorCode.HCI_ERR_NONE != errCode) {
    ShowMessage("face detect error");
    return false;
}
printDetectResult(detectConfig,detectResult);
for (AfrDetectFace face : detectResult.getFaceList()) {
    faceIds.add(face.getFaceId());
}

if (faceIds.size() > 0)
{
    //选择识辨的faceid
    identifyConfig.addParam(AfrConfig.SessionConfig.PARAM_KEY_FACE_ID, 
                            faceIds.get(0));
}
//辨识
errCode = HciCloudAfr.hciAfrIdentify(session,
        identifyConfig.getStringConfig(), result);
if (HciErrorCode.HCI_ERR_NONE != errCode) {
    ShowMessage("Hciafr hciAfrIdentify return " + errCode);
    HciCloudAfr.hciAfrSessionStop(session);
    return false;
} else {
    //显示辨识结果
    for (AfrIdentifyResultItem item : result.getIdentifyResultItemList()) {
        String identifyInfo = String.format("identify user(%s,%d) in group(%s)\n",
                          item.getUserId(),
                          item.getScore(),
                          identifyConfig.getParam(AfrConfig
                                                 .UserConfig.PARAM_KEY_GROUP_ID));
        ShowMessage(identifyInfo);
    }
}

//释放检测结果。
HciCloudAfr.hciAfrFreeDetectResult(detectResult);

C++示例代码

//人脸检测
err_code = hci_afr_set_image_buffer(sessionId, file.buff_, file.buff_len_);
if (err_code != HCI_ERR_NONE)
{
    printf("failed to set image.\n");
    return err_code;
}

err_code = hci_afr_detect(sessionId, sessionConfig.c_str(), &detectResult);
if (err_code != HCI_ERR_NONE)
{
    printf("failed to detect face from image.\n");
    return err_code;
}
else
{
    PrintDetectResult(detectResult);
}

//保存人脸检测结果用户ID列表。
for (int i = 0; i < detectResult.nFaceCount; i++)
{
    faceIds.push_back(detectResult.pFaceList[i].pszFaceId);
}

string config = "groupId=" + groupId;
config += ",faceId=" + faceIds[0];

printf("hci_afr_verify config [%s]\n", config.c_str());

//人脸辨识
AFR_IDENTIFY_RESULT result;

err_code = hci_afr_identify(sessionId, config.c_str(), &result);
if( err_code != HCI_ERR_NONE )
{
    printf("hci_afr_identify return (%d) \n",err_code);
    return err_code;
}
else
{
    for (int i = 0; i < result.uiIdentifyResultItemCount; i++)
    {
        printf("identify result userid = %s, score = %d\n", 
            result.pIdentifyResultItemList[i].pszUserId, 
            result.pIdentifyResultItemList[i].uiScore);
    }
}

userId = result.pIdentifyResultItemList[0].pszUserId;
hci_afr_free_identify_result(&result);

// 释放人脸检测结果。
hci_afr_free_detect_result(&detectResult);

iOS示例代码

//设置检测的图像
NSString *fileName = @"face.jpg";       //待检测的图片地址
errCode = hci_afr_set_image_file(sessionID,fileName.UTF8String);
if (errCode != HCI_ERR_NONE){
    NSLog(@"failed to set image.");
    return;
}

//人脸检测
do{
    errCode = hci_afr_detect(sessionID, sessionConfig.UTF8String, &result);
    if (errCode != HCI_ERR_NONE){
        NSLog(@"failed to detect face from image.");
        break;
    }

    NSMutableArray *faceIds = [NSMutableArray array];
    // 保存人脸检测结果用户ID列表。
    for (int i = 0; i < detectResult.nFaceCount; i++){
        NSString *faceId = [NSString stringWithFormat:@"%s",
            detectResult.pFaceList[i].pszFaceId];
        [faceIds addObject:faceId];    
        NSLog(@"detect face id = %s", detectResult.pFaceList[i].pszFaceId);
    }

    if (!faceIds.count){
        NSLog(@"fail to detect face from image.");
        hci_afr_session_stop(sessionID);
        return;
    }

    //groupId可以通过创建用户组的方式获得,详见hci_create_group,hci_add_user函数
    NSString *config = [NSString stringWithFormat:@"groupId=%@,faceId=%@",@"xxxxx",
                       faceIds[0]];

    NSLog(@"hci_afr_verify config [%@]", config);

    // 人脸辨识
    AFR_IDENTIFY_RESULT result;
    errCode = hci_afr_identify(sessionID, config.UTF8String, &result);
    if( err_code != HCI_ERR_NONE){
        NSLog(@"hci_afr_identify return (%d)",errCode);
        break;
    }

    if (result.uiIdentifyResultItemCount == 0){
        NSLog(@"failed to identify");
        break;
    }else{
        for (int i = 0; i < result.uiIdentifyResultItemCount; i++){
            NSLog(@"identify result userid = %s, score = %d",
                    result.pIdentifyResultItemList[i].pszUserId,
                    result.pIdentifyResultItemList[i].uiScore);
        }
    }

    userId = result.pIdentifyResultItemList[0].pszUserId;
    NSLog(@"hci_afr_identify success");
    hci_afr_free_identify_result(&result);
} while (0);

常见errcode,详见灵云SDK开发手册

3.8 结束识别

最后我们需要反初始化,依次关闭会话,终止AFR能力,关闭灵云系统。

Android示例代码

//关闭AFR识别会话
errCode = HciCloudAfr.hciAfrSessionStop(session);
//终止AFR能力
errCode = HciCloudAfr.hciAfrRelease();
//终止灵云系统
errCode = HciCloudSys.hciRelease();

C++示例代码

//关闭AFR识别会话
errCode = hci_afr_session_stop(nSessionId);
//终止AFR能力
errCode = hci_afr_release();
//终止灵云系统
errCode = hci_release();

iOS示例代码

//关闭AFR识别会话
errCode = hci_afr_session_stop(nSessionId);
//终止AFR能力
errCode = hci_afr_release();
//终止灵云系统
errCode = hci_release();

4. FAQ

Q: 我运行你们的 SDK 报 19 号错误:START LOG FAILED, 应该如何解决? A: 出现此问题,一般由两种原因造成。

工程文件里引入了中文路径,导致SDK启动时,读写对应的日志路径报错。 日志文件定义的路径由于权限问题不可读写,比如在 Android 平台上运行时,没有 WRITE_EXTERNAL_STORAGE的权限。

Q: 我运行你们的 SDK 报 23 号错误:LOAD_FUNCTION_FROM_DLL FAILED,应该如何解决? A: 这种情况,通常是由于缺库。最常见的场景是使用本地能力的 capkey,如 afr.loacl.recog,没有将库文件对应组入(我们 SDK 示例程序,与 example 同层有全套库文件,示例程序内默认只组入了云端库),将相关库补齐即可使用。此外,由于 AFR能力引用了第三方的 MKL 库,因此如果第三方库没有拷入,也会导致此问题。

Q: 我运行你们的 SDK 报 14 号错误:LOCAL_RES_MISSING,应该如何解决? A: 本地能力常会遇到此问题,此问题是由于没有组入对应的本地资源文件。请在我们开发者社区下载需求的本地资源(VPR本地模型)等,并将资源文件组入代码 datapath 指定路径,然后再次尝试运行程序。

Q: 我运行你们的 SDK 报 11 号错误:SERVICE_RESPONSE_FAILED ,应该如何解决? A: 此问题原因较为复杂,可能是传入的参数问题与服务器不匹配,如调用私有云时,没有传入 property 等配置项。也可能是服务端内部的返回原因,请联系技术支持排查。

Q: 我运行你们的SDK报 7 号错误:CONFIG_UNSUPPORT ,应该如何解决? A: 与 11号错误类似,还是配置串问题,7 号错误原因为传入了不支持的配置串。请仔细检查各接口传入的所有配置串,并联系技术支持排查。

Q: 我运行你们的SDK报 9 号错误: SERVICE_TIMEOUT ,应该如何解决? A: 这个是因为您请求我们服务器到返回结果的时间,超过了上限。请检查网络环境相关的原因,并协助提供日志。

Q: 我运行你们的 SDK 报 16 号错误: SESSION_INVALID ,应该如何解决? A: 这个需要检查详细的代码调用过程,调用每个能力核心接口时,都是需要传入 sessionid 的,如果在 sessionstart 的时候,已经发生了错误,或者使用的id,并不是 sessionstart 时候创建的,就会返回此错误,请联系技术支持排查。

Q: 我运行你们的 SDK 报 0 号错误: ERROR NONE,应该如何解决? A: SDK 报 0 号错误, ERROR NONE,代表执行成功,请您继续后续的集成。

results matching ""

    No results matching ""