Krótkie wprowadzenie do Androida

Na tej stronie pokazano, jak zbudować aplikację na Androida za pomocą TensorFlow Lite do analizowania obrazu z kamery na żywo i identyfikowania obiektów. Ten przypadek użycia uczenia maszynowego nazywa się wykrywaniem obiektów . Przykładowa aplikacja korzysta z biblioteki zadań TensorFlow Lite do obsługi wizji za pośrednictwem usług Google Play , aby umożliwić wykonanie modelu uczenia maszynowego wykrywania obiektów, co jest zalecanym podejściem do tworzenia aplikacji ML za pomocą TensorFlow Lite.

Animowane demo wykrywania obiektów

Skonfiguruj i uruchom przykład

W pierwszej części tego ćwiczenia pobierz przykładowy kod z GitHub i uruchom go przy użyciu Android Studio . W poniższych sekcjach tego dokumentu omówiono odpowiednie sekcje przykładowego kodu, dzięki czemu można je zastosować do własnych aplikacji na Androida. Musisz mieć zainstalowane następujące wersje tych narzędzi:

  • Android Studio 4.2 lub nowszy
  • Android SDK w wersji 21 lub nowszej

Pobierz przykładowy kod

Utwórz lokalną kopię przykładowego kodu, aby móc go skompilować i uruchomić.

Aby sklonować i skonfigurować przykładowy kod:

  1. Sklonuj repozytorium git
    git clone https://github.com/tensorflow/examples.git
    
  2. Skonfiguruj swoją instancję git tak, aby korzystała z rzadkiego pobierania, więc będziesz mieć tylko pliki dla przykładowej aplikacji do wykrywania obiektów:
    cd examples
    git sparse-checkout init --cone
    git sparse-checkout set lite/examples/object_detection/android_play_services
    

Zaimportuj i uruchom projekt

Użyj Android Studio, aby utworzyć projekt na podstawie pobranego przykładowego kodu, skompiluj projekt i uruchom go.

Aby zaimportować i zbudować przykładowy projekt kodu:

  1. Uruchom Android Studio .
  2. Na stronie powitalnej Android Studio wybierz opcję Importuj projekt lub wybierz opcję Plik > Nowy > Importuj projekt .
  3. Przejdź do przykładowego katalogu kodu zawierającego plik build.gradle ( ...examples/lite/examples/object_detection/android_play_services/build.gradle ) i wybierz ten katalog.

Po wybraniu tego katalogu Android Studio tworzy nowy projekt i go kompiluje. Po zakończeniu kompilacji Android Studio wyświetla komunikat BUILD SUCCESSFUL w panelu stanu wyników kompilacji .

Aby uruchomić projekt:

  1. W Android Studio uruchom projekt, wybierając opcję Uruchom > Uruchom… i MainActivity .
  2. Wybierz podłączone urządzenie z Androidem i kamerą, aby przetestować aplikację.

Jak działa przykładowa aplikacja

Przykładowa aplikacja wykorzystuje wstępnie wyszkolony model wykrywania obiektów, taki jak mobilenetv1.tflite , w formacie TensorFlow Lite wyszukuje obiekty w strumieniu wideo na żywo z kamery urządzenia z systemem Android. Kod tej funkcji znajduje się głównie w następujących plikach:

  • ObjectDetectorHelper.kt — inicjuje środowisko wykonawcze, umożliwia przyspieszenie sprzętowe i uruchamia model ML do wykrywania obiektów.
  • CameraFragment.kt - Buduje strumień danych obrazu z kamery, przygotowuje dane do modelu i wyświetla wyniki wykrycia obiektu.

W następnych sekcjach przedstawiono kluczowe składniki tych plików kodu, dzięki czemu można modyfikować aplikację dla systemu Android w celu dodania tej funkcji.

Zbuduj aplikację

W poniższych sekcjach wyjaśniono najważniejsze kroki tworzenia własnej aplikacji dla systemu Android i uruchamiania modelu pokazanego w przykładowej aplikacji. W niniejszych instrukcjach jako punkt odniesienia wykorzystano pokazaną wcześniej przykładową aplikację.

Dodaj zależności projektu

W podstawowej aplikacji na Androida dodaj zależności projektu umożliwiające uruchamianie modeli uczenia maszynowego TensorFlow Lite i uzyskiwanie dostępu do funkcji narzędzia do obsługi danych ML. Te funkcje narzędziowe konwertują dane, takie jak obrazy, do formatu danych tensorowych, który może być przetwarzany przez model.

Przykładowa aplikacja korzysta z biblioteki zadań TensorFlow Lite do obsługi wizji z usług Google Play, aby umożliwić wykonanie modelu uczenia maszynowego z wykrywaniem obiektów. Poniższe instrukcje wyjaśniają, jak dodać wymagane zależności bibliotek do własnego projektu aplikacji dla systemu Android.

Aby dodać zależności modułów:

  1. W module aplikacji na Androida korzystającym z TensorFlow Lite zaktualizuj plik build.gradle modułu, aby uwzględnić następujące zależności. W przykładowym kodzie plik ten znajduje się tutaj: ...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. W Android Studio zsynchronizuj zależności projektu, wybierając: Plik > Synchronizuj projekt z plikami Gradle .

Zainicjuj usługi Google Play

Jeśli używasz usług Google Play do uruchamiania modeli TensorFlow Lite, musisz zainicjować usługę, zanim będziesz mógł z niej skorzystać. Jeśli chcesz korzystać z obsługi akceleracji sprzętowej w usłudze, na przykład akceleracji GPU, włącz tę obsługę również w ramach tej inicjalizacji.

Aby zainicjować TensorFlow Lite z usługami Google Play:

  1. Utwórz obiekt TfLiteInitializationOptions i zmodyfikuj go, aby włączyć obsługę procesora GPU:

    val options = TfLiteInitializationOptions.builder()
        .setEnableGpuDelegateSupport(true)
        .build()
    
  2. Użyj metody TfLiteVision.initialize() , aby umożliwić korzystanie ze środowiska wykonawczego usług Play i ustaw detektor w celu sprawdzenia, czy załadowanie zakończyło się pomyślnie:

    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)
        }
    }
    

Zainicjuj interpreter modelu ML

Zainicjuj interpreter modelu uczenia maszynowego TensorFlow Lite, ładując plik modelu i ustawiając parametry modelu. Model TensorFlow Lite zawiera plik .tflite zawierający kod modelu. Powinieneś przechowywać swoje modele w katalogu src/main/assets swojego projektu rozwojowego, na przykład:

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

Aby zainicjować model:

  1. Dodaj plik modelu .tflite do katalogu src/main/assets swojego projektu programistycznego, na przykład ssd_mobilenet_v1 .
  2. Ustaw zmienną modelName , aby określić nazwę pliku modelu ML:

    val modelName = "mobilenetv1.tflite"
    
  3. Ustaw opcje modelu, takie jak próg przewidywania i rozmiar zestawu wyników:

    val optionsBuilder =
        ObjectDetector.ObjectDetectorOptions.builder()
            .setScoreThreshold(threshold)
            .setMaxResults(maxResults)
    
  4. Włącz akcelerację GPU za pomocą opcji i pozwól, aby kod działał płynnie, jeśli akceleracja nie jest obsługiwana na urządzeniu:

    try {
        optionsBuilder.useGpu()
    } catch(e: Exception) {
        objectDetectorListener.onError("GPU is not supported on this device")
    }
    
    
  5. Użyj ustawień z tego obiektu, aby skonstruować obiekt TensorFlow Lite ObjectDetector zawierający model:

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

Aby uzyskać więcej informacji na temat używania delegatów akceleracji sprzętowej z TensorFlow Lite, zobacz Delegaty TensorFlow Lite .

Przygotuj dane do modelu

Przygotowujesz dane do interpretacji przez model, przekształcając istniejące dane, takie jak obrazy, do formatu danych Tensor , aby mogły być przetwarzane przez Twój model. Dane w Tensorze muszą mieć określone wymiary lub kształt pasujący do formatu danych używanych do uczenia modelu. W zależności od używanego modelu może być konieczne przekształcenie danych w celu dopasowania do oczekiwań modelu. Przykładowa aplikacja używa obiektu ImageAnalysis do wyodrębniania klatek obrazu z podsystemu kamery.

Aby przygotować dane do przetwarzania przez model:

  1. Zbuduj obiekt ImageAnalysis , aby wyodrębnić obrazy w wymaganym formacie:

    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. Podłącz analizator do podsystemu kamery i utwórz bufor mapy bitowej, który będzie zawierał dane otrzymane z kamery:

            .also {
            it.setAnalyzer(cameraExecutor) { image ->
                if (!::bitmapBuffer.isInitialized) {
                    bitmapBuffer = Bitmap.createBitmap(
                        image.width,
                        image.height,
                        Bitmap.Config.ARGB_8888
                    )
                }
                detectObjects(image)
            }
        }
    
  3. Wyodrębnij określone dane obrazu potrzebne modelowi i przekaż informacje o obrocie obrazu:

    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. Dokończ wszelkie końcowe transformacje danych i dodaj dane obrazu do obiektu TensorImage , jak pokazano w metodzie ObjectDetectorHelper.detect() przykładowej aplikacji:

    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))
    

Uruchom prognozy

Po utworzeniu obiektu TensorImage z danymi obrazu w odpowiednim formacie można uruchomić model na podstawie tych danych, aby uzyskać przewidywanie lub wnioskowanie . W przykładowej aplikacji ten kod jest zawarty w metodzie ObjectDetectorHelper.detect() .

Aby uruchomić model i wygenerować prognozy na podstawie danych obrazu:

  • Uruchom prognozę, przekazując dane obrazu do funkcji przewidywania:

    val results = objectDetector?.detect(tensorImage)
    

Obsługuj dane wyjściowe modelu

Po uruchomieniu danych obrazu w oparciu o model wykrywania obiektów generowana jest lista wyników przewidywań, które musi obsłużyć kod aplikacji, wykonując dodatkową logikę biznesową, wyświetlając wyniki użytkownikowi lub podejmując inne działania. Model wykrywania obiektów w przykładowej aplikacji generuje listę przewidywań i ramek ograniczających dla wykrytych obiektów. W przykładowej aplikacji wyniki przewidywania są przekazywane do obiektu nasłuchującego w celu dalszego przetwarzania i wyświetlania użytkownikowi.

Aby obsłużyć wyniki przewidywania modelu:

  1. Użyj wzorca odbiornika, aby przekazać wyniki do kodu aplikacji lub obiektów interfejsu użytkownika. Przykładowa aplikacja używa tego wzorca do przekazywania wyników wykrywania z obiektu ObjectDetectorHelper do obiektu CameraFragment :

    objectDetectorListener.onResults( // instance of CameraFragment
        results,
        inferenceTime,
        tensorImage.height,
        tensorImage.width)
    
  2. Działaj na podstawie wyników, na przykład wyświetlając prognozę użytkownikowi. Przykładowa aplikacja rysuje nakładkę na obiekcie CameraPreview , aby pokazać wynik:

    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()
        }
    }
    

Następne kroki