Google Cloud Vision API e Image Recognition: cos’è e come integrarla nella tua app mobile

Google Cloud Vision API e Image Recognition: cos’è e come integrarla nella tua app mobile

Pubblicato da Leonardo Pirro il 09/02/2018 in Thinking

FYI: Questo articolo è disponibile in lingua inglese su Medium.

Il tema dell’Artificial Intelligence (IA) e del Machine Learning (ML) sta entrando in modo dirompente in ogni settore e trasformando il modo in cui i consumatori usufruiscono di alcuni servizi e prodotti. Google, una delle aziende leader in questo campo, ha messo a disposizione degli sviluppatori vari tool di sviluppo in grado di abilitare nuove esperienze ed infinite possibilità.

Attraverso questo articolo, andremo ad analizzare l’API Cloud Vision e vedremo come integrarla nelle nostre app.

Google Cloud Vision API: che cos’è

Cloud Vision API è un particolare tipo di API che permette agli sviluppatori di analizzare il contenuto delle immagini, sfruttando modelli di machine learning già consolidati e in continua evoluzione, il tutto in una singola API Rest. Grazie a queste API possiamo avere informazioni contestualizzate su una data immagine e riuscire a classificare rapidamente le immagini in varie categorie e sottocategorie, raggiungendo un livello di dettaglio dell’informazione sempre più profondo.

Prendiamo come esempio la seguente immagine:

Image Recognition - IQUII

Le Vision API permettono di individuare il contenuto di un’immagine con molta precisione. In questo caso, le API danno informazioni dettagliate sul tipo di animale (cane), nella maggior parte dei casi anche sulla razza (beagle) e sul contesto e sfondo (montagne).

Oltre alla classificazione delle immagini, queste API hanno varie funzionalità:

  • Rilevamento Etichette: permette di rilevare un set di categorie all’interno di un’immagine (come nell’esempio che abbiamo fatto poco fa);
  • Rilevamento di contenuti espliciti: permette di rilevare se ci sono contenuti espliciti (per adulti o violenti);
  • Rilevamento di luoghi: permette di rilevare luoghi, opere d’arte, monumenti, ecc.;
  • Rilevamento punti di riferimento: permette di rilevare strutture naturali e artificiali;
  • Optical Character Recognition: permette di rilevare ed estrarre il testo da un’immagine, rilevandone anche la lingua;
  • Rilevamento facciale: consente di rilevare volti, estraendo in automatico anche altri attributi come lo stato emotivo o un copricapo indossato, come un cappello;
  • Attributi delle immagini: consente di rilevare attributi generali di un’immagine come i colori dominanti e i suggerimenti per ritagliare le foto in modo appropriato e ottenere ad esempio la foto profilo perfetta.

Nell’esempio pratico, vedremo in azione due di queste funzionalità: Rilevamento Etichette e Optical Character Recognition.

Ora che abbiamo le informazioni di base sulle Vision API vediamo come sfruttarle su Android. Creeremo un progetto di esempio che ci permetterà di selezionare un’immagine dalla galleria e ricevere informazioni su di essa sfruttando queste API.

Let’s get into action!

Abilitare l’account per usare le Google Cloud API

Per utilizzare queste API dobbiamo prima abilitarle dalla Google Cloud Developer Console, per farlo bastano alcuni passi:

  • Crea un progetto nella Google Cloud Console;
  • Abilita il Billing per il progetto. Se è la prima volta che accedi, puoi usufruire della modalità free trial. Potrebbe essere necessario inserire i dati della propria carta di credito per validare la tua identità, ma non sarai addebitato. Inoltre, per il nostro progetto di esempio saremo ampiamente al di sotto della soglia quindi non correremo il rischio di addebiti;
  • Abilita le Cloud Vision API utilizzando questo link;
  • Una volta abilitate, seleziona Credenziali dal menu laterale;
  • Clicca su Crea credenziali e dal menu a tendina seleziona ID client OAuth;
  • Seleziona Android su Tipo Applicazione;
  • Dai un nome appropriato (es: Android Cloud Vision API);
  • Inserisci la nostra chiave SHA1 (se non sai come ottenere questa chiave, dai questo comando da terminale: keytool -exportcert -keystore path-del-vostro-keystore -list -v);
  • Fatto questo inserisci il nome del package della nostra app: deve corrispondere a quello che trove nel gradle del progetto android, sotto la variabile applicationId. (Nel mio caso è com.lpirro.cloudvision);

Fatto, configurate le API su Google Cloud Console siamo pronti.

Let’s start coding.

Cloud Vision API in Action

Creiamo un nuovo progetto su Android Studio e ricordiamo che il package name deve corrispondere con quello inserito nel progetto nella Google Cloud Developer Console. Una volta creato il progetto, apriamo il build.gradle ed inseriamo le dependency per utilizzare le API.

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:27.0.1'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    
    // Google Cloud Vision API
    implementation 'com.google.android.gms:play-services-base:11.8.0'
    implementation 'com.google.android.gms:play-services-auth:11.8.0'
    implementation 'com.google.apis:google-api-services-vision:v1-rev16-1.22.0'
    implementation ('com.google.api-client:google-api-client-android:1.22.0') {
        exclude module: 'httpclient'
    }
    implementation ('com.google.http-client:google-http-client-gson:1.20.0') {
        exclude module: 'httpclient'
    }
}

 

A questo punto apriamo l’ AndroidManifest.xml ed aggiungiamo i permessi necessari per effettuare le chiamate di rete e per ricevere le informazioni sugli account (necessario per l’OAuth request). Inseriamo quindi i permessi:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.lpirro.cloudvision">

    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
    <uses-permission android:name="android.permission.INTERNET"/>

    ...

</manifest>

Fatto questo, possiamo creare l’activity che ci permetterà di selezionare un’immagine della galleria e chiamare i servizi di Cloud Vision per ottenere le informazioni sull’immagine.

Il layout della nostra activity sarà molto banale, avrà una ImageView per mostrare l’immagine selezionata dalla galleria, due TextView per mostrare i risultati e un Button per selezionare l’immagine da scansionare.

Image Recognition - IQUII

E il relativo layout XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="16dp"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:paddingTop="16dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/selected_image_txt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:textStyle="bold"
        android:textSize="20sp"
        android:gravity="center"
        android:text="Selected Image "/>

    <ImageView
        android:id="@+id/selected_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/selected_image_txt"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"/>

    <TextView
        android:id="@+id/labels"
        android:text="Labels:"
        android:textStyle="bold"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/selected_image"
        android:layout_marginTop="10dp"/>

    <TextView
        android:id="@+id/tv_label_results"
        android:text="-"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/labels"
        android:layout_marginTop="10dp"/>

    <TextView
        android:id="@+id/texts"
        android:text="Texts:"
        android:textStyle="bold"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tv_label_results"
        android:layout_marginTop="10dp"/>

    <TextView
        android:id="@+id/tv_texts_results"
        android:text="-"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/texts"
        android:layout_marginTop="10dp"/>

    <Button
        android:id="@+id/select_image_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:text="Choose an Image"/>
</RelativeLayout>

Definito il layout possiamo passare all’Activity. In questo esempio, per le chiamate di rete utilizzeremo la libreria Google API Client per Java e, dato che eseguiremo una OAuth request, prima di tutto dobbiamo ottenere un auth token da Google. Quindi, definiamo prima una classe che ci permetterà di ottenere un OAuth token.

Nota: Per semplicità utilizzeremo un AsyncTask per eseguire questa ed altre operazioni di rete, ma nel caso si utilizzi queste API per un progetto reale, prendi in considerazione l’idea di utilizzare Retrofit, magari in accoppiata con RxJava.

public class GetOAuthToken extends AsyncTask<Void, Void, Void> {
    Activity mActivity;
    Account mAccount;
    int mRequestCode;
    String mScope;

    GetOAuthToken(Activity activity, Account account, String scope, int requestCode) {
        this.mActivity = activity;
        this.mScope = scope;
        this.mAccount = account;
        this.mRequestCode = requestCode;
    }

    @Override
    protected Void doInBackground(Void... params) {
        try {
            String token = fetchToken();
            if (token != null) {
                ((MainActivity)mActivity).onTokenReceived(token);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    protected String fetchToken() throws IOException {
        String accessToken;
        try {
            accessToken = GoogleAuthUtil.getToken(mActivity, mAccount, mScope);
            GoogleAuthUtil.clearToken (mActivity, accessToken);
            accessToken = GoogleAuthUtil.getToken(mActivity, mAccount, mScope);
            return accessToken;
        } catch (UserRecoverableAuthException userRecoverableException) {
            mActivity.startActivityForResult(userRecoverableException.getIntent(), mRequestCode);
        } catch (GoogleAuthException fatalException) {
            fatalException.printStackTrace();
        }
        return null;
    }
}

A questo punto abbiamo tutto il necessario per chiamare le API Cloud Vision dalla nostra app e ricevere i risultati desiderati:

protected BatchAnnotateImagesResponse doInBackground(Object... params) {
            try {
                GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
                HttpTransport httpTransport = AndroidHttp.newCompatibleTransport();
                JsonFactory jsonFactory = GsonFactory.getDefaultInstance();
    
                Vision.Builder builder = new Vision.Builder
                (httpTransport, jsonFactory, credential);
                Vision vision = builder.build();
    
                List<Feature> featureList = new ArrayList<>();
                Feature labelDetection = new Feature();
                labelDetection.setType("LABEL_DETECTION");
                labelDetection.setMaxResults(10);
                featureList.add(labelDetection);
    
                Feature textDetection = new Feature();
                textDetection.setType("TEXT_DETECTION");
                textDetection.setMaxResults(10);
                featureList.add(textDetection);
    
                List<AnnotateImageRequest> imageList = new ArrayList<>();
                AnnotateImageRequest annotateImageRequest = new AnnotateImageRequest();
                Image base64EncodedImage = getBase64EncodedJpeg(bitmap);
                annotateImageRequest.setImage(base64EncodedImage);
                annotateImageRequest.setFeatures(featureList);
                imageList.add(annotateImageRequest);
    
                BatchAnnotateImagesRequest batchAnnotateImagesRequest =
                new BatchAnnotateImagesRequest();
                batchAnnotateImagesRequest.setRequests(imageList);
    
                Vision.Images.Annotate annotateRequest =
                vision.images().annotate(batchAnnotateImagesRequest);
                annotateRequest.setDisableGZipContent(true);
                Log.d(TAG, "Sending request to Google Cloud");
    
                BatchAnnotateImagesResponse response = annotateRequest.execute();
                return response;
    
            } catch (GoogleJsonResponseException e) {
                Log.e(TAG, "Request error: " + e.getContent());
            } catch (IOException e) {
                Log.d(TAG, "Request error: " + e.getMessage());
            }
            return null;
        }

con il metodo setType andiamo a definire il tipo di funzionalità che andremo ad utilizzare, nel nostro caso avremo quindi LABEL_DETECTION e TEXT_DETECTION. L’immagine da scansionare va passata nel formato Base64. Fatto questo, una volta ricevuti i risultati, vengono passati al metodo getDetectedText() che non fa altro che formattare la stringa per filtrare le informazioni e visualizzarle finalmente sulla UI.

That’s it.

Image Recognition: infinite possibilità non solo per il business

Cloud Vision API rappresenta un ulteriore passo in avanti per Google, il cui obiettivo è quello di abbassare le barriere all’ingresso e ampliare sempre più la community di developer in ambito Artificial Intelligence e di Machine Learning, due forti propulsori della Digital Transformation.

Attraverso la creazione di servizi moderni di Machine Learning implementati su modelli già pre-istruiti, come ad esempio le API che svolgono determinati compiti, Google sta offrendo nuove opportunità alle aziende per poter rendere le applicazioni ancora più scalabili e smart.

Anche se l’impegno nel rendere accessibile l’AI a tutti è ancora un inizio, il trend dell’Image Recognition ha le carte in regola per  ampliarsi. Mentre Facebook, per esempio, sta già sfruttando questa tecnologia per suggerire di taggare una persona in una foto quando viene rilevato il volto, Google invece la utilizza per organizzare le foto dello smartphone in automatico, assegnando dei tag per facilitare ricerca e organizzazione. In Google Photos, infatti, si può trovare velocemente tutte le foto associate a un tag: cercando “foto al mare”, ad esempio, verranno proposte tutte le foto scattate al mare.

Il riconoscimento di immagini sta quindi diventando un must have da integrare nelle applicazioni per aiutare l’utente a leggere qualsiasi testo di un’immagine, da una fattura a un elenco di un esercizio commerciale in modo sempre più rapido e preciso.

Per approfondire puoi scaricare il sorgente di questo progetto di esempio nella repository su GitHub.


Leonardo Pirro

UX addicted and Android Developer.


Non perderti i prossimi post! Ricevili via mail per leggerli quando vuoi.

Dai un'occhiata all'archivio


Nel caso di commenti i dati verranno trattati come da informativa

ARTICOLI CORRELATI

di IQUII

13 Tech e Digital Trend che influenzeranno la Digital Transformation nel 2018

Nel nostro #ForwardThinking, abbiamo individuato 13 Tech e Digital Trend che permetteranno a molti contesti di business di crescere.

in: Newsletter , Thinking

di IQUII

IQUII porta EventXP ad AppShow 2017, il primo congresso europeo sull’App Economy

In occasione del primo congresso europeo sull’App Economy in Italia, IQUII parteciperà come partner e app provider ufficiale con EventXP.

in: Comunicati Stampa

CONTATTACI SUBITO

IQUII S.r.l.Part of Be Group


Sede Legale: Viale dell'Esperanto 71 – 00144 Roma
Sede Operativa: Via Vincenzo Lamaro 13/15 Ed.U, Roma

P.iva 11289201003 - Cap.Soc. 10.000 €
Reg. Imprese di Roma REA n.1293642

Email. [email protected]
Tel. +39 06 72.15.125

Mobile Analytics

NEWSLETTER

Ricevi una volta al mese il nostro #ForwardThinking / Dai un'occhiata all'archivio