人脸识别实现RGB摄像头和IR摄像头对齐

632 阅读2分钟

背景介绍:

最近在做人脸识别的项目,我选择接入的是虹软的Arcface SDK,有个需求是比如在RGB摄像头和IR摄像头同时开启时候,如何保证两个摄像头活体检测到的是同一个人脸。

在保证RGB摄像头和IR摄像头分辨率、成像方向、焦距等一致后,接下来就是如何实现在应用层用代码判断了。

判断检测到是否是同一人脸其实有两种方案:

1.一旦人脸框相交,即判断为同一人脸,但此方案误差太大故不考虑;

2.去计算两个人脸框重叠的面积,根据设置的阈值精准判断是否为同一人脸。 本文选择第二种方案,流程图参考下图:

image.png

详细步骤:

  1. 在IR进行活体检测前,先通过detectFaces检测人脸信息,获取人脸框。由于rgbFaceInfo里面只有一张人脸,所以只需要通过keepMaxFace方法保留IR最大人脸,然后调用isFaceSame方法去判断RGB和IR检测到的是否是同一个人脸。

    // 检测人脸信息
    FaceInfo rgbFaceInfo = faceInfo;
    List<FaceInfo> irFaceInfoList = new ArrayList<>();
    int fdCode = flEngine.detectFaces(nv21Data, width, height, format, irFaceInfoList);
    boolean isFaceOverlap = false;
    if(fdCode == ErrorInfo.MOK && irFaceInfoList .size()>0){
     keepMaxFace(irFaceInfoList);
     isFaceOverlap = isFaceSame(irFaceInfoList.get(0),rgbFaceInfo,0.3);
    }
    
  2. 如果是同一个人脸,则调用IR活体检测接口processIr

    if (fdCode == ErrorInfo.MOK && isFaceOverlap) {
       flCode = flEngine.processIr(nv21Data, width, height, format, irFaceInfoList, FaceEngine.ASF_IR_LIVENESS);
    } else {
      // 错误处理
    }
    
  3. getOverlapArea方法判断两个矩形框是否有重叠,如果没有重叠区域,则返回空的矩形。

    public Rect getOverlapArea (Rect rect1, Rect rect2) {
       int left = Math.max(rect1.left, rect2.left);
       int right = Math.min(rect1.right, rect2.right);
       int top = Math.max(rect1.top, rect2.top);
       int bottom = Math.min(rect1.bottom, rect2.bottom);
    
       // 如果没有重叠区域,则返回空的矩形
       if (left < right && top < bottom) {
           return new Rect(left, top, right, bottom);
       }
       return null;  // 无重叠
    }
    
  4. isFaceSame方法需要具体实现:计算两个矩形的重叠面积,以判断它们的重叠程度。第三个参数是阈值,这样可以通过调整阈值更精确地确定是否是同一个人脸。

    // 可能并不需要两个面部框完全重叠,只需要有一定比例的重叠即可判定是同一张脸。
    // 因此可以设置一个重叠阈值,当两个矩形的重叠面积超过某个阈值时,认为是同一张脸。
    public boolean isFaceSame(FaceInfo rgbFaceInfo, FaceInfo irFaceInfo, double threshold) {
           Rect rect1 = rgbFaceInfo.getRect();
           Rect rect2 = irFaceInfo.getRect();
           Rect overlapRect = getOverlapArea(rect1, rect2);
           if (overlapRect != null) {
               int overlapArea = overlapRect.width() * overlapRect.height();
               int face1Area = rect1.width() * rect1.height();
               int face2Area = rect2.width() * rect2.height();
               // 计算重叠面积占两个矩形面积的比例
               double overlapRatio = (double) overlapArea / Math.min(face1Area, face2Area);
               Log.d(TAG, "overlapRatio:" + overlapRatio + "," + threshold);
    
               return overlapRatio > threshold;
           }
           return false;
       }
    
  5. 当活体检测通过后,就可以获取RGB和IR的活体检测信息了

    if (flCode == ErrorInfo.MOK) {
       if (livenessType == LivenessType.RGB) {
            flCode = flEngine.getLiveness(livenessInfoList);
       } else {
            flCode = flEngine.getIrLiveness(livenessInfoList);
       }
    }
    
Tips:

以上代码可以参考虹软 arcface demo中的FaceHelper.java文件,路径:app/src/main/java/com/arcsoft/arcfacedemo/util/face/FaceHelper.java