En introduksjon til ansiktsgjenkjenning på Android

An Introduksjon til ansiktsgjenkjenning på Android

15
Del
12
Del
Dette Cyber ​​mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.

Introdusert med Vision bibliotekene i Play Services 8.1, gjør det enkelt for deg som utvikler til å analysere en video eller bilde for å finne ansikter ansiktsgjenkjenning. Når du har en liste over ansikter på et bilde, kan du samle informasjon om hvert ansikt, for eksempel orientering, sannsynligheten for smilende, om noen har øynene åpne eller lukket, og bestemte landemerker i ansiktet.

Denne informasjonen kan være nyttig for flere programmer, for eksempel et kamera app som automatisk tar bilde når alle i rammen smiler med øynene åpne, eller for å forsterke bilder med tåpelige effekter, for eksempel unicorn horn. Det er viktig å merke seg at ansiktsgjenkjenning er
ikke ansiktsgjenkjenning. Mens informasjonen kan samles om et ansikt, er at informasjonen ikke brukes av Vision biblioteket for å avgjøre om to ansikter kommer fra samme person.

Denne opplæringen vil bruke et stillbilde for å kjøre ansiktsgjenkjenning API og samle informasjon om personer i bildet, samtidig som illustrerer denne informasjonen med overtrukket grafikk. All kode for denne opplæringen kan bli funnet på GitHub.

1. Prosjektet Setup

Hvis du vil legge til Vision biblioteket til prosjektet, må du importere Play Services 8.1 eller mer inn i prosjektet. Denne opplæringen importen bare Play Services Vision bibliotek. Åpne prosjektets build.gradle fil og legge til følgende kompilere linje til avhengig node
kompilere. Com.google.android.gms: play-tjenester-visjon: 8.1.0 '

Når du har tatt Play Services inn i prosjektet, kan du lukke prosjektets build.gradle fil og åpne AndroidManifest.xml. Du må legge til en meta-data element som definerer ansiktet avhengighet under søknaden node av manifest. Dette lar Vision bibliotek vet at du har tenkt til å gjenkjenne ansikter i søknaden din
< meta-data android. Name = "com.google.android.gms.vision.DEPENDENCIES" android: value = "ansikt" />

Når du er ferdig med å sette opp AndroidManifest.xml, kan du gå videre og lukke den. Deretter må du opprette en ny klasse som heter FaceOverlayView.java. Denne klassen strekker Se og inneholder logikken for å detektere ansikter i prosjektet, viser bitmap som ble analysert og tegning på toppen av bildet for å illustrere poeng.

For nå begynne med å legge medlemsvariabler på toppen av klassen og definere konstruktører. The Bitmap objektet vil bli brukt til å lagre bitmap som vil bli analysert og SparseArray av Face objekter vil lagre hvert ansikt funnet i bitmap
public class FaceOverlayView strekker Vis {private Bitmap mBitmap.; private SparseArray < Face > mFaces; offentlig FaceOverlayView (Context kontekst) {dette (kontekst, null); } Public FaceOverlayView (Context kontekst, AttributeSet attrs) {dette (sammenheng attrs, 0); } Offentlig FaceOverlayView (Context kontekst, AttributeSet attrs, int defStyleAttr) {super (kontekst, attrs, defStyleAttr); }}

Deretter legger du til en ny metode innsiden av FaceOverlayView kalt SetBitmap (Bitmap bitmap). For nå vil dette bare lagre bitmap sendes til det, men senere vil du bruke denne metoden for å analysere bilde
public void SetBitmap (Bitmap bitmap) {mBitmap = bitmap;}.

Deretter må du punktgrafikk. Jeg har tatt en i prøveprosjektet på GitHub, men du kan bruke hvilket som helst bilde som du ønsker for å spille med ansiktsgjenkjenning og se hva som fungerer og hva som ikke virker. Når du har valgt et bilde, legg det inn i res /rå katalogen. Denne opplæringen vil anta at bildet kalles face.jpg.

Etter at du har plassert bildet ditt inn i res /rå katalog, åpen res /layout /activity_main.xml. Dette oppsettet inneholder en referanse til FaceOverlayView slik at det vises i MainActivity
< xml version = "1.0" encoding = "UTF-8" > < com.tutsplus.facedetection.FaceOverlayView xmlns:.? Android = "http://schemas.android.com/apk/res/android" android: id = "+ id /face_overlay" android: layout_width = "match_parent" android: layout_height = "match_parent" />

Med layout definert, åpen MainActivity og sette opp FaceOverlayView fra onCreate (). Du gjør dette ved å få en henvisning til visningen, lese face.jpg bildefil fra rå katalogen som en inngang strøm, og konvertere den til et bitmap. Når du har bitmap, kan du ringe SetBitmap på FaceOverlayView å passere bildet til tilpasset visning
public class MainActivity strekker AppCompatActivity {private FaceOverlayView mFaceOverlayView.; Override Beskyttet void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); mFaceOverlayView = (FaceOverlayView) findViewById (R.id.face_overlay); . Input stream = getResources () openRawResource (R.raw.face); Bitmap bitmap = BitmapFactory.decodeStream (stream); mFaceOverlayView.setBitmap (bitmap); }}
2. Registrere ansikter

Nå som prosjektet er satt opp, er det på tide å begynne å oppdage ansikter. I SetBitmap (Bitmap bitmap) du trenger for å lage en FaceDetector. Dette kan gjøres ved hjelp av en FaceDetector.Builder, slik at du kan definere flere parametere som påvirker hvor raskt ansikter vil bli oppdaget og hvilke andre data FaceDetector vil generere.

Innstillingene som du plukker avhenge av hva du er forsøker å gjøre i programmet. Hvis du aktiverer søker etter landemerker, står da vil bli oppdaget saktere. Som med de fleste ting i programmering, har alt sine avveininger. Hvis du vil vite mer om de tilgjengelige alternativene for FaceDetector.Builder, kan du finne den offisielle dokumentasjonen på Androids utvikler hjemmeside.
FaceDetector detektor = new FaceDetector.Builder (getContext ()) .setTrackingEnabled (falsk) .setLandmarkType (FaceDetector.ALL_LANDMARKS) .setMode (FaceDetector.FAST_MODE) att bygga ();

Du må også ha en sjekk for å se om FaceDetector er i drift. Når en bruker benytter ansiktsgjenkjenning for første gang på sin enhet, Play Services trenger å gå ut og få et sett med små innfødte biblioteker for å behandle forespørselen for programmet. Selv om dette vil nesten alltid gjøres før app er ferdig starter, er det viktig å håndtere beredskaps at dette har mislyktes.

Hvis FaceDetector er i drift, så kan du konvertere bitmap inn i en ramme objekt og pass Det til detektoren for å samle inn data om ansiktene i bildet. Når du er ferdig, må du slippe detektoren for å forhindre en minnelekkasje. Når du er ferdig med å detektere ansikter, ring ugyldig () for å utløse redrawing utsikten.
If (! Detector.isOperational ()) {//Håndtak beredskaps} else {Frame ramme = new Frame.Builder (). SetBitmap (bitmap ).bygge(); mFaces = detector.detect (ramme); detector.release ();} ugyldig ();

Nå som du har oppdaget ansiktene i bildet, er det på tide å bruke dem. For dette eksempelet, vil du bare trekke en grønn boks rundt hvert ansikt. Siden ugyldig () ble kalt etter ansiktene ble oppdaget, kan du legge all nødvendig logikk inn onDraw (Canvas lerret). Denne metoden sikrer at bitmap og ansikter er satt, deretter trekke bitmap på lerretet, og deretter tegne en boks rundt hvert ansikt.

Siden forskjellige enheter har ulike skjermstørrelser, du vil også holde styr på bitmap s . skalert størrelse slik at hele bildet er alltid synlig på enheten, og alle overlegg er trukket riktig
Overrideprotected void onDraw (lerret lerret) {super.onDraw (lerret); if ((mBitmap = null) &! & (mFaces = null)) {double skala = drawBitmap (lerret); drawFaceBox (lerret, skala); }}

drawBitmap (Canvas lerret) metoden trekker bitmap på lerretet og størrelser det på riktig måte samtidig tilbake en multiplikator for skalering dine andre dimensjoner riktig.
privat dobbel drawBitmap (lerret lerret) {double viewWidth = lerret. getWidth (); double viewHeight = canvas.getHeight (); double imageWidth = mBitmap.getWidth (); double imageHeight = mBitmap.getHeight (); dobbel skala = Math.min (viewWidth /imageWidth, viewHeight /imageHeight); Rektangel destBounds = new rect (0, 0, (int) (imageWidth * skala), (int) (imageHeight * skala)); canvas.drawBitmap (mBitmap, null, destBounds, null); returnere skala;}

drawFaceBox (Canvas lerret, dobbel skala) metoden blir litt mer interessant. Hvert ansikt som ble detektert og lagret posisjon har en verdi over og til venstre for hver flate. Denne metoden vil ta den posisjonen og tegne en grønn firkant fra det til å omfatte hvert ansikt basert på sin bredde og høyde.

Du må definere din Paint objekt og deretter sløyfe gjennom hver Face i SparseArray å finne sin posisjon , bredde og høyde, og tegne rektangelet på lerretet ved hjelp av denne informasjonen.
private void drawFaceBox (Canvas lerret, dobbel skala) {//maling bør defineres som et medlem variabel i stedet //opprettes på hver onDraw forespørsel, men til venstre her for //vekt. Maling maling = ny lakk (); paint.setColor (Color.GREEN); paint.setStyle (Paint.Style.STROKE); paint.setStrokeWidth (5); flyter venstre = 0; flyte over = 0; flyte rett = 0; flyte under = 0; for (int i = 0; i < mFaces.size (); i ++) {Face face = mFaces.valueAt (i); venstre = (float) (face.getPosition () x * skala.); top = (float) (face.getPosition () y * skala.); høyre = (float) skala * (face.getPosition () x + face.getWidth ().); under = (float) skalere * (face.getPosition () y + face.getHeight ().); canvas.drawRect (venstre, topp, høyre, nederst, maling); }}

På dette punktet, bør du være i stand til å kjøre programmet og se bildet med rektangler rundt hvert ansikt som har blitt oppdaget. Det er viktig å merke seg at ansiktsgjenkjenning API er fortsatt ganske ny på tidspunktet for dette skriftlig, og det kan ikke oppdage hvert ansikt. Du kan spille med noen av innstillingene i FaceDetector.Builder gjenstand for å forhåpentligvis samle mer data, selv om det ikke er garantert.

3. Forstå Landemerker

Landemerker er interessante på et ansikt. The Face Detection API ikke bruker landemerker for å oppdage et ansikt, men heller oppdager et ansikt i sin helhet før du ser etter landemerker. Det er derfor oppdage landemerker er en valgfri innstilling som kan aktiveres via FaceDetector.Builder.

Du kan bruke disse landemerkene som en ekstra kilde til informasjon, som hvor motivets øyne er, slik at du kan reagere hensiktsmessig i din app. Det er tolv landemerker som er mulig å finne:

venstre og høyre øye

venstre og høyre øre

venstre og høyre øre tips

bunnen av nesen

venstre og høyre kinn

til venstre og høyre hjørne av munnen

bunnen av munnen

De landemerker som er tilgjengelige avhenger av vinkelen til det detekterte ansiktet. For eksempel vil noen som vender ut til siden bare har ett øye synlig, noe som betyr at det andre øyet ikke vil være detekterbar. Tabellen nedenfor viser hvilke landemerker skal være synlig basert på Euler Y vinkelen (retning venstre eller høyre) i ansiktet
Euler Y
Synlige Merker
<.; -36 ° venstre øye, forlot munnen, venstre øre, nese base, venstre kinn 36 ° til -12 ° venstre munn, nese base, bunn munnen, høyre øye, venstre øye, venstre kinn, venstre øre tip-12 ° til 12 ° høyre øye, venstre øye, nese base, venstre kinn, høyre kinn, venstre munn, rett munn, bunn mouth12 ° til 36 ° høyre munn, nese base, bunn munn, venstre øye, høyre øye, høyre kinn, høyre øre tips > 36 ° høyre øye, rett munn, høyre øre, nese base, høyre kinn

Landemerker er også utrolig lett å bruke i programmet som du allerede har tatt dem i løpet av ansiktsgjenkjenning. Du trenger bare å ringe getLandmarks () på et ansikt objekt for å få en liste over Landmark objekter som du kan arbeide med.

I denne opplæringen, vil du male en liten sirkel på hvert oppdaget landemerke ved å ringe en ny metode , drawFaceLandmarks (Canvas lerret, dobbel skala), fra onDraw (canvas lerret) i stedet for drawFaceBox (Canvas lerret, dobbel skala). Denne metoden tar posisjonen til hver landemerke, justerer det for omfanget av punktgrafikk, og viser deretter landemerke indikator sirkel
private void drawFaceLandmarks (lerret lerret, dobbel akse) {Paint maling = ny Paint (.); paint.setColor (Color.GREEN); paint.setStyle (Paint.Style.STROKE); paint.setStrokeWidth (5); for (int i = 0; i < mFaces.size (); i ++) {Face face = mFaces.valueAt (i); for (Landmark Landmark: face.getLandmarks ()) {int CX = (int) (. landmark.getPosition () x * skala); int cy = (int) (landmark.getPosition () y * skala.); canvas.drawCircle (cx, CY, 10, maling); }}}

Etter å ringe denne metoden, bør du se små grønne sirklene som dekker de oppdagede ansikter som vist i eksempelet nedenfor.

4. Tilleggsansiktsdata

Mens plasseringen av et ansikt og dets landemerker er nyttige, kan du også finne mer informasjon om hvert ansikt oppdaget i programmet ditt gjennom noen innebygde metoder fra Face objektet. De getIsSmilingProbability (), getIsLeftEyeOpenProbability () og getIsRightEyeOpenProbability () metoder forsøke å finne ut om øynene er åpne eller hvis personen oppdaget smiler ved å returnere en flottør som spenner fra 0.0 til 1.0. Jo nærmere 1.0, jo mer sannsynlig at personen smiler eller har sin venstre eller høyre øye åpent.

Du kan også finne vinkelen på ansiktet på Y og Z-aksene i et bilde ved å sjekke Euler verdier . Z Euler verdi vil alltid bli rapportert, men du må bruke nøyaktig modus når det oppdages ansikter for å få X-verdien. . Du kan se et eksempel på hvordan du kan få disse verdiene i følgende kodebiten
private void logFaceData () {float smilingProbability; flyte leftEyeOpenProbability; flyte rightEyeOpenProbability; flyte eulerY; flyte eulerZ; for (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", "Venstre øye åpent:" + leftEyeOpenProbability); Log.e ("Tuts + Face Detection", "Høyre øye åpent:" + rightEyeOpenProbability); Log.e ("Tuts + Face Detection", "Euler Y:" + eulerY); Log.e ("Tuts + Face Detection", "Euler Z:" + eulerZ); }}
Konklusjon

I denne opplæringen, har du lært om en av de viktigste komponentene i Play Services Vision bibliotek, ansiktsgjenkjenning. Du vet nå hvordan å gjenkjenne ansikter i et stillbilde, hvordan å samle informasjon, og finne viktige landemerker for hvert ansikt.

Bruk det du har lært, bør du være i stand til å legge til noen flotte funksjoner til dine egne apps for å forsterke stillbilder, sporing ansikter i en video feed, eller noe annet du kan tenke deg.



Previous:No