Guida al rilevamento di oggetti per Android

L'attività Rilevamento di oggetti consente di rilevare la presenza e la posizione di più classi di oggetti. Ad esempio, un rilevatore di oggetti può individuare dei cani all'interno di un'immagine. Queste istruzioni mostrano come utilizzare l'attività Rilevamento di oggetti su Android. L'esempio di codice descritto in queste istruzioni è disponibile su GitHub. Puoi vedere questa attività in azione visualizzando questa 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 rilevamento di oggetti per Android. L'esempio utilizza la fotocamera di un dispositivo Android fisico per rilevare in modo continuo gli oggetti e può utilizzare anche immagini e video della galleria del dispositivo per rilevare 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 rilevatore di oggetti è 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 la tua istanza Git in modo che utilizzi il pagamento sparse, in modo da avere solo i file per l'app di esempio di rilevamento di oggetti:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/object_detection/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 l'applicazione di esempio di rilevamento di oggetti:

Configurazione

Questa sezione descrive i passaggi chiave per configurare l'ambiente di sviluppo e i progetti di codice per l'utilizzo di Rilevamento di oggetti. 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

Il rilevatore di oggetti 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à Rilevamento di oggetti MediaPipe richiede un modello addestrato compatibile con questa attività. Per ulteriori informazioni sui modelli addestrati disponibili per il rilevatore di oggetti, consulta la panoramica dell'attività nella sezione Modelli.

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

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

Usa il metodo BaseOptions.Builder.setModelAssetPath() per specificare il percorso utilizzato dal modello. Per un esempio di codice, consulta la sezione successiva.

Creare 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, lista consentita delle categorie e lista bloccata. Se non viene specificata un'opzione di configurazione, viene usato il valore predefinito. Per ulteriori informazioni sulle opzioni di configurazione, consulta Panoramica della configurazione.

L'attività Rilevamento di oggetti 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

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.IMAGE)
    .setMaxResults(5)
    .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

Video

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.VIDEO)
    .setMaxResults(5)
    .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

Live streaming

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setMaxResults(5)
    .setResultListener((result, inputImage) -> {
      // Process the detection result here.
    })
    .setErrorListener((result, inputImage) -> {
      // Process the classification errors here.
    })
   .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

L'implementazione di codice di esempio del rilevatore di oggetti consente all'utente di passare da una modalità di elaborazione all'altra. Questo approccio rende più complicato il codice per la creazione delle attività e potrebbe non essere appropriato per il tuo caso d'uso. Puoi vedere questo codice nella funzione ObjectDetectorHelper della classe setupObjectDetector().

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
displayNamesLocales 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 Metadata Writer di TensorFlow Lite Codice impostazioni internazionali it
maxResults Imposta il numero massimo facoltativo di risultati di rilevamento con il punteggio più alto da restituire. Eventuali numeri positivi -1 (vengono restituiti tutti i risultati)
scoreThreshold Imposta la soglia del punteggio di previsione che sostituisce quella fornita nei metadati del modello (se presenti). I risultati inferiori a questo valore vengono rifiutati. Qualsiasi elemento in virgola mobile Non impostata
categoryAllowlist Consente di impostare l'elenco facoltativo di nomi di categorie consentite. Se il campo non è vuoto, i risultati del rilevamento il cui nome di categoria non è in questo set verranno filtrati. I nomi di categoria duplicati o sconosciuti vengono ignorati. Questa opzione si esclude a vicenda con categoryDenylist e l'utilizzo di entrambe genera un errore. Qualsiasi stringa Non impostata
categoryDenylist Consente di impostare l'elenco facoltativo di nomi di categorie non consentiti. Se il campo non è vuoto, i risultati del rilevamento il cui nome di categoria è presente in questo set verranno filtrati. I nomi di categoria duplicati o sconosciuti vengono ignorati. Questa opzione si esclude a vicenda con categoryAllowlist e l'uso di entrambe genera un errore. Qualsiasi stringa Non impostata
resultListener Imposta il listener dei risultati per ricevere i risultati del rilevamento in modo asincrono quando il rilevatore dell'oggetto è in modalità live streaming. Puoi utilizzare questa opzione solo se imposti runningMode su LIVE_STREAM. Non applicabile Non impostata

Preparazione dei dati

Devi convertire l'immagine o il frame di input in un oggetto com.google.mediapipe.framework.image.MPImage prima di passarlo al rilevatore di oggetti.

I seguenti esempi spiegano e mostrano come preparare i dati per il trattamento per ciascuno dei tipi di dati disponibili:

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 values. Use these values
// 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()
MPImage mpImage = new MediaImageBuilder(mediaImage).build();
    

Nel codice di esempio di Object Detector, la preparazione dei dati viene gestita nella classe ObjectDetectorHelper all'interno delle funzioni detectImage(), detectVideoFile(), detectLivestreamFrame().

Esegui l'attività

A seconda del tipo di dati con cui lavori, utilizza il metodo ObjectDetector.detect...() specifico per quel tipo di dati. Utilizza detect() per le singole immagini, detectForVideo() per i frame nei file video e detectAsync() per gli stream video. Quando esegui rilevamenti su uno stream video, assicurati di eseguirli in un thread separato per evitare di bloccare il thread dell'interfaccia utente.

I seguenti esempi di codice mostrano semplici esempi di come eseguire Rilevamento di oggetti in queste diverse modalità dati:

Immagine

ObjectDetectorResult detectionResult = objectDetector.detect(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.
ObjectDetectorResult detectionResult =
    objectDetector.detectForVideo(image, frameTimestampMs);
    

Live streaming

// Run inference on the frame. The detection results will be available
// via the `resultListener` provided in the `ObjectDetectorOptions` when
// the object detector was created.
objectDetector.detectAsync(image, frameTimestampMs);
    

L'esempio di codice del rilevatore di oggetti mostra le implementazioni di ciascuna di queste modalità in modo più dettagliato detect(), detectVideoFile() e detectAsync(). Il codice di esempio consente all'utente di passare da una modalità di elaborazione all'altra, il che potrebbe non essere necessario per il tuo caso d'uso.

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à di rilevamento di oggetti.
  • Quando viene eseguita in modalità immagine o video, l'attività Rilevamento di oggetti bloccherà il thread corrente fino a quando 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à Rilevamento oggetti 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 di rilevamento viene chiamata quando l'attività di rilevamento di oggetti è impegnata a elaborare un altro frame, il nuovo frame di input viene ignorato.

Gestire e visualizzare i risultati

Dopo l'esecuzione dell'inferenza, l'attività di rilevamento di oggetti restituisce un oggetto ObjectDetectorResult che descrive gli oggetti che ha trovato nell'immagine di input.

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

ObjectDetectorResult:
 Detection #0:
  Box: (x: 355, y: 133, w: 190, h: 206)
  Categories:
   index       : 17
   score       : 0.73828
   class name  : dog
 Detection #1:
  Box: (x: 103, y: 15, w: 138, h: 369)
  Categories:
   index       : 17
   score       : 0.73047
   class name  : dog

L'immagine seguente mostra una visualizzazione dell'output dell'attività:

Il codice di esempio del rilevatore di oggetti mostra come visualizzare i risultati del rilevamento restituiti dall'attività. Per ulteriori dettagli, consulta la classe OverlayView.