转到控制台

在 Android 上使用机器学习套件检测面部

利用机器学习套件,您可以使用基于设备的模型或云端模型检测图片和视频中的面部。要了解每种方法的优势,请参阅概览

准备工作

  1. 设置一个 Firebase 项目:
    1. 如果您还没有 Firebase 项目,请在 Firebase 控制台中创建一个。如果您已经有与自己的移动应用相关联的现有 Google 项目,请点击导入 Google 项目。如果没有,请点击添加项目
    2. 点击将 Firebase 添加到您的 Android 应用,然后按设置步骤操作。如果您是导入现有 Google 项目,系统可能会自动执行这些操作,您只需下载配置文件即可。
    3. 出现提示时,输入应用的软件包名称。请务必输入应用在使用的软件包名称;只有在将应用添加到 Firebase 项目时您才能进行此设置。
    4. 最后,您要下载一个 google-services.json 文件。您可以随时重新下载配置文件
    5. 如果尚未将此文件复制到项目的模块文件夹(通常是 app/),请执行此操作。
  2. 将您从自己的 EAP 联系人那里接收到的 SDK 解压缩:
    unzip -d $SDK_DIR 3p_sdk.m2repo.zip
    
  3. 将 SDK 和 Google 服务插件解压缩到的目录添加到您的项目级 build.gradle
    buildscript {
      // ...
      dependencies {
          // ...
          classpath 'com.google.gms:google-services:3.2.0' // google-services plugin
      }
    }
    
    allprojects {
      repositories {
        // Add this
        maven {
          url "$SDK_DIR"
        }
        // This should already be here
        jcenter()
    
        ...
      }
    }
    
  4. 然后,添加机器学习套件的依赖项,并将 apply plugin 行添加到您的应用级 build.gradle 文件:

    dependencies {
      // ...
      compile 'com.google.firebase:firebase-core:12.8.0-SNAPSHOT'
      compile 'com.google.firebase:firebase-ml-vision:12.8.0-SNAPSHOT'
    }
    
    // ADD THIS AT THE BOTTOM OF THE FILE
    apply plugin: 'com.google.gms.google-services'
    

现在,您就可以使用基于设备的模型云端模型检测面部了。

基于设备的面部检测

配置面部检测器

在对图片应用面部检测之前,如果您想更改面部检测器的任何默认设置,请使用 FirebaseVisionFaceDetectorOptions 对象指定这些设置。您可以更改以下设置:

设置
检测模式 FAST_MODE(默认值)| ACCURATE_MODE

在检测面部时更注重速度还是准确性。

检测标志 NO_LANDMARKS(默认值)| ALL_LANDMARKS

是否尝试识别面部“标志”:眼睛、耳朵、鼻子、脸颊、嘴巴。

对面部分类 NO_CLASSIFICATIONS(默认值)| ALL_CLASSIFICATIONS

是否将面部分为不同类别(例如“微笑”和“睁眼”)。

面部大小下限 float(默认值:0.1f

要检测的面部的大小下限(相对于图片)。

启用面部跟踪 false(默认值)| true

是否为面部分配 ID,以用于跨图片跟踪面部。

例如,要更改所有默认设置,请按照以下示例构建 FirebaseVisionFaceDetectorOptions 对象:

FirebaseVisionFaceDetectorOptions options =
    new FirebaseVisionFaceDetectorOptions.Builder()
        .setModeType(FirebaseVisionFaceDetectorOptions.ACCURATE_MODE)
        .setLandmarkType(FirebaseVisionFaceDetectorOptions.ALL_LANDMARKS)
        .setClassificationType(FirebaseVisionFaceDetectorOptions.ALL_CLASSIFICATIONS)
        .setMinFaceSize(0.2f)
        .setTrackingEnabled(true)
        .build();

运行面部检测器

要识别图片中的面部,请将图片作为 ByteBuffer 对象传递给 FirebaseVisionFaceDetectordetectInBuffer 方法,或将图片作为 android.graphics.Bitmap 对象传递给 detectInImage 方法。

  1. 获取 FirebaseVisionFaceDetector 的一个实例:

    FirebaseVisionFaceDetector detector = FirebaseVision.getInstance()
        .getVisionFaceDetector(options);
    
  2. 创建一个包含图片元数据的 FirebaseVisionImageMetadata 对象。

    如果要将图片作为 ByteBuffer 传递,则必须指定图片的高度、宽度、颜色编码格式和显示方向:

    FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
        .setWidth(1280)
        .setHeight(720)
        .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
        .setRotation(FirebaseVisionImageMetadata.ROTATION_0)
        .build();
    

    如果要将图片作为 Bitmap 传递,则只需指定图片的显示方向:

    FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
        .setRotation(FirebaseVisionImageMetadata.ROTATION_0)
        .build();
    
  3. 最后,将图片传递给 detectInBufferdetectInImage 方法:

    Task<SparseArray<FirebaseVisionFace>> result =
        detector.detectInImage(image, metadata)  // or detectInBuffer(buffer, metadata)
        .addOnSuccessListener(
            this,
            new OnSuccessListener<SparseArray<FirebaseVisionFace>>() {
              @Override
              public void onSuccess(SparseArray<FirebaseVisionFace> faces) {
                // Task completed successfully
                // ...
              }
            })
        .addOnFailureListener(
            this,
            new OnFailureListener() {
              @Override
              public void onFailure(@NonNull Exception e) {
                // Task failed with an exception
                // ...
              }
            });
    

获取检测到的面部的相关信息

如果面部识别操作成功,则系统会向成功侦听器传递一组 FirebaseVisionFace 对象。每个 FirebaseVisionFace 对象代表一张在图片中检测到的面孔。对于每张面孔,您可以获取它在输入图片中的边界坐标,以及您已配置面部检测器查找的任何其他信息。例如:

for(int i = 0; i < faces.size(); i++) {
  FirebaseVisionFace face = faces.valueAt(i);

  Rect bounds = face.getBoundingBox();
  if (face.hasHeadEulerAngleY()) {
    float rotY = face.getHeadEulerAngleY();  // Head is rotated to the right rotY degrees
  }
  if (face.hasHeadEulerAngleZ()) {
    float rotZ = face.getHeadEulerAngleZ();  // Head is rotated upward rotZ degrees
  }

  // If landmark detection was enabled (mouth, ears, eyes, cheeks, and
  // nose available):
  if (face.hasLeftEarPosition()) {
    PointF leftEarPos = face.getLeftEarPosition();
  }
  if (face.hasNoseBasePosition()) {
    PointF nosePos = face.getNoseBasePosition();
  }

  // If classification was enabled:
  if (face.hasSmilingProbability()) {
    float smileProb = face.getSmilingProbability();
  }
  if (face.hasRightEyeOpenProbability()) {
    float rightEyeOpenProb = face.getRightEyeOpenProbability();
  }

  // If face tracking was enabled:
  if (face.hasTrackingId()) {
    int id = face.getTrackingId();
  }
}

Cloud 面部检测

配置面部检测器

默认情况下,Cloud 检测器使用模型的 STABLE 版本并最多返回 10 个结果。如果您想更改这两个设置中的任何一个,请使用 FirebaseVisionCloudDetectorOptions 对象进行指定。

例如,要将两项默认设置全部更改,请按照以下示例构建一个 FirebaseVisionCloudDetectorOptions 对象:

FirebaseVisionCloudDetectorOptions options =
    new FirebaseVisionCloudDetectorOptions.Builder()
        .setModelType(FirebaseVisionCloudDetectorOptions.LATEST_MODEL)
        .setMaxResults(15)
        .build();

要使用默认设置,可以在下一步中使用 FirebaseVisionCloudDetectorOptions.DEFAULT

运行面部检测器

要识别图片中的面部,请将图片作为 ByteBuffer 对象传递给 FirebaseVisionCloudFaceDetectordetectInBuffer 方法,或将图片作为 android.graphics.Bitmap 对象传递给 detectInImage 方法。

  1. 获取 FirebaseVisionCloudFaceDetector 的一个实例:

    FirebaseVisionCloudFaceDetector detector = FirebaseMachineLearning.getInstance()
        .getVisionFaceDetector(options);
    
  2. 创建一个包含图片元数据的 FirebaseVisionImageMetadata 对象。

    如果要将图片作为 ByteBuffer 传递,则必须指定图片的高度、宽度、颜色编码格式和显示方向:

    FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
        .setWidth(1280)
        .setHeight(720)
        .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
        .setRotation(FirebaseVisionImageMetadata.ROTATION_0)
        .build();
    

    如果要将图片作为 Bitmap 传递,则只需指定图片的显示方向:

    FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
        .setRotation(FirebaseVisionImageMetadata.ROTATION_0)
        .build();
    
  3. 最后,将图片传递给 detectInBufferdetectInImage 方法:

    Task<SparseArray<FirebaseVisionCloudFace>> result =
        detector.detectInImage(image, metadata)  // or detectInBuffer(buffer, metadata)
        .addOnSuccessListener(
            this,
            new OnSuccessListener<SparseArray<FirebaseVisionCloudFace>>() {
              @Override
              public void onSuccess(SparseArray<FirebaseVisionCloudFace> faces) {
                // Task completed successfully
                // ...
              }
            })
        .addOnFailureListener(
            this,
            new OnFailureListener() {
              @Override
              public void onFailure(@NonNull Exception e) {
                // Task failed with an exception
                // ...
              }
            });
    

获取检测到的面部的相关信息

如果面部识别操作成功,则系统会向成功侦听器传递一组 FirebaseVisionCloudFace 对象。每个 FirebaseVisionCloudFace 对象代表一张在图片中检测到的面孔。对于每张面孔,您可以获取它在输入图片中的边界坐标、相对于相机的旋转角度以及识别到的面部特征的位置。例如:

for(int i = 0; i < faces.size(); i++) {
  FirebaseVisionFace face = faces.valueAt(i);

  // Face position and rotation
  Rect bounds = face.getBoundingBox();
  float rotY = face.getHeadEulerAngleY();  // Head is rotated to the right rotY degrees
  float rotZ = face.getHeadEulerAngleZ();  // Head is rotated upward rotZ degrees

  // Facial features
  PointF leftEarPos = face.getLeftEarPosition();
  PointF nosePos = face.getNoseBasePosition();

  // Face classification
  float sorrowProb = face.getSorrowProbability();
  float rightEyeOpenProb = face.getRightEyeOpenProbability();
}