Guida rapida per Android

Questa pagina mostra come creare un'app Android con TensorFlow Lite per analizzare il feed di una telecamera in tempo reale e identificare gli oggetti. Questo caso d'uso del machine learning è chiamato rilevamento di oggetti . L'app di esempio utilizza la libreria di attività TensorFlow Lite per la visione tramite i servizi Google Play per consentire l'esecuzione del modello di machine learning di rilevamento oggetti, che è l'approccio consigliato per creare un'applicazione ML con TensorFlow Lite.

Demo animata di rilevamento oggetti

Configura ed esegui l'esempio

Per la prima parte di questo esercizio, scarica il codice di esempio da GitHub ed eseguilo utilizzando Android Studio . Le sezioni seguenti di questo documento esplorano le sezioni pertinenti dell'esempio di codice, in modo da poterle applicare alle tue app Android. È necessario che siano installate le seguenti versioni di questi strumenti:

  • Android Studio 4.2 o versione successiva
  • Android SDK versione 21 o successiva

Ottieni il codice di esempio

Crea una copia locale del codice di esempio in modo da poterlo compilare ed eseguire.

Per clonare e configurare il codice di esempio:

  1. Clona il repository git
    git clone https://github.com/tensorflow/examples.git
    
  2. Configura la tua istanza git per utilizzare il checkout sparse, in modo da avere solo i file per l'app di esempio di rilevamento oggetti:
    cd examples
    git sparse-checkout init --cone
    git sparse-checkout set lite/examples/object_detection/android_play_services
    

Importare ed eseguire il progetto

Utilizza Android Studio per creare un progetto dal codice di esempio scaricato, creare il progetto ed eseguirlo.

Per importare e creare il progetto di codice di esempio:

  1. Avvia Android Studio .
  2. Dalla pagina di benvenuto di Android Studio, scegli Importa progetto oppure seleziona File > Nuovo > Importa progetto .
  3. Passare alla directory del codice di esempio contenente il file build.gradle ( ...examples/lite/examples/object_detection/android_play_services/build.gradle ) e selezionare quella directory.

Dopo aver selezionato questa directory, Android Studio crea un nuovo progetto e lo compila. Una volta completata la build, Android Studio visualizza un messaggio BUILD SUCCESSFUL nel pannello di stato dell'output della build .

Per eseguire il progetto:

  1. Da Android Studio, esegui il progetto selezionando Run > Run… e MainActivity .
  2. Seleziona un dispositivo Android collegato con una fotocamera per testare l'app.

Come funziona l'app di esempio

L'app di esempio utilizza un modello di rilevamento di oggetti preaddestrato, come mobilenetv1.tflite , nel formato TensorFlow Lite per cercare oggetti in un flusso video in diretta dalla fotocamera di un dispositivo Android. Il codice per questa funzionalità si trova principalmente in questi file:

  • ObjectDetectorHelper.kt : inizializza l'ambiente di runtime, abilita l'accelerazione hardware ed esegue il modello ML di rilevamento oggetti.
  • CameraFragment.kt : crea il flusso di dati dell'immagine della telecamera, prepara i dati per il modello e visualizza i risultati del rilevamento degli oggetti.

Le sezioni successive mostrano i componenti chiave di questi file di codice, quindi puoi modificare un'app Android per aggiungere questa funzionalità.

Costruisci l'app

Le sezioni seguenti spiegano i passaggi chiave per creare la tua app Android ed eseguire il modello mostrato nell'app di esempio. Queste istruzioni utilizzano l'app di esempio mostrata in precedenza come punto di riferimento.

Aggiungi dipendenze del progetto

Nella tua app Android di base, aggiungi le dipendenze del progetto per l'esecuzione dei modelli di machine learning TensorFlow Lite e l'accesso alle funzioni di utilità dei dati ML. Queste funzioni di utilità convertono dati come immagini in un formato dati tensore che può essere elaborato da un modello.

L'app di esempio utilizza la libreria di attività TensorFlow Lite per la visione dei servizi Google Play per consentire l'esecuzione del modello di machine learning di rilevamento oggetti. Le seguenti istruzioni spiegano come aggiungere le dipendenze della libreria richieste al tuo progetto di app Android.

Per aggiungere dipendenze del modulo:

  1. Nel modulo dell'app Android che utilizza TensorFlow Lite, aggiorna il file build.gradle del modulo per includere le seguenti dipendenze. Nel codice di esempio, questo file si trova qui: ...examples/lite/examples/object_detection/android_play_services/app/build.gradle

    ...
    dependencies {
    ...
        // Tensorflow Lite dependencies
        implementation 'org.tensorflow:tensorflow-lite-task-vision-play-services:0.4.2'
        implementation 'com.google.android.gms:play-services-tflite-gpu:16.1.0'
    ...
    }
    
  2. In Android Studio, sincronizza le dipendenze del progetto selezionando: File > Sincronizza progetto con file Gradle .

Inizializza i servizi Google Play

Quando utilizzi Google Play Services per eseguire modelli TensorFlow Lite, devi inizializzare il servizio prima di poterlo utilizzare. Se desideri utilizzare il supporto dell'accelerazione hardware con il servizio, ad esempio l'accelerazione GPU, abiliti anche tale supporto come parte di questa inizializzazione.

Per inizializzare TensorFlow Lite con i servizi Google Play:

  1. Crea un oggetto TfLiteInitializationOptions e modificalo per abilitare il supporto GPU:

    val options = TfLiteInitializationOptions.builder()
        .setEnableGpuDelegateSupport(true)
        .build()
    
  2. Utilizza il metodo TfLiteVision.initialize() per abilitare l'uso del runtime dei servizi di riproduzione e imposta un ascoltatore per verificare che sia stato caricato correttamente:

    TfLiteVision.initialize(context, options).addOnSuccessListener {
        objectDetectorListener.onInitialized()
    }.addOnFailureListener {
        // Called if the GPU Delegate is not supported on the device
        TfLiteVision.initialize(context).addOnSuccessListener {
            objectDetectorListener.onInitialized()
        }.addOnFailureListener{
            objectDetectorListener.onError("TfLiteVision failed to initialize: "
                    + it.message)
        }
    }
    

Inizializza l'interprete del modello ML

Inizializza l'interprete del modello di machine learning TensorFlow Lite caricando il file del modello e impostando i parametri del modello. Un modello TensorFlow Lite include un file .tflite contenente il codice del modello. Dovresti archiviare i tuoi modelli nella directory src/main/assets del tuo progetto di sviluppo, ad esempio:

.../src/main/assets/mobilenetv1.tflite`

Per inizializzare il modello:

  1. Aggiungi un file modello .tflite alla directory src/main/assets del tuo progetto di sviluppo, ad esempio ssd_mobilenet_v1 .
  2. Imposta la variabile modelName per specificare il nome file del modello ML:

    val modelName = "mobilenetv1.tflite"
    
  3. Imposta le opzioni per il modello, come la soglia di previsione e la dimensione del set di risultati:

    val optionsBuilder =
        ObjectDetector.ObjectDetectorOptions.builder()
            .setScoreThreshold(threshold)
            .setMaxResults(maxResults)
    
  4. Abilita l'accelerazione GPU con le opzioni e consenti al codice di fallire correttamente se l'accelerazione non è supportata sul dispositivo:

    try {
        optionsBuilder.useGpu()
    } catch(e: Exception) {
        objectDetectorListener.onError("GPU is not supported on this device")
    }
    
    
  5. Utilizza le impostazioni di questo oggetto per costruire un oggetto TensorFlow Lite ObjectDetector che contiene il modello:

    objectDetector =
        ObjectDetector.createFromFileAndOptions(
            context, modelName, optionsBuilder.build())
    

Per ulteriori informazioni sull'utilizzo dei delegati di accelerazione hardware con TensorFlow Lite, consulta Delegati TensorFlow Lite .

Preparare i dati per il modello

Prepari i dati per l'interpretazione da parte del modello trasformando i dati esistenti come le immagini nel formato dati Tensor , in modo che possano essere elaborati dal tuo modello. I dati in un tensore devono avere dimensioni, o forma, specifiche che corrispondano al formato dei dati utilizzati per addestrare il modello. A seconda del modello utilizzato, potrebbe essere necessario trasformare i dati per adattarli alle aspettative del modello. L'app di esempio usa un oggetto ImageAnalysis per estrarre fotogrammi di immagine dal sottosistema della fotocamera.

Per preparare i dati per l'elaborazione da parte del modello:

  1. Crea un oggetto ImageAnalysis per estrarre le immagini nel formato richiesto:

    imageAnalyzer =
        ImageAnalysis.Builder()
            .setTargetAspectRatio(AspectRatio.RATIO_4_3)
            .setTargetRotation(fragmentCameraBinding.viewFinder.display.rotation)
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .setOutputImageFormat(OUTPUT_IMAGE_FORMAT_RGBA_8888)
            .build()
            ...
    
  2. Collegare l'analizzatore al sottosistema della fotocamera e creare un buffer bitmap per contenere i dati ricevuti dalla fotocamera:

            .also {
            it.setAnalyzer(cameraExecutor) { image ->
                if (!::bitmapBuffer.isInitialized) {
                    bitmapBuffer = Bitmap.createBitmap(
                        image.width,
                        image.height,
                        Bitmap.Config.ARGB_8888
                    )
                }
                detectObjects(image)
            }
        }
    
  3. Estrai i dati dell'immagine specifici necessari al modello e trasmetti le informazioni sulla rotazione dell'immagine:

    private fun detectObjects(image: ImageProxy) {
        // Copy out RGB bits to the shared bitmap buffer
        image.use { bitmapBuffer.copyPixelsFromBuffer(image.planes[0].buffer) }
        val imageRotation = image.imageInfo.rotationDegrees
        objectDetectorHelper.detect(bitmapBuffer, imageRotation)
    }    
    
  4. Completa eventuali trasformazioni finali dei dati e aggiungi i dati dell'immagine a un oggetto TensorImage , come mostrato nel metodo ObjectDetectorHelper.detect() dell'app di esempio:

    val imageProcessor = ImageProcessor.Builder().add(Rot90Op(-imageRotation / 90)).build()
    
    // Preprocess the image and convert it into a TensorImage for detection.
    val tensorImage = imageProcessor.process(TensorImage.fromBitmap(image))
    

Esegui previsioni

Una volta creato un oggetto TensorImage con dati immagine nel formato corretto, puoi eseguire il modello rispetto a tali dati per produrre una previsione o un'inferenza . Nell'app di esempio, questo codice è contenuto nel metodo ObjectDetectorHelper.detect() .

Per eseguire un modello e generare previsioni dai dati dell'immagine:

  • Esegui la previsione passando i dati dell'immagine alla funzione di previsione:

    val results = objectDetector?.detect(tensorImage)
    

Gestire l'output del modello

Dopo aver eseguito i dati dell'immagine rispetto al modello di rilevamento degli oggetti, viene prodotto un elenco di risultati di previsione che il codice dell'app deve gestire eseguendo logica aziendale aggiuntiva, visualizzando i risultati all'utente o eseguendo altre azioni. Il modello di rilevamento degli oggetti nell'app di esempio produce un elenco di previsioni e riquadri di delimitazione per gli oggetti rilevati. Nell'app di esempio, i risultati della previsione vengono passati a un oggetto listener per un'ulteriore elaborazione e visualizzazione all'utente.

Per gestire i risultati della previsione del modello:

  1. Utilizza un pattern listener per passare i risultati al codice dell'app o agli oggetti dell'interfaccia utente. L'app di esempio utilizza questo modello per passare i risultati del rilevamento dall'oggetto ObjectDetectorHelper all'oggetto CameraFragment :

    objectDetectorListener.onResults( // instance of CameraFragment
        results,
        inferenceTime,
        tensorImage.height,
        tensorImage.width)
    
  2. Agire sui risultati, ad esempio mostrando la previsione all'utente. L'app di esempio disegna una sovrapposizione sull'oggetto CameraPreview per mostrare il risultato:

    override fun onResults(
      results: MutableList<Detection>?,
      inferenceTime: Long,
      imageHeight: Int,
      imageWidth: Int
    ) {
        activity?.runOnUiThread {
            fragmentCameraBinding.bottomSheetLayout.inferenceTimeVal.text =
                String.format("%d ms", inferenceTime)
    
            // Pass necessary information to OverlayView for drawing on the canvas
            fragmentCameraBinding.overlay.setResults(
                results ?: LinkedList<Detection>(),
                imageHeight,
                imageWidth
            )
    
            // Force a redraw
            fragmentCameraBinding.overlay.invalidate()
        }
    }
    

Prossimi passi