Ville det ikke vært bra hvis en Android-app kunne se og forstå omgivelsene sine? Kan du forestille deg hvor mye bedre brukergrensesnittet kan være hvis det kan se på brukerne og umiddelbart kjenne sine aldre, kjønn og følelser? Vel, en slik app kan virke futuristisk, men det er helt gjennomførbart i dag.
Med IBM Watson Visual Recognition-tjenesten er det enklere enn noensinne å lage mobilapper som nøyaktig kan oppdage og analysere objekter i bilder. I denne veiledningen viser jeg deg hvordan du bruker den til å lage en smart Android-app som kan gjette en persons alder og kjønn og identifisere fremtredende objekter på et fotografi.
For å kunne følge denne opplæringen må du ha:
Som alle Watson-tjenester må også Visual Recognition-tjenesten aktiveres manuelt før den kan brukes i en app. Så logg inn på IBM Bluemix-konsollen og naviger til Tjenester> Watson. På siden som åpnes, trykk på Opprett Watson service knapp.
Fra listen over tilgjengelige tjenester som vises neste, velg Visuell anerkjennelse.
Du kan nå gi et meningsfylt navn til tjenesten og trykke på Skape knapp.
Når tjenesten er klar, genereres en API-nøkkel for den. Du kan vise det ved å åpne Tjenestegodkjenninger fanen og trykke på Se påloggingsinformasjon knapp.
I denne opplæringen bruker vi Watson Java og Android SDKs mens du samhandler med tjenesten Visual Recognition. Vi bruker også Picasso-biblioteket for å hente og vise bilder fra Internett. Legg derfor til følgende gjennomføring
avhengigheter til din app
modulens build.gradle fil:
implementering 'com.ibm.watson.developer_cloud: visuell anerkjennelse: 3.9.1' implementering 'com.ibm.watson.developer_cloud: android-sdk: 0.4.2' implementering 'com.squareup.picasso: picasso: 2.5.2'
For å kunne kommunisere med Watsons servere, trenger appen din INTERNETT
Tillatelse, så be om det i prosjektets AndroidManifest.xml fil.
I tillegg vil appen vi skal skape i dag, trenge tilgang til enhetens kamera og eksterne lagringsmedier, så du må også be om KAMERA
og WRITE_EXTERNAL_STORAGE
tillatelser.
Til slutt legger du til API-nøkkelen for Visual Recognition-tjenesten til strings.xml fil.
a1234567890bcdefe
Watson Java SDK avslører alle funksjonene Visual Recognition-tjenesten tilbyr gjennom VisualRecognition
klasse. Derfor må du initialisere en forekomst av den ved hjelp av sin konstruktør, som forventer både en versionsdato og API-nøkkelen som sine argumenter.
Når du bruker tjenesten Visual Recognition, vil du vanligvis ta bilder med enhetens kamera. Watson Android SDK har en CameraHelper
klassen for å hjelpe deg med å gjøre det. Selv om du ikke trenger det, foreslår jeg at du også initialiserer en forekomst av den inne i aktiviteten din onCreate ()
metode.
privat VisualRecognition vrClient; privat CameraHelper hjelper; @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); // Initialiser Visual Recognition-klienten vrClient = ny VisualRecognition (VisualRecognition.VERSION_DATE_2016_05_20, getString (R.string.api_key)); // Initialiser kamerahjelpshjelpen = ny CameraHelper (dette);
På dette punktet har du alt du trenger for å begynne å analysere bilder med tjenesten.
Tjenesten Visual Recognition kan oppdage et stort utvalg av fysiske objekter. Som input, forventer det et rimelig godt opplyst bilde hvis oppløsning er minst 224 x 224 piksler. For nå, la oss bruke enhetskameraet til å ta et slikt bilde.
Brukeren må kunne trykke på en knapp for å ta bildet, så aktivitetens layout XML-fil må ha en Knapp
widget. Det må også ha a TextView
widget for å liste opp objekter som er oppdaget.
Eventuelt kan du kaste inn en Imageview
widget for å vise bildet.
I den ovennevnte koden har vi lagt til en hendelseshåndterer på klikk på Knapp
widget. Du kan generere en stub for denne widgeten i kode den ved å klikke på lyspæren vist ved siden av den.
offentlig tomgang ta bilde (se visning) // Mer kode her
Du kan ta et bilde ved å bare ringe til CameraHelper
objektets dispatchTakePictureIntent ()
metode, så legg til følgende kode inne i hendelseshandleren:
helper.dispatchTakePictureIntent ();
Ovenstående metode bruker enhetens standard kameraapp for å ta bildet. Det betyr å få tilgang til bildet tatt, du må overstyre aktiviteten din onActivityResult ()
metode og se etter resultater hvis forespørselskode er REQUEST_IMAGE_CAPTURE
. Slik gjør du det:
@Override protected void onActivityResult (int requestCode, int resultCode, Intent data) super.onActivityResult (requestCode, resultCode, data); hvis (requestCode == CameraHelper.REQUEST_IMAGE_CAPTURE) // Mer kode her
Når du har funnet det riktige resultatet, kan du trekke bildet ut av det i form av a bitmap
objekt ved hjelp av getBitmap ()
metode av CameraHelper
klasse. Du kan også få den absolutte banen til bildet ved hjelp av getFile ()
metode. Vi trenger både bitmappen og den absolutte banen, så legg til følgende kode neste:
siste Bitmap photo = helper.getBitmap (resultCode); endelig fil photoFile = helper.getFile (resultCode);
Hvis du valgte å legge til Imageview
widget til oppsettet ditt, kan du vise bildet nå ved å sende bitmapet direkte til det setImageBitmap ()
metode.
ImageView forhåndsvisning = findViewById (R.id.preview); preview.setImageBitmap (foto);
For å oppdage elementer i bildet, må du sende bildet som en inngang til klassifisere()
metode av VisualRecognition
gjenstand. Før du gjør det, må du imidlertid pakke det inn i en ClassifyImagesOptions
objekt, som kan opprettes ved hjelp av ClassifyImagesOptions.Builder
klasse.
Returneringsverdien til klassifisere()
metoden er a ServiceCall
objekt, som støtter både synkron og asynkron nettverksforespørsler. For nå, la oss ringe det henrette()
metode for å lage en synkron forespørsel. Selvfølgelig, fordi nettverksoperasjoner ikke er tillatt på brukergrensesnittet, må du huske å gjøre det fra en ny tråd.
AsyncTask.execute (new Runnable () @Override public void run () VisualClassification response = vrClient.classify (ny ClassifyImagesOptions.Builder () .images (photoFile) .build ()) .execute (); // Mer kode her );
De klassifisere()
Metoden er bygget for å håndtere flere bilder samtidig. Følgelig er responsen en liste over klassifikasjonsdetaljer. Fordi vi for tiden jobber med et enkelt bilde, trenger vi bare det første elementet i listen. Slik kan du få det:
ImageClassification klassifisering = response.getImages (). Get (0); VisualClassifier classifier = klassifisering.getClassifiers (). Get (0);
Tjenesten Visual Recognition behandler hvert element det har oppdaget som en egen klasse av type VisualClassifier.VisualClass
. Ved å ringe getClasses ()
Metode, du kan få en liste over alle klassene.
Hver klasse har blant annet et navn og en tillitsscore som er knyttet til den. Følgende kode viser deg hvordan du går gjennom listen over klasser og viser navnene til bare de som har en score på over 70% i TextView
widget.
siste StringBuffer-utgang = ny StringBuffer (); for (VisualClassifier.VisualClass objekt: classifier.getClasses ()) if (object.getScore ()> 0.7f) output.append ("<") .append(object.getName()) .append("> "); runOnUiThread (ny Runnable () @Override public void run () TextView detectedObjects = findViewById (R.id.detected_objects); detectedObjects.setText (output););
Vær oppmerksom på at koden ovenfor bruker runOnUiThread ()
metode fordi innholdet i TextView
widgeten kan bare oppdateres fra brukergrensesnittet.
Hvis du kjører appen nå og tar et bilde, vil du kunne se Watsons bildeklassifisering arbeid.
Tjenesten Visual Recognition har en dedikert metode for å behandle menneskelige ansikter. Det kan bestemme alder og kjønn til en person i et hvilket som helst fotografi. Hvis personen er kjent, kan den også nevne ham eller henne.
Analysere ansikter med tjenesten Visual Recognition er ikke så annerledes enn å klassifisere objekter. Så du er fri til å gjenbruke layoutet du opprettet tidligere. Men for å introdusere deg til noen flere funksjoner tjenesten tilbyr, skal jeg lage et nytt layout, denne med en litt annen funksjonalitet.
Denne gangen, i stedet for å ta bilder ved hjelp av kameraet og sende dem til tjenesten, la oss direkte sende en bildeadresse til den. For å la brukeren skrive inn en nettadresse og starte analysen, trenger vår layout en EditText
widget og a Knapp
widget. Det vil også trenge en TextView
widget for å vise resultatene av analysen.
Jeg foreslår at du også legger til en Imageview
widget til oppsettet slik at brukeren kan se bildet URL-adressen peker på.
Inne i klikkhåndtereren på Knapp
widget, kan du ringe GetText ()
metode av EditText
widget for å bestemme bildeadressen som brukeren skrev inn. Når du kjenner nettadressen, kan du bare sende den til Picassos laste()
og inn i()
metoder for å laste ned og vise bildet i Imageview
widget.
EditText imageURLInput = findViewById (R.id.image_url); siste streng url = imageURLInput.getText (). toString (); ImageView forhåndsvisning = findViewById (R.id.preview); Picasso.with (denne) .load (url) .into (forhåndsvisning);
For å kjøre ansiktsanalyse på nettadressen, må du bruke detectFaces ()
metode av VisualRecognition
klient. Akkurat som klassifisere()
metode, denne metoden har også behov for a VisualRecognitionOptions
objekt som sin inngang.
Fordi du allerede vet hvordan du bruker henrette()
Metode for å lage synkrone forespørsler, la oss nå ringe Enqueue ()
metode i stedet, som går asynkront og trenger tilbakekalling. Følgende kode viser deg hvordan:
vrClient.detectFaces (ny VisualRecognitionOptions.Builder () .url (url) .build ()) .enqueue (ny ServiceCallback() @Override offentlig ugyldig onResponse (DetectedFaces respons) // Mer kode her @Override public void onFailure (Unntak e) );
Som du kan se i koden ovenfor, inne i onResponse ()
Metode for tilbakeringingsobjektet, du har tilgang til a DetectedFaces
objekt, som inneholder en liste over ansiktsanalyseresultater. Fordi vi brukte et enkelt bilde som vår inngang, behøver vi bare det første elementet i listen. Ved å ringe det getFaces ()
metode, du får en liste over alle Ansikt
objekter oppdaget.
Listeansikter = response.getImages (). get (0) .getFaces ();
Hver Ansikt
objektet har et kjønn og aldersgruppe som er tilknyttet det, som kan nås ved å ringe getGender ()
og getAge ()
fremgangsmåter.
De getGender ()
Metoden returnerer faktisk a Kjønn
gjenstand. Du må ringe sin egen getGender ()
metode for å få kjønn som en streng, som enten er "MALE" eller "FEMALE". På samme måte, getAge ()
Metoden returnerer en Alder
gjenstand. Ved å ringe det getMin ()
og getMax ()
metoder, kan du bestemme ansiktets omtrentlige alder i år.
Følgende kode viser deg hvordan du går gjennom listen over Ansikt
objekter, generer en streng som inneholder kjønnene og alderen til alle ansiktene, og vis den i TextView
widget:
String output = ""; for (ansiktsflate: ansikter) output + = "<" + face.getGender().getGender() + ", " + face.getAge().getMin() + " - " + face.getAge().getMax() + " years old>\ n "; TextView personDetails = findViewById (R.id.person_details); personDetails.setText (output);
Her er et resultat for prøveanalyseanalyse:
Watson Visual Recognition-tjenesten gjør det svært enkelt for deg å lage apps som er klare og klar over omgivelsene. I denne opplæringen lærte du hvordan du bruker den med Watson Java og Android SDK til å oppdage og analysere generiske objekter og ansikter.
For å lære mer om tjenesten, kan du se den offisielle dokumentasjonen.
Og sørg for å sjekke ut noen av våre andre innlegg om maskinlæring her på Envato Tuts+!