从零玩转人脸识别之RGB人脸活体检测2

简介: 从零玩转人脸识别之RGB人脸活体检测

二、改造ArcFace工程

效果图

image-20210702145621981.pngimage-20210702150025572.png

1. 创建FaceRecognitionUtils

package top.yangbuyi.utils;
import com.arcsoft.face.*;
import com.arcsoft.face.enums.*;
import com.arcsoft.face.toolkit.ImageFactory;
import com.arcsoft.face.toolkit.ImageInfo;
import com.arcsoft.face.toolkit.ImageInfoEx;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
 * @program: ArcFace
 * @ClassName: FaceRecognitionUtils
 * @create: 2021-07-01 11:00
 * @author: Yang shuai
 * @FaceRecognitionUtils: 人脸识别简易版$实现人脸检测活体是否为人脸,追踪人脸
 **/
public class FaceRecognitionUtils {
  /**
   * APP ID,请先在虹软开发者中心注册、认证之后创建应用获取
   */
  @Value("crm.appId")
  private static String APP_ID = "";
  /**
   * SDK KEY,请先在虹软开发者中心注册、认证之后创建应用获取
   */
  @Value("crm.sdk")
  private static String SDK_KEY = "";
  /**
   * dll插件库地址
   * linx 和 win 是不一样的
   */
  @Value("crm.face")
  private static String FACE_ENGINE = "WIN64";
  private final static Logger logger = LogManager.getLogger(FaceRecognitionUtils.class.getName());
  // 人脸引擎
  private static FaceEngine faceEngine = new FaceEngine(FACE_ENGINE);
  // 创建引擎功能对象(用于初始化引擎)
  private static FunctionConfiguration functionConfiguration1 = new FunctionConfiguration();
  // 创建引擎功能对象(用于人脸检测)
  private static FunctionConfiguration functionConfiguration2 = new FunctionConfiguration();
  static {
    // 初始化引擎功能(用于初始化引擎)
    {
      // 是否支持年龄检测功能
      functionConfiguration1.setSupportAge(true);
      // 是否支持3D检测功能
      functionConfiguration1.setSupportFace3dAngle(true);
      // 是否支持人脸检测功能
      functionConfiguration1.setSupportFaceDetect(true);
      // 是否支持人脸识别功能
      functionConfiguration1.setSupportFaceRecognition(true);
      // 是否支持性别检测功能
      functionConfiguration1.setSupportGender(true);
      // 是否支持RGB活体检测功能
      functionConfiguration1.setSupportLiveness(true);
      // 是否支持IR活体检测功能
      functionConfiguration1.setSupportIRLiveness(true);
    }
    // 初始化引擎功能(用于人脸检测)
    {
      // 是否支持年龄检测功能
      functionConfiguration2.setSupportAge(true);
      // 是否支持3D检测功能
      functionConfiguration2.setSupportFace3dAngle(true);
      // 是否支持性别检测功能
      functionConfiguration2.setSupportGender(true);
      // 是否支持RGB活体检测功能
      functionConfiguration2.setSupportLiveness(true);
    }
  }
  /**
   * 在线激活SDK
   *
   * @return
   */
  public static void sdkActivation() {
    int errorCode = faceEngine.activeOnline(APP_ID, SDK_KEY);
    if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
      // SDK激活失败
      logger.error("在线激活SDK失败!错误码:" + errorCode);
    } else {
      // SDK激活成功
      logger.info("在线激活SDK成功!");
    }
  }
  /**
   * 初始化引擎
   *
   * @param detectMode   检测模式(推荐IMAGE 模式)
   * @param detectOrient 人脸检测角度(推荐人脸检测角度,逆时针0度)
   * @param faceMaxNum   人脸检测最大数量(推荐10)
   * @param faceScaleVal 最小人脸比例(VIDEO模式推荐16;IMAGE模式推荐32)
   */
  public static void InitializeTheEngine(DetectMode detectMode, DetectOrient detectOrient, int faceMaxNum, int faceScaleVal) {
    // 创建引擎配置类
    EngineConfiguration engineConfiguration = new EngineConfiguration();
    // 设置detectMode参数
    engineConfiguration.setDetectMode(detectMode);
    // 设置detectFaceOrientPriority参数
    engineConfiguration.setDetectFaceOrientPriority(detectOrient);
    // 设置人脸检测最大数量
    engineConfiguration.setDetectFaceMaxNum(faceMaxNum);
    // 设置detectFaceScaleVal参数为:识别的最小人脸比例 = 图片长边 / 人脸框长边的比值
    engineConfiguration.setDetectFaceScaleVal(faceScaleVal);
    // 配置引擎功能
    engineConfiguration.setFunctionConfiguration(functionConfiguration1);
    // 检测角度
//    engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
    // 初始化引擎
    int errorCode = faceEngine.init(engineConfiguration);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 引擎初始化失败
      logger.error("引擎初始化失败!错误码:" + errorCode);
    } else {
      // 引擎初始化成功
      logger.info("引擎初始化成功!");
    }
  }
  /**
   * 人脸检测(传入分离的图像信息数据)
   *
   * @param imageInfo    图像信息
   * @param faceInfoList 人脸信息列表
   * @return 检测结果,检测成功或是失败!
   */
  public static boolean faceDetection1(ImageInfo imageInfo, List<FaceInfo> faceInfoList) {
    int errorCode = faceEngine.detectFaces(imageInfo.getImageData(),
        imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(),
        faceInfoList);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 人脸检测失败
      logger.error("人脸检测失败!错误码:" + errorCode);
      return false;
    } else {
      // 人脸检测成功
      logger.info("人脸检测成功!");
      return true;
    }
  }
  /**
   * 人脸检测(传入ImageInfoEx图像信息数据)
   *
   * @param imageInfo    图像信息
   * @param faceInfoList 人脸信息列表
   * @return 检测结果,检测成功或是失败!
   */
  public static boolean faceDetection2(ImageInfo imageInfo, List<FaceInfo> faceInfoList) {
    ImageInfoEx imageInfoEx = new ImageInfoEx();
    imageInfoEx.setHeight(imageInfo.getHeight());
    imageInfoEx.setWidth(imageInfo.getWidth());
    imageInfoEx.setImageFormat(imageInfo.getImageFormat());
    imageInfoEx.setImageDataPlanes(new byte[][]{imageInfo.getImageData()});
    imageInfoEx.setImageStrides(new int[]{imageInfo.getWidth() * 3});
    int errorCode = faceEngine.detectFaces(imageInfoEx,
        DetectModel.ASF_DETECT_MODEL_RGB, faceInfoList);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 人脸检测失败
      logger.error("人脸检测失败!错误码:" + errorCode);
      return false;
    } else {
      // 人脸检测成功
      logger.info("人脸检测成功!");
      return true;
    }
  }
  /**
   * 人脸特征提取,是否检测到人脸
   *
   * @param imageInfo
   * @return
   */
  public static byte[] extractFaceFeature(ImageInfo imageInfo) {
    try {
      //人脸检测得到人脸列表
      List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
      //人脸检测
      int i = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
      if (faceInfoList.size() > 0) {
        FaceFeature faceFeature = new FaceFeature();
        //提取人脸特征
        faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
        return faceFeature.getFeatureData();
      }
    } catch (Exception e) {
      logger.error("", e);
    }
    return null;
  }
  /**
   * 人脸特征提取(传入分离的图像信息数据)
   *
   * @param imageInfo 图像信息
   * @param faceInfo  人脸信息
   * @return 人脸特征
   */
  public static FaceFeature faceFeatureExtraction1(ImageInfo imageInfo, FaceInfo faceInfo) {
    FaceFeature faceFeature = new FaceFeature();
    int errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(),
        imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(),
        faceInfo, faceFeature);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 人脸特征提取失败
      logger.error("人脸特征提取失败!错误码:" + errorCode);
      return null;
    } else {
      // 人脸特征提取成功
      logger.info("人脸特征提取成功!");
      return faceFeature;
    }
  }
  /**
   * 人脸特征提取(传入ImageInfoEx图像信息数据)
   *
   * @param imageInfo 图像信息
   * @param faceInfo  人脸信息
   * @return 人脸特征
   */
  public static FaceFeature faceFeatureExtraction2(ImageInfo imageInfo, FaceInfo faceInfo) {
    ImageInfoEx imageInfoEx = new ImageInfoEx();
    imageInfoEx.setHeight(imageInfo.getHeight());
    imageInfoEx.setWidth(imageInfo.getWidth());
    imageInfoEx.setImageFormat(imageInfo.getImageFormat());
    imageInfoEx.setImageDataPlanes(new byte[][]{imageInfo.getImageData()});
    imageInfoEx.setImageStrides(new int[]{imageInfo.getWidth() * 3});
    // 创建人脸特征对象
    FaceFeature faceFeature = new FaceFeature();
    int errorCode = faceEngine.extractFaceFeature(imageInfoEx, faceInfo, faceFeature);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 人脸特征提取失败
      logger.error("人脸特征提取失败!错误码:" + errorCode);
      return null;
    } else {
      // 人脸特征提取成功
      logger.info("人脸特征提取成功!");
      return faceFeature;
    }
  }
  /**
   * 人脸特征比对
   *
   * @param targetFaceFeature 目标人脸特征
   * @param sourceFaceFeature 来源人脸特征
   * @param compareModel      比对模型
   * @return 比对相似度
   */
  public static Float faceFeatureComparison(FaceFeature targetFaceFeature, FaceFeature sourceFaceFeature, CompareModel compareModel) {
    // 创建比对相似度对象
    FaceSimilar faceSimilar = new FaceSimilar();
    int errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, compareModel, faceSimilar);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 人脸特征比对失败
      logger.error("人脸特征比对失败!错误码:" + errorCode);
      return null;
    } else {
      // 人脸特征比对成功
      logger.info("人脸特征比对成功!");
      return faceSimilar.getScore();
    }
  }
  /**
   * 人脸特征比对(默认LIFE_PHOTO比对模型)
   *
   * @param targetFaceFeature 目标人脸特征
   * @param sourceFaceFeature 来源人脸特征
   * @return 比对相似度
   */
  public static Float faceFeatureComparison(FaceFeature targetFaceFeature, FaceFeature sourceFaceFeature) {
    // 创建比对相似度对象
    FaceSimilar faceSimilar = new FaceSimilar();
    int errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature,
        faceSimilar);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 人脸特征比对失败
      logger.error("人脸特征比对失败!错误码:" + errorCode);
      return null;
    } else {
      // 人脸特征比对成功
      logger.info("人脸特征比对成功!");
      return faceSimilar.getScore();
    }
  }
  /**
   * 人脸属性检测(传入分离的图像信息数据)
   *
   * @param imageInfo    图像信息
   * @param faceInfoList 人脸信息列表
   * @return 检测结果,检测成功或是失败!
   */
  public static boolean faceAttributeDetection1(ImageInfo imageInfo, List<FaceInfo> faceInfoList) {
    int errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(),
        imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, functionConfiguration2);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 人脸属性检测失败
      logger.error("人脸属性检测失败!错误码:" + errorCode);
      return false;
    } else {
      // 人脸属性检测成功
      logger.info("人脸属性检测成功!");
      return true;
    }
  }
  /**
   * 人脸属性检测(传入ImageInfoEx图像信息数据)
   *
   * @param imageInfo    图像信息
   * @param faceInfoList 人脸信息列表
   * @return 检测结果,检测成功或是失败!
   */
  public static boolean faceAttributeDetection2(ImageInfo imageInfo, List<FaceInfo> faceInfoList) {
    ImageInfoEx imageInfoEx = new ImageInfoEx();
    imageInfoEx.setHeight(imageInfo.getHeight());
    imageInfoEx.setWidth(imageInfo.getWidth());
    imageInfoEx.setImageFormat(imageInfo.getImageFormat());
    imageInfoEx.setImageDataPlanes(new byte[][]{imageInfo.getImageData()});
    imageInfoEx.setImageStrides(new int[]{imageInfo.getWidth() * 3});
    int errorCode = faceEngine.process(imageInfoEx, faceInfoList,
        functionConfiguration2);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 人脸属性检测失败
      logger.error("人脸属性检测失败!错误码:" + errorCode);
      return false;
    } else {
      // 人脸属性检测成功
      logger.info("人脸属性检测成功!");
      return true;
    }
  }
  /**
   * 获取年龄信息
   * 注意:人脸属性检测之后方可调用
   *
   * @return 获取结果,获取失败或是成功!
   */
  public static boolean getAgeInfo(List<AgeInfo> ageInfoList) {
    int errorCode = faceEngine.getAge(ageInfoList);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 获取年龄信息失败
      logger.error("获取年龄信息失败!错误码:" + errorCode);
      return false;
    } else {
      // 已成功获取年龄信息
      logger.info("已成功获取年龄信息!");
      return true;
    }
  }
  /**
   * 获取性别(0为男性,1为女性。)
   * 注意:人脸属性检测之后方可调用
   *
   * @return 获取结果,获取失败或是成功!
   */
  public static boolean getGender(List<GenderInfo> genderInfoList) {
    // 性别检测
    int errorCode = faceEngine.getGender(genderInfoList);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 获取性别失败
      logger.error("获取性别失败!错误码:" + errorCode);
      return false;
    } else {
      // 已成功获取年龄信息
      logger.info("已成功获取性别!");
      return true;
    }
  }
  /**
   * 获取人脸三维角度信息
   * 人脸3D角度:俯仰角(pitch), 横滚角(roll), 偏航角(yaw)。
   * 注意:人脸属性检测之后方可调用
   *
   * @return 获取结果,获取失败或是成功!
   */
  public static boolean getFace3DAngle(List<Face3DAngle> face3DAngleList) {
    // 人脸三维角度检测
    int errorCode = faceEngine.getFace3DAngle(face3DAngleList);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 获取人脸三维角度信息失败
      logger.error("获取人脸三维角度信息失败!错误码:" + errorCode);
      return false;
    } else {
      // 已成功获取人脸三维角度信息
      logger.info("已成功获取人脸三维角度信息!");
      return true;
    }
  }
  /**
   * 获取RGB活体信息
   * RGB活体值,未知=-1 、非活体=0 、活体=1、超出人脸=-2
   * 注意:人脸属性检测之后方可调用
   *
   * @return 获取结果,获取失败或是成功!
   */
  public static boolean getLiveness(List<LivenessInfo> livenessInfoList) {
    // RGB活体检测
    int errorCode = faceEngine.getLiveness(livenessInfoList);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 获取RGB活体信息失败
      logger.error("获取RGB活体信息失败!错误码:" + errorCode);
      return false;
    } else {
      // 已成功获取RGB活体信息
      logger.info("已成功获取RGB活体信息!");
      return true;
    }
  }
  private static String base64Process(String base64Str) {
    if (!StringUtils.isEmpty(base64Str)) {
      String photoBase64 = base64Str.substring(0, 30).toLowerCase();
      int indexOf = photoBase64.indexOf("base64,");
      if (indexOf > 0) {
        base64Str = base64Str.substring(indexOf + 7);
      }
      return base64Str;
    } else {
      return "";
    }
  }
  /**
   * IR活体检测(传入分离的图像信息数据)
   * 注意:
   * 引擎需要支持IR活体检测功能
   *
   * @return 检测结果,检测成功或是失败!
   */
  public static boolean detectionLiveness_IR1(String string) throws IOException {
    // 创建图像信息
//    ImageInfo imageInfoGray = getGrayData(file);
    byte[] decode = Base64.decode(base64Process(string));
    BufferedImage bufImage = ImageIO.read(new ByteArrayInputStream(decode));
    ImageInfo imageInfoGray = ImageFactory.bufferedImage2ImageInfo(bufImage);
    // 创建人脸信息列表
    List<FaceInfo> faceInfoListGray = new ArrayList<FaceInfo>();
    // 人脸检测(传入分离的图像信息数据)
    int errorCode1 = faceEngine.detectFaces(imageInfoGray.getImageData(),
        imageInfoGray.getWidth(), imageInfoGray.getHeight(),
        imageInfoGray.getImageFormat(), faceInfoListGray);
    // 创建引擎功能实例对象
    FunctionConfiguration configuration = new FunctionConfiguration();
    // 设置引擎支持IR活体检测
    configuration.setSupportIRLiveness(true);
    // IR活体检测
    int errorCode2 = faceEngine.processIr(imageInfoGray.getImageData(),
        imageInfoGray.getWidth(), imageInfoGray.getHeight(),
        imageInfoGray.getImageFormat(), faceInfoListGray, configuration);
    if (errorCode1 != ErrorInfo.MOK.getValue() || errorCode2 != ErrorInfo.MOK.getValue()) {
      String errorCode = errorCode1 == 0 ? errorCode2 + "" : errorCode1 + "";
      // IR活体检测失败
      logger.error("IR活体检测失败!错误码:" + errorCode);
      return false;
    } else {
      // IR活体检测成功
      logger.info("IR活体检测成功!");
      return true;
    }
  }
  /**
   * IR活体检测(传入ImageInfoEx图像信息数据)
   * 注意:
   * 引擎需要支持年龄检测功能
   *
   * @param imageInfo 图像信息
   * @return 检测结果,检测成功或是失败!
   */
  public static boolean detectionLiveness_IR2(ImageInfo imageInfo) {
    ImageInfoEx imageInfoEx = new ImageInfoEx();
    imageInfoEx.setHeight(imageInfo.getHeight());
    imageInfoEx.setWidth(imageInfo.getWidth());
    imageInfoEx.setImageFormat(imageInfo.getImageFormat());
    imageInfoEx.setImageDataPlanes(new byte[][]{imageInfo.getImageData()});
    imageInfoEx.setImageStrides(new int[]{imageInfo.getWidth() * 3});
    List<FaceInfo> faceInfoList1 = new ArrayList<>();
    int errorCode1 = faceEngine.detectFaces(imageInfoEx,
        DetectModel.ASF_DETECT_MODEL_RGB, faceInfoList1);
    FunctionConfiguration fun = new FunctionConfiguration();
    fun.setSupportAge(true);
    int errorCode2 = faceEngine.processIr(imageInfoEx, faceInfoList1,
        fun);
    if (errorCode1 != ErrorInfo.MOK.getValue() || errorCode2 != ErrorInfo.MOK.getValue()) {
      String errorCode = errorCode1 == 0 ? errorCode2 + "" : errorCode1 + "";
      // IR活体检测失败
      logger.error("IR活体检测失败!错误码:" + errorCode);
      return false;
    } else {
      // IR活体检测成功
      logger.info("IR活体检测成功!");
      return true;
    }
  }
  /**
   * 获取IR活体信息
   * IR活体值,未知=-1 、非活体=0 、活体=1、超出人脸=-2
   *
   * @return 获取结果,获取失败或是成功!
   */
  public static boolean getIrLiveness(List<IrLivenessInfo> irLivenessInfo) {
    // IR活体检测
    int errorCode = faceEngine.getLivenessIr(irLivenessInfo);
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 获取IR活体信息失败
      logger.error("获取IR活体信息失败!错误码:" + errorCode);
      return false;
    } else {
      // 已成功获取IR活体信息
      logger.info("已成功获取IR活体信息!");
      return true;
    }
  }
  /**
   * 销毁SDK引擎
   */
  public static void destroyTheSDKEngine() {
    int errorCode = faceEngine.unInit();
    if (errorCode != ErrorInfo.MOK.getValue()) {
      // 销毁SDK引擎失败
      logger.error("销毁SDK引擎失败!错误码:" + errorCode);
    } else {
      // 销毁SDK引擎成功
      logger.info("销毁SDK引擎成功!");
    }
  }
}

2.创建ErrorCodeEnum

package top.yangbuyi.constant;
/**
 * 错误代码枚举
 *
 * @author yang buyi
 * @date 2021/07/02
 */
public enum ErrorCodeEnum {
  MOK(0, "成功"),
  UNKNOWN(1, "未知错误"),
  INVALID_PARAM(2, "无效参数"),
  UNSUPPORTED(3, "引擎不支持"),
  NO_MEMORY(4, "内存不足"),
  BAD_STATE(5, "状态错误"),
  USER_CANCEL(6, "用户取消相关操作"),
  EXPIRED(7, "操作时间过期"),
  USER_PAUSE(8, "用户暂停操作"),
  BUFFER_OVERFLOW(9, "缓冲上溢"),
  BUFFER_UNDERFLOW(10, "缓冲下溢"),
  NO_DISKSPACE(11, "存贮空间不足"),
  COMPONENT_NOT_EXIST(12, "组件不存在"),
  GLOBAL_DATA_NOT_EXIST(13, "全局数据不存在"),
  NO_FACE_DETECTED(14, "未检出到人脸"),
  FACE_DOES_NOT_MATCH(15, "人脸不匹配"),
  INVALID_APP_ID(28673, "无效的AppId"),
  INVALID_SDK_ID(28674, "无效的SdkKey"),
  INVALID_ID_PAIR(28675, "AppId和SdkKey不匹配"),
  MISMATCH_ID_AND_SDK(28676, "SdkKey 和使用的SDK 不匹配"),
  SYSTEM_VERSION_UNSUPPORTED(28677, "系统版本不被当前SDK所支持"),
  LICENCE_EXPIRED(28678, "SDK有效期过期,需要重新下载更新"),
  APS_ENGINE_HANDLE(69633, "引擎句柄非法"),
  APS_MEMMGR_HANDLE(69634, "内存句柄非法"),
  APS_DEVICEID_INVALID(69635, " Device ID 非法"),
  APS_DEVICEID_UNSUPPORTED(69636, "Device ID 不支持"),
  APS_MODEL_HANDLE(69637, "模板数据指针非法"),
  APS_MODEL_SIZE(69638, "模板数据长度非法"),
  APS_IMAGE_HANDLE(69639, "图像结构体指针非法"),
  APS_IMAGE_FORMAT_UNSUPPORTED(69640, "图像格式不支持"),
  APS_IMAGE_PARAM(69641, "图像参数非法"),
  APS_IMAGE_SIZE(69642, "图像尺寸大小超过支持范围"),
  APS_DEVICE_AVX2_UNSUPPORTED(69643, "处理器不支持AVX2指令"),
  FR_INVALID_MEMORY_INFO(73729, "无效的输入内存"),
  FR_INVALID_IMAGE_INFO(73730, "无效的输入图像参数"),
  FR_INVALID_FACE_INFO(73731, "无效的脸部信息"),
  FR_NO_GPU_AVAILABLE(73732, "当前设备无GPU可用"),
  FR_MISMATCHED_FEATURE_LEVEL(73733, "待比较的两个人脸特征的版本不一致"),
  FACEFEATURE_UNKNOWN(81921, "人脸特征检测错误未知"),
  FACEFEATURE_MEMORY(81922, "人脸特征检测内存错误"),
  FACEFEATURE_INVALID_FORMAT(81923, "人脸特征检测格式错误"),
  FACEFEATURE_INVALID_PARAM(81924, "人脸特征检测参数错误"),
  FACEFEATURE_LOW_CONFIDENCE_LEVEL(81925, "人脸特征检测结果置信度低"),
  ASF_EX_BASE_FEATURE_UNSUPPORTED_ON_INIT(86017, "Engine不支持的检测属性"),
  ASF_EX_BASE_FEATURE_UNINITED(86018, "需要检测的属性未初始化"),
  ASF_EX_BASE_FEATURE_UNPROCESSED(86019, "待获取的属性未在process中处理过"),
  ASF_EX_BASE_FEATURE_UNSUPPORTED_ON_PROCESS(86020, "PROCESS不支持的检测属性,例如FR,有自己独立的处理函数"),
  ASF_EX_BASE_INVALID_IMAGE_INFO(86021, "无效的输入图像"),
  ASF_EX_BASE_INVALID_FACE_INFO(86022, "无效的脸部信息"),
  ASF_BASE_ACTIVATION_FAIL(90113, "人脸比对SDK激活失败,请打开读写权限"),
  ASF_BASE_ALREADY_ACTIVATED(90114, "人脸比对SDK已激活"),
  ASF_BASE_NOT_ACTIVATED(90115, "人脸比对SDK未激活"),
  ASF_BASE_SCALE_NOT_SUPPORT(90116, "detectFaceScaleVal 不支持"),
  ASF_BASE_VERION_MISMATCH(90117, "SDK版本不匹配"),
  ASF_BASE_DEVICE_MISMATCH(90118, "设备不匹配"),
  ASF_BASE_UNIQUE_IDENTIFIER_MISMATCH(90119, "唯一标识不匹配"),
  ASF_BASE_PARAM_NULL(90120, "参数为空"),
  ASF_BASE_SDK_EXPIRED(90121, "SDK已过期"),
  ASF_BASE_VERSION_NOT_SUPPORT(90122, "版本不支持"),
  ASF_BASE_SIGN_ERROR(90123, "签名错误"),
  ASF_BASE_DATABASE_ERROR(90124, "数据库插入错误"),
  ASF_BASE_UNIQUE_CHECKOUT_FAIL(90125, "唯一标识符校验失败"),
  ASF_BASE_COLOR_SPACE_NOT_SUPPORT(90126, "输入的颜色空间不支持"),
  ASF_BASE_IMAGE_WIDTH_NOT_SUPPORT(90127, "输入图像的byte数据长度不正确"),
  ASF_NETWORK_BASE_COULDNT_RESOLVE_HOST(94209, "无法解析主机地址"),
  ASF_NETWORK_BASE_COULDNT_CONNECT_SERVER(94210, "无法连接服务器"),
  ASF_NETWORK_BASE_CONNECT_TIMEOUT(94211, "网络连接超时"),
  ASF_NETWORK_BASE_UNKNOWN_ERROR(94212, "未知错误");
  private Integer code;
  private String description;
  ErrorCodeEnum(Integer code, String description) {
    this.code = code;
    this.description = description;
  }
  public Integer getCode() {
    return code;
  }
  public void setCode(Integer code) {
    this.code = code;
  }
  public String getDescription() {
    return description;
  }
  public void setDescription(String description) {
    this.description = description;
  }
  public static ErrorCodeEnum getDescriptionByCode(Integer code) {
    for (ErrorCodeEnum errorCodeEnum : ErrorCodeEnum.values()) {
      if (code.equals(errorCodeEnum.getCode())) {
        return errorCodeEnum;
      }
    }
    return ErrorCodeEnum.UNKNOWN;
  }
}

3.创建ArcFaceController

package top.yangbuyi.controller;
import com.arcsoft.face.*;
import com.arcsoft.face.enums.DetectMode;
import com.arcsoft.face.enums.DetectOrient;
import com.arcsoft.face.toolkit.ImageFactory;
import com.arcsoft.face.toolkit.ImageInfo;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import top.yangbuyi.constant.ErrorCodeEnum;
import top.yangbuyi.utils.FaceRecognitionUtils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @program: ArcFace
 * @ClassName: ArcFaceController
 * @create: 2021-07-01 14:30
 * @author: Yang Shuai
 * @since: JDK1.8
 * @ArcFaceController: 人脸活体检测$
 **/
@RestController
@Slf4j
@RequestMapping("arcFace")
public class ArcFaceController {
  /**
   * 人脸识别检测
   *
   * @param url base64 地址
   * @param oId 组织架构 ID
   * @param uid 当前登录检测的用户ID
   * @return
   */
  @RequestMapping(value = "arcFaceSearch", method = RequestMethod.POST)
  public Map arcFaceSearch(@RequestParam String url, @RequestParam Integer oId, @RequestParam Integer uid) {
    // 前端展示原图
    String urlTemp = url;
    // ...业务
    final HashMap<String, Object> stringObjectHashMap = new HashMap<>(14);
    stringObjectHashMap.put("success", false);
    // 初始化引擎
    FaceRecognitionUtils.InitializeTheEngine(DetectMode.ASF_DETECT_MODE_IMAGE, DetectOrient.ASF_OP_0_ONLY, 10, 32);
    if (!StringUtils.isEmpty(url)) {
      String photoBase64 = url.substring(0, 30).toLowerCase();
      int indexOf = photoBase64.indexOf("base64,");
      if (indexOf > 0) {
        url = url.substring(indexOf + 7);
      }
      // 开始转码
      byte[] decode = Base64.decode(url);
      BufferedImage bufImage = null;
      try {
        bufImage = ImageIO.read(new ByteArrayInputStream(decode));
      } catch (IOException e) {
        e.printStackTrace();
        return stringObjectHashMap;
      }
      // 获取图片信息
      ImageInfo imageInfo = ImageFactory.bufferedImage2ImageInfo(bufImage);
      //人脸特征获取
      byte[] bytes = FaceRecognitionUtils.extractFaceFeature(imageInfo);
      // 校验是否显示出人脸
      if (bytes == null) {
        System.out.println(ErrorCodeEnum.NO_FACE_DETECTED.getDescription());
        stringObjectHashMap.put("msg", ErrorCodeEnum.NO_FACE_DETECTED.getDescription());
        return stringObjectHashMap;
      }
      // 创建图像中的人脸信息对象列表
      List<FaceInfo> faceInfoList1 = new ArrayList<>();
      // 检测图像中人脸
      FaceRecognitionUtils.faceDetection1(imageInfo, faceInfoList1);
      // 检测图像中人脸属性
      FaceRecognitionUtils.faceAttributeDetection1(imageInfo, faceInfoList1);
      // 检测人脸特征
      /* 图像中的人脸年龄 */
      {
        // 创建图像中的人脸年龄列表
        List<AgeInfo> ageInfoList1 = new ArrayList<>();
        // 检测图像中的人脸年龄列表
        FaceRecognitionUtils.getAgeInfo(ageInfoList1);
        // 将图像中的年龄列表打印到控制台
        if (ageInfoList1.size() > 0) {
          stringObjectHashMap.put("age", ageInfoList1.get(0).getAge());
        }
      }
      /* 图像中的人脸性别 */
      // 创建图像中的人脸性别列表
      List<GenderInfo> genderInfoList1 = new ArrayList<>();
      // 检测图像中的人脸性别列表
      FaceRecognitionUtils.getGender(genderInfoList1);
      // 将图像中的性别列表打印到控制台
      if (genderInfoList1.size() > 0) {
        stringObjectHashMap.put("gender", genderInfoList1.get(0).getGender() == 0 ? "男" : "女");
      }
      /* 图像1中的人脸三维角度 */
      // 创建图像中的人脸三维角度信息列表
      List<Face3DAngle> face3DAngleList1 = new ArrayList<>();
      // 获取图像1中的人脸三维角度信息列表
      FaceRecognitionUtils.getFace3DAngle(face3DAngleList1);
      // 将图像中的人脸三维角度信息列表打印到控制台
      if (face3DAngleList1.size() > 0) {
        List<Map<String, Object>> td = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        map.put("俯仰角", face3DAngleList1.get(0).getPitch());
        map.put("横滚角", face3DAngleList1.get(0).getRoll());
        map.put("偏航角", face3DAngleList1.get(0).getYaw());
        td.add(map);
        stringObjectHashMap.put("ThreeDimensional", td);
      }
      /* 图像1中的人脸RGB活体值 */
      // 创建图像中的RGB活体信息列表
      List<LivenessInfo> livenessInfoList1 = new ArrayList<>();
      // 获取图像1中的RGB活体信息列表
      FaceRecognitionUtils.getLiveness(livenessInfoList1);
      // 将图像中的RGB活体信息列表打印到控制台
      if (livenessInfoList1.size() > 0) {
        stringObjectHashMap.put("RgbLiveness", livenessInfoList1.get(0).getLiveness());
      }
      /**
       * 注意: 活体只能支持一个人脸否则返回未知
       * 所以我们可以进行使用他来判断是否有多个人检测 直接判定失败
       */
      if (livenessInfoList1.size() > 0 && livenessInfoList1.get(0).getLiveness() == 1) {
        stringObjectHashMap.put("success", true);
        stringObjectHashMap.put("baseUrl", urlTemp);
      }
    } else {
      stringObjectHashMap.put("data", "url,不允许为空");
    }
    return stringObjectHashMap;
  }
}

4. 创建路由跳转前端页面 RouteController

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
/**
 * @program: ArcFace
 * @ClassName: RouteController
 * @create: 2021-07-02 09:14
 * @author: Yang Shuai
 * @since: JDK1.8
 * @RouteController: $
 **/
@Controller
public class RouteController {
  @GetMapping("/")
  public String yby() {
      // ...业务
      return "index";
  }
}


相关文章
|
6月前
|
JSON 安全 Java
人脸识别活体检测之张张嘴和眨眨眼
人脸识别活体检测之张张嘴和眨眨眼
|
4月前
|
机器学习/深度学习 监控 算法框架/工具
使用Python实现深度学习模型:人脸识别与人脸表情分析
【7月更文挑战第18天】 使用Python实现深度学习模型:人脸识别与人脸表情分析
215 2
|
5月前
|
机器学习/深度学习 数据采集 监控
人脸识别与检测
人脸识别与检测
96 4
|
5月前
|
移动开发 文字识别 算法
视觉智能开放平台产品使用合集之人脸核身是否包含静默活体检测
视觉智能开放平台是指提供一系列基于视觉识别技术的API和服务的平台,这些服务通常包括图像识别、人脸识别、物体检测、文字识别、场景理解等。企业或开发者可以通过调用这些API,快速将视觉智能功能集成到自己的应用或服务中,而无需从零开始研发相关算法和技术。以下是一些常见的视觉智能开放平台产品及其应用场景的概览。
|
5月前
|
文字识别 算法 API
视觉智能开放平台产品使用合集之活体检测通过后,从返回结果中选择哪张图片进行人脸核身
视觉智能开放平台是指提供一系列基于视觉识别技术的API和服务的平台,这些服务通常包括图像识别、人脸识别、物体检测、文字识别、场景理解等。企业或开发者可以通过调用这些API,快速将视觉智能功能集成到自己的应用或服务中,而无需从零开始研发相关算法和技术。以下是一些常见的视觉智能开放平台产品及其应用场景的概览。
|
5月前
|
机器学习/深度学习 监控 固态存储
人脸识别与检测
人脸识别与检测
52 0
|
6月前
|
计算机视觉
人脸识别活体检测之张张嘴和眨眨眼——login.jsp
人脸识别活体检测之张张嘴和眨眨眼——login.jsp
|
6月前
|
弹性计算 Java PHP
新手用户注册阿里云账号、实名认证、购买云服务器图文教程参考
对于初次购买阿里云产品的用户来说,第一步要做的是注册账号并完成实名认证,然后才是购买阿里云服务器或者其他云产品,本文为大家以图文形式展示一下新手用户从注册阿里云账号、实名认证到购买云服务器完整详细教程,以供参考。
新手用户注册阿里云账号、实名认证、购买云服务器图文教程参考
|
5月前
|
文字识别 算法 API
视觉智能开放平台产品使用合集之uniapp框架如何使用阿里云金融级人脸识别
视觉智能开放平台是指提供一系列基于视觉识别技术的API和服务的平台,这些服务通常包括图像识别、人脸识别、物体检测、文字识别、场景理解等。企业或开发者可以通过调用这些API,快速将视觉智能功能集成到自己的应用或服务中,而无需从零开始研发相关算法和技术。以下是一些常见的视觉智能开放平台产品及其应用场景的概览。
137 0