Guida all'incorporamento delle immagini per Android

L'attività Incorporamento di immagini MediaPipe consente di convertire i dati delle immagini in una rappresentazione numerica per svolgere attività di elaborazione delle immagini relative al machine learning, come il confronto della somiglianza tra due immagini. Queste istruzioni mostrano come usare Image Embedder con app per Android.

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 incorporamento di immagini per Android. L'esempio utilizza la fotocamera di un dispositivo Android fisico per incorporare in modo continuo le immagini e può anche eseguire l'incorporamento sui file immagine archiviati sul dispositivo.

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 dell'incorporamento 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 il seguente comando:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Facoltativamente, configura l'istanza Git in modo da utilizzare un pagamento sparse, in modo da avere solo i file per l'app di esempio di Image Embedder:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_embedder/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 incorporamento di immagini:

  • ImageEmbedderHelper.kt: inizializza l'incorporamento dell'immagine e gestisce il modello e delega la selezione.
  • MainActivity.kt: implementa l'applicazione e assembla i componenti dell'interfaccia utente.

Configurazione

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

Dipendenze

L'incorporamento di immagini utilizza la libreria com.google.mediapipe:tasks-vision. Aggiungi questa dipendenza al file build.gradle del tuo progetto di sviluppo di app Android. Importa le dipendenze richieste con il seguente codice:

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

Modello

L'attività Incorporamento di immagini MediaPipe richiede un modello addestrato compatibile con questa attività. Per ulteriori informazioni sui modelli addestrati disponibili per l'incorporamento di immagini, consulta la sezione Modelli della panoramica dell'attività.

Seleziona e scarica il modello, quindi archivialo all'interno della directory del progetto:

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

Specifica il percorso del modello all'interno del parametro ModelAssetPath. Nel codice di esempio, il modello è definito nella funzione setupImageEmbedder() del file ImageEmbedderHelper.kt:

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

Creare l'attività

Puoi utilizzare la funzione createFromOptions per creare l'attività. La funzione createFromOptions accetta le opzioni di configurazione per impostare le opzioni di incorporamento. Per ulteriori informazioni sulle opzioni di configurazione, consulta Panoramica della configurazione.

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

Immagine

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.IMAGE)
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

Video

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.VIDEO)
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

Live streaming

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setResultListener((result, inputImage) -> {
         // Process the embedding result here.
    })
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

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

Opzioni di configurazione

Questa attività prevede 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 singole immagini.

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 configurare un listener per ricevere i risultati in modo asincrono.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
l2_normalize Indica se normalizzare il vettore di caratteristiche restituito con la norma L2. Utilizza questa opzione solo se il modello non contiene già un'operatività TFLite L2_NORMALIZATION nativa. Nella maggior parte dei casi, è già così e la normalizzazione L2 viene quindi ottenuta tramite l'inferenza TFLite senza necessità di questa opzione. Boolean False
quantize Indica se l'incorporamento restituito deve essere quantizzato in byte tramite la quantizzazione scalare. Gli incorporamenti si presume implicitamente come unità-norm, pertanto è garantito che ogni dimensione abbia un valore in [-1.0, 1.0]. In caso contrario, utilizza l'opzione l2_normalize. Boolean False
resultListener Imposta il listener dei risultati per ricevere i risultati di incorporamento in modo asincrono quando l'incorporamento di immagini è in modalità di live streaming. Può essere utilizzato solo quando la modalità di esecuzione è impostata su LIVE_STREAM N/A Non impostata
errorListener Imposta un listener di errori facoltativo. N/A Non impostata

Preparazione dei dati

L'incorporamento di immagini funziona con immagini, file video e video in live streaming. L'attività gestisce la pre-elaborazione dell'input dei 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 passarlo all'attività Image Embedder.

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, la preparazione dei dati viene gestita nel file ImageEmbedderHelper.kt.

Esegui l'attività

Puoi chiamare la funzione embed corrispondente alla modalità di esecuzione per attivare le inferenze. L'API Image Embedder restituisce i vettori di incorporamento per l'immagine o il frame di input.

Immagine

ImageEmbedderResult embedderResult = imageEmbedder.embed(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.
ImageEmbedderResult embedderResult =
    imageEmbedder.embedForVideo(image, frameTimestampMs);
    

Live streaming


// Run inference on the frame. The embedding results will be available
// via the `resultListener` provided in the `ImageEmbedderOptions` when
// the image embedder was created.
imageEmbedder.embedAsync(image, frameTimestampMs);
    

Tieni presente quanto riportato di seguito:

  • Quando l'esecuzione è in modalità video o live streaming, devi anche fornire il timestamp del frame di input all'attività Incorporamento di immagini.
  • Quando è in esecuzione in modalità immagine o video, l'attività Incorporamento di immagini bloccherà il thread corrente finché non completa l'elaborazione dell'immagine o del frame di input. Per evitare di bloccare il thread corrente, esegui l'elaborazione in un thread in background.
  • Quando è in esecuzione in modalità live streaming, l'attività di incorporamento di immagini non blocca il thread corrente, ma restituisce immediatamente. Richiama il proprio listener dei risultati con il risultato del rilevamento ogni volta che ha terminato l'elaborazione di un frame di input. Se la funzione embedAsync viene richiamata quando l'attività di incorporamento di immagini è impegnata a elaborare un altro frame, l'attività ignora il nuovo frame di input.

Nel codice di esempio, la funzione embed è definita nel file ImageEmbedderHelper.kt.

Gestire e visualizzare i risultati

Dopo l'esecuzione dell'inferenza, l'attività Incorporamento immagini restituisce un oggetto ImageEmbedderResult che contiene un elenco di incorporamenti (in virgola mobile o quantizzati scalari) per l'immagine di input.

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

ImageEmbedderResult:
  Embedding #0 (sole embedding head):
    float_embedding: {0.0, 0.0, ..., 0.0, 1.0, 0.0, 0.0, 2.0}
    head_index: 0

Questo risultato è stato ottenuto incorporando la seguente immagine:

Puoi confrontare la somiglianza di due incorporamenti utilizzando la funzione ImageEmbedder.cosineSimilarity. Per un esempio, vedi il codice che segue.

// Compute cosine similarity.
double similarity = ImageEmbedder.cosineSimilarity(
  result.embeddingResult().embeddings().get(0),
  otherResult.embeddingResult().embeddings().get(0));