Rilevamento dei volti con ML Kit su iOS

Puoi utilizzare ML Kit per rilevare i volti nelle immagini e nei video.

Prova

  • Prova l'app di esempio per vedere un utilizzo di esempio di questa API.
  • Prova a utilizzare il codice autonomamente con il codelab.

Prima di iniziare

  1. Includi i seguenti pod ML Kit nel podfile:
    pod 'GoogleMLKit/FaceDetection', '3.2.0'
    
  2. Dopo aver installato o aggiornato i pod del progetto, apri il progetto Xcode utilizzando il relativo .xcworkspace. ML Kit è supportato in Xcode versione 12.4 o successiva.

Linee guida per l'immagine di input

Per il riconoscimento facciale, devi utilizzare un'immagine di almeno 480 x 360 pixel. Affinché ML Kit possa rilevare con precisione i volti, le immagini di input devono contenere volti rappresentati da sufficienti dati di pixel. In generale, ogni volto da rilevare in un'immagine deve essere di almeno 100 x 100 pixel. Se vuoi rilevare i contorni dei volti, ML Kit richiede un input di risoluzione più elevato: ogni faccia deve essere di almeno 200 x 200 pixel.

Se rilevi i volti in un'applicazione in tempo reale, puoi anche considerare le dimensioni complessive delle immagini di input. Le immagini più piccole possono essere elaborate più velocemente, quindi per ridurre la latenza, acquisisci immagini a risoluzioni più basse, ma tieni presente i requisiti di accuratezza sopra indicati e assicurati che il volto del soggetto occupi la maggior parte dell'immagine possibile. Consulta anche i suggerimenti per migliorare il rendimento in tempo reale.

Anche una scarsa messa a fuoco dell'immagine può influire sulla precisione. Se non ottieni risultati accettabili, chiedi all'utente di acquisire nuovamente l'immagine.

Anche l'orientamento del volto rispetto alla videocamera può influire sulle caratteristiche facciali rilevate da ML Kit. Consulta i concetti del rilevamento facciale.

1. Configura il rilevatore di volti

Prima di applicare il rilevamento dei volti a un'immagine, se vuoi modificare una qualsiasi delle impostazioni predefinite del rilevatore di volti, specifica queste impostazioni con un oggetto FaceDetectorOptions. Puoi modificare le seguenti impostazioni:

Impostazioni
performanceMode fast (valore predefinito) | accurate

Favorire la velocità o la precisione durante il rilevamento dei volti.

landmarkMode none (valore predefinito) | all

Indica se tentare di rilevare i "punti di riferimento" facciali (occhi, orecchie, naso, guance, bocca) di tutti i volti rilevati.

contourMode none (valore predefinito) | all

Indica se rilevare i contorni delle caratteristiche del viso. I contorni vengono rilevati solo per il volto più in evidenza in un'immagine.

classificationMode none (valore predefinito) | all

Indica se classificare o meno i volti in categorie come "sorridente" e "occhi aperti".

minFaceSize CGFloat (valore predefinito: 0.1)

Imposta le dimensioni minime del volto, espresse come rapporto tra la larghezza della testa e la larghezza dell'immagine.

isTrackingEnabled false (valore predefinito) | true

Indica se assegnare o meno un ID per i volti, che può essere utilizzato per tracciare i volti nelle immagini.

Tieni presente che quando è abilitato il rilevamento dei contorni, viene rilevato un solo volto, quindi il monitoraggio dei volti non produce risultati utili. Per questo motivo, e per migliorare la velocità di rilevamento, non attivare sia il rilevamento dei contorni che il rilevamento dei volti.

Ad esempio, crea un oggetto FaceDetectorOptions come in uno dei seguenti esempi:

Swift

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

// Real-time contour detection of multiple faces
// options.contourMode = .all

Objective-C

// High-accuracy landmark detection and face classification
MLKFaceDetectorOptions *options = [[MLKFaceDetectorOptions alloc] init];
options.performanceMode = MLKFaceDetectorPerformanceModeAccurate;
options.landmarkMode = MLKFaceDetectorLandmarkModeAll;
options.classificationMode = MLKFaceDetectorClassificationModeAll;

// Real-time contour detection of multiple faces
// options.contourMode = MLKFaceDetectorContourModeAll;

2. Prepara l'immagine di input

Per rilevare i volti in un'immagine, passa l'immagine come UIImage o CMSampleBufferRef a FaceDetector utilizzando il metodo process(_:completion:) o results(in:):

Crea un oggetto VisionImage utilizzando UIImage o CMSampleBuffer.

Se usi un UIImage, segui questi passaggi:

  • Crea un oggetto VisionImage con il UIImage. Assicurati di specificare il valore .orientation corretto.

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

Se usi un CMSampleBuffer, segui questi passaggi:

  • Specifica l'orientamento dei dati immagine contenuti in CMSampleBuffer.

    Per ottenere l'orientamento dell'immagine:

    Swift

    func imageOrientation(
      deviceOrientation: UIDeviceOrientation,
      cameraPosition: AVCaptureDevice.Position
    ) -> UIImage.Orientation {
      switch deviceOrientation {
      case .portrait:
        return cameraPosition == .front ? .leftMirrored : .right
      case .landscapeLeft:
        return cameraPosition == .front ? .downMirrored : .up
      case .portraitUpsideDown:
        return cameraPosition == .front ? .rightMirrored : .left
      case .landscapeRight:
        return cameraPosition == .front ? .upMirrored : .down
      case .faceDown, .faceUp, .unknown:
        return .up
      }
    }
          

    Objective-C

    - (UIImageOrientation)
      imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                             cameraPosition:(AVCaptureDevicePosition)cameraPosition {
      switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored
                                                                : UIImageOrientationRight;
    
        case UIDeviceOrientationLandscapeLeft:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored
                                                                : UIImageOrientationUp;
        case UIDeviceOrientationPortraitUpsideDown:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored
                                                                : UIImageOrientationLeft;
        case UIDeviceOrientationLandscapeRight:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored
                                                                : UIImageOrientationDown;
        case UIDeviceOrientationUnknown:
        case UIDeviceOrientationFaceUp:
        case UIDeviceOrientationFaceDown:
          return UIImageOrientationUp;
      }
    }
          
  • Crea un oggetto VisionImage utilizzando l'oggetto CMSampleBuffer e l'orientamento:

    Swift

    let image = VisionImage(buffer: sampleBuffer)
    image.orientation = imageOrientation(
      deviceOrientation: UIDevice.current.orientation,
      cameraPosition: cameraPosition)

    Objective-C

     MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
     image.orientation =
       [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                    cameraPosition:cameraPosition];

3. Ottieni un'istanza di FaceDetector

Ottieni un'istanza di FaceDetector:

Swift

let faceDetector = FaceDetector.faceDetector(options: options)

Objective-C

MLKFaceDetector *faceDetector = [MLKFaceDetector faceDetectorWithOptions:options];
      

4. Elabora l'immagine

Quindi, passa l'immagine al metodo process():

Swift

weak var weakSelf = self
faceDetector.process(visionImage) { faces, error in
  guard let strongSelf = weakSelf else {
    print("Self is nil!")
    return
  }
  guard error == nil, let faces = faces, !faces.isEmpty else {
    // ...
    return
  }

  // Faces detected
  // ...
}

Objective-C

[faceDetector processImage:image
                completion:^(NSArray<MLKFace *> *faces,
                             NSError *error) {
  if (error != nil) {
    return;
  }
  if (faces.count > 0) {
    // Recognized faces
  }
}];

5. Ricevere informazioni sui volti rilevati

Se il rilevamento dei volti ha esito positivo, il rilevatore passa un array di oggetti Face al gestore del completamento. Ogni oggetto Face rappresenta un volto rilevato nell'immagine. Per ogni volto, puoi ottenere le coordinate di delimitazione nell'immagine di input, nonché qualsiasi altra informazione trovata dal rilevatore di volti. Ad esempio:

Swift

for face in faces {
  let frame = face.frame
  if face.hasHeadEulerAngleX {
    let rotX = face.headEulerAngleX  // Head is rotated to the uptoward rotX degrees
  }
  if face.hasHeadEulerAngleY {
    let rotY = face.headEulerAngleY  // Head is rotated to the right rotY degrees
  }
  if face.hasHeadEulerAngleZ {
    let rotZ = face.headEulerAngleZ  // Head is tilted sideways 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
  }
}

Objective-C

for (MLKFace *face in faces) {
  // Boundaries of face in image
  CGRect frame = face.frame;
  if (face.hasHeadEulerAngleX) {
    CGFloat rotX = face.headEulerAngleX;  // Head is rotated to the upward rotX degrees
  }
  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):
  MLKFaceLandmark *leftEar = [face landmarkOfType:FIRFaceLandmarkTypeLeftEar];
  if (leftEar != nil) {
    MLKVisionPoint *leftEarPosition = leftEar.position;
  }

  // If contour detection was enabled:
  MLKFaceContour *upperLipBottomContour = [face contourOfType:FIRFaceContourTypeUpperLipBottom];
  if (upperLipBottomContour != nil) {
    NSArray<MLKVisionPoint *> *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;
  }
}

Esempio di contorni del volto

Se è attivo il rilevamento dei contorni del volto, viene visualizzato un elenco di punti per ogni caratteristica del volto rilevata. Questi punti rappresentano la forma dell'elemento. Per informazioni dettagliate su come vengono rappresentati i contorni, consulta la sezione Concetti di rilevamento facciale.

L'immagine seguente illustra come questi punti vengano mappati a un volto; fai clic sull'immagine per ingrandirla:

esempio di mesh del volto rilevato

Rilevamento dei volti in tempo reale

Se vuoi utilizzare il rilevamento dei volti in un'applicazione in tempo reale, segui queste linee guida per ottenere le frequenze fotogrammi ottimali:

  • Configura il rilevatore di volti in modo che utilizzi il rilevamento o la classificazione dei volti e il rilevamento dei punti di riferimento, ma non entrambi:

    Rilevamento dei contorni
    Rilevamento dei punti di riferimento
    Classificazione
    Rilevamento e classificazione dei punti di riferimento
    Rilevamento e rilevamento dei punti di riferimento
    Rilevamento e classificazione dei contorni
    Rilevamento e classificazione dei punti di riferimento
    Rilevamento dei contorni, rilevamento e classificazione dei punti di riferimento

  • Attiva la modalità fast (attivata per impostazione predefinita).

  • Valuta la possibilità di acquisire immagini a una risoluzione più bassa. Tuttavia, tieni presente anche i requisiti di dimensione delle immagini di questa API.

  • Per elaborare i fotogrammi video, utilizza l'API sincrona results(in:) del rilevatore. Richiama questo metodo dalla funzione captureOutput(_, didOutput:from:) di AVCaptureVideoDataOutputSampleBufferDelegate per ottenere in modo sincrono i risultati dal frame video specificato. Mantieni il valore true per alwaysDiscardsLateVideoFrames di AVCaptureVideoDataOutput per limitare le chiamate al rilevatore. Se un nuovo frame video diventa disponibile mentre il rilevatore è in esecuzione, questo verrà eliminato.
  • Se utilizzi l'output del rilevatore per sovrapporre gli elementi grafici all'immagine di input, recupera prima il risultato da ML Kit, quindi esegui il rendering dell'immagine e dell'overlay in un solo passaggio. In questo modo, esegui il rendering sulla piattaforma di visualizzazione solo una volta per ogni frame di input elaborato. Per un esempio, vedi updatePreviewOverlayViewWithLastFrame nell'esempio della guida rapida di ML Kit.