Skulle det inte vara bra om en Android-app kunde se och förstå omgivningen? Kan du föreställa dig hur mycket bättre användargränssnittet skulle kunna vara om det kunde titta på sina användare och känner direkt till sina åldrar, kön och känslor? Tja, en sådan app kan verka futuristisk, men det är helt genomförbart idag.
Med IBM Watson Visual Recognition-tjänsten är det enklare än någonsin att skapa mobilappar som kan identifiera och analysera objekt i bilder på ett korrekt sätt. I den här handledningen visar jag dig hur du använder den för att skapa en smart Android-app som kan gissa en persons ålder och kön och identifiera framstående objekt på ett fotografi.
För att kunna följa denna handledning måste du ha:
Liksom alla Watson-tjänster måste Visual Recognition-tjänsten också aktiveras manuellt innan den kan användas i en app. Så logga in på IBM Bluemix-konsolen och navigera till Tjänster> Watson. På sidan som öppnas trycker du på Skapa Watson service knapp.
Från listan över tillgängliga tjänster som visas nästa väljer du Visuell erkännande.
Du kan nu ge ett meningsfullt namn till tjänsten och trycka på Skapa knapp.
När tjänsten är klar kommer en API-nyckel att genereras för den. Du kan se den genom att öppna Serviceuppgifter fliken och tryck på Visa referenser knapp.
I den här handledningen använder vi Watson Java och Android SDK: n samtidigt som vi interagerar med tjänsten Visual Recognition. Vi använder också Picasso-biblioteket för att hämta och visa bilder från Internet. Lägg därför till följande genomförande
beroenden till din app
modulens build.gradle fil:
implementering "com.ibm.watson.developer_cloud: visual-recognition: 3.9.1" implementation "com.ibm.watson.developer_cloud: android-sdk: 0.4.2" implementation "com.squareup.picasso: picasso: 2.5.2 '
För att kunna interagera med Watsons servrar behöver din app den INTERNET
tillstånd, så begär det i ditt projekt AndroidManifest.xml fil.
Dessutom kommer appen vi skapar idag att behöva tillgång till enhetens kamera och externa lagringsmedia, så du måste också begära KAMERA
och WRITE_EXTERNAL_STORAGE
behörigheter.
Slutligen lägg till din Visual Recognition-tjänstens API-nyckel till strings.xml fil.
a1234567890bcdefe
Watson Java SDK avslöjar alla funktioner som Visual Recognition-tjänsten erbjuder via VisualRecognition
klass. Därför måste du nu initiera en instans av den med hjälp av sin konstruktör, som förväntar sig både ett versionsdatum och API-nyckeln som dess argument.
Medan du använder tjänsten Visual Recognition vill du vanligtvis ta bilder med enhetens kamera. Watson Android SDK har en CameraHelper
klass för att hjälpa dig att göra det. Även om du inte behöver, föreslår jag att du också initierar en förekomst av den inom din verksamhet onCreate ()
metod.
privat VisualRecognition vrClient; privat CameraHelper-hjälpen; @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); // Initiera Visual Recognition-klienten vrClient = ny VisualRecognition (VisualRecognition.VERSION_DATE_2016_05_20, getString (R.string.api_key)); // Initiera hjälpen för kamerahjälpen = ny CameraHelper (detta);
Nu har du allt du behöver för att börja analysera bilder med tjänsten.
Tjänsten Visual Recognition kan upptäcka en mängd olika fysiska objekt. Som inmatning förväntar man sig en relativt väl upplyst bild vars upplösning är minst 224 x 224 pixlar. För nu, låt oss använda enhetskameran för att ta en sådan bild.
Användaren måste kunna trycka på en knapp för att ta bilden, så din aktivitetens layout XML-fil måste ha en Knapp
widget. Det måste också ha en Textview
widget för att lista de upptäckta objekten.
Eventuellt kan du kasta in en Imageview
widget för att visa bilden.
I ovanstående kod har vi lagt till en händelsehanterare på sidan Knapp
widget. Du kan skapa en stub för denna widget i kod den genom att klicka på lampan som visas bredvid den.
public void takePicture (View view) // Mer kod här
Du kan ta en bild genom att bara ringa CameraHelper
objekt dispatchTakePictureIntent ()
metod, så lägg till följande kod i händelsehanteraren:
helper.dispatchTakePictureIntent ();
Ovanstående metod använder enhetens standardkameraapp för att ta bilden. Det innebär att få tillgång till bilden som tas, du måste åsidosätta din verksamhet onActivityResult ()
metod och leta efter resultat vars förfrågan kod är REQUEST_IMAGE_CAPTURE
. Så här kan du göra det:
@Override protected void onActivityResult (int requestCode, int resultCode, Intent data) super.onActivityResult (requestCode, resultCode, data); om (requestCode == CameraHelper.REQUEST_IMAGE_CAPTURE) // Mer kod här
När du har hittat rätt resultat kan du extrahera bilden från den i form av a Bitmap
objekt med hjälp av getBitmap ()
metod för CameraHelper
klass. Du kan också få den absoluta vägen för bilden med hjälp av Få fil()
metod. Vi behöver både bitmappen och den absoluta sökvägen, så lägg till följande kod nästa:
sista Bitmap photo = helper.getBitmap (resultCode); sista filen photoFile = helper.getFile (resultCode);
Om du valde att lägga till Imageview
widget till din layout, kan du visa bilden nu genom att direkt överföra bitmappen till dess setImageBitmap ()
metod.
ImageView förhandsgranskning = findViewById (R.id.preview); preview.setImageBitmap (bild);
För att upptäcka objekt i bilden måste du skicka bilden som en inmatning till klassificera()
metod för VisualRecognition
objekt. Innan du gör det måste du dock sätta i det i en ClassifyImagesOptions
objekt som kan skapas med hjälp av ClassifyImagesOptions.Builder
klass.
Returvärdet av klassificera()
metoden är a Service
objekt som stöder både synkrona och asynkrona nätverksförfrågningar. För nu, låt oss ringa det Kör()
Metod för att göra en synkron förfrågan. Naturligtvis, eftersom nätverksoperationer inte är tillåtna på användargränssnittet, måste du komma ihåg att göra det från en ny tråd.
AsyncTask.execute (new Runnable () @Override public void run () VisualClassification response = vrClient.classify (nya ClassifyImagesOptions.Builder () .images (photoFile) .build ()) .execute (); // Mer kod här );
De klassificera()
Metoden är byggd för att hantera flera bilder samtidigt. Följaktligen är dess svar en lista över klassificeringsdetaljer. Eftersom vi för närvarande arbetar med en enda bild behöver vi bara det första objektet i listan. Så här kan du få det:
ImageClassification classification = response.getImages (). Get (0); VisualClassifier classifier = classification.getClassifiers (). Get (0);
Tjänsten Visual Recognition behandlar varje objekt som det har upptäckt som en separat klass av typ VisualClassifier.VisualClass
. Genom att ringa getClasses ()
metod kan du få en lista över alla klasser.
Varje klass har bland annat ett namn och ett konfidenspoäng i samband med det. Följande kod visar hur du går igenom klasslistan och visar namnen på endast de som har mer än 70% av poängen i Textview
widget.
slutlig StringBuffer-utmatning = ny StringBuffer (); för (VisualClassifier.VisualClass-objekt: classifier.getClasses ()) if (object.getScore ()> 0.7f) output.append ("<") .append(object.getName()) .append("> "); runOnUiThread (new Runnable () @Override public void run () TextView detectedObjects = findViewById (R.id.detected_objects); detectedObjects.setText (output););
Observera att ovanstående kod använder runOnUiThread ()
metod eftersom innehållet i Textview
widgeten kan bara uppdateras från användargränssnittet.
Om du kör appen nu och ta en bild kan du se Watsons bildklassificering.
Tjänsten Visual Recognition har en dedikerad metod att bearbeta mänskliga ansikten. Det kan avgöra en persons ålder och kön på något fotografi. Om personen är känd kan den också namnge honom eller henne.
Analysera ansikten med tjänsten Visual Recognition är inte så annorlunda än att klassificera objekt. Så du är fri att återanvända den layout du skapade tidigare. Men för att presentera dig för några fler funktioner tjänsten erbjuder, kommer jag att skapa en ny layout, den här med en något annorlunda funktion.
Den här gången ska vi, istället för att ta bilder med kameran och överföra dem till tjänsten, skicka direkt en bildadress till den. För att användaren ska kunna skriva in en webbadress och börja analysen behöver vår layout en Redigera text
widget och a Knapp
widget. Det kommer också att behöva en Textview
widget för att visa resultaten av analysen.
Jag föreslår att du också lägger till en Imageview
widget till layouten så att användaren kan se bilden som URL-adressen pekar på.
Inne i klickhanteraren på Knapp
widget, kan du ringa gettext ()
metod för Redigera text
widget för att bestämma bildadressen som användaren skrev in. När du känner till webbadressen kan du helt enkelt skicka den till Picassos ladda()
och in i()
metoder för att ladda ner och visa bilden i Imageview
widget.
EditText imageURLInput = findViewById (R.id.image_url); Final String url = imageURLInput.getText (). toString (); ImageView förhandsgranskning = findViewById (R.id.preview); Picasso.with (this) .load (url) .into (förhandsgranskning);
För att köra ansiktsanalys på webbadressen måste du använda detectFaces ()
metod för VisualRecognition
klient. Precis som klassificera()
metod, den här metoden behöver också a VisualRecognitionOptions
objekt som inmatning.
Eftersom du redan vet hur du använder Kör()
Metod för att göra synkrona förfrågningar, låt oss nu ringa enqueue ()
metod istället, som kör asynkront och behöver en återuppringning. Följande kod visar hur:
vrClient.detectFaces (nya VisualRecognitionOptions.Builder () .url (url) .build ()) .enqueue (ny ServiceCallback() @Override public void onResponse (DetectedFaces svar) // Mer kod här @Override public void onFailure (Exception e) );
Som du kan se i ovanstående kod, inuti onResponse ()
Metoden för återuppringningsobjektet, du har tillgång till a DetectedFaces
objekt som innehåller en lista över ansiktsanalysresultat. Eftersom vi använde en enda bild som vår inmatning behöver vi bara det första objektet i listan. Genom att ringa dess getFaces ()
metod får du en lista över alla Ansikte
objekt som detekterats.
Listafaces = response.getImages (). get (0) .getFaces ();
Varje Ansikte
objektet har ett kön och åldersintervall associerat med det, vilket kan nås genom att ringa getGender ()
och getAge ()
metoder.
De getGender ()
Metoden returnerar faktiskt a Kön
objekt. Du måste ringa egen getGender ()
Metod för att få könet som en sträng, som antingen är "MALE" eller "FEMALE". På samma sätt, getAge ()
Metoden returnerar en Ålder
objekt. Genom att ringa dess getMin ()
och getMax ()
metoder, kan du bestämma ungefärlig ålder av ansiktet i år.
Följande kod visar hur du går igenom listan över Ansikte
objekt, skapa en sträng som innehåller könen och åldrarna i alla ansikten och visa den i Textview
widget:
Strängutmatning = ""; för (Ansiktsyta: ansikten) output + = "<" + face.getGender().getGender() + ", " + face.getAge().getMin() + " - " + face.getAge().getMax() + " years old>\ n "; TextView personDetails = findViewById (R.id.person_details); personDetails.setText (output);
Här är ett resultatanalysresultat:
Watson Visual Recognition-tjänsten gör det extremt enkelt för dig att skapa appar som är klara och medvetna om omgivningen. I den här handledningen lärde du dig hur du använder den med Watson Java och Android SDK för att upptäcka och analysera generiska objekt och ansikten.
För mer information om tjänsten kan du referera till den officiella dokumentationen.
Och se till att kolla in några av våra andra inlägg om maskininlärning här på Envato Tuts+!