Guida all'incorporamento delle immagini per Android

L'attività MediaPipe Image Embedder consente di convertire i dati delle immagini in una rappresentazione numerica per eseguire attività di elaborazione delle immagini correlate all'IA, ad esempio il confronto della somiglianza di due immagini. Queste istruzioni mostrano come utilizzare lo strumento di incorporamento delle immagini con le 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 continuamente le immagini e può anche eseguire l'incorporatore 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 di Image Embedder è ospitato su GitHub.

Scarica il codice

Le istruzioni riportate di seguito 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. Se vuoi, configura l'istanza Git in modo da utilizzare il controllo sparse, in modo da avere solo i file per l'app di esempio 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 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'embedder di immagini e gestisce la selezione del modello e del delegato.
  • 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 utilizzare Image Embedder. Per informazioni generali sulla configurazione dell'ambiente di sviluppo per l'utilizzo delle attività MediaPipe, inclusi i requisiti della versione della piattaforma, consulta la guida alla configurazione per Android.

Dipendenze

Image Embedder utilizza 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à MediaPipe Image Embedder richiede un modello addestrato compatibile con questa attività. Per ulteriori informazioni sui modelli addestrati disponibili per Image Embedder, consulta la sezione Modelli della panoramica dell'attività.

Seleziona e scarica il modello, quindi memorizzalo nella 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() nel file ImageEmbedderHelper.kt:

Utilizza il metodo BaseOptions.Builder.setModelAssetPath() per specificare il percorso utilizzato dal modello. A questo metodo viene fatto riferimento nell'esempio di codice nella sezione successiva.

Crea l'attività

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

L'attività di incorporamento di immagini supporta tre tipi di dati di input: immagini, file video e streaming video dal vivo. 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 scoprire 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 del codice di esempio consente all'utente di passare da una modalità di elaborazione all'altra. L'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 setupImageEmbedder() nel file ImageEmbedderHelper.kt.

Opzioni di configurazione

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

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

IMMAGINE: la modalità per l'inserimento 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 ascoltatore 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'operazione L2_NORMALIZATION TFLite nativa. Nella maggior parte dei casi, è già così e la normalizzazione L2 viene quindi raggiunta tramite l'inferenza TFLite senza bisogno di questa opzione. Boolean False
quantize Indica se l'embedding restituito deve essere quantizzato in byte tramite la quantizzazione scalare. Si presume implicitamente che gli incorporamenti siano di norma unitaria e quindi qualsiasi dimensione abbia un valore garantito compreso tra -1,0 e 1,0. Utilizza l'opzione l2_normalize se non è così. Boolean False
resultListener Imposta l'ascoltatore dei risultati in modo da ricevere i risultati dell'inserimento in modo asincrono quando lo strumento di inserimento di immagini è in modalità live streaming. Può essere utilizzato solo quando la modalità di esecuzione è impostata su LIVE_STREAM N/D Non impostato
errorListener Imposta un listener di errore facoltativo. N/D Non impostato

Preparazione dei dati

L'editor di incorporamento di immagini funziona con immagini, file video e video in live streaming. L'attività gestisce la preelaborazione dei dati di input, tra cui ridimensionamento, rotazione e normalizzazione dei valori.

Devi convertire l'immagine o l'inquadratura di input in un oggetto com.google.mediapipe.framework.image.MPImage prima di trasmetterlo all'attività di incorporamento delle immagini.

Immagine

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

// Load an image on the users device as a Bitmap object using BitmapFactory.

// Convert an Androids Bitmap object to a MediaPipes 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 videos metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT value. Youll need them
// to calculate the timestamp of each frame later.

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

// Convert the Androids Bitmap object to a MediaPipes 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 CameraXs ImageAnalysis to continuously receive frames
// from the devices camera. Configure it to output frames in RGBA_8888
// format to match with what is required by the model.

// For each Androids ImageProxy object received from the ImageAnalysis,
// extract the encapsulated Androids Image object and convert it to
// a MediaPipes 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 segue:

  • Quando esegui l'attività in modalità video o live streaming, devi anche fornire il timestamp del frame di input all'attività di incorporamento delle immagini.
  • Quando viene eseguita in modalità immagine o video, l'attività di incorporamento delle immagini blocca il thread corrente fino al termine dell'elaborazione dell'immagine o del frame di input. Per evitare di bloccare il thread corrente, esegui l'elaborazione in un thread in background.
  • Quando viene eseguito in modalità live streaming, il task di incorporamento delle immagini non blocca il thread corrente, ma restituisce immediatamente. Evocherà il suo ascoltatore dei risultati con il risultato del rilevamento ogni volta che ha terminato l'elaborazione di un frame di input. Se la funzione embedAsync viene chiamata quando l'attività Inserimento 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à di inserimento di immagini restituisce un oggetto ImageEmbedderResult che contiene un elenco di embedding (a 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 inserendo la seguente immagine:

Inquadratura media di un gatto esotico

Puoi confrontare la somiglianza di due embedding utilizzando la funzione ImageEmbedder.cosineSimilarity. Vedi il codice seguente per un esempio.

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