Wykrywanie obiektów w obrazach za pomocą modelu wytrenowanego przez AutoML na Androidzie

Gdy wytrenujesz własny model przy użyciu AutoML Vision Edge, możesz używać go w swojej aplikacji do wykrywania obiektów na obrazach.

Istnieją 2 sposoby integracji modeli wytrenowanych w AutoML Vision Edge: skompiluj model, umieszczając go w folderze zasobów aplikacji. pobierać dynamicznie je z Firebase.

Opcje grupowania modeli
Pakiet w aplikacji
  • Model jest częścią pakietu APK aplikacji
  • Model jest dostępny od razu, nawet gdy urządzenie z Androidem jest offline
  • Nie potrzeba projektu Firebase
Hostowane w Firebase

Zanim zaczniesz

  1. Jeśli chcesz pobrać model, dodaj Firebase do swojego projektu na Androida, jeśli jeszcze nie zostało to zrobione. Nie jest to wymagane, gdy łączysz model w pakiet.

  2. Dodaj zależności do biblioteki zadań TensorFlow Lite do biblioteki modułu plik Gradle na poziomie aplikacji, który zwykle ma wartość app/build.gradle:

    Aby dołączyć model do aplikacji:

    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 również Firebase ML zależność:

    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. Wczytaj model

Skonfiguruj źródło modelu lokalnego

Aby połączyć model z aplikacją:

  1. Rozpakuj model z archiwum ZIP pobranego z konsoli Google Cloud.
  2. Umieść model w pakiecie aplikacji:
    1. Jeśli w projekcie nie masz folderu zasobów, utwórz go kliknij prawym przyciskiem myszy folder app/, a następnie kliknij Nowe > Folder > Folder Zasoby.
    2. Skopiuj do zasobów plik modelu tflite z osadzonymi metadanymi folderu Dysku.
  3. Dodaj te fragmenty do pliku build.gradle z informacjami o aplikacji, aby mieć pewność, że: Gradle nie kompresuje pliku modelu podczas tworzenia aplikacji:

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

    Plik modelu zostanie dołączony do pakietu aplikacji i będzie dostępny jako nieprzetworzony zasób.

Skonfiguruj źródło modelu hostowanego w Firebase

Aby używać modelu hostowanego zdalnie, utwórz obiekt RemoteModel, określając nazwę przypisaną do modelu podczas jego publikowania:

Java

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

Kotlin

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

Następnie uruchom zadanie pobierania modelu, określając warunki, które którym chcesz zezwolić na pobieranie. Jeśli nie ma modelu na urządzeniu lub jest on nowszy gdy dostępna będzie wersja modelu, zadanie asynchronicznie pobierze model z Firebase:

Java

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

Kotlin

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

Wiele aplikacji rozpoczyna zadanie pobierania w kodzie inicjowania, możesz to zrobić w dowolnym momencie, zanim trzeba będzie skorzystać z modelu.

Tworzenie wzorca do wykrywania obiektów na podstawie modelu

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

Jeśli masz tylko model dołączony lokalnie, utwórz wzorzec do wykrywania obiektów na podstawie pliku modelu i skonfigurować wskaźnik ufności próg, który chcesz zastosować (zobacz Ocena modelu):

Java

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

Kotlin

// 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, musisz sprawdzić, czy został pobrane przed uruchomieniem. Stan pobierania modelu możesz sprawdzić za pomocą metody isModelDownloaded() menedżera modeli.

Mimo że musisz to potwierdzić tylko przed uruchomieniem wykrywania obiektów, korzystają zarówno z modelu hostowanego zdalnie, jak i z pakietu lokalnego, może to sprawić, warto przeprowadzić tę kontrolę przy tworzeniu wystąpienia detektora obiektów: utwórz detektora obiektów z modelu zdalnego, jeśli został pobrany, oraz z lokalnego w inny sposób.

Java

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

Kotlin

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

        }

Jeśli masz tylko model hostowany zdalnie, wyłącz powiązany z nim model funkcji – np. wyszarzenia lub ukrycia części interfejsu – potwierdzasz, że model został pobrany. Aby to zrobić, dołącz detektor do metody download() menedżera modeli.

Gdy dowiesz się, że model został pobrany, utwórz detektor obiektów w plik modelu:

Java

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

Kotlin

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

2. Przygotowywanie obrazu wejściowego

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

Java

TensorImage image = TensorImage.fromBitmap(bitmap);

Kotlin

val image = TensorImage.fromBitmap(bitmap)

Jeśli dane obrazu nie znajdują się w Bitmap, możesz wczytać tablicę pikseli w sposób pokazany na dokumentach TensorFlow Lite.

3. Uruchom detektor obiektów

Aby wykrywać obiekty na obrazie, przekaż obiekt TensorImage do funkcji Metoda detect() użytkownika ObjectDetector.

Java

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

Kotlin

val results = objectDetector.detect(image)

4. Uzyskiwanie informacji o obiektach oznaczonych etykietami

Jeśli operacja wykrywania obiektów się powiedzie, wyświetli się lista Detection obiektów. Każdy obiekt Detection reprezentuje coś, co zostało wykryte w . Możesz pobrać ramkę ograniczającą każdego obiektu i jej etykiety.

Przykład:

Java

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

Kotlin

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

Wskazówki dotyczące poprawy skuteczności w czasie rzeczywistym

Jeśli chcesz oznaczać obrazy w aplikacji działającej w czasie rzeczywistym, postępuj zgodnie z tymi instrukcjami wytycznych dotyczących uzyskiwania najlepszej liczby klatek na sekundę:

  • Ogranicz wywołania do osoby oznaczającej obrazy. Jeśli nowa klatka wideo dostępne podczas działania narzędzia do etykietowania obrazów, upuść ramkę. Zobacz VisionProcessorBase w przykładowej aplikacji z krótkim wprowadzeniem.
  • Jeśli używasz danych wyjściowych osoby oznaczającej obrazy do nakładania grafiki na obraz wejściowy, najpierw uzyskaj wynik, a następnie wyrenderuj obraz i nakładanie nakładek w jednym kroku. W ten sposób renderowanie na powierzchni tylko raz na każdą ramkę wejściową. Zobacz CameraSourcePreview i GraphicOverlay w przykładowej aplikacji z krótkim wprowadzeniem dla przykład.
  • Jeśli korzystasz z interfejsu API Camera2, rób zdjęcia w Format: ImageFormat.YUV_420_888.

    Jeśli używasz starszej wersji interfejsu Camera API, rób zdjęcia w Format: ImageFormat.NV21.