Introduite avec les bibliothèques Vision dans Play Services 8.1, la détection de visage vous permet, en tant que développeur, d'analyser facilement une vidéo ou une image afin de localiser des visages humains. Une fois que vous avez une liste de visages détectés sur une image, vous pouvez collecter des informations sur chaque visage, telles que l'orientation, la probabilité de sourire, si une personne a les yeux ouverts ou fermés et des repères spécifiques sur le visage..
Ces informations peuvent être utiles pour plusieurs applications, telles qu'une application appareil photo qui prend automatiquement une photo lorsque tout le monde dans le cadre sourit les yeux ouverts ou pour augmenter les images avec des effets stupides, tels que des cornes de licorne. Il est important de noter que la détection de visage est ne pas la reconnaissance faciale. Bien que des informations puissent être collectées sur un visage, ces informations ne sont pas utilisées par la bibliothèque Vision pour déterminer si deux visages proviennent de la même personne..
Ce tutoriel utilisera une image fixe pour exécuter l'API de détection de visage et collecter des informations sur les personnes figurant sur la photo, tout en illustrant ces informations avec des graphiques superposés. Tous les codes de ce tutoriel sont disponibles sur GitHub.
Pour ajouter la bibliothèque Vision à votre projet, vous devez importer Play Services 8.1 ou une version ultérieure dans votre projet. Ce didacticiel importe uniquement la bibliothèque Play Services Vision. Ouvrir votre projet build.gradle fichier et ajouter la ligne de compilation suivante à la les dépendances
nœud.
compilez 'com.google.android.gms: play-services-vision: 8.1.0'
Une fois que vous avez inclus Play Services dans votre projet, vous pouvez fermer celui-ci. build.gradle déposer et ouvrir AndroidManifest.xml. Vous devez ajouter un méta-données
élément définissant la dépendance du visage sous la application
noeud de votre manifeste. Cela permet à la bibliothèque Vision de savoir que vous prévoyez de détecter les visages dans votre application..
Une fois que vous avez fini de vous installer AndroidManifest.xml, vous pouvez aller de l'avant et le fermer. Ensuite, vous devez créer une nouvelle classe nommée FaceOverlayView.java. Cette classe s'étend Vue
et contient la logique de détection des visages dans le projet, affichant le bitmap analysé et dessiné au-dessus de l'image pour illustrer des points.
Pour l'instant, commencez par ajouter les variables membres en haut de la classe et en définissant les constructeurs. le Bitmap
objet sera utilisé pour stocker le bitmap qui sera analysé et le SparseArray
de Visage
les objets vont stocker chaque visage trouvé dans le bitmap.
Classe publique FaceOverlayView extend View private Bitmap mBitmap; SparseArray privémFaces; public FaceOverlayView (contexte de contexte) this (contexte, null); public FaceOverlayView (contexte de contexte, AttributeSet attrs) this (contexte, attrs, 0); public FaceOverlayView (contexte de contexte, AttributeSet attrs, int defStyleAttr) super (contexte, attrs, defStyleAttr);
Ensuite, ajoutez une nouvelle méthode dans FaceOverlayView
appelé setBitmap (bitmap bitmap)
. Pour l'instant, cela va simplement sauvegarder le bitmap qui lui est passé, mais vous utiliserez plus tard cette méthode pour analyser l'image..
public void setBitmap (Bitmap bitmap) mBitmap = bitmap;
Ensuite, vous avez besoin d'un bitmap. J'en ai inclus un dans l'exemple de projet sur GitHub, mais vous pouvez utiliser l'image de votre choix pour jouer avec la détection de visage et voir ce qui fonctionne et ce qui ne fonctionne pas. Lorsque vous avez sélectionné une image, placez-la dans le res / raw annuaire. Ce tutoriel supposera que l'image s'appelle face.jpg.
Après avoir placé votre image dans le res / raw répertoire, ouvert res / layout / activity_main.xml. Cette mise en page contient une référence à FaceOverlayView
afin qu'il soit affiché dans Activité principale
.
Avec la mise en page définie, ouvrez Activité principale
et mettre en place le FaceOverlayView
de onCreate ()
. Vous faites cela en obtenant une référence à la vue, en lisant le face.jpg fichier image à partir du répertoire raw en tant que flux d'entrée et conversion de celui-ci en bitmap. Une fois que vous avez le bitmap, vous pouvez appeler setBitmap
sur le FaceOverlayView
passer l'image à votre vue personnalisée.
Classe publique MainActivity étend AppCompatActivity private FaceOverlayView mFaceOverlayView; @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); mFaceOverlayView = (FaceOverlayView) findViewById (R.id.face_overlay); InputStream stream = getResources (). OpenRawResource (R.raw.face); Bitmap bitmap = BitmapFactory.decodeStream (stream); mFaceOverlayView.setBitmap (bitmap);
Maintenant que votre projet est configuré, il est temps de commencer à détecter les visages. Dans setBitmap (bitmap bitmap)
vous devez créer un FaceDetector
. Cela peut être fait en utilisant un FaceDetector.Builder
, vous permettant de définir plusieurs paramètres qui affectent la rapidité de détection des visages et les autres données FaceDetector
va générer.
Les paramètres que vous choisissez dépendent de ce que vous essayez de faire dans votre application. Si vous activez la recherche de points de repère, les visages seront détectés plus lentement. Comme avec la plupart des choses dans la programmation, tout a ses compromis. Pour en savoir plus sur les options disponibles pour FaceDetector.Builder
, vous pouvez trouver la documentation officielle sur le site du développeur Android.
Détecteur FaceDetector = new FaceDetector.Builder (getContext ()) .setTrackingEnabled (false) .setLandmarkType (FaceDetector.ALL_LANDMARKS) .setMode (FaceDetector.FAST_MODE) .build ();
Vous devez également vérifier si le FaceDetector
est opérationnel. Lorsqu'un utilisateur utilise la détection de visage pour la première fois sur son appareil, Play Services doit accéder à un ensemble de petites bibliothèques natives pour traiter la demande de votre application. Bien que cela soit presque toujours fait avant que votre application ait été lancée, il est important de gérer le risque que cela échoue..
Si la FaceDetector
est opérationnel, alors vous pouvez convertir votre bitmap en un Cadre
objet et transmettez-le au détecteur pour recueillir des données sur les visages dans l’image. Lorsque vous avez terminé, vous devez libérer le détecteur pour éviter toute fuite de mémoire. Lorsque vous avez fini de détecter les visages, appelez invalider()
déclencher le rafraîchissement de la vue.
if (! detect.isOperational ()) // Gérer les imprévus else Frame frame = new Frame.Builder (). setBitmap (bitmap) .build (); mFaces = detect.detect (frame); Detector.release (); invalidate ();
Maintenant que vous avez détecté les visages dans votre image, il est temps de les utiliser. Pour cet exemple, vous allez simplement dessiner une boîte verte autour de chaque face. Puisque invalider()
a été appelé après la détection des visages, vous pouvez ajouter toute la logique nécessaire dans onDraw (toile de toile)
. Cette méthode garantit que le bitmap et les faces sont définis, puis tracez la bitmap sur la toile, puis tracez un cadre autour de chaque face..
Etant donné que les différents périphériques ont des tailles d'affichage différentes, vous garderez également une trace de la taille mise à l'échelle du bitmap afin que toute l'image soit toujours visible sur le périphérique et que toutes les superpositions soient dessinées correctement..
@Override protected void onDraw (toile Canvas) super.onDraw (toile); if ((mBitmap! = null) && (mFaces! = null)) double scale = drawBitmap (canvas); drawFaceBox (canvas, scale);
le drawBitmap (toile Canvas)
méthode dessine votre bitmap sur la toile et la redimensionne de manière appropriée, tout en renvoyant un multiplicateur permettant de redimensionner correctement vos autres dimensions.
private double drawBitmap (toile Canvas) double viewWidth = canvas.getWidth (); double viewHeight = canvas.getHeight (); double imageWidth = mBitmap.getWidth (); double imageHeight = mBitmap.getHeight (); double scale = Math.min (viewWidth / imageWidth, viewHeight / imageHeight); Rect destBounds = new Rect (0, 0, (int) (imageWidth * scale), (int) (imageHeight * scale)); canvas.drawBitmap (mBitmap, null, destBounds, null); échelle de retour;
le drawFaceBox (toile Canvas, double échelle)
la méthode devient un peu plus intéressante. Chaque face qui a été détectée et enregistrée a une valeur de position au-dessus et à gauche de chaque face. Cette méthode prend cette position et dessine un rectangle vert pour englober chaque face en fonction de sa largeur et de sa hauteur..
Vous devez définir votre Peindre
objet, puis boucle à travers chaque Visage
dans ton SparseArray
pour trouver sa position, sa largeur et sa hauteur et dessinez le rectangle sur la toile à l'aide de cette information.
private void drawFaceBox (Canevas, double échelle) // peindre doit être défini comme une variable membre plutôt que // étant créé à chaque demande onDraw, mais laissé ici pour // l'emphase. Paint Paint = new Paint (); paint.setColor (Color.GREEN); paint.setStyle (Paint.Style.STROKE); paint.setStrokeWidth (5); float left = 0; float top = 0; float right = 0; fond de flotteur = 0; pour (int i = 0; i < mFaces.size(); i++ ) Face face = mFaces.valueAt(i); left = (float) ( face.getPosition().x * scale ); top = (float) ( face.getPosition().y * scale ); right = (float) scale * ( face.getPosition().x + face.getWidth() ); bottom = (float) scale * ( face.getPosition().y + face.getHeight() ); canvas.drawRect( left, top, right, bottom, paint );
À ce stade, vous devriez pouvoir exécuter votre application et voir votre image avec des rectangles autour de chaque visage détecté. Il est important de noter que l'API de détection de visage est encore relativement nouvelle au moment d'écrire ces lignes et qu'il est possible qu'elle ne détecte pas tous les visages. Vous pouvez jouer avec certains des paramètres de la FaceDetector.Builder
objet afin de recueillir, espérons-le, plus de données, bien que cela ne soit pas garanti.
Les points de repère sont des points d'intérêt sur un visage. L'API de détection de visage n'utilise pas de points de repère pour détecter un visage, mais détecte plutôt un visage dans son intégralité avant de rechercher des points de repère. C’est pourquoi la découverte de points de repère est un paramètre facultatif qui peut être activé via le FaceDetector.Builder
.
Vous pouvez utiliser ces points de repère comme source d'informations supplémentaire, par exemple l'endroit où se trouvent les yeux du sujet, pour pouvoir réagir de manière appropriée au sein de votre application. Il y a douze points de repère qu'il est possible de trouver:
Les points de repère disponibles dépendent de l'angle du visage détecté. Par exemple, une personne faisant face sur le côté n'aura qu'un œil visible, ce qui signifie que l'autre œil ne sera pas détectable. Le tableau suivant indique quels points de repère devraient être détectables en fonction de l'angle d'Euler Y (direction gauche ou droite) du visage..
Euler Y | Monuments visibles |
---|---|
< -36° | œil gauche, bouche gauche, oreille gauche, base du nez, joue gauche |
-36 ° à -12 ° | bouche gauche, base du nez, bouche inférieure, œil droit, œil gauche, joue gauche, extrémité de l'oreille gauche |
-12 ° à 12 ° | œil droit, œil gauche, base du nez, joue gauche, joue droite, bouche gauche, bouche droite, bouche inférieure |
12 ° à 36 ° | bouche droite, base du nez, bouche inférieure, œil gauche, œil droit, joue droite, extrémité de l'oreille droite |
> 36 ° | oeil droit, bouche droite, oreille droite, base du nez, joue droite |
Les repères sont également incroyablement faciles à utiliser dans votre application, car vous les avez déjà inclus lors de la détection des visages. Vous avez simplement besoin d'appeler getLandmarks ()
sur un Visage
objet pour obtenir un liste
de Point de repère
objets avec lesquels vous pouvez travailler.
Dans ce tutoriel, vous allez dessiner un petit cercle sur chaque repère détecté en appelant une nouvelle méthode., drawFaceLandmarks (toile Canvas, double échelle)
, de onDraw (toile de toile)
au lieu de drawFaceBox (toile Canvas, double échelle)
. Cette méthode prend la position de chaque point de repère, l’ajuste à l’échelle du bitmap, puis affiche le cercle indicateur de point de repère..
private void drawFaceLandmarks (toile Canvas, double échelle) Paint Paint = new Paint (); paint.setColor (Color.GREEN); paint.setStyle (Paint.Style.STROKE); paint.setStrokeWidth (5); pour (int i = 0; i < mFaces.size(); i++ ) Face face = mFaces.valueAt(i); for ( Landmark landmark : face.getLandmarks() ) int cx = (int) ( landmark.getPosition().x * scale ); int cy = (int) ( landmark.getPosition().y * scale ); canvas.drawCircle( cx, cy, 10, paint );
Après avoir appelé cette méthode, vous devriez voir de petits cercles verts recouvrant les visages détectés, comme indiqué dans l'exemple ci-dessous..
Bien que la position d’un visage et ses repères soient utiles, vous pouvez également obtenir plus d’informations sur chaque visage détecté dans votre application grâce aux méthodes intégrées de la Visage
objet. le getIsSmilingProbability ()
, getIsLeftEyeOpenProbability ()
et getIsRightEyeOpenProbability ()
méthodes tentent de déterminer si les yeux sont ouverts ou si la personne détectée sourit en renvoyant un flotteur allant de 0.0 à 1,0. Plus la valeur 1.0 est proche, plus cette personne sourit ou a l'œil gauche ou droit ouvert.
Vous pouvez également trouver l'angle du visage sur les axes Y et Z d'une image en vérifiant ses valeurs d'Euler. La valeur de Z Euler sera toujours signalée. Toutefois, vous devez utiliser un mode précis pour détecter les visages afin de recevoir la valeur X. Vous pouvez voir un exemple d'obtention de ces valeurs dans l'extrait de code suivant..
logFaceData () float smilingProbability; float leftEyeOpenProbability; float rightEyeOpenProbability; float eulerY; float eulerZ; pour (int i = 0; i < mFaces.size(); i++ ) Face face = mFaces.valueAt(i); smilingProbability = face.getIsSmilingProbability(); leftEyeOpenProbability = face.getIsLeftEyeOpenProbability(); rightEyeOpenProbability = face.getIsRightEyeOpenProbability(); eulerY = face.getEulerY(); eulerZ = face.getEulerZ(); Log.e( "Tuts+ Face Detection", "Smiling: " + smilingProbability ); Log.e( "Tuts+ Face Detection", "Left eye open: " + leftEyeOpenProbability ); Log.e( "Tuts+ Face Detection", "Right eye open: " + rightEyeOpenProbability ); Log.e( "Tuts+ Face Detection", "Euler Y: " + eulerY ); Log.e( "Tuts+ Face Detection", "Euler Z: " + eulerZ );
Dans ce tutoriel, vous avez découvert l’un des composants principaux de la bibliothèque Play Services Vision., Détection facial. Vous savez maintenant comment détecter des visages dans une image fixe, comment rassembler des informations et trouver des repères importants pour chaque visage..
En utilisant ce que vous avez appris, vous devriez pouvoir ajouter de superbes fonctionnalités à vos propres applications pour augmenter les images fixes, suivre les visages dans un flux vidéo, ou tout autre chose que vous pouvez imaginer..