Tutorial sul deployment di Edge per Android

Cosa creerai

In questo tutorial scaricherai un modello TensorFlow Lite personalizzato esportato creato utilizzando AutoML Vision Edge. Poi eseguirai un'app per Android preconfigurata che utilizza il modello per identificare le immagini di fiori.

Screenshot per dispositivo mobile del prodotto finale
Credito immagine: Felipe Venâncio, "dal giardino di mia madre" (CC BY 2.0, immagine mostrata nell'app).

Obiettivi

In questa procedura dettagliata introduttiva end-to-end, utilizzerai il codice per:

  • Esegui un modello preaddestrato in un'app per Android utilizzando l'interprete TFLite.

Prima di iniziare

Addestra un modello da AutoML Vision Edge

Prima di poter eseguire il deployment di un modello su un dispositivo periferico, devi addestrare ed esportare un modello TF Lite da AutoML Vision Edge seguendo la guida rapida sul modello di dispositivi Edge.

Dopo aver completato la guida rapida, dovresti aver esportato i file dei modelli addestrati: un file TF Lite, un file delle etichette e un file di metadati, come mostrato di seguito.

file di modello tf lite per spazio di archiviazione sul cloud

Installa TensorFlow

Prima di iniziare il tutorial devi installare diversi software:

Se hai un'installazione Python in esecuzione, esegui questi comandi per scaricare il software:

pip install --upgrade  "tensorflow==1.7.*"
pip install PILLOW

In caso di problemi con questa procedura, consulta la documentazione di TensorFlow ufficiale.

clona il repository Git

Utilizza la riga di comando per clonare il repository Git con il seguente comando:

git clone https://github.com/googlecodelabs/tensorflow-for-poets-2

Vai alla directory del clone locale del repository (directory tensorflow-for-poets-2). Da questa directory eseguirai tutti gli esempi di codice seguenti:

cd tensorflow-for-poets-2

Configura l'app per Android

Installare Android Studio

Se necessario, installa Android Studio 3.0 o versioni successive in locale.

Aprire il progetto con Android Studio

Per aprire un progetto con Android Studio:

  1. Apri Android Studio Icona di avvio di Android Studio. Dopo il caricamento, seleziona Icona Apri progetto di Android Studio "Apri un progetto Android Studio esistente" da questo popup:

    Popup di apertura del progetto di Android Studio

  2. Nel selettore di file, scegli tensorflow-for-poets-2/android/tflite dalla directory di lavoro.

  3. La prima volta che aprirai il progetto verrà visualizzata una finestra popup "Gradle Sync" che ti chiede di utilizzare il wrapper Gradle. Seleziona "OK".

    Popup di apertura del progetto di Android Studio

Esegui il test dell'app

L'app può essere eseguita su un dispositivo Android reale o nell'emulatore di Android Studio.

Configurare un dispositivo Android

Non puoi caricare l'app da Android Studio sul telefono se non attivi "modalità sviluppatore" e "Debug USB".

Per completare questa procedura di configurazione una tantum, segui queste instructions.

Configura l'emulatore con accesso alla fotocamera (facoltativo)

Se scegli di usare un emulatore anziché un vero dispositivo Android, Android Studio semplifica la configurazione dell'emulatore.

Poiché questa app utilizza la videocamera, configura la videocamera dell'emulatore in modo che utilizzi la videocamera del computer anziché la sequenza di test predefinita.

Per configurare la videocamera dell'emulatore, devi creare un nuovo dispositivo in "Gestione dispositivi virtuali Android", un servizio a cui puoi accedere con questo pulsante Icona Gestione dispositivi virtuali. Nella pagina AVDM principale, seleziona "Create Virtual Device" (Crea dispositivo virtuale):

Opzione per creare un dispositivo virtuale con Android Studio

Nella pagina "Verifica configurazione", nell'ultima pagina della configurazione del dispositivo virtuale, seleziona "Mostra impostazioni avanzate":

Opzione per creare un dispositivo virtuale con Android Studio

Con le impostazioni avanzate visualizzate, puoi impostare entrambe le origini della videocamera in modo che utilizzino la webcam del computer host:

Android Studio: scelta dell'opzione di origine della fotocamera

Esegui l'app originale

Prima di apportare modifiche all'app, esegui la versione fornita con il repository.

Per avviare il processo di compilazione e installazione, esegui una sincronizzazione Gradle.

Icona di sincronizzazione Gradle

Dopo aver eseguito una sincronizzazione Gradle, seleziona Riproduci Icona di riproduzione di Android Studio.

Dopo aver selezionato il pulsante di riproduzione, dovrai selezionare il tuo dispositivo da questo popup:

seleziona la finestra popup del dispositivo

Dopo aver selezionato il dispositivo, devi consentire alla demo Tensorflow di accedere alla fotocamera e ai tuoi file:

consenti finestre di accesso alla fotocamera

Ora che l'app è installata, fai clic sulla relativa icona Icona dell'app Android Studio per avviarla. Questa versione dell'app utilizza MobileNet standard, preaddestrato sulle 1000 categorie ImageNet.

Dovrebbe avere un aspetto simile al seguente:

esegui app di prova

Esegui l'app personalizzata

La configurazione dell'app predefinita classifica le immagini in una delle 1000 classi ImageNet utilizzando la MobileNet standard senza riaddestrare.

Ora apporta le modifiche in modo che l'app utilizzi un modello creato da AutoML Vision Edge per le tue categorie di immagini personalizzate.

Aggiungi i file del modello al progetto

Il progetto demo è configurato per cercare un file graph.lite e un labels.txt nella directory android/tflite/app/src/main/assets/.

Sostituisci i due file originali con le tue versioni con i seguenti comandi:

cp [Downloads]/model.tflite android/tflite/app/src/main/assets/graph.lite
cp [Downloads]/dict.txt  android/tflite/app/src/main/assets/labels.txt

Modifica l'app

Questa app utilizza un modello float, mentre il modello creato da AutoML Vision Edge è quantizzato. per consentire all'app di usare il modello.

Modifica il tipo di dati di labelProbArray e filterLabelProbArray da in virgola mobile a byte, nella definizione dei membri della classe e nell'inizializzazione ImageClassifier.

private byte[][] labelProbArray = null;
private byte[][] filterLabelProbArray = null;

labelProbArray = new byte[1][labelList.size()];
filterLabelProbArray = new byte[FILTER_STAGES][labelList.size()];

Alloca imgData in base al tipo int8 nell'inizializzazione di ImageClassifier.

    imgData =
        ByteBuffer.allocateDirect(
            DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE);

Trasmetti il tipo di dati di labelProbArray da int8 a float, in printTopKLabels():

  private String printTopKLabels() {
    for (int i = 0; i < labelList.size(); ++i) {
      sortedLabels.add(
          new AbstractMap.SimpleEntry<>(labelList.get(i), (float)labelProbArray[0][i]));
      if (sortedLabels.size() > RESULTS_TO_SHOW) {
        sortedLabels.poll();
      }
    }
    String textToShow = "";
    final int size = sortedLabels.size();
    for (int i = 0; i < size; ++i) {
      Map.Entry<String, Float> label = sortedLabels.poll();
      textToShow = String.format("\n%s: %4.2f",label.getKey(),label.getValue()) + textToShow;
    }
    return textToShow;
  }

Eseguire l'app

Esegui una sincronizzazione Gradle in Android Studio affinché il sistema di compilazione possa trovare i tuoi file:

Icona di sincronizzazione Gradle

Dopo aver eseguito una sincronizzazione Gradle, seleziona Riproduci Icona di riproduzione di Android Studio per avviare il processo di compilazione e installazione come prima.

Dovrebbe avere un aspetto simile al seguente:

Screenshot per dispositivo mobile del prodotto finale
Immagine di credito: Felipe Venâncio, "dal giardino di mia madre" (CC BY 2.0, immagine mostrata nell'app).

Per acquisire uno screenshot, puoi tenere premuti contemporaneamente il tasto di accensione e il tasto Abbassa il volume.

Testa l'app aggiornata puntando la fotocamera su diverse immagini di fiori per vedere se sono classificati correttamente.

Come funziona?

Ora che l'app è in esecuzione, esamina il codice specifico di TensorFlow Lite.

AAR TensorFlow-Android

Questa app utilizza un archivio Android TFLite (AAR) precompilato. Questo AAR è ospitato su jcenter.

Le seguenti righe del file build.gradle del modulo includono la versione più recente dell'AAR dal repository bintray maven di TensorFlow nel progetto.

build.gradle

repositories {
    maven {
        url 'https://google.bintray.com/tensorflow'
    }
}

dependencies {
    // ...
    compile 'org.tensorflow:tensorflow-lite:+'
}

Usa il blocco seguente per indicare allo strumento di creazione di pacchetti di asset Android che gli asset .lite o .tflite non devono essere compressi. Questo è importante, poiché il file .lite sarà mappato in memoria e non funzionerà quando il file viene compresso.

build.gradle

android {
    aaptOptions {
        noCompress "tflite"
        noCompress "lite"
    }
}

Utilizzo dell'API TFLite Java

Il codice di interfacciamento con TFLite è tutto incluso in ImageClassifier.java.

Configurazione

Il primo blocco di interesse è il costruttore di ImageClassifier:

ImageClassifier.java

ImageClassifier(Activity activity) throws IOException {
    tflite = new Interpreter(loadModelFile(activity));
    labelList = loadLabelList(activity);
    imgData =
        ByteBuffer.allocateDirect(
            4 * DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE);
    imgData.order(ByteOrder.nativeOrder());
    labelProbArray = new float[1][labelList.size()];
    Log.d(TAG, "Created a Tensorflow Lite Image Classifier.");
}

Ci sono alcune righe di particolare interesse.

La riga seguente crea l'interprete TFLite:

ImageClassifier.java

tflite = new Interpreter(loadModelFile(activity));

Questa riga crea un'istanza di un interprete TFLite. L'interprete funziona in modo simile a tf.Session (per chi ha familiarità con TensorFlow al di fuori di TFLite). Passi all'interprete un MappedByteBuffer contenente il modello. La funzione locale loadModelFile crea un MappedByteBuffer contenente il file di asset graph.lite dell'attività.

Le seguenti righe creano il buffer dei dati di input:

ImageClassifier.java

imgData = ByteBuffer.allocateDirect(
    4 * DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE);

Questo buffer di byte viene ridimensionato in modo da contenere i dati dell'immagine una volta convertito in numero in virgola mobile. L'interprete può accettare direttamente array fluttuanti come input, ma ByteBuffer è più efficiente in quanto evita copie aggiuntive nell'interprete.

Le seguenti righe caricano l'elenco delle etichette e creano il buffer di output:

labelList = loadLabelList(activity);
//...
labelProbArray = new float[1][labelList.size()];

Il buffer di output è un array a virgola mobile con un elemento per ogni etichetta in cui il modello scriverà le probabilità di output.

esegui il modello

Il secondo blocco di interesse è il metodo classifyFrame. Questo metodo prende un Bitmap come input, esegue il modello e restituisce il testo da stampare nell'app.

ImageClassifier.java

String classifyFrame(Bitmap bitmap) {
 // ...
 convertBitmapToByteBuffer(bitmap);
 // ...
 tflite.run(imgData, labelProbArray);
 // ...
 String textToShow = printTopKLabels();
 // ...
}

Questo metodo ha tre funzioni. Innanzitutto, il metodo converte e copia l'input Bitmap in imgData ByteBuffer per l'input nel modello. Quindi, il metodo chiama il metodo di esecuzione dell'interprete, passando il buffer di input e l'array di output come argomenti. L'interprete imposta i valori nell'array di output sulla probabilità calcolata per ogni classe. I nodi di input e di output sono definiti dagli argomenti per il passaggio di conversione toco che ha creato in precedenza il file modello .lite.

Cosa devo fare adesso?

Hai completato una procedura dettagliata di un'app di classificazione dei fiori Android utilizzando un modello Edge. Hai testato un'app di classificazione delle immagini prima di modificarla e ottenere annotazioni di esempio. Hai quindi esaminato il codice specifico di TensorFlow Lite per capire le funzionalità sottostanti.