40 votes

Détection de visage avec caméra

Comment puis-je faire face à la détection en temps réel de même que la "Caméra" n'?

enter image description here

J'ai remarqué que AVCaptureStillImageOutput est obsolète après 10.0, donc j'utilise AVCapturePhotoOutput à la place. Toutefois, je trouve que l'image que j'ai enregistré pour la détection de visage n'est pas satisfait? Des idées?


Mise à JOUR

Après avoir essayer de @Shravya Boggarapu mentionné. Actuellement, j'utilise AVCaptureMetadataOutput pour détecter le visage sans CIFaceDetector. Il fonctionne comme prévu. Cependant, quand je suis en train de dessiner les limites de la face, il semble mislocated. 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: AVCaptureMetadataOutputObjectsDelegate {
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
    if findFaceControl {
        findFaceControl = false
        for metadataObject in metadataObjects {
            if (metadataObject as AnyObject).type == AVMetadataObjectTypeFace {
                print("

13voto

Shravya Boggarapu Points 384

Il y a 2 façons d'aller sur la détection des visages: l'Un est CIFaceDetector et l'autre est AVCaptureMetadataOutput

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, AVCaptureMetadataOutput est calculée sur les images et les visages détectés sont suivis et il n'y a pas de code supplémentaire nécessaire pour être ajoutés par nous. Je trouve que, parce que le suivi des visages sont détectés de manière plus fiable dans ce processus. Le con, c'est que vous aurez simplement à détecter les visages, pas de la position des yeux/bouche. Un autre avantage de cette méthode est que les questions d'orientation sont moins comme vous pouvez le videoOrientation chaque fois que l'appareil change de position et l'orientation de la face va être par rapport à cette orientation

Dans mon cas, mon application utilise YUV420 que le format requis, donc à l'aide d'CIDetector (qui fonctionne avec RVB) en temps réel n'était pas viable. À l'aide de AVCaptureMetadataOutput sauvé beaucoup d'efforts et exécutée de manière plus fiable en raison d'un suivi continu.

Une fois que j'ai eu de la boîte englobante pour le visage, j'ai codé des fonctionnalités supplémentaires, telles que la peau, la détection et l'a appliqué sur l'image.

Remarque: Lors de la capture d'image, le visage de la boîte de l'information est ajoutée avec les métadonnées donc, pas de problèmes de synchronisation.

Vous pouvez également utiliser une combinaison des deux afin d'obtenir de meilleurs résultats.

Ne étudier et d'évaluer les avantages et les inconvénients selon votre demande.

Mise à JOUR

Face rectangle est wrt image d'origine. Donc, pour l'écran, il peut être différent. Utiliser les éléments suivants:

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 */
}

8voto

Willjay Points 2888

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

OMI, Google Mobile Vision fournit de meilleures performances.

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


Après la WWDC 2017, Apple introduit CoreML dans iOS 11. La Vision du cadre rend la détection de visage plus précis :)

J'ai fait un Projet de Démonstration. contenant de la Vision de la c. s. CIDetector. Il contient également face à des monuments de la détection en temps réel.

3voto

Elena Points 11

Un peu en retard, mais ici, c'est la solution pour les coordonnées problème. Il y a une méthode que vous pouvez appeler à l'aperçu de la couche de transformer l'objet de métadonnées pour votre système de coordonnées: transformedMetadataObject(pour: 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

Par ailleurs, dans le cas où vous utilisez (ou de mise à niveau de votre projet de Swift 4, le délégué de la méthode de AVCaptureMetadataOutputsObject a changer:

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

Cordialement

2voto

jnblanchard Points 366
 extension CameraViewController: AVCaptureMetadataOutputObjectsDelegate {
  func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
    if findFaceControl {
      findFaceControl = false
      let faces = metadata.flatMap { $0 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 didOutputMetadataObjects.

Garder une trace des identifiants faciaux actifs est le meilleur moyen de le faire ^

De même, lorsque vous essayez de localiser les visages pour votre couche d'aperçu, il est beaucoup plus facile d'utiliser les données et les transformer. De plus, je pense que CIDetector est indésirable, metadataoutput utilisera du matériel pour la détection des visages, ce qui le rend très rapide.

0voto

ricardopereira Points 3249

En regardant ton code, je l'ai détecté 2 choses qui pourrait conduire à un mauvais/pauvres détection de visage.

  1. L'un d'eux est le visage détecteur dispose d'options lorsque vous filtrez les résultats en [CIDetectorSmile: true, CIDetectorEyeBlink: true]. Essayez de le mettre à néant: faceDetector?.features(in: faceImage, options: nil)
  2. Un autre pense que j'ai est le résultat de l'image de l'orientation. 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 l'image avec une orientation spécifique, de type Left/LandscapeLeft, je pense. Donc, fondamentalement, vous pouvez dire à la face du détecteur d'avoir cela à l'esprit en utilisant l' CIDetectorImageOrientation - clés.

CIDetectorImageOrientation: la valeur de cette clé est un nombre entier NSNumber à partir de 1..8 comme on en trouve dans kCGImagePropertyOrientation. Si elle est présente, la détection se fera en fonction de cette orientation, mais les coordonnées dans le retour de fonctionnalités seront toujours basées sur celles de l'image.

Essayez de le définir comme faceDetector?.features(in: faceImage, options: [CIDetectorImageOrientation: 8 /*Left, bottom*/]).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X