Wykrywaj obiekty na obrazach za pomocą modelu przeszkolonego przez AutoML na Androidzie

Po wytrenowaniu własnego modelu za pomocą AutoML Vision Edge możesz użyć go w swojej aplikacji do wykrywania obiektów na obrazach.

Istnieją dwa sposoby integrowania modeli wytrenowanych w AutoML Vision Edge: możesz połączyć model w pakiet, umieszczając go w folderze zasobów aplikacji, lub możesz go dynamicznie pobrać z Firebase.

Opcje łączenia modeli
Dołączone do Twojej aplikacji
  • Model jest częścią pakietu APK Twojej aplikacji
  • Model jest dostępny od ręki, nawet gdy urządzenie z Androidem jest offline
  • Nie ma potrzeby tworzenia projektu Firebase
Hostowane w Firebase
  • Hostuj model, przesyłając go do Firebase Machine Learning
  • Zmniejsza rozmiar pliku APK
  • Model jest pobierany na żądanie
  • Wysyłaj aktualizacje modeli bez ponownego publikowania aplikacji
  • Łatwe testowanie A/B dzięki zdalnej konfiguracji Firebase
  • Wymaga projektu Firebase

Zanim zaczniesz

  1. Jeśli chcesz pobrać model , pamiętaj o dodaniu Firebase do swojego projektu na Androida , jeśli jeszcze tego nie zrobiłeś. Nie jest to wymagane w przypadku spakowania modelu.

  2. Dodaj zależności dla biblioteki zadań TensorFlow Lite do pliku gradle na poziomie aplikacji modułu, którym zwykle jest app/build.gradle :

    Aby połączyć model z aplikacją:

    dependencies {
      // ...
      // Object detection with a bundled Auto ML model
      implementation 'org.tensorflow:tensorflow-lite-task-vision:0.0.0-nightly-SNAPSHOT'
    }
    

    Aby dynamicznie pobierać model z Firebase, dodaj także zależność Firebase ML:

    dependencies {
      // ...
      // Object detection with an Auto ML model deployed to Firebase
      implementation platform('com.google.firebase:firebase-bom:26.1.1')
      implementation 'com.google.firebase:firebase-ml-model-interpreter'
    
      implementation 'org.tensorflow:tensorflow-lite-task-vision:0.0.0-nightly'
    }
    

1. Załaduj model

Skonfiguruj lokalne źródło modelu

Aby połączyć model z aplikacją:

  1. Wyodrębnij model z archiwum zip pobranego z konsoli Google Cloud.
  2. Dołącz swój model do pakietu aplikacji:
    1. Jeśli nie masz folderu zasobów w swoim projekcie, utwórz go, klikając prawym przyciskiem myszy app/ folder, a następnie klikając Nowy > Folder > Folder zasobów .
    2. Skopiuj plik modelu tflite z osadzonymi metadanymi do folderu zasobów.
  3. Dodaj następujące elementy do pliku build.gradle swojej aplikacji, aby mieć pewność, że Gradle nie kompresuje pliku modelu podczas tworzenia aplikacji:

    android {
        // ...
        aaptOptions {
            noCompress "tflite"
        }
    }
    

    Plik modelu zostanie zawarty w pakiecie aplikacji i będzie dostępny jako surowy zasób.

Skonfiguruj źródło modelu hostowane w Firebase

Aby użyć modelu hostowanego zdalnie, utwórz obiekt RemoteModel , podając nazwę, którą przypisałeś modelowi podczas jego publikowania:

Jawa

// Specify the name you assigned when you deployed the model.
FirebaseCustomRemoteModel remoteModel =
        new FirebaseCustomRemoteModel.Builder("your_model").build();

Kotlina

// Specify the name you assigned when you deployed the model.
val remoteModel =
    FirebaseCustomRemoteModel.Builder("your_model_name").build()

Następnie rozpocznij zadanie pobierania modelu, określając warunki, na jakich chcesz zezwolić na pobieranie. Jeśli modelu nie ma na urządzeniu lub jeśli dostępna jest nowsza wersja modelu, zadanie asynchronicznie pobierze model z Firebase:

Jawa

DownloadConditions downloadConditions = new DownloadConditions.Builder()
        .requireWifi()
        .build();
RemoteModelManager.getInstance().download(remoteModel, downloadConditions)
        .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(@NonNull Task<Void> task) {
                // Success.
            }
        });

Kotlina

val downloadConditions = DownloadConditions.Builder()
    .requireWifi()
    .build()
RemoteModelManager.getInstance().download(remoteModel, downloadConditions)
    .addOnSuccessListener {
        // Success.
    }

Wiele aplikacji rozpoczyna zadanie pobierania w kodzie inicjującym, ale można to zrobić w dowolnym momencie, zanim będzie konieczne użycie modelu.

Utwórz detektor obiektów na podstawie swojego modelu

Po skonfigurowaniu źródeł modelu utwórz obiekt ObjectDetector na podstawie jednego z nich.

Jeśli masz tylko model powiązany lokalnie, po prostu utwórz detektor obiektów na podstawie pliku modelu i skonfiguruj wymagany próg wyniku zaufania (zobacz Oceń swój model ):

Jawa

// Initialization
ObjectDetectorOptions options = ObjectDetectorOptions.builder()
    .setScoreThreshold(0)  // Evaluate your model in the Google Cloud console
                           // to determine an appropriate value.
    .build();
ObjectDetector objectDetector = ObjectDetector.createFromFileAndOptions(context, modelFile, options);

Kotlina

// Initialization
val options = ObjectDetectorOptions.builder()
    .setScoreThreshold(0)  // Evaluate your model in the Google Cloud console
                           // to determine an appropriate value.
    .build()
val objectDetector = ObjectDetector.createFromFileAndOptions(context, modelFile, options)

Jeśli masz model hostowany zdalnie, przed uruchomieniem musisz sprawdzić, czy został pobrany. Możesz sprawdzić status zadania pobierania modelu, korzystając z metody isModelDownloaded() menedżera modeli.

Chociaż musisz to potwierdzić jedynie przed uruchomieniem detektora obiektów, jeśli masz zarówno model hostowany zdalnie, jak i model powiązany lokalnie, sensowne może być wykonanie tej kontroli podczas tworzenia instancji detektora obiektów: utwórz detektor obiektów ze zdalnego model, jeśli został pobrany, lub z modelu lokalnego w przeciwnym razie.

Jawa

FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
        .addOnSuccessListener(new OnSuccessListener<Boolean>() {
            @Override
            public void onSuccess(Boolean isDownloaded) {
            }
        });

Kotlina

FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
        .addOnSuccessListener { success ->

        }

Jeśli masz tylko model hostowany zdalnie, wyłącz funkcje związane z modelem — na przykład wyszarz lub ukryj część interfejsu użytkownika — do czasu potwierdzenia, że ​​model został pobrany. Można to zrobić, dołączając odbiornik do metody download() menedżera modelu.

Kiedy już wiesz, że Twój model został pobrany, utwórz detektor obiektów na podstawie pliku modelu:

Jawa

FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
        .addOnCompleteListener(new OnCompleteListener<File>() {
            @Override
            public void onComplete(@NonNull Task<File> task) {
                File modelFile = task.getResult();
                if (modelFile != null) {
                    ObjectDetectorOptions options = ObjectDetectorOptions.builder()
                            .setScoreThreshold(0)
                            .build();
                    objectDetector = ObjectDetector.createFromFileAndOptions(
                            getApplicationContext(), modelFile.getPath(), options);
                }
            }
        });

Kotlina

FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
        .addOnSuccessListener { modelFile ->
            val options = ObjectDetectorOptions.builder()
                    .setScoreThreshold(0f)
                    .build()
            objectDetector = ObjectDetector.createFromFileAndOptions(
                    applicationContext, modelFile.path, options)
        }

2. Przygotuj obraz wejściowy

Następnie dla każdego obrazu, który chcesz oznaczyć etykietą, utwórz na podstawie obrazu obiekt TensorImage . Możesz utworzyć obiekt TensorImage z Bitmap za pomocą metody fromBitmap :

Jawa

TensorImage image = TensorImage.fromBitmap(bitmap);

Kotlina

val image = TensorImage.fromBitmap(bitmap)

Jeśli danych obrazu nie ma w Bitmap , możesz załadować tablicę pikseli, jak pokazano w dokumentacji TensorFlow Lite .

3. Uruchom detektor obiektów

Aby wykryć obiekty na obrazie, przekaż obiekt TensorImage do metody detect() obiektu ObjectDetector .

Jawa

List<Detection> results = objectDetector.detect(image);

Kotlina

val results = objectDetector.detect(image)

4. Uzyskaj informacje o oznaczonych obiektach

Jeśli operacja wykrywania obiektu powiedzie się, zwraca listę obiektów Detection . Każdy obiekt Detection reprezentuje coś, co zostało wykryte na obrazie. Możesz pobrać obwiednię każdego obiektu i jego etykiety.

Na przykład:

Jawa

for (Detection result : results) {
    RectF bounds = result.getBoundingBox();
    List<Category> labels = result.getCategories();
}

Kotlina

for (result in results) {
    val bounds = result.getBoundingBox()
    val labels = result.getCategories()
}

Wskazówki, jak poprawić wydajność w czasie rzeczywistym

Jeśli chcesz oznaczać obrazy w aplikacji działającej w czasie rzeczywistym, postępuj zgodnie z poniższymi wskazówkami, aby uzyskać najlepszą liczbę klatek na sekundę:

  • Ogranicz wywołania do modułu etykietowania obrazów. Jeśli w trakcie działania narzędzia do etykietowania obrazów dostępna będzie nowa klatka wideo, usuń ją. Aby zapoznać się z przykładem, zobacz klasę VisionProcessorBase w przykładowej aplikacji szybkiego startu.
  • Jeśli używasz danych wyjściowych modułu etykietowania obrazów do nakładania grafiki na obraz wejściowy, najpierw uzyskaj wynik, a następnie wyrenderuj obraz i nakładkę w jednym kroku. W ten sposób renderujesz na powierzchnię wyświetlacza tylko raz dla każdej klatki wejściowej. Aby zapoznać się z przykładem, zobacz klasy CameraSourcePreview i GraphicOverlay w przykładowej aplikacji szybkiego startu.
  • Jeśli korzystasz z interfejsu API Camera2, przechwytuj obrazy w formacie ImageFormat.YUV_420_888 .

    Jeśli używasz starszego interfejsu Camera API, przechwytuj obrazy w formacie ImageFormat.NV21 .