Analiza obrazu

analizę obrazu, dostarcza aplikacji obraz dostępny dla procesora, do przetwarzania obrazu, rozpoznawania obrazów lub wnioskowania z wykorzystaniem systemów uczących się. aplikacja implementuje analyze() uruchamianą w każdej ramce.

Aby dowiedzieć się, jak zintegrować pakiet ML Kit od Google z aplikacją CameraX, zobacz ML Kit Analyzer.

Tryby pracy

Gdy potok analizy aplikacji nie nadąża za ramką kamery X związane z szybkością działania, aparat X można skonfigurować tak, by pomijał klatki na jeden z tych sposobów:

  • non-blocking (nieblokujący): w tym trybie wykonawcy zawsze buforują najnowszy obraz w buforze obrazów (podobny do kolejki z głębią obrazu) a aplikacja analizuje poprzedni obraz. Jeśli AparatX otrzymuje nowy obraz przed zakończeniem przetwarzania aplikacji, nowy obraz jest zapisywany w tym samym buforze, zastępując poprzedni. Pamiętaj, że funkcja ImageAnalysis.Builder.setImageQueueDepth() nie ma wpływu w w tym scenariuszu, a zawartość bufora jest zawsze zastępowana. Możesz włączyć ten tryb nieblokujący, dzwoniąc setBackpressureStrategy() z STRATEGY_KEEP_ONLY_LATEST Więcej informacji o konsekwencjach dla wykonawców znajdziesz w dokumentacji dokumentacja dla STRATEGY_KEEP_ONLY_LATEST

  • blokowanie: w tym trybie wewnętrzny wykonawca może dodać wiele obrazów do wewnętrznej kolejki obrazów i rozpoczyna usuwanie klatek dopiero wtedy, gdy kolejka pełny. Blokowanie obejmuje cały aparat: jeśli urządzenia z aparatem ma wiele powiązanych przypadków użycia, wszystkie te przypadki użycia zostaną zablokowane, gdy CameraX przetwarza te zdjęcia. Dla: Gdy zarówno podgląd, jak i analiza obrazu są powiązane z aparatem, podgląd byłby też blokowany, gdy AparatX przetwarza zdjęcia. Aby włączyć tryb blokowania, musisz przekazać STRATEGY_BLOCK_PRODUCER do setBackpressureStrategy() Głębokość kolejki obrazów możesz też skonfigurować za pomocą ImageAnalysis.Builder.setImageQueueDepth().

Dzięki krótkim opóźnieniom analizatora o dużej wydajności może analiza obrazu jest krótsza niż czas trwania klatki w aparacie CameraX (np. 16 ms przy 60 kl./s). Każdy tryb operacyjny zapewnia płynne działanie z myślą o użytkownikach. Tryb blokowania jest nadal przydatny w niektórych sytuacjach, na przykład: do radzenia sobie z bardzo krótkimi zakłóceniami w systemie.

Dzięki dużym opóźnieniom i wysokiej wydajności analizatorowi, tryb blokowania z użyciem jest dłuższa kolejka, aby skompensować opóźnienie. Pamiętaj jednak, że nadal może przetworzyć wszystkie klatki.

Dzięki dużym opóźnieniom i czasochłonnym analizatorowi (analizator nie jest w stanie przetworzyć wszystkich ramki), tryb nieblokujący może bardziej odpowiedni wybór, ponieważ klatki są pomijane w ramach ścieżki analizy, ale inne powiązane przypadki użycia równolegle mogą nadal wyświetlać wszystkie klatki.

Implementacja

Aby użyć analizy obrazu w swojej aplikacji, wykonaj te czynności:

Natychmiast po powiązaniu Aparat X wysyła obrazy do zarejestrowanego analizatora. Po zakończeniu analizy wywołaj ImageAnalysis.clearAnalyzer() lub usuń powiązanie przypadku użycia ImageAnalysis, aby zatrzymać analizę.

Przypadek użycia analizy obrazu

ImageAnalysis – połączenia z analizatora (konsumenta obrazów) do aplikacji CameraX, która jest producentem obrazów. Aplikacje, których można używać ImageAnalysis.Builder aby utworzyć obiekt ImageAnalysis. Dzięki ImageAnalysis.Builder, aplikacja może skonfigurować te ustawienia:

Aplikacje mogą ustawiać rozdzielczość lub format obrazu, ale nie i jednym, i drugim. Dokładna rozdzielczość danych wyjściowych zależy od żądanego rozmiaru aplikacji (lub format obrazu) i możliwości sprzętowe, które mogą różnić się od żądanych rozmiar lub proporcje. Informacje o algorytmie dopasowywania rozdzielczości znajdziesz tutaj dokumentację setTargetResolution()

Aplikacja może skonfigurować piksele obrazu wyjściowego tak, aby były w YUV (domyślnie) i przestrzeni kolorów RGBA. Przy ustawianiu formatu wyjściowego RGBA aplikacja CameraX wewnętrznie konwertuje obrazy z przestrzeni kolorów YUV na RGBA i umieszcza bity obrazu w ByteBuffer pierwszej płaszczyzny interfejsu ImageProxy (pozostałe 2 płaszczyzny nie są używane) z elementem w następującej kolejności:

ImageProxy.getPlanes()[0].buffer[0]: alpha
ImageProxy.getPlanes()[0].buffer[1]: red
ImageProxy.getPlanes()[0].buffer[2]: green
ImageProxy.getPlanes()[0].buffer[3]: blue
...

Podczas wykonywania skomplikowanej analizy obrazu, w którym urządzenie nie może z liczbą klatek na sekundę, możesz skonfigurować aparat X tak, aby pomijał klatki strategie opisane w sekcji Tryby operacyjne tego tematu.

Tworzenie analizatora

Aplikacje mogą tworzyć analizatory, implementując ImageAnalysis.Analyzer i zastępowanie analyze(ImageProxy image) Każdy analizator otrzymuje ImageProxy, który jest kodem w polu Media.Image. W przypadku zapytań o format obrazu ImageProxy.getFormat() Format to jedna z następujących wartości, którą aplikacja udostępnia ImageAnalysis.Builder:

  • ImageFormat.RGBA_8888, jeśli aplikacja prosi o OUTPUT_IMAGE_FORMAT_RGBA_8888.
  • ImageFormat.YUV_420_888, jeśli aplikacja prosi o OUTPUT_IMAGE_FORMAT_YUV_420_888.

Zobacz przypadek użycia tworzenia analizy obrazu. dla konfiguracji przestrzeni kolorów i miejsca, w którym można pobierać bajty pikseli.

Wewnątrz analizatora aplikacja powinna wykonywać te czynności:

  1. Przeprowadź analizę danej klatki tak szybko, jak to możliwe, najlepiej w z określoną liczbą klatek (np. poniżej 32 ms w przypadku reklamy 30 kl./s). Jeśli aplikacja nie jest w stanie przeanalizować klatki wystarczająco szybko, jeden z obsługiwanych mechanizmów pomijania klatek.
  2. Puść przycisk ImageProxy na AparatX, wywołując ImageProxy.close() Pamiętaj, że nie należy wywoływać funkcji zamykania opakowanych obiektów Media.Image. (Media.Image.close()).

Aplikacje mogą używać opakowanego obiektu Media.Image bezpośrednio w ImageProxy. Po prostu nie wywołaj funkcji Media.Image.close() na opakowanym obrazie, ponieważ spowoduje to uszkodzenie obrazu. mechanizm udostępniania zdjęć w AparacieX; zamiast tego użyj funkcji ImageProxy.close(). do udostępnienia bazowego zasobu Media.Image w AparatuX.

Konfigurowanie analizatora pod kątem analizy ImageAnalysis

Po utworzeniu analizatora użyj ImageAnalysis.setAnalyzer() , aby go zarejestrować i rozpocząć analizę. Po zakończeniu analizy użyj ImageAnalysis.clearAnalyzer() aby usunąć zarejestrowany analizator.

Na potrzeby analizy obrazu można skonfigurować tylko jeden aktywny analizator. Łączę ImageAnalysis.setAnalyzer() zastępuje zarejestrowany analizator, jeśli już go istnieje. Aplikacje mogą ustawić nowy analizator w dowolnym momencie, przed powiązaniem lub po nim dla danego przypadku użycia.

Powiąż analizę obrazu z cyklem życia

Zdecydowanie zalecamy powiązanie ImageAnalysis z dotychczasowym w Androidzie X ProcessCameraProvider.bindToLifecycle(). . Pamiętaj, że funkcja bindToLifecycle() zwraca wybraną Urządzenie Camera, którego można używać aby dostosować ustawienia zaawansowane, takie jak ekspozycja i inne. Więcej informacji o sterowaniu wyjściem kamery znajdziesz w tym przewodniku.

W poniższym przykładzie połączono wszystkie informacje z poprzednich kroków, wiązanie Przypadki użycia AparatuX ImageAnalysis i Preview dla właściciela lifeCycle:

Kotlin

val imageAnalysis = ImageAnalysis.Builder()
    // enable the following line if RGBA output is needed.
    // .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
    .setTargetResolution(Size(1280, 720))
    .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
    .build()
imageAnalysis.setAnalyzer(executor, ImageAnalysis.Analyzer { imageProxy ->
    val rotationDegrees = imageProxy.imageInfo.rotationDegrees
    // insert your code here.
    ...
    // after done, release the ImageProxy object
    imageProxy.close()
})

cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, imageAnalysis, preview)

Java

ImageAnalysis imageAnalysis =
    new ImageAnalysis.Builder()
        // enable the following line if RGBA output is needed.
        //.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
        .setTargetResolution(new Size(1280, 720))
        .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
        .build();

imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
    @Override
    public void analyze(@NonNull ImageProxy imageProxy) {
        int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees();
            // insert your code here.
            ...
            // after done, release the ImageProxy object
            imageProxy.close();
        }
    });

cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, imageAnalysis, preview);

Dodatkowe materiały

Więcej informacji o aparacie Aparat X znajdziesz w dodatkowych materiałach poniżej.

Ćwiczenia z programowania

  • Pierwsze kroki z AparatemX
  • Przykładowy kod

  • Przykładowe aplikacje CameraX