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?
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?
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("
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 */
}
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.
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.
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)
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
en regardant votre code j'ai détecté 2 choses qui pourraient conduire à une mauvaise / mauvaise détection du visage.
- 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)
- 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 typeLeft
/