You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google ML Kit人脸检测问题:部分人脸可见时返回不可见关键点

解决方案:过滤ML Kit人脸检测的推断关键点,仅保留画面内可见特征

问题根源

Google ML Kit的人脸检测器会基于部分可见的人脸特征推断缺失的关键点(比如只看到左脸时,模型会预测右脸关键点的位置),这是模型的设计逻辑,并非bug。要实现“仅完整人脸可见时捕获图像”的需求,需要在应用层添加过滤逻辑。

可行解决方案

1. 基于相机预览边界过滤关键点

人脸的bounding box可能包含模型推断的区域,因此应该用相机实际预览的尺寸来判断关键点是否在画面内,而不是人脸自身的bounding box。

  • 步骤:
    • 保存相机预览的尺寸(比如在相机初始化时获取previewSize)
    • 修改关键点校验逻辑,判断每个关键点的坐标是否在相机预览范围内

2. 修正人脸关键点类型的错误

你的代码中存在一个明显错误:将chin的类型设为FaceLandmarkType.leftCheek,这会导致下巴的校验逻辑完全失效,需要修正为FaceLandmarkType.chin。

3. 优化置信度判断逻辑

用face.confidence替代trackingId作为置信度判断依据,confidence直接反映模型对人脸检测的置信程度,比trackingId更可靠(trackingId仅用于跟踪,不代表检测质量)。

修改后的代码示例

假设你已经获取了相机预览的尺寸Size previewSize:

String _checkFacePosition(Face face, Size previewSize) {
  final double? rotY = face.headEulerAngleY; // 左右倾斜
  final double? rotZ = face.headEulerAngleZ; // 上下倾斜

  // 1. 校验人脸尺寸和置信度
  bool isBoundingBoxValid = face.boundingBox.width > 120 && face.boundingBox.height > 100;
  bool isConfidenceHigh = face.confidence > 0.8; // 用confidence替代trackingId

  if (!isBoundingBoxValid) {
    return "请调整你的位置。";
  }
  if (!isConfidenceHigh) {
    return "请调整你的位置。";
  }

  // 2. 校验头部姿态
  bool isFaceStraight = face.headEulerAngleX!.abs() < 10 &&
      (rotY?.abs() ?? 90) < 10 &&
      (rotZ?.abs() ?? 90) < 10;

  if (!isFaceStraight) {
    return "请调整你的位置,保持面部正对镜头。";
  }

  // 3. 修正关键点类型,获取正确的特征点
  final nose = face.landmarks[FaceLandmarkType.noseBase];
  final bottomLip = face.landmarks[FaceLandmarkType.bottomMouth];
  final chin = face.landmarks[FaceLandmarkType.chin]; // 修正此处的类型错误
  final leftEar = face.landmarks[FaceLandmarkType.leftEar];
  final rightEar = face.landmarks[FaceLandmarkType.rightEar];
  final rightEye = face.landmarks[FaceLandmarkType.rightEye];
  final leftEye = face.landmarks[FaceLandmarkType.leftEye];
  final rightCheek = face.landmarks[FaceLandmarkType.rightCheek];
  final leftMouth = face.landmarks[FaceLandmarkType.leftMouth];
  final rightMouth = face.landmarks[FaceLandmarkType.rightMouth];

  // 4. 检查所有关键点是否存在
  final requiredLandmarks = [nose, bottomLip, chin, leftEar, rightEar, rightEye, leftEye, rightCheek, leftMouth, rightMouth];
  if (requiredLandmarks.any((landmark) => landmark == null)) {
    return "请确保面部居中,眼睛、耳朵、鼻子、嘴唇、下巴等特征完全可见。";
  }

  // 5. 基于相机预览边界判断关键点是否在画面内
  bool isLandmarkInPreview(Point<int>? position) {
    if (position == null) return false;
    return position.y >= 0 &&
        position.y <= previewSize.height &&
        position.x >= 0 &&
        position.x <= previewSize.width;
  }

  // 校验所有关键点是否在相机预览范围内
  if (!(isLandmarkInPreview(nose!.position) &&
      isLandmarkInPreview(bottomLip!.position) &&
      isLandmarkInPreview(chin!.position) &&
      isLandmarkInPreview(leftEar!.position) &&
      isLandmarkInPreview(rightEar!.position) &&
      isLandmarkInPreview(leftEye!.position) &&
      isLandmarkInPreview(rightEye!.position) &&
      isLandmarkInPreview(rightMouth!.position) &&
      isLandmarkInPreview(leftMouth!.position) &&
      isLandmarkInPreview(rightCheek!.position))) {
    return "请确保面部居中,所有特征完全出现在画面中。";
  }

  return ""; // 所有校验通过
}

额外优化建议

  • 调整minFaceSize:如果你的应用场景是近距离人脸捕获,可以将minFaceSize提高到0.4~0.5,减少部分人脸被检测到的概率。
  • 添加人脸居中校验:判断人脸bounding box的中心是否接近相机预览的中心,确保面部不会偏移到画面边缘。

内容的提问来源于stack exchange,提问作者Akhil George

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:16:06