Introdotto con le librerie di Vision in Play Services 8.1, Face Detection rende facile per te come sviluppatore analizzare un video o un'immagine per individuare volti umani. Una volta che hai un elenco di volti rilevati su un'immagine, puoi raccogliere informazioni su ciascuna faccia, come l'orientamento, la probabilità di sorridere, se qualcuno ha gli occhi aperti o chiusi e punti di riferimento specifici sul loro viso.
Queste informazioni possono essere utili per più applicazioni, ad esempio un'applicazione per fotocamera che scatta automaticamente una foto quando tutti i soggetti nella cornice stanno sorridendo con gli occhi aperti o per aumentare le immagini con effetti stupidi, come le corna di unicorno. È importante notare che Face Detection è non riconoscimento facciale. Mentre le informazioni possono essere raccolte su un volto, tali informazioni non vengono utilizzate dalla libreria Vision per determinare se due volti provengono dalla stessa persona.
Questo tutorial utilizzerà un'immagine fissa per eseguire l'API Face Detection e raccogliere informazioni sulle persone nella foto, oltre a illustrare tali informazioni con grafici sovrapposti. Tutto il codice per questo tutorial può essere trovato su GitHub.
Per aggiungere la libreria Vision al tuo progetto, devi importare Play Services 8.1 o versione successiva nel tuo progetto. Questo tutorial importa solo la libreria Play Services Vision. Aperto il tuo progetto build.gradle file e aggiungere la seguente riga di compilazione al file dipendenze
nodo.
compila "com.google.android.gms: play-services-vision: 8.1.0"
Una volta inclusi i servizi di gioco nel tuo progetto, puoi chiudere i tuoi progetti build.gradle file e aperto AndroidManifest.xml. Devi aggiungere un meta-dati
elemento che definisce la dipendenza del viso sotto il applicazione
nodo del tuo manifest. Ciò consente alla libreria Vision di sapere che si intende rilevare i volti all'interno dell'applicazione.
Al termine della configurazione AndroidManifest.xml, puoi andare avanti e chiuderlo. Successivamente, è necessario creare una nuova classe chiamata FaceOverlayView.java. Questa classe si estende vista
e contiene la logica per rilevare i volti nel progetto, visualizzando la bitmap che è stata analizzata e disegnata sopra l'immagine per illustrare i punti.
Per ora, inizia aggiungendo le variabili membro all'inizio della classe e definendo i costruttori. Il Bitmap
l'oggetto verrà utilizzato per memorizzare la bitmap che verrà analizzata e il file SparseArray
di Viso
gli oggetti memorizzeranno ogni faccia trovata nella bitmap.
public class FaceOverlayView estende View private Bitmap mBitmap; SparseArray privatomFaces; public FaceOverlayView (Context context) this (context, null); public FaceOverlayView (Context context, AttributeSet attrs) this (context, attrs, 0); public FaceOverlayView (Contesto contesto, AttributeSet attrs, int defStyleAttr) super (context, attrs, defStyleAttr);
Successivamente, aggiungi un nuovo metodo all'interno di FaceOverlayView
chiamato setBitmap (bitmap bitmap)
. Per ora questo semplicemente salverà la bitmap passata ad esso, tuttavia in seguito userete questo metodo per analizzare l'immagine.
public void setBitmap (Bitmap bitmap) mBitmap = bitmap;
Successivamente, hai bisogno di una bitmap. Ne ho incluso uno nel progetto di esempio su GitHub, ma puoi usare qualsiasi immagine che desideri per giocare con Face Detection e vedere cosa funziona e cosa no. Quando hai selezionato un'immagine, inseriscila nel res / raw directory. Questo tutorial assumerà che l'immagine sia stata chiamata face.jpg.
Dopo aver inserito la tua immagine nel res / raw directory, aperto res / layout / activity_main.xml. Questo layout contiene un riferimento a FaceOverlayView
in modo che sia visualizzato in Attività principale
.
Con il layout definito, aperto Attività principale
e impostare il FaceOverlayView
a partire dal onCreate ()
. Lo fai ottenendo un riferimento alla vista, leggendo il face.jpg file di immagine dalla directory raw come flusso di input e convertendolo in una bitmap. Una volta che hai la bitmap, puoi chiamare SetBitmap
sul FaceOverlayView
per passare l'immagine alla tua visualizzazione personalizzata.
public class MainActivity estende 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);
Ora che il tuo progetto è impostato, è tempo di iniziare a rilevare i volti. Nel setBitmap (bitmap bitmap)
devi creare un FaceDetector
. Questo può essere fatto usando a FaceDetector.Builder
, consentendo di definire più parametri che influenzano la rapidità con cui i volti saranno rilevati e quali altri dati FaceDetector
genererà.
Le impostazioni scelte dipendono da ciò che stai tentando di fare nella tua applicazione. Se abiliti la ricerca di punti di riferimento, i volti verranno rilevati più lentamente. Come per la maggior parte delle cose in programmazione, tutto ha i suoi compromessi. Per saperne di più sulle opzioni disponibili per FaceDetector.Builder
, puoi trovare la documentazione ufficiale sul sito web degli sviluppatori di Android.
FaceDetector detector = new FaceDetector.Builder (getContext ()) .setTrackingEnabled (false) .setLandmarkType (FaceDetector.ALL_LANDMARKS) .setMode (FaceDetector.FAST_MODE) .build ();
È inoltre necessario avere un controllo per vedere se il FaceDetector
è operativo. Quando un utente utilizza il rilevamento volti per la prima volta sul proprio dispositivo, Play Services deve uscire e ottenere una serie di piccole librerie native per elaborare la richiesta dell'applicazione. Sebbene ciò avvenga quasi sempre prima che l'app abbia terminato l'avvio, è importante gestire l'eventualità che ciò non abbia funzionato.
Se la FaceDetector
è operativo, quindi puoi convertire la tua bitmap in a Telaio
oggetto e passarlo al rilevatore per raccogliere dati sui volti nell'immagine. Al termine, sarà necessario rilasciare il rilevatore per evitare perdite di memoria. Quando hai finito di rilevare i volti, chiama invalidate ()
per avviare il ridisegno della vista.
if (! detector.isOperational ()) // Handle contingency else Frame frame = new Frame.Builder (). setBitmap (bitmap) .build (); mFaces = detector.detect (frame); detector.release (); invalidate ();
Ora che hai rilevato i volti nell'immagine, è ora di usarli. Per questo esempio, disegnerai semplicemente una casella verde attorno a ciascuna faccia. Da invalidate ()
è stato chiamato dopo che sono stati rilevati i volti, è possibile aggiungere tutta la logica necessaria in onDraw (Canvas canvas)
. Questo metodo garantisce che la bitmap e le facce siano impostate, quindi disegnare la bitmap sull'area di disegno e quindi disegnare una casella attorno a ciascuna faccia.
Poiché diversi dispositivi hanno dimensioni di visualizzazione diverse, si terrà anche traccia delle dimensioni ridimensionate della bitmap in modo che l'intera immagine sia sempre visibile sul dispositivo e tutti gli overlay siano disegnati in modo appropriato.
@Override protected void onDraw (Canvas canvas) super.onDraw (canvas); if ((mBitmap! = null) && (mFaces! = null)) double scale = drawBitmap (canvas); drawFaceBox (tela, scala);
Il drawBitmap (Canvas canvas)
metodo disegna la tua bitmap sulla tela e la adatta in modo appropriato, mentre restituisce un moltiplicatore per ridimensionare correttamente le altre dimensioni.
private double drawBitmap (Canvas 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); scala di ritorno;
Il drawFaceBox (Canvas canvas, doppia scala)
il metodo diventa un po 'più interessante. Ogni faccia che è stata rilevata e salvata ha un valore di posizione sopra e alla sinistra di ogni faccia. Questo metodo prenderà quella posizione e traccerà un rettangolo verde da esso per racchiudere ogni faccia in base alla sua larghezza e altezza.
Devi definire il tuo Dipingere
oggetto e quindi passano in rassegna ciascuno Viso
nel tuo SparseArray
per trovare la sua posizione, larghezza e altezza e disegnare il rettangolo sulla tela usando quell'informazione.
private void drawFaceBox (Canvas canvas, double scale) // paint dovrebbe essere definito come una variabile membro piuttosto che // essere creato su ogni richiesta onDraw, ma lasciato qui per // emphasis. 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; float bottom = 0; per (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 );
A questo punto, dovresti essere in grado di eseguire la tua applicazione e vedere l'immagine con rettangoli attorno a ogni faccia che è stata rilevata. È importante notare che l'API Face Detection è ancora abbastanza nuova al momento della stesura di questo documento e potrebbe non rilevare ogni volto. Puoi giocare con alcune delle impostazioni nel FaceDetector.Builder
oggetto per poter eventualmente raccogliere più dati, anche se non è garantito.
I punti di riferimento sono punti di interesse su una faccia. L'API Face Detection non utilizza i punti di riferimento per rilevare un volto, ma rileva un volto nella sua interezza prima di cercare i punti di riferimento. Questo è il motivo per cui la scoperta di punti di riferimento è un'impostazione facoltativa che può essere attivata tramite FaceDetector.Builder
.
Puoi utilizzare questi punti di riferimento come ulteriore fonte di informazioni, ad esempio dove sono gli occhi del soggetto, in modo che tu possa reagire in modo appropriato all'interno della tua app. Ci sono dodici punti di riferimento che è possibile trovare:
I punti di riferimento disponibili dipendono dall'angolo del volto rilevato. Ad esempio, qualcuno che si trova di fronte vedrà solo un occhio visibile, il che significa che l'altro occhio non sarà rilevabile. La seguente tabella evidenzia quali punti di riferimento dovrebbero essere rilevabili in base all'angolo di Eulero Y (direzione sinistra o destra) del viso.
Eulero Y | Punti di riferimento visibili |
---|---|
< -36° | occhio sinistro, bocca sinistra, orecchio sinistro, base del naso, guancia sinistra |
-Da 36 ° a -12 ° | bocca sinistra, base del naso, bocca inferiore, occhio destro, occhio sinistro, guancia sinistra, orecchio sinistro |
-12 ° a 12 ° | occhio destro, occhio sinistro, base del naso, guancia sinistra, guancia destra, bocca sinistra, bocca destra, bocca inferiore |
12 ° a 36 ° | bocca destra, base del naso, bocca in basso, occhio sinistro, occhio destro, guancia destra, orecchio destro |
> 36 ° | occhio destro, bocca destra, orecchio destro, base del naso, guancia destra |
I punti di riferimento sono anche incredibilmente facili da usare nella tua applicazione come li hai già inclusi durante il rilevamento dei volti. Devi semplicemente chiamare getLandmarks ()
a Viso
oggetto di ottenere un Elenco
di Punto di riferimento
oggetti con cui puoi lavorare.
In questo tutorial, dipingi un piccolo cerchio su ogni punto di riferimento rilevato chiamando un nuovo metodo, drawFaceLandmarks (Canvas canvas, doppia scala)
, a partire dal onDraw (canvas canvas)
invece di drawFaceBox (Canvas canvas, doppia scala)
. Questo metodo prende la posizione di ciascun punto di riferimento, lo regola per la scala della bitmap e quindi visualizza il cerchio dell'indicatore del punto di riferimento.
private void drawFaceLandmarks (Canvas canvas, double scale) Paint paint = new Paint (); paint.setColor (Color.GREEN); paint.setStyle (Paint.Style.STROKE); paint.setStrokeWidth (5); per (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 );
Dopo aver chiamato questo metodo, dovresti vedere piccoli cerchi verdi che coprono i volti rilevati, come mostrato nell'esempio seguente.
Mentre la posizione di un volto e i suoi punti di riferimento sono utili, puoi anche trovare ulteriori informazioni su ciascun volto rilevato nella tua app attraverso alcuni metodi incorporati del Viso
oggetto. Il getIsSmilingProbability ()
, getIsLeftEyeOpenProbability ()
e getIsRightEyeOpenProbability ()
i metodi tentano di determinare se gli occhi sono aperti o se la persona rilevata sorride restituendo un galleggiante che va da 0.0 a 1.0. Più si avvicina a 1.0, più è probabile che quella persona sorrida o abbia l'occhio sinistro o destro aperto.
Puoi anche trovare l'angolo della faccia sugli assi Y e Z di un'immagine controllando i suoi valori di Eulero. Il valore di Z Eulero verrà sempre riportato, tuttavia, è necessario utilizzare la modalità precisa quando si rilevano i volti per ricevere il valore X. Puoi vedere un esempio di come ottenere questi valori nel seguente frammento di codice.
private void logFaceData () float smilingProbability; float leftEyeOpenProbability; float rightEyeOpenProbability; float eulerY; float eulerZ; per (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 );
In questo tutorial, hai imparato a conoscere uno dei componenti principali della libreria Play Services Vision, Riconoscimento facciale. Ora sai come rilevare i volti in un'immagine fissa, come raccogliere informazioni e trovare punti di riferimento importanti per ogni faccia.
Usando ciò che hai imparato, dovresti essere in grado di aggiungere alcune fantastiche funzioni alle tue app per aumentare le immagini fisse, il tracciamento dei volti in un feed video o qualsiasi altra cosa tu possa immaginare.