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

1.3 识别流程

2. 能力使用说明

2.1 准备工作

在集成 ASR 之前,开发者需要在灵云开发者社区创建相关应用,并保存appkey,developerkey等信息。

2.4 使用iOS版SDK

  • 必选模块

    • libcurl_device_simulator_iOS7.1.a
    • libhci_sys_device_simulator_iOS7.1.a
    • libhci_afr_device_simulator_iOS7.1.a
  • 云端识别

    • libhci_afr_cloud_recog_device_simulator_iOS7.1.a
  • 适配器选择

    • libhci_afr_only_cloud_adapter_device_simulator_iOS7.1.a(只使用云端能力)

3. 能力集成说明

3.1 通用模块初始化

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

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");
}

3.2 授权检测

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

  • 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初始化

  • 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;
    

3.4 开启会话(session)

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

  • 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的人脸注册。

  • 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);
    

3.6 人脸确认

  • 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);
    

3.7 人脸辨识

  • 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);
    

3.8 结束识别

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

  • 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 ""