Guida rapida per Android

Questa pagina mostra come creare un'app Android con TensorFlow Lite per analizzare un feed live della telecamera e identificare gli oggetti. Questo caso d'uso di machine learning è chiamato rilevamento di oggetti . L'app di esempio utilizza la libreria TensorFlow Lite Task per la visione tramite i servizi di Google Play per consentire l'esecuzione del modello di apprendimento automatico per il rilevamento di oggetti, che è l'approccio consigliato per la creazione di 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. Sono necessarie le seguenti versioni di questi strumenti installati:

  • Android Studio 4.2 o versioni successive
  • 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 impostare 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 degli oggetti:
    cd examples
    git sparse-checkout init --cone
    git sparse-checkout set lite/examples/object_detection/android_play_services
    

Importa ed esegui il progetto

Usa Android Studio per creare un progetto dal codice di esempio scaricato, compilare 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 o 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. Al termine della build, Android Studio visualizza un messaggio BUILD SUCCESSFUL nel pannello di stato Build Output .

Per eseguire il progetto:

  1. Da Android Studio, esegui il progetto selezionando Esegui > Esegui... 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 degli oggetti pre-addestrato, come mobilenetv1.tflite , nel formato TensorFlow Lite cerca gli oggetti in un flusso video live dalla fotocamera di un dispositivo Android. Il codice per questa funzione è principalmente in questi file:

  • ObjectDetectorHelper.kt - Inizializza l'ambiente di runtime, abilita l'accelerazione hardware ed esegue il modello ML di rilevamento degli 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 illustrano 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 le 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 TensorFlow Lite Task per la visione dai servizi di Google Play per consentire l'esecuzione del modello di machine learning per il rilevamento di oggetti. Le istruzioni seguenti spiegano come aggiungere le dipendenze della libreria richieste al tuo progetto di app Android.

Per aggiungere le 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 di Google Play

Quando utilizzi i servizi di Google Play per eseguire i 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. Utilizzare il metodo TfLiteVision.initialize() per abilitare l'uso del runtime dei servizi di riproduzione e impostare un listener 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)
        }
    }
    

Inizializzare l'interprete del modello ML

Inizializzare l'interprete del modello di apprendimento automatico 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 del file del tuo 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 non riuscire correttamente se l'accelerazione non è supportata sul dispositivo:

    try {
        optionsBuilder.useGpu()
    } catch(e: Exception) {
        objectDetectorListener.onError("GPU is not supported on this device")
    }
    
    
  5. Utilizzare 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, vedere Delegati di TensorFlow Lite .

Preparare i dati per il modello

Si preparano 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 modello. I dati in un Tensor 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 a ciò che il modello si aspetta. L'app di esempio usa un oggetto ImageAnalysis per estrarre i fotogrammi dell'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 telecamera e creare un buffer bitmap per contenere i dati ricevuti dalla telecamera:

            .also {
            it.setAnalyzer(cameraExecutor) { image ->
                if (!::bitmapBuffer.isInitialized) {
                    bitmapBuffer = Bitmap.createBitmap(
                        image.width,
                        image.height,
                        Bitmap.Config.ARGB_8888
                    )
                }
                detectObjects(image)
            }
        }
    
  3. Estrarre i dati dell'immagine specifici necessari al modello e passare 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 le 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

Dopo aver creato un oggetto TensorImage con i dati dell'immagine nel formato corretto, puoi eseguire il modello su 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 tua 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 una logica aziendale aggiuntiva, visualizzando i risultati per l'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. Usa un modello listener per passare i risultati al codice dell'app o agli oggetti dell'interfaccia utente. L'app di esempio usa 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, come mostrare 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