Détection de visage avec caméra

Comment puis-je faire la détection de visage en temps réel comme "caméra" le fait?

enter image description here

j'ai remarqué que AVCaptureStillImageOutput est obsolète après 10.0, donc j'utilise AVCapturePhotoOutput à la place. Cependant, j'ai trouvé que l'image que j'ai enregistrée pour la détection faciale n'est pas si satisfaite? Des idées?


UPDATE

après un essai de @Shravya Boggarapu mentionner. Actuellement, j'utilise AVCaptureMetadataOutput pour détecter le visage sans CIFaceDetector. Il fonctionne comme prévu. Cependant, quand j'essaie de tracer les limites du visage, il semble mal placé. Une idée?

enter image description here

let metaDataOutput = AVCaptureMetadataOutput()

captureSession.sessionPreset = AVCaptureSessionPresetPhoto
    let backCamera = AVCaptureDevice.defaultDevice(withDeviceType: .builtInWideAngleCamera, mediaType: AVMediaTypeVideo, position: .back)
    do {
        let input = try AVCaptureDeviceInput(device: backCamera)

        if (captureSession.canAddInput(input)) {
            captureSession.addInput(input)

            // MetadataOutput instead
            if(captureSession.canAddOutput(metaDataOutput)) {
                captureSession.addOutput(metaDataOutput)

                metaDataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
                metaDataOutput.metadataObjectTypes = [AVMetadataObjectTypeFace]

                previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
                previewLayer?.frame = cameraView.bounds
                previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill

                cameraView.layer.addSublayer(previewLayer!)
                captureSession.startRunning()
            }

        }

    } catch {
        print(error.localizedDescription)
    }

et

 extension CameraViewController: Avcapturemetatataoutputobjectsdelegate {
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, à partir d'une connexion: AVCaptureConnection!) {
    si findFaceControl {
        findFaceControl = false
        pour le projet metadata dans les projets metadata {
            si (metadataObject as AnyObject).type = = AVMetadataObjectTypeFace {
                imprimer("            
37
demandé sur Willjay 2016-12-28 05:46:36

6 réponses

il y a 2 façons de détecter les visages: L'une est CIFaceDetector et L'autre est Avcapturemetataoutput

selon vos besoins, choisissez ce qui est pertinent pour vous.

CIFaceDetector a plus de fonctionnalités-par exemple: vous donne l'emplacement des yeux et de la bouche, détecteur de sourire, etc

D'autre part, Avcapturemetaoutput est calculé sur les trames et les faces détectées sont tracées et il n'y a pas de code supplémentaire à ajouter par nous. Je trouve qu'en raison des faces de pistage sont détectées de façon plus fiable dans ce processus. Le contre de ceci est que vous détecterez simplement des visages, aucune position des yeux/bouche. Un autre avantage de cette méthode est que les problèmes d'orientation sont moindres car vous pouvez videoOrientation chaque fois que l'orientation du périphérique est modifiée et l'orientation des faces sera relative à cette orientation

dans mon cas, mon application utilise YUV420 comme format requis donc en utilisant CIDetector (qui fonctionne avec RGB) dans en temps réel n'était pas viable. L'utilisation de Avcapturemetataoutput a permis d'économiser beaucoup d'efforts et de réaliser plus fiable en raison d'un suivi continu.

Une fois que j'ai eu la boîte limite pour les visages, j'ai codé des caractéristiques supplémentaires, telles que la détection de la peau et je l'ai appliquée sur l'image fixe.

Note: Lorsque vous capturez l'image fixe, l'information de la boîte de dialogue est ajoutée avec les métadonnées, donc pas de problèmes de synchronisation.

Vous pouvez également utiliser une combinaison des deux pour obtenir de meilleurs résultats.

explorez et évaluez les avantages et les inconvénients selon votre demande.

UPDATE

le rectangle de la Face est l'origine de l'image wrt. Donc pour l'écran, ça peut être différent. Utilisez ce qui suit:

for (AVMetadataFaceObject *faceFeatures in metadataObjects) {
    CGRect face = faceFeatures.bounds;
    CGRect facePreviewBounds = CGRectMake(face.origin.y * previewLayerRect.size.width,
                               face.origin.x * previewLayerRect.size.height,
                               face.size.width * previewLayerRect.size.height,
                               face.size.height * previewLayerRect.size.width);

    /* Draw rectangle facePreviewBounds on screen */
}
10
répondu Shravya Boggarapu 2017-10-06 13:21:51

Pour effectuer la détection de visage sur iOS, il y a soit des CIDetector (Apple) ou Vision Mobile (Google) API.

IMO, Google Mobile Vision offre de meilleures performances.

Si vous êtes intéressés, voici le projet que vous pouvez jouer avec. (iOS 10.2, Swift 3)


après la WWDC 2017, Apple introduit CoreML dans iOS 11. Vision le cadre fait la détection de la taille plus précis :)

j'ai fait un Projet De Démonstration. contenant Vision v. S. CIDetector. En outre, il contient la détection de points de repère de visage en temps réel.

6
répondu Willjay 2017-10-26 07:12:43
extension CameraViewController: AVCaptureMetadataOutputObjectsDelegate {
  func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
    if findFaceControl {
      findFaceControl = false
      let faces = metadata.flatMap {  as? AVMetadataFaceObject } .flatMap { (face) -> CGRect in
                  guard let localizedFace =
      previewLayer?.transformedMetadataObject(for: face) else { return nil }
                  return localizedFace.bounds }
      for face in faces {
        let temp = UIView(frame: face)
        temp.layer.borderColor = UIColor.white
        temp.layer.borderWidth = 2.0
        view.addSubview(view: temp)
      }
    }
  }
}

assurez-vous de supprimer les vues créées par didoutputmetataobjects.

Garder une trace de l'actif du visage id est la meilleure façon de le faire ^

aussi quand vous essayez de trouver l'emplacement des visages pour votre couche de prévisualisation, il est beaucoup plus facile d'utiliser des données faciales et de transformer. En outre, je pense que CIDetector est junk, metadataoutput va utiliser du matériel pour la détection de visage ce qui le rend vraiment rapide.

1
répondu jnblanchard 2017-12-18 01:19:49

un peu en retard, mais ici c'est la solution pour le problème des coordonnées. Il existe une méthode permettant de faire appel à la couche preview pour transformer l'objet metadata en votre système de coordonnées: transformedMetadataObject(metadataObject).

guard let transformedObject = previewLayer.transformedMetadataObject(for: metadataObject) else {
     continue
}
let bounds = transformedObject.bounds
showBounds(at: bounds)

Source: https://developer.apple.com/documentation/avfoundation/avcapturevideopreviewlayer/1623501-transformedmetadataobjectformeta

soit dit en passant, si vous utilisez (ou mettez à jour votre projet vers) Swift 4, la méthode delegate AVCaptureMetadataOutputsObject a changé en:

func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection)

cordialement

1
répondu Elena 2018-06-17 12:15:23

en regardant votre code j'ai détecté 2 choses qui pourraient conduire à une mauvaise / mauvaise détection du visage.

  1. l'Un d'eux est le visage détecteur dispose d'options lorsque vous filtrez les résultats par [CIDetectorSmile: true, CIDetectorEyeBlink: true]. Essayez de le mettre à néant: faceDetector?.features(in: faceImage, options: nil)
  2. l'Autre suppose que j'ai, c'est le résultat orientation de l'image. J'ai remarqué que vous utilisez AVCapturePhotoOutput.jpegPhotoDataRepresentation méthode pour générer de l'image source pour la détection et le système, par défaut, il génère cette image avec une orientation spécifique, de type Left/