Rilevamento dei volti con ML Kit su iOS

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

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

Prova subito

Prima di iniziare

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

Linee guida sull'immagine di input

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

Se rilevi i volti in un'applicazione in tempo reale, puoi anche prendere in considerazione le dimensioni complessive delle immagini di input. Le immagini più piccole possono essere elaborate più rapidamente, quindi per ridurre la latenza, acquisisci immagini a risoluzioni inferiori, ma tieni presente i requisiti di accuratezza sopra riportati e assicurati che il volto del soggetto occupi la maggiore quantità possibile di immagini. Consulta anche i suggerimenti per migliorare le prestazioni in tempo reale.

Una messa a fuoco dell'immagine scadente può anche influire sulla precisione. Se non ottieni risultati accettabili, chiedi all'utente di riprendere l'immagine.

L'orientamento di un volto rispetto alla fotocamera può influire sulle caratteristiche del viso rilevate da ML Kit. Consulta Concetti sul rilevamento dei volti.

1. Configura il rilevatore del volto

Prima di applicare il rilevamento dei volti a un'immagine, se vuoi modificare le impostazioni predefinite del rilevatore del volto, specificale con un oggetto FaceDetectorOptions. Puoi modificare le seguenti impostazioni:

Impostazioni
performanceMode fast (valore predefinito) | accurate

Favorisci la velocità o l'accuratezza nel rilevamento dei volti.

landmarkMode none (valore predefinito) | all

Consente di specificare se cercare o meno di rilevare i "segnali" facciali (occhio, orecchie, naso, guance, bocca) di tutti i volti rilevati.

contourMode none (valore predefinito) | all

Consente di stabilire 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

Consente di specificare se classificare o meno i volti in categorie quali "sorriso" e "occhio aperto".

minFaceSize CGFloat (valore predefinito: 0.1)

Consente di impostare la dimensione minima del volto, espressa come rapporto tra la larghezza della testa e la larghezza dell'immagine.

isTrackingEnabled false (valore predefinito) | true

Consente di specificare se assegnare o meno i volti a un ID, che può essere utilizzato per monitorare i volti nelle immagini.

Tieni presente che quando viene attivato 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 il rilevamento dei contorni e il monitoraggio dei volti.

Ad esempio, crea un oggetto FaceDetectorOptions come nel seguente esempio:

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 un UIImage o un CMSampleBuffer.

Se utilizzi un UIImage, segui questi passaggi:

  • Crea un oggetto VisionImage con il UIImage. Assicurati di specificare il .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 utilizzi un CMSampleBuffer, segui questi passaggi:

  • Specifica l'orientamento dei dati dell'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 e l'orientamento CMSampleBuffer:

    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 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. Visualizzare le informazioni sui volti rilevati

Se l'operazione di rilevamento dei volti ha esito positivo, il rilevatore trasmette un array di oggetti Face al gestore di completamento. Ogni oggetto Face rappresenta un volto rilevato nell'immagine. Per ogni volto, puoi visualizzarne le coordinate di delimitazione nell'immagine di input, nonché eventuali altre informazioni che hai configurato per il rilevamento del volto. 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 hai attivato il rilevamento dei contorni del volto, ricevi un elenco di punti per ogni caratteristica del viso che è stata rilevata. Questi punti rappresentano la forma della funzionalità. Consulta la pagina Concetti sul rilevamento dei volti per maggiori dettagli su come vengono rappresentati i contorni.

La seguente immagine illustra come questi punti vengono mappati a un volto, fai clic sull'immagine per ingrandirla:

esempio di mesh di contorno 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 la migliore frequenza fotogrammi:

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

    Rilevamento del profilo
    Rilevamento del punto di riferimento
    Classificazione
    Rilevamento e classificazione del profilo
    Rilevamento del profilo e rilevamento del punto di riferimento
    Rilevamento e classificazione del profilo
    Rilevamento del profilo, rilevamento del punto di riferimento e classificazione

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

  • Potresti acquisire immagini a una risoluzione inferiore. Tuttavia, tieni presente anche i requisiti per le dimensioni delle immagini di questa API.

  • Per l'elaborazione dei frame 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 alwaysDiscardsLateVideoFrames di AVCaptureVideoDataOutput come true per limitare le chiamate al rilevatore. Se un nuovo video diventa disponibile mentre il rilevatore è in esecuzione, viene eliminato.
  • Se utilizzi l'output del rilevatore per sovrapporre la grafica all'immagine di input, prima ottieni il risultato da ML Kit, quindi visualizza l'immagine e l'overlay in un solo passaggio. In questo modo, visualizzerai nella piattaforma display solo una volta per ogni frame di input elaborato. Guarda un esempio di updateAnteprimaOverlayViewWithLastFrame nell'esempio della guida rapida di ML Kit.