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ącsetBackpressureStrategy()
zSTRATEGY_KEEP_ONLY_LATEST
Więcej informacji o konsekwencjach dla wykonawców znajdziesz w dokumentacji dokumentacja dlaSTRATEGY_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
dosetBackpressureStrategy()
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:
- Tworzenie
ImageAnalysis
dla każdego przypadku użycia. - Utwórz
ImageAnalysis.Analyzer
- Ustaw analizator na
ImageAnalysis
. - Powiąż
właściciela cyklu życia, selektora aparatu i przypadek użycia
ImageAnalysis
do ich cyklu życia.
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:
- Parametry wyjściowe obrazu:
- Format: obsługiwany przez CameraX
YUV_420_888
orazRGBA_8888
dosetOutputImageFormat(int)
. Domyślny format toYUV_420_888
. - Rozwiązanie i AspectRatio: Możesz ustawić dowolny z tych parametrów, ale pamiętaj, że nie możesz ustawić obu w tym samym czasie.
- Rotacja.
- Target Name (Nazwa celu): Ten parametr służy do debugowania.
- Format: obsługiwany przez CameraX
- Elementy sterujące przepływem obrazu:
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 oOUTPUT_IMAGE_FORMAT_RGBA_8888
.ImageFormat.YUV_420_888
, jeśli aplikacja prosi oOUTPUT_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:
- 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.
- Puść przycisk
ImageProxy
na AparatX, wywołującImageProxy.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
Przykładowy kod