Guida alla classificazione delle immagini per Android

L'attività Classificatore di immagini di MediaPipe consente di eseguire la classificazione sulle immagini. Puoi utilizzare questa attività per identificare ciò che un'immagine rappresenta in un insieme di categorie definite durante l'addestramento. Queste istruzioni mostrano come usare il classificatore di immagini con le app per Android. L'esempio di codice descritto in queste istruzioni è disponibile su GitHub.

Puoi vedere questa attività in azione visualizzando la demo web. Per ulteriori informazioni sulle funzionalità, sui modelli e sulle opzioni di configurazione di questa attività, consulta la Panoramica.

Esempio di codice

Il codice di esempio di MediaPipe Tasks è una semplice implementazione di un'app di classificazione di immagini per Android. L'esempio utilizza la fotocamera di un dispositivo Android fisico per classificare continuamente gli oggetti e può anche utilizzare immagini e video della galleria dei dispositivi per classificare gli oggetti in modo statico.

Puoi utilizzare l'app come punto di partenza per la tua app per Android o farvi riferimento quando modifichi un'app esistente. Il codice di esempio del classificatore di immagini è ospitato su GitHub.

Scarica il codice

Le seguenti istruzioni mostrano come creare una copia locale del codice di esempio utilizzando lo strumento a riga di comando git.

Per scaricare il codice di esempio:

  1. Clona il repository git utilizzando questo comando:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Facoltativamente, configura l'istanza Git in modo da utilizzare il pagamento sparso, in modo da avere solo i file per l'app di esempio Classificatore di immagini:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_classification/android
    

Dopo aver creato una versione locale del codice di esempio, puoi importare il progetto in Android Studio ed eseguire l'app. Per le istruzioni, consulta la Guida alla configurazione per Android.

Componenti chiave

I seguenti file contengono il codice fondamentale per questa applicazione di esempio di classificazione delle immagini:

Imposta

Questa sezione descrive i passaggi chiave per configurare l'ambiente di sviluppo e i progetti di codice per utilizzare il classificatore di immagini. Per informazioni generali sulla configurazione dell'ambiente di sviluppo per l'utilizzo delle attività di MediaPipe, inclusi i requisiti di versione della piattaforma, consulta la Guida alla configurazione per Android.

Dipendenze

La categoria di classificazione di immagini usa la libreria com.google.mediapipe:tasks-vision. Aggiungi questa dipendenza al file build.gradle del tuo progetto di sviluppo di app per Android. Importa le dipendenze richieste con il seguente codice:

dependencies {
    ...
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}

Modello

L'attività classificatore di immagini MediaPipe richiede un modello addestrato compatibile con questa attività. Per maggiori informazioni sui modelli addestrati disponibili per il classificatore di immagini, consulta la panoramica delle attività nella sezione Modelli.

Seleziona e scarica il modello, quindi archivialo nella directory del progetto:

<dev-project-root>/src/main/assets

Utilizza il metodo BaseOptions.Builder.setModelAssetPath() per specificare il percorso utilizzato dal modello. Questo metodo è indicato nell'esempio di codice della sezione successiva.

Nel codice di esempio del classificatore di immagini, il modello è definito nel file ImageClassifierHelper.kt.

Crea l'attività

Puoi utilizzare la funzione createFromOptions per creare l'attività. La funzione createFromOptions accetta opzioni di configurazione tra cui modalità di esecuzione, impostazioni internazionali dei nomi visualizzati, numero massimo di risultati, soglia di confidenza e una lista di categorie consentite o bloccate. Per ulteriori informazioni sulle opzioni di configurazione, consulta Panoramica della configurazione.

L'attività Classificatore di immagini supporta tre tipi di dati di input: immagini fisse, file video e stream video in diretta. Quando crei l'attività, devi specificare la modalità di esecuzione corrispondente al tipo di dati di input. Scegli la scheda corrispondente al tipo di dati di input per vedere come creare l'attività ed eseguire l'inferenza.

Immagine

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.IMAGE)
    .setMaxResults(5)
    .build();
imageClassifier = ImageClassifier.createFromOptions(context, options);
    

Video

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.VIDEO)
    .setMaxResults(5)
    .build();
imageClassifier = ImageClassifier.createFromOptions(context, options);
    

Live streaming

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setMaxResults(5)
    .setResultListener((result, inputImage) -> {
         // Process the classification result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the classification errors here.
    })
    .build()
imageClassifier = ImageClassifier.createFromOptions(context, options)
    

L'implementazione del codice di esempio del classificatore di immagini consente all'utente di passare da una modalità di elaborazione all'altra. Questo approccio rende il codice di creazione delle attività più complicato e potrebbe non essere appropriato per il tuo caso d'uso. Puoi vedere questo codice nella funzione setupImageClassifier() del file ImageClassifierHelper.kt.

Opzioni di configurazione

Questa attività include le seguenti opzioni di configurazione per le app per Android:

Nome opzione Descrizione Intervallo di valori Valore predefinito
runningMode Imposta la modalità di esecuzione per l'attività. Esistono tre modalità:

IMAGE: la modalità per gli input di immagini singole.

VIDEO: la modalità per i fotogrammi decodificati di un video.

LIVE_STREAM: la modalità per un live streaming di dati di input, ad esempio da una videocamera. In questa modalità, resultListener deve essere chiamato per impostare un listener in modo da ricevere i risultati in modo asincrono.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
displayNamesLocale Imposta la lingua delle etichette da utilizzare per i nomi visualizzati forniti nei metadati del modello dell'attività, se disponibili. Il valore predefinito è en per l'inglese. Puoi aggiungere etichette localizzate ai metadati di un modello personalizzato utilizzando l'API TensorFlow Metadata Writer Codice impostazioni internazionali it
maxResults Imposta il numero massimo facoltativo di risultati della classificazione con il punteggio più alto da restituire. Se < 0, vengono restituiti tutti i risultati disponibili. Qualsiasi numero positivo -1
scoreThreshold Imposta la soglia del punteggio della previsione che sostituisce quella fornita nei metadati del modello (se presente). I risultati al di sotto di questo valore vengono rifiutati. Qualsiasi numero in virgola mobile Non impostata
categoryAllowlist Consente di impostare l'elenco facoltativo di nomi di categorie consentiti. Se non è vuoto, i risultati della classificazione il cui nome della categoria non è incluso in questo set verranno filtrati. I nomi di categorie duplicati o sconosciuti vengono ignorati. Questa opzione si esclude a vicenda con categoryDenylist e utilizza entrambi i risultati in un errore. Qualsiasi stringa Non impostata
categoryDenylist Consente di impostare un elenco facoltativo di nomi di categorie non consentiti. Se il campo non è vuoto, i risultati della classificazione con nome della categoria incluso in questo set verranno filtrati. I nomi di categorie duplicati o sconosciuti vengono ignorati. Questa opzione si esclude a vicenda con categoryAllowlist e utilizza entrambi i risultati in un errore. Qualsiasi stringa Non impostata
resultListener Imposta il listener dei risultati in modo che riceva i risultati della classificazione in modo asincrono quando il classificatore di immagini è in modalità live streaming. Può essere utilizzato solo quando la modalità di corsa è impostata su LIVE_STREAM N/A Non impostata
errorListener Imposta un listener di errori facoltativo. N/A Non impostata

preparazione dei dati

Il classificatore di immagini funziona con immagini, file video e video in live streaming. L'attività gestisce la pre-elaborazione dell'input di dati, tra cui il ridimensionamento, la rotazione e la normalizzazione dei valori.

Devi convertire l'immagine o il frame di input in un oggetto com.google.mediapipe.framework.image.MPImage prima di passarli al classificatore di immagini.

Immagine

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load an image on the user’s device as a Bitmap object using BitmapFactory.

// Convert an Android’s Bitmap object to a MediaPipe’s Image object.
Image mpImage = new BitmapImageBuilder(bitmap).build();
    

Video

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load a video file on the user's device using MediaMetadataRetriever

// From the video’s metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT value. You’ll need them
// to calculate the timestamp of each frame later.

// Loop through the video and load each frame as a Bitmap object.

// Convert the Android’s Bitmap object to a MediaPipe’s Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

Live streaming

import com.google.mediapipe.framework.image.MediaImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Create a CameraX’s ImageAnalysis to continuously receive frames 
// from the device’s camera. Configure it to output frames in RGBA_8888
// format to match with what is required by the model.

// For each Android’s ImageProxy object received from the ImageAnalysis, 
// extract the encapsulated Android’s Image object and convert it to 
// a MediaPipe’s Image object.
android.media.Image mediaImage = imageProxy.getImage()
Image mpImage = new MediaImageBuilder(mediaImage).build();
    

Nel codice di esempio del classificatore di immagini, la preparazione dei dati viene gestita nel file ImageClassifierHelper.kt.

Esegui l'attività

Puoi chiamare la funzione classify corrispondente alla tua modalità di corsa per attivare le inferenze. L'API Image Classifier restituisce le possibili categorie per l'oggetto all'interno dell'immagine o del frame di input.

Immagine

ImageClassifierResult classifierResult = imageClassifier.classify(image);
    

Video

// Calculate the timestamp in milliseconds of the current frame.
long frame_timestamp_ms = 1000 * video_duration * frame_index / frame_count;

// Run inference on the frame.
ImageClassifierResult classifierResult =
    imageClassifier.classifyForVideo(image, frameTimestampMs);
    

Live streaming


// Run inference on the frame. The classifications results will be available 
// via the `resultListener` provided in the `ImageClassifierOptions` when 
// the image classifier was created.
imageClassifier.classifyAsync(image, frameTimestampMs);
    

Tieni presente quanto riportato di seguito:

  • Quando utilizzi la modalità video o live streaming, devi anche fornire il timestamp del frame di input all'attività Classificatore di immagini.
  • Quando viene eseguita in modalità immagine o video, l'attività Classificatore di immagini blocca il thread corrente fino a quando non termina l'elaborazione dell'immagine o del frame di input. Per evitare di bloccare l'interfaccia utente, esegui l'elaborazione in un thread in background.
  • Quando viene eseguita in modalità live streaming, l'attività Classificatore di immagini non blocca il thread corrente, ma restituisce immediatamente. Richiamo l'listener dei risultati con il risultato del rilevamento ogni volta che termina l'elaborazione di un frame di input. Se la funzione classifyAsync viene chiamata quando l'attività Classificatore di immagini è impegnata a elaborare un altro frame, l'attività ignora il nuovo frame di input.

Nel codice di esempio del classificatore di immagini, le funzioni classify sono definite nel file ImageClassifierHelper.kt.

Gestire e visualizzare i risultati

Quando viene eseguita l'inferenza, l'attività Classificatore di immagini restituisce un oggetto ImageClassifierResult che contiene l'elenco di possibili categorie per gli oggetti all'interno dell'immagine o del frame di input.

Di seguito è riportato un esempio dei dati di output di questa attività:

ImageClassifierResult:
 Classifications #0 (single classification head):
  head index: 0
  category #0:
   category name: "/m/01bwb9"
   display name: "Passer domesticus"
   score: 0.91406
   index: 671
  category #1:
   category name: "/m/01bwbt"
   display name: "Passer montanus"
   score: 0.00391
   index: 670

Questo risultato è stato ottenuto eseguendo la classe Bird Classifier su:

Nel codice di esempio del classificatore di immagini, la classe ClassificationResultsAdapter nel file ClassificationResultsAdapter.kt gestisce i risultati:

fun updateResults(imageClassifierResult: ImageClassifierResult? = null) {
    categories = MutableList(adapterSize) { null }
    if (imageClassifierResult != null) {
        val sortedCategories = imageClassifierResult.classificationResult()
            .classifications()[0].categories().sortedBy { it.index() }
        val min = kotlin.math.min(sortedCategories.size, categories.size)
        for (i in 0 until min) {
            categories[i] = sortedCategories[i]
        }
    }
}