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 i cani all'interno di un'immagine. Queste istruzioni mostrano come utilizzare l'attività Rilevamento 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 Rilevamento di oggetti per Android. L'esempio utilizza la fotocamera di un dispositivo Android fisico per rilevare continuamente gli oggetti e può anche utilizzare immagini e video dalla galleria del dispositivo per rilevare 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 di Rilevamento oggetti è 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 Object Detector:
    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 istruzioni, consulta la Guida alla configurazione per Android.

Componenti chiave

I seguenti file contengono il codice fondamentale per l'applicazione di esempio Rilevamento oggetti:

Configurazione

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

Rilevamento 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à MediaPipe Object Detector richiede un modello addestrato compatibile con questa attività. Per ulteriori informazioni sui modelli addestrati disponibili per Rilevamento di oggetti, 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

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

Crea l'attività

Puoi utilizzare la funzione createFromOptions per creare l'attività. La funzione createFromOptions accetta opzioni di configurazione, tra cui modalità di esecuzione, locale dei nomi visualizzati, numero massimo di risultati, soglia di confidenza, elenco consentiti e elenco vietati delle categorie. Se non viene specificata un'opzione di configurazione, verrà utilizzato il valore predefinito. Per ulteriori informazioni sulle opzioni di configurazione, consulta Panoramica della configurazione.

L'attività Rilevamento 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 scoprire 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 del codice di esempio di Rilevamento oggetti 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 setupObjectDetector() della classe ObjectDetectorHelper.

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
displayNamesLocales Imposta la lingua delle etichette da utilizzare per i nomi visualizzati forniti nei metadati del modello dell'attività, se disponibile. Il valore predefinito è en per l'inglese. Puoi aggiungere etichette localizzate ai metadati di un modello personalizzato utilizzando l'API TensorFlow Lite Metadata Writer Codice delle impostazioni internazionali it
maxResults Imposta il numero massimo facoltativo di risultati di rilevamento con il punteggio più alto da restituire. Qualsiasi numero positivo -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 stato mobile Non impostato
categoryAllowlist Imposta l'elenco facoltativo dei nomi delle categorie consentite. Se non è vuoto, i risultati di rilevamento il cui nome della categoria non è presente in questo insieme verranno eliminati. I nomi di categorie duplicati o sconosciuti vengono ignorati. Questa opzione è mutuamente esclusiva con categoryDenylist e l'utilizzo di entrambe genera un errore. Qualsiasi stringa Non impostato
categoryDenylist Imposta l'elenco facoltativo dei nomi di categorie non consentiti. Se non è vuoto, i risultati di rilevamento il cui nome della categoria è presente in questo insieme verranno esclusi. I nomi di categorie duplicati o sconosciuti vengono ignorati. Questa opzione è mutuamente esclusa da categoryAllowlist e l'utilizzo di entrambe genera un errore. Qualsiasi stringa Non impostato
resultListener Imposta l'ascoltatore dei risultati in modo da ricevere i risultati del rilevamento in modo asincrono quando il rilevatore di oggetti è in modalità live streaming. Puoi utilizzare questa opzione solo se imposti runningMode su LIVE_STREAM. Non applicabile Non impostato

Preparazione dei dati

Devi convertire l'immagine o l'inquadratura di input in un oggetto com.google.mediapipe.framework.image.MPImage prima di trasmetterlo a Rilevatore di oggetti.

Gli esempi riportati di seguito spiegano e mostrano come preparare i dati per l'elaborazione 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 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 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 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()
MPImage mpImage = new MediaImageBuilder(mediaImage).build();
    

Nel codice di esempio del Rilevamento di oggetti, 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 stai lavorando, utilizza il metodo ObjectDetector.detect...() specifico per quel tipo di dati. Utilizza detect() per le singole immagini, detectForVideo() per i fotogrammi nei file video e detectAsync() per gli stream video. Quando esegui i rilevamenti su un spostamento video, assicurati di eseguirli in un thread separato per evitare di bloccare il thread dell'interfaccia utente.

I seguenti esempi di codice mostrano esempi semplici di come eseguire Rilevamento oggetti in queste diverse modalità di 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 Rilevamento 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, che potrebbe non essere necessaria per il tuo caso d'uso.

Tieni presente quanto segue:

  • Quando esegui l'operazione in modalità video o live streaming, devi anche fornire il timestamp del frame di input all'attività di rilevamento oggetti.
  • Quando viene eseguita in modalità immagine o video, l'attività Rilevamento oggetti 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 eseguita in modalità live streaming, l'attività di rilevamento degli oggetti 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 di rilevamento viene chiamata quando l'attività di rilevamento degli oggetti è impegnata a elaborare un altro frame, il nuovo frame di input verrà ignorato.

Gestire e visualizzare i risultati

Dopo aver eseguito l'inferenza, l'attività Rilevamento oggetti restituisce un oggetto ObjectDetectorResult che descrive gli oggetti trovati 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à:

Due cani evidenziati con i riquadri di delimitazione

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