Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Detectar rostros con ML Kit en iOS

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

Puede usar ML Kit para detectar rostros en imágenes y videos.

Antes de que empieces

  1. Si aún no ha agregado Firebase a su aplicación, hágalo siguiendo los pasos de la guía de inicio .
  2. Incluya las bibliotecas de ML Kit en su Podfile:
    pod 'Firebase/MLVision', '6.25.0'
    # If you want to detect face contours (landmark detection and classification
    # don't require this additional model):
    pod 'Firebase/MLVisionFaceModel', '6.25.0'
    
    Después de instalar o actualizar los Pods de su proyecto, asegúrese de abrir su proyecto Xcode usando su .xcworkspace .
  3. En su aplicación, importe Firebase:

    Rápido

    import Firebase

    C objetivo

    @import Firebase;

Directrices de la imagen de entrada

Para que ML Kit detecte rostros con precisión, las imágenes de entrada deben contener rostros que estén representados por suficientes datos de píxeles. En general, cada rostro que desee detectar en una imagen debe tener al menos 100x100 píxeles. Si desea detectar los contornos de las caras, ML Kit requiere una entrada de mayor resolución: cada cara debe tener al menos 200x200 píxeles.

Si está detectando rostros en una aplicación en tiempo real, es posible que también desee considerar las dimensiones generales de las imágenes de entrada. Las imágenes más pequeñas se pueden procesar más rápido, por lo tanto, para reducir la latencia, capture imágenes a resoluciones más bajas (teniendo en cuenta los requisitos de precisión anteriores) y asegúrese de que la cara del sujeto ocupe la mayor parte posible de la imagen. Consulte también Sugerencias para mejorar el rendimiento en tiempo real .

Un mal enfoque de la imagen puede perjudicar la precisión. Si no obtiene resultados aceptables, intente pedirle al usuario que vuelva a capturar la imagen.

La orientación de un rostro en relación con la cámara también puede afectar las características faciales que detecta el ML Kit. Consulte Conceptos de detección de rostros .

1. Configurar el detector de rostros

Antes de aplicar la detección de rostros a una imagen, si desea cambiar alguna de las configuraciones predeterminadas del detector de rostros, especifique esas configuraciones con un objeto VisionFaceDetectorOptions . Puede cambiar los siguientes ajustes:

Ajustes
performanceMode fast (predeterminado) | accurate

Favorece la velocidad o la precisión al detectar rostros.

landmarkMode none (predeterminado) | all

Ya sea para intentar detectar los "puntos de referencia" faciales (ojos, oídos, nariz, mejillas, boca) de todos los rostros detectados.

contourMode none (predeterminado) | all

Ya sea para detectar los contornos de los rasgos faciales. Los contornos se detectan solo para la cara más prominente de una imagen.

classificationMode none (predeterminado) | all

Si clasificar o no las caras en categorías como "sonriendo" y "ojos abiertos".

minFaceSize CGFloat (predeterminado: 0.1 )

El tamaño mínimo, relativo a la imagen, de las caras a detectar.

isTrackingEnabled false (predeterminado) | true

Si asignar o no rostros a una identificación, que se puede usar para rastrear rostros en imágenes.

Tenga en cuenta que cuando la detección de contornos está habilitada, solo se detecta un rostro, por lo que el seguimiento de rostros no produce resultados útiles. Por este motivo, y para mejorar la velocidad de detección, no habilite tanto la detección de contornos como el seguimiento de rostros.

Por ejemplo, cree un objeto VisionFaceDetectorOptions como uno de los siguientes ejemplos:

Rápido

// High-accuracy landmark detection and face classification
let options = VisionFaceDetectorOptions()
options.performanceMode = .accurate
options.landmarkMode = .all
options.classificationMode = .all

// Real-time contour detection of multiple faces
let options = VisionFaceDetectorOptions()
options.contourMode = .all

C objetivo

// High-accuracy landmark detection and face classification
FIRVisionFaceDetectorOptions *options = [[FIRVisionFaceDetectorOptions alloc] init];
options.performanceMode = FIRVisionFaceDetectorPerformanceModeAccurate;
options.landmarkMode = FIRVisionFaceDetectorLandmarkModeAll;
options.classificationMode = FIRVisionFaceDetectorClassificationModeAll;

// Real-time contour detection of multiple faces
FIRVisionFaceDetectorOptions *options = [[FIRVisionFaceDetectorOptions alloc] init];
options.contourMode = FIRVisionFaceDetectorContourModeAll;

2. Ejecute el detector de rostros

Para detectar rostros en una imagen, pase la imagen como UIImage o CMSampleBufferRef al VisionFaceDetector detect(in:) de VisionFaceDetector:

  1. Obtenga una instancia de VisionFaceDetector :

    Rápido

    lazy var vision = Vision.vision()
    
    let faceDetector = vision.faceDetector(options: options)
    

    C objetivo

    FIRVision *vision = [FIRVision vision];
    FIRVisionFaceDetector *faceDetector = [vision faceDetector];
    // Or, to change the default settings:
    // FIRVisionFaceDetector *faceDetector =
    //     [vision faceDetectorWithOptions:options];
    
  2. Cree un objeto VisionImage usando UIImage o CMSampleBufferRef .

    Para usar una UIImage :

    1. Si es necesario, gire la imagen para que su propiedad imageOrientation sea .up .
    2. Cree un objeto VisionImage usando la UIImage girada correctamente. No especifique ningún metadato de rotación; se debe usar el valor predeterminado, .topLeft .

      Rápido

      let image = VisionImage(image: uiImage)

      C objetivo

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

    Para usar un CMSampleBufferRef :

    1. Cree un objeto VisionImageMetadata que especifique la orientación de los datos de imagen contenidos en el búfer CMSampleBufferRef .

      Para obtener la orientación de la imagen:

      Rápido

      func imageOrientation(
          deviceOrientation: UIDeviceOrientation,
          cameraPosition: AVCaptureDevice.Position
          ) -> VisionDetectorImageOrientation {
          switch deviceOrientation {
          case .portrait:
              return cameraPosition == .front ? .leftTop : .rightTop
          case .landscapeLeft:
              return cameraPosition == .front ? .bottomLeft : .topLeft
          case .portraitUpsideDown:
              return cameraPosition == .front ? .rightBottom : .leftBottom
          case .landscapeRight:
              return cameraPosition == .front ? .topRight : .bottomRight
          case .faceDown, .faceUp, .unknown:
              return .leftTop
          }
      }

      C objetivo

      - (FIRVisionDetectorImageOrientation)
          imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                                 cameraPosition:(AVCaptureDevicePosition)cameraPosition {
        switch (deviceOrientation) {
          case UIDeviceOrientationPortrait:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationLeftTop;
            } else {
              return FIRVisionDetectorImageOrientationRightTop;
            }
          case UIDeviceOrientationLandscapeLeft:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationBottomLeft;
            } else {
              return FIRVisionDetectorImageOrientationTopLeft;
            }
          case UIDeviceOrientationPortraitUpsideDown:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationRightBottom;
            } else {
              return FIRVisionDetectorImageOrientationLeftBottom;
            }
          case UIDeviceOrientationLandscapeRight:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationTopRight;
            } else {
              return FIRVisionDetectorImageOrientationBottomRight;
            }
          default:
            return FIRVisionDetectorImageOrientationTopLeft;
        }
      }

      Luego, crea el objeto de metadatos:

      Rápido

      let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
      let metadata = VisionImageMetadata()
      metadata.orientation = imageOrientation(
          deviceOrientation: UIDevice.current.orientation,
          cameraPosition: cameraPosition
      )

      C objetivo

      FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
      AVCaptureDevicePosition cameraPosition =
          AVCaptureDevicePositionBack;  // Set to the capture device you used.
      metadata.orientation =
          [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                       cameraPosition:cameraPosition];
    2. Cree un objeto VisionImage utilizando el objeto CMSampleBufferRef y los metadatos de rotación:

      Rápido

      let image = VisionImage(buffer: sampleBuffer)
      image.metadata = metadata

      C objetivo

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  3. Luego, pasa la imagen al método detect(in:) :

    Rápido

    faceDetector.process(visionImage) { faces, error in
      guard error == nil, let faces = faces, !faces.isEmpty else {
        // ...
        return
      }
    
      // Faces detected
      // ...
    }
    

    C objetivo

    [faceDetector detectInImage:image
                     completion:^(NSArray<FIRVisionFace *> *faces,
                                  NSError *error) {
      if (error != nil) {
        return;
      } else if (faces != nil) {
        // Recognized faces
      }
    }];
    

3. Obtenga información sobre las caras detectadas

Si la operación de detección de rostros tiene éxito, el detector de rostros pasa una matriz de objetos VisionFace al controlador de finalización. Cada objeto VisionFace representa un rostro que se detectó en la imagen. Para cada rostro, puede obtener sus coordenadas delimitadoras en la imagen de entrada, así como cualquier otra información que haya configurado para encontrar el detector de rostros. Por ejemplo:

Rápido

for face in faces {
  let frame = face.frame
  if face.hasHeadEulerAngleY {
    let rotY = face.headEulerAngleY  // Head is rotated to the right rotY degrees
  }
  if face.hasHeadEulerAngleZ {
    let rotZ = face.headEulerAngleZ  // Head is rotated upward rotZ degrees
  }

  // If landmark detection was enabled (mouth, ears, eyes, cheeks, and
  // nose available):
  if let leftEye = face.landmark(ofType: .leftEye) {
    let leftEyePosition = leftEye.position
  }

  // If contour detection was enabled:
  if let leftEyeContour = face.contour(ofType: .leftEye) {
    let leftEyePoints = leftEyeContour.points
  }
  if let upperLipBottomContour = face.contour(ofType: .upperLipBottom) {
    let upperLipBottomPoints = upperLipBottomContour.points
  }

  // If classification was enabled:
  if face.hasSmilingProbability {
    let smileProb = face.smilingProbability
  }
  if face.hasRightEyeOpenProbability {
    let rightEyeOpenProb = face.rightEyeOpenProbability
  }

  // If face tracking was enabled:
  if face.hasTrackingID {
    let trackingId = face.trackingID
  }
}

C objetivo

for (FIRVisionFace *face in faces) {
  // Boundaries of face in image
  CGRect frame = face.frame;

  if (face.hasHeadEulerAngleY) {
    CGFloat rotY = face.headEulerAngleY;  // Head is rotated to the right rotY degrees
  }
  if (face.hasHeadEulerAngleZ) {
    CGFloat rotZ = face.headEulerAngleZ;  // Head is tilted sideways rotZ degrees
  }

  // If landmark detection was enabled (mouth, ears, eyes, cheeks, and
  // nose available):
  FIRVisionFaceLandmark *leftEar = [face landmarkOfType:FIRFaceLandmarkTypeLeftEar];
  if (leftEar != nil) {
    FIRVisionPoint *leftEarPosition = leftEar.position;
  }

  // If contour detection was enabled:
  FIRVisionFaceContour *upperLipBottomContour = [face contourOfType:FIRFaceContourTypeUpperLipBottom];
  if (upperLipBottomContour != nil) {
    NSArray<FIRVisionPoint *> *upperLipBottomPoints = upperLipBottomContour.points;
    if (upperLipBottomPoints.count > 0) {
      NSLog("Detected the bottom contour of the subject's upper lip.")
    }
  }

  // If classification was enabled:
  if (face.hasSmilingProbability) {
    CGFloat smileProb = face.smilingProbability;
  }
  if (face.hasRightEyeOpenProbability) {
    CGFloat rightEyeOpenProb = face.rightEyeOpenProbability;
  }

  // If face tracking was enabled:
  if (face.hasTrackingID) {
    NSInteger trackingID = face.trackingID;
  }
}

Ejemplo de contornos de cara

Cuando tiene habilitada la detección del contorno facial, obtiene una lista de puntos para cada característica facial que se detectó. Estos puntos representan la forma de la característica. Consulte la descripción general de los conceptos de detección de rostros para obtener detalles sobre cómo se representan los contornos.

La siguiente imagen ilustra cómo estos puntos se asignan a una cara (haga clic en la imagen para ampliarla):

Detección de rostros en tiempo real

Si desea utilizar la detección de rostros en una aplicación en tiempo real, siga estas pautas para lograr las mejores velocidades de cuadro:

  • Configure el detector de rostros para usar la detección de contornos faciales o la clasificación y la detección de puntos de referencia, pero no ambas:

    Detección de contorno
    Detección de puntos de referencia
    Clasificación
    Detección y clasificación de puntos de referencia
    Detección de contornos y detección de puntos de referencia
    Detección y clasificación de contornos
    Detección de contornos, detección de puntos de referencia y clasificación

  • Habilitar el modo fast (habilitado de forma predeterminada).

  • Considere capturar imágenes a una resolución más baja. Sin embargo, también tenga en cuenta los requisitos de dimensión de imagen de esta API.

  • Llamadas del acelerador al detector. Si un nuevo cuadro de video está disponible mientras el detector está funcionando, suelte el cuadro.
  • Si está utilizando la salida del detector para superponer gráficos en la imagen de entrada, primero obtenga el resultado de ML Kit, luego renderice la imagen y superponga en un solo paso. Al hacerlo, renderiza en la superficie de visualización solo una vez para cada cuadro de entrada. Consulte las clases previewOverlayView y FIRDetectionOverlayView en la aplicación de ejemplo de presentación para ver un ejemplo.