Konfigurujesz każdy przypadek użycia AparatuX, aby kontrolować różne aspekty użycia na jego temat.
Na przykład w przypadku rejestrowania obrazów możesz określić docelowy format obrazu i tryb lampy błyskowej. Oto przykład:
Kotlin
val imageCapture = ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build()
Java
ImageCapture imageCapture = new ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build();
Oprócz opcji konfiguracyjnych w niektórych przypadkach użycia interfejsy API udostępniają dynamicznie zmienić ustawienia po utworzeniu przypadku użycia. Informacje na temat: do konkretnych przypadków użycia znajdziesz w sekcji Implementowanie podgląd, Analiza obrazy i Obrazy .
CameraXConfig,
Dla uproszczenia Aparat X ma domyślne konfiguracje, takie jak wewnętrzne wykonawców
i moduły obsługi, które nadają się do większości zastosowań. Jeśli jednak
aplikacja ma specjalne wymagania lub preferuje ich dostosowanie
konfiguracje, CameraXConfig
to interfejs do tego celu.
Dzięki CameraXConfig
aplikacja może wykonywać te czynności:
- Zoptymalizuj czas oczekiwania na uruchomienie dzięki
setAvailableCameraLimiter()
- Przekaż wykonawcy aplikacji CameraX kod
setCameraExecutor()
- Zastąp domyślny moduł obsługi algorytmu szeregowania
setSchedulerHandler()
- Zmień poziom rejestrowania za pomocą
setMinimumLoggingLevel()
Model wykorzystania
Aby dowiedzieć się, jak używać właściwości CameraXConfig
, wykonaj te czynności:
- Utwórz obiekt
CameraXConfig
z własnymi konfiguracjami. - Zaimplementuj tag
CameraXConfig.Provider
wApplication
oraz zwraca obiektCameraXConfig
wgetCameraXConfig()
. - Dodaj zajęcia
Application
do plikuAndroidManifest.xml
jako opisane tutaj.
Na przykład ten przykładowy kod ogranicza logowanie w aplikacji CameraX do błędów tylko wiadomości:
Kotlin
class CameraApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setMinimumLoggingLevel(Log.ERROR).build() } }
Zachowaj lokalną kopię obiektu CameraXConfig
, jeśli aplikacja tego wymaga
i poznanie konfiguracji kamery X.
Ogranicznik aparatu
Podczas pierwszego wywołania funkcji
ProcessCameraProvider.getInstance()
CameraX wylicza i zapyta o cechy aparatów dostępnych na
urządzenia. KameraX musi komunikować się z komponentami sprzętowymi,
Może to zająć niezbyt dużo czasu dla każdej kamery, zwłaszcza
niższych urządzeń. Jeśli aplikacja używa tylko określonych aparatów na urządzeniu,
takich jak domyślny przedni aparat, w aparacie CameraX możesz ustawić ignorowanie innych kamer,
co może zmniejszyć czas oczekiwania na uruchomienie
kamer używanych przez Twoją aplikację.
Jeśli CameraSelector
zaliczono
do
CameraXConfig.Builder.setAvailableCamerasLimiter()
odfiltrowuje kamerę, więc AparatX zachowuje się tak, jakby ona nie istniała. Dla:
poniższy kod ogranicza aplikację do korzystania wyłącznie
domyślny tylny aparat:
Kotlin
class MainApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setAvailableCamerasLimiter(CameraSelector.DEFAULT_BACK_CAMERA) .build() } }
Wątki
Wiele interfejsów API platformy, na których opiera się aplikacja CameraX, wymaga blokowania
komunikację międzyprocesową (IPC) za pomocą sprzętu, który czasami może trwać setki,
na odpowiedź w ciągu milisekund. Z tego powodu CameraX wywołuje te interfejsy API tylko z
wątki w tle, dzięki czemu wątek główny nie zostanie zablokowany, a UI
pozostaje płynny. CameraX wewnętrznie zarządza wątkami działającymi w tle,
zachowanie wydaje się przejrzyste. Niektóre aplikacje wymagają jednak ścisłej kontroli
wątków. CameraXConfig
zezwala aplikacji na ustawianie wątków w tle
używane przez
CameraXConfig.Builder.setCameraExecutor()
.
oraz
CameraXConfig.Builder.setSchedulerHandler()
Wykonawca aparatu
Wykonawca kamery jest też używany we wszystkich wewnętrznych wywołaniach interfejsu API platformy aparatu oraz
, jak w przypadku wywołań zwrotnych z tych interfejsów API. CameraX przydziela
Executor
.
Jeśli jednak Twoja aplikacja wymaga większej kontroli nad wątkami, użyj funkcji
CameraXConfig.Builder.setCameraExecutor()
Moduł obsługi algorytmu szeregowania
Moduł obsługi algorytmu szeregowania służy do planowania zadań wewnętrznych w stałych odstępach czasu,
np. ponawiać próby otwarcia aparatu, gdy nie jest on dostępny. Ten moduł obsługi
nie wykonuje zadań, a jedynie wysyła je do wykonawcy kamery. Jest także
na starszych platformach API, które wymagają
Handler
na potrzeby wywołań zwrotnych. W takich przypadkach
wywołania zwrotne są nadal wysyłane tylko bezpośrednio do wykonawcy kamery. Aparat X
zarządza wewnętrznymi zasobami
HandlerThread
, aby wykonać te zadania,
ale możesz go zastąpić kodem CameraXConfig.Builder.setSchedulerHandler()
.
Logowanie
Rejestrowanie w CameraX pozwala aplikacjom filtrować komunikaty logcat, , aby unikać szczegółowych komunikatów w kodzie produkcyjnym. Aparat X obsługuje 4 poziomy rejestrowania, od najbardziej szczegółowego do najpoważniejszego:
Log.DEBUG
(domyślnie)Log.INFO
Log.WARN
Log.ERROR
Zapoznaj się z dokumentacją dziennika Androida.
. Używaj
CameraXConfig.Builder.setMinimumLoggingLevel(int)
aby ustawić odpowiedni poziom logowania dla aplikacji.
Automatyczny wybór
CameraX automatycznie udostępnia funkcje właściwe dla urządzenia, która działa. Na przykład AparatX automatycznie określa najlepszej rozdzielczości, jeśli nie została określona nie jest obsługiwane. Biblioteka zajmuje się tym wszystkim, eliminując na potrzeby napisania kodu przeznaczonego na konkretne urządzenie.
Celem aplikacji CameraX jest pomyślne zainicjowanie sesji kamery. Oznacza to, że W zależności od możliwości urządzenia CameraX ogranicza rozdzielczość i formaty obrazu. Do naruszenia zabezpieczeń może dojść, ponieważ:
- Urządzenie nie obsługuje żądanej rozdzielczości.
- na urządzeniu występują problemy ze zgodnością, na przykład starsze urządzenia, które wymagają w pewnych rozdzielczościach, aby działać prawidłowo.
- Na niektórych urządzeniach pewne formaty są dostępne tylko w określonych aspektach współczynników proporcji.
- Urządzenie preferuje „najbliższy model 16” JPEG lub wideo
kodowanie. Więcej informacji:
SCALER_STREAM_CONFIGURATION_MAP
Chociaż AparatX tworzy sesję i zarządza nią, zawsze sprawdzaj zwracały rozmiary obrazów na danych wyjściowych przypadku użycia w kodzie i odpowiednio je dostosuj.
Obrót
Domyślnie obrót kamery jest ustawiony na obrót domyślnego wyświetlacza. podczas tworzenia przypadku użycia. W tym domyślnym przypadku Aparat X generuje pozwala aplikacji dopasować się do tego, czego oczekujesz podgląd. Aby obsługiwać wiele reklam displayowych, możesz zmienić rotację na wartość niestandardową. przez przekazanie bieżącej orientacji wyświetlacza podczas konfigurowania przypadku użycia Obiekty lub dynamicznie po ich utworzeniu.
Aplikacja może ustawić rotację docelową za pomocą ustawień konfiguracji. Następnie może
aktualizować ustawienia rotacji za pomocą metod z interfejsów API przypadków użycia (takich jak
ImageAnalysis.setTargetRotation()
),
nawet wtedy, gdy cykl życia jest uruchomiony. Możesz użyć tej opcji, gdy aplikacja
jest zablokowany w trybie pionowym, więc ponowna konfiguracja nie jest przeprowadzana
rotacji, ale w przypadku zastosowania zdjęcia lub analizy muszą one być świadome
aktualnego obrotu urządzenia. Na przykład świadomość rotacji może być potrzebna
więc
twarze są poprawnie zorientowane na potrzeby wykrywania twarzy lub zdjęcia są ustawione w orientacji poziomej
lub w orientacji pionowej.
Dane zrobionych obrazów mogą być przechowywane bez informacji o rotacji. Dane EXIF zawiera informacje o obrocie, dzięki czemu aplikacje galerii mogą wyświetlać obraz ustaw prawidłową orientację po zapisaniu.
Aby wyświetlić dane podglądu w prawidłowej orientacji, możesz użyć metadanych
dane wyjściowe z
Preview.PreviewOutput()
do tworzenia przekształceń.
Przeanalizuj przykładowy kod poniżej, aby dowiedzieć się, jak ustawić rotację w przypadku zdarzenia orientacji:
Kotlin
override fun onCreate() { val imageCapture = ImageCapture.Builder().build() val orientationEventListener = object : OrientationEventListener(this as Context) { override fun onOrientationChanged(orientation : Int) { // Monitors orientation values to determine the target rotation value val rotation : Int = when (orientation) { in 45..134 -> Surface.ROTATION_270 in 135..224 -> Surface.ROTATION_180 in 225..314 -> Surface.ROTATION_90 else -> Surface.ROTATION_0 } imageCapture.targetRotation = rotation } } orientationEventListener.enable() }
Java
@Override public void onCreate() { ImageCapture imageCapture = new ImageCapture.Builder().build(); OrientationEventListener orientationEventListener = new OrientationEventListener((Context)this) { @Override public void onOrientationChanged(int orientation) { int rotation; // Monitors orientation values to determine the target rotation value if (orientation >= 45 && orientation < 135) { rotation = Surface.ROTATION_270; } else if (orientation >= 135 && orientation < 225) { rotation = Surface.ROTATION_180; } else if (orientation >= 225 && orientation < 315) { rotation = Surface.ROTATION_90; } else { rotation = Surface.ROTATION_0; } imageCapture.setTargetRotation(rotation); } }; orientationEventListener.enable(); }
W zależności od ustawionego obrotu w każdym przypadku użycia obracamy dane obrazu. bezpośrednio lub dostarcza metadane obrotu konsumentom nieobróconego obrazu. i skalowalnych danych.
- Podgląd: podawane są dane wyjściowe metadanych, aby zapewnić rotację środowiska docelowego
rozdzielczość jest znana za pomocą
Preview.getTargetRotation()
. - ImageAnalysis (Analiza obrazu): dostarcza metadane, dzięki czemu obraz jest buforowany. są znane w odniesieniu do współrzędnych wyświetlania.
- ImageCapture: metadane Exif obrazu, bufor lub zarówno bufor, jak i metadane są zmieniane, by uwzględnić ustawienie rotacji. Zmieniona wartość zależy od wdrożenia HAL.
Przytnij jako prostokąt
Domyślnie prostokąt przycinania jest pełnym prostokątem bufora. Możesz go dostosować w ten sposób:
ViewPort
i
UseCaseGroup
Według użycia przez grupowanie
i określając widoczny obszar, aparatX gwarantuje, że
przypadki użycia w grupie wskazują na ten sam obszar czujnika aparatu.
Fragment kodu poniżej pokazuje, jak używać tych 2 klas:
Kotlin
val viewPort = ViewPort.Builder(Rational(width, height), display.rotation).build() val useCaseGroup = UseCaseGroup.Builder() .addUseCase(preview) .addUseCase(imageAnalysis) .addUseCase(imageCapture) .setViewPort(viewPort) .build() cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, useCaseGroup)
Java
ViewPort viewPort = new ViewPort.Builder( new Rational(width, height), getDisplay().getRotation()).build(); UseCaseGroup useCaseGroup = new UseCaseGroup.Builder() .addUseCase(preview) .addUseCase(imageAnalysis) .addUseCase(imageCapture) .setViewPort(viewPort) .build(); cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, useCaseGroup);
ViewPort
określa pole bufora widoczne dla użytkowników. Następnie AparatX oblicza obliczenia
największego możliwego prostokąta przycinania na podstawie właściwości widocznego obszaru
załączonych przypadków użycia. Zwykle do uzyskania efektu WYSIWYG wystarczy skonfigurować
na podstawie przypadku użycia podglądu. Prosty sposób na uzyskanie widocznego obszaru to
aby użyć narzędzia PreviewView
.
Poniższe fragmenty kodu pokazują, jak pobrać obiekt ViewPort
:
Kotlin
val viewport = findViewById<PreviewView>(R.id.preview_view).viewPort
Java
ViewPort viewPort = ((PreviewView)findViewById(R.id.preview_view)).getViewPort();
W poprzednim przykładzie dane aplikacji uzyskane dzięki ImageAnalysis
i
Wartość ImageCapture
odpowiada temu, co widzi użytkownik w elemencie PreviewView
, przy założeniu, że
Typ skali PreviewView
jest ustawiony na domyślny FILL_CENTER
. Po zastosowaniu
prostokąta przycinania i obrót do bufora wyjściowego – obraz ze wszystkich przypadków użycia
jest taki sam, choć możliwe, że ma różną rozdzielczość. Więcej
o tym, jak zastosować informacje o przekształceniu, dowiesz się z artykułu Transform (Przekształć)
dane wyjściowe.
Wybór aparatu
CameraX automatycznie wybiera najlepszy aparat dla danej aplikacji do wymagań i przypadków użycia. Jeśli chcesz użyć innego urządzenia niż to, dostępnych jest kilka opcji:
- Zażądaj domyślnego przedniego aparatu, używając
CameraSelector.DEFAULT_FRONT_CAMERA
- Zażądaj domyślnego tylnego aparatu, używając
CameraSelector.DEFAULT_BACK_CAMERA
- Przefiltruj listę dostępnych urządzeń według
CameraCharacteristics
zCameraSelector.Builder.addCameraFilter()
Poniższy przykładowy kod pokazuje, jak utworzyć CameraSelector
do
wpływać na wybór urządzenia:
Kotlin
fun selectExternalOrBestCamera(provider: ProcessCameraProvider):CameraSelector? { val cam2Infos = provider.availableCameraInfos.map { Camera2CameraInfo.from(it) }.sortedByDescending { // HARDWARE_LEVEL is Int type, with the order of: // LEGACY < LIMITED < FULL < LEVEL_3 < EXTERNAL it.getCameraCharacteristic(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) } return when { cam2Infos.isNotEmpty() -> { CameraSelector.Builder() .addCameraFilter { it.filter { camInfo -> // cam2Infos[0] is either EXTERNAL or best built-in camera val thisCamId = Camera2CameraInfo.from(camInfo).cameraId thisCamId == cam2Infos[0].cameraId } }.build() } else -> null } } // create a CameraSelector for the USB camera (or highest level internal camera) val selector = selectExternalOrBestCamera(processCameraProvider) processCameraProvider.bindToLifecycle(this, selector, preview, analysis)
Wybierz kilka kamer jednocześnie
Począwszy od CameraX 1.3, można również wybrać wiele aparatów jednocześnie. Możesz na przykład powiązać przedni i tylny aparat, aby robić zdjęcia lub nagrywać filmów z obu perspektyw.
Gdy jest używana funkcja Równoczesna kamera, urządzenie może obsługiwać 2 kamery.
z różnymi obiektywami w tym samym czasie, albo obsługiwać dwa tylne aparaty
o tej samej nazwie. Poniższy blok kodu pokazuje, jak ustawić dwie kamery, gdy
wywołującego funkcję bindToLifecycle
i dowiedzieć się, jak uzyskać obydwa obiekty aparatu ze zwróconego
ConcurrentCamera
obiekt.
Kotlin
// Build ConcurrentCameraConfig val primary = ConcurrentCamera.SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ) val secondary = ConcurrentCamera.SingleCameraConfig( secondaryCameraSelector, useCaseGroup, lifecycleOwner ) val concurrentCamera = cameraProvider.bindToLifecycle( listOf(primary, secondary) ) val primaryCamera = concurrentCamera.cameras[0] val secondaryCamera = concurrentCamera.cameras[1]
Java
// Build ConcurrentCameraConfig SingleCameraConfig primary = new SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ); SingleCameraConfig secondary = new SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ); ConcurrentCamera concurrentCamera = mCameraProvider.bindToLifecycle(Arrays.asList(primary, secondary)); Camera primaryCamera = concurrentCamera.getCameras().get(0); Camera secondaryCamera = concurrentCamera.getCameras().get(1);
Rozdzielczość aparatu
Możesz pozwolić, by Aparat X ustawiał rozdzielczość zdjęcia na podstawie kombinacji możliwości urządzenia, obsługiwany sprzęt poziomu usługi, przypadku użycia i współczynnika proporcji. Możesz też określić konkretny adres, lub określony format obrazu w przypadkach, które umożliwiają konfiguracji.
Automatyczna rozdzielczość
CameraX może automatycznie określić najlepsze ustawienia rozdzielczości na podstawie
przypadków użycia opisanych w zasadzie cameraProcessProvider.bindToLifecycle()
. Kiedykolwiek
należy określić wszystkie przypadki użycia
wymagane do jednoczesnego działania w jednym
w pojedynczym wywołaniu bindToLifecycle()
. AparatX określa rozdzielczość
na podstawie zbioru przypadków użycia
po uwzględnieniu
na poziomie sprzętowym i uwzględniając różnice w zależności od urządzenia (gdy urządzenie
przekracza lub nie spełnia konfiguracji strumienia
).
Dzięki temu aplikacja będzie działać na wielu różnych urządzeniach
minimalizując liczbę ścieżek kodu
przeznaczonych na konkretne urządzenia.
Domyślny współczynnik proporcji w przypadku przechwytywania i analizy obrazów to 4:3.
Przypadki użycia mają konfigurowalny współczynnik proporcji, co pozwala aplikacji określić z odpowiednim współczynnikiem proporcji. Dane wyjściowe AparatuX są generowane w celu: format obrazu musi być ściśle dopasowany do formatu obsługiwanego przez urządzenie. Jeśli ta rozdzielczość nie jest obsługiwana, ale ta, która spełnia większość warunków zaznaczono. Aplikacja określa więc sposób wyświetlania kamery na a AparatX określa najlepsze ustawienia rozdzielczości, na różnych urządzeniach.
Aplikacja może na przykład wykonywać dowolne z tych czynności:
- W przypadku zastosowania określ docelową rozdzielczość 4:3 lub 16:9
- Określ niestandardową rozdzielczość, w której CameraX będzie próbował znaleźć najbliższą dopasuj do
- Określ współczynnik proporcji kadrowania na potrzeby obrazu
ImageCapture
Aparat X automatycznie wybiera rozdzielczość wewnętrznej powierzchni aparatu Camera2. Rozdzielczości znajdziesz w poniższej tabeli:
Przypadek użycia | Rozdzielczość powierzchni wewnętrznej | Rozdzielczość danych wyjściowych |
---|---|---|
Podgląd | Współczynnik proporcji: rozdzielczość, która najlepiej pasuje do docelowego obrazu . | Rozdzielczość powierzchni wewnętrznej. Podane metadane umożliwiają przycięcie widoku danych, i obrócić, aby dostosować go do docelowego współczynnika proporcji. |
Rozdzielczość domyślna: najwyższa rozdzielczość podglądu lub najwyższa. preferowanej przez urządzenie rozdzielczości, która jest zgodna z formatem obrazu podglądu. | ||
Maksymalna rozdzielczość:rozmiar podglądu oznacza najlepszy rozmiar. do rozdzielczości ekranu urządzenia lub do 1080p (1920 x 1080), zależnie od tego, która wartość jest mniejsza. | ||
Analiza obrazu | Format obrazu: rozdzielczość, która najlepiej pasuje do docelowego obrazu . | Rozdzielczość powierzchni wewnętrznej. |
Rozdzielczość domyślna: domyślne ustawienie rozdzielczości docelowej to 640x480. Dostosowywanie docelowej rozdzielczości i odpowiednich formatów obrazu pozwala uzyskać najlepszą możliwą rozdzielczość. | ||
Maksymalna rozdzielczość: maksymalna rozdzielczość wyjściowa aparatu
Format YUV_420_888, który jest pobierany z
StreamConfigurationMap.getOutputSizes() .
Domyślna rozdzielczość docelowa to 640 x 480, więc jeśli chcesz uzyskać rozdzielczość większą niż 640 x 480, musisz użyć
setTargetResolution()
oraz
setTargetAspectRatio()
aby uzyskać najbardziej zbliżoną rozdzielczość.
|
||
Robienie zdjęć | Format obrazu: format obrazu, który najlepiej pasuje do ustawienia. | Rozdzielczość powierzchni wewnętrznej. |
Rozdzielczość domyślna: najwyższa dostępna rozdzielczość preferowanej przez urządzenie rozdzielczości, która odpowiada formatowi obrazu w Zrób zdjęcie. | ||
Maksymalna rozdzielczość: maksymalna rozdzielczość wyjściowa aparatu w
format JPEG. Używaj
StreamConfigurationMap.getOutputSizes()
.
|
Określ rozdzielczość
Podczas tworzenia przypadków użycia możesz ustawić określone rozdzielczości
setTargetResolution(Size resolution)
zgodnie z tym kodem
przykład:
Kotlin
val imageAnalysis = ImageAnalysis.Builder() .setTargetResolution(Size(1280, 720)) .build()
Java
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder() .setTargetResolution(new Size(1280, 720)) .build();
Nie możesz ustawić jednocześnie docelowego formatu obrazu i rozdzielczości docelowej
tych kwestii. Powoduje to zgłoszenie żądania IllegalArgumentException
podczas tworzenia konfiguracji.
obiektu.
Wyraź rozdzielczość Size
we współrzędnej
po obróceniu obsługiwanych rozmiarów zgodnie z rotacją docelową. Na przykład plik
urządzenie z naturalną orientacją pionową w naturalnej rotacji celu
obraz pionowy może mieć rozdzielczość 480 x 640, a to samo urządzenie obrócone o 90 stopni
w przypadku kierowania poziomego można określić rozdzielczość 640 x 480 pikseli.
Docelowa rozdzielczość ma na celu ustalenie minimalnej granicy obrazu i ich rozwiązania. Rzeczywista rozdzielczość obrazu to najbliższa dostępna rozdzielczość rozmiar nie mniejszy niż docelowa rozdzielczość, zgodnie z Implementacja za pomocą aparatu.
Jeśli jednak nie ma rozwiązania równego
jest większa niż rozdzielczość docelowa, najbliższa dostępna rozdzielczość jest mniejsza niż
wybieramy rozdzielczość docelową. Rozdzielczości o tym samym współczynniku proporcji
przesłane Size
mają wyższy priorytet niż rozdzielczości różnych
formatów obrazu.
Aparat X stosuje najlepszą odpowiednią rozdzielczość na podstawie liczby żądań. Jeśli
główna potrzeba to spełnienie współczynnika proporcji, określ tylko setTargetAspectRatio
,
a Aparat X określa rozdzielczość odpowiednią na potrzeby urządzenia.
jeśli aplikacja potrzebuje określonej rozdzielczości, aby utworzyć obraz.
(np. małe lub średnie obrazy oparte na
możliwości przetwarzania na urządzeniu), użyj funkcji setTargetResolution(Size resolution)
.
Jeśli aplikacja wymaga dokładnej rozdzielczości, zapoznaj się z tabelą w sekcji
createCaptureSession()
aby określić, jakie maksymalne rozdzielczości są obsługiwane przez poszczególne poziomy sprzętowe. Do
Sprawdź rozdzielczości obsługiwane przez bieżące urządzenie, patrz
StreamConfigurationMap.getOutputSizes(int)
Jeśli Twoja aplikacja działa na Androidzie 10 lub nowszym, możesz używać
isSessionConfigurationSupported()
aby zweryfikować konkretny punkt SessionConfiguration
.
Steruj wyjściem kamery
Oprócz tego, że w zależności od potrzeb można skonfigurować wyjścia z kamery do indywidualnego użycia, CameraX implementuje również poniższe interfejsy, aby operacje kamery typowe dla wszystkich powiązanych przypadków użycia:
CameraControl
umożliwia konfigurować często używane funkcje aparatu.CameraInfo
umożliwia wysyłanie zapytań i stanów tych wspólnych cech.
Następujące funkcje aparatu są obsługiwane przez funkcję CameraControl:
- Zoom
- Latarka
- Ostrość i pomiar (dotknij, aby ustawić ostrość)
- Kompensacja ekspozycji
Pobieranie instancji CameraControl i CameraInfo
Pobierz instancje CameraControl
i CameraInfo
za pomocą polecenia
Obiekt Camera
zwrócony przez
ProcessCameraProvider.bindToLifecycle()
Oto przykład:
Kotlin
val camera = processCameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview) // For performing operations that affect all outputs. val cameraControl = camera.cameraControl // For querying information and states. val cameraInfo = camera.cameraInfo
Java
Camera camera = processCameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview) // For performing operations that affect all outputs. CameraControl cameraControl = camera.getCameraControl() // For querying information and states. CameraInfo cameraInfo = camera.getCameraInfo()
Możesz na przykład przesłać powiększenie i inne operacje CameraControl
po
Dzwonię pod numer bindToLifecycle()
. Po zatrzymaniu lub zniszczeniu działania używanego do powiązania
instancja kamery, CameraControl
nie może już wykonywać operacji i
zwraca błąd ListenableFuture
.
Zoom
CameraControl umożliwia zmianę poziomu powiększenia na dwa sposoby:
setZoomRatio()
ustawia powiększenie.Współczynnik musi się mieścić w zakresie od
CameraInfo.getZoomState().getValue().getMinZoomRatio()
iCameraInfo.getZoomState().getValue().getMaxZoomRatio()
W przeciwnym razie funkcja zwraca błądListenableFuture
.setLinearZoom()
ustawia bieżące powiększenie na wartość powiększenia liniowego z zakresu od 0 do 1,0.Zaletą powiększenia liniowego jest to, że przekształca on pole widzenia ze zmianami powiększenia. Dzięki temu idealnie nadaje się do użycia
Slider
wyświetlenie.
CameraInfo.getZoomState()
zwraca LiveData bieżącego stanu powiększenia. Wartość zmienia się, gdy kamera
zostanie zainicjowany albo poziom powiększenia zostanie ustawiony przy użyciu elementu setZoomRatio()
lub
setLinearZoom()
Wywołanie dowolnej z tych metod ustawia wsteczne wartości
ZoomState.getZoomRatio()
oraz
ZoomState.getLinearZoom()
Jest to przydatne, jeśli chcesz wyświetlić tekst współczynnika powiększenia obok suwaka.
Wystarczy, że będziesz obserwować ZoomState
LiveData
, aby aktualizować obie wersje bez konieczności wykonywania
konwersji.
Pole ListenableFuture
zwrócone przez oba interfejsy API umożliwia aplikacjom
zostanie powiadomiony, gdy powtarzające się żądanie z określoną wartością powiększenia zostanie
. Ponadto jeśli ustawisz nową wartość powiększenia podczas poprzedniej operacji,
wciąż trwa, nie uda się ListenableFuture
poprzedniej operacji powiększenia
natychmiast.
Latarka
CameraControl.enableTorch(boolean)
włącza lub wyłącza latarkę.
CameraInfo.getTorchState()
może posłużyć do odpytywania bieżącego stanu lampy. Możesz sprawdzić zwrócona wartość
autor:
CameraInfo.hasFlashUnit()
aby ustalić, czy jest dostępna latarka. Jeśli nie, dzwonię
CameraControl.enableTorch(boolean)
sprawia, że zwrócona wartość ListenableFuture
ma wartość
natychmiast z nieudanym wynikiem i ustawia stan lampki na
TorchState.OFF
Gdy latarka jest włączona, pozostaje włączona podczas robienia zdjęć i nagrywania filmów
bez względu na ustawienie
flashMode.
flashMode
in
ImageCapture
działa tylko wtedy, gdy latarka jest wyłączona.
Ostrość i pomiar
CameraControl.startFocusAndMetering()
uruchamia autofokus i pomiar ekspozycji, ustawiając regiony pomiaru AF/AE/AWB
na podstawie danej właściwości FocusMeteringAction. Jest to często stosowane, by zaimplementować metodę kliknięcia
funkcję ostrości” w wielu aplikacjach aparatu.
Punkt mierniczy
Na początek utwórz
MeteringPoint
za pomocą
MeteringPointFactory.createPoint(float x, float y, float
size)
MeteringPoint
oznacza pojedynczy punkt kamery
Surface
Przechowujemy go w znormalizowanej postaci.
tak, aby można było go łatwo przekonwertować na współrzędne czujnika w celu określenia
Regiony AF/AE/AWB.
Rozmiar MeteringPoint
mieści się w zakresie od 0 do 1, a rozmiar domyślny to
0,15f. Podczas wywoływania funkcji MeteringPointFactory.createPoint(float x, float y, float
size)
aparat CameraX tworzy prostokątny obszar wyśrodkowany na (x, y)
dla podanego obszaru
size
Ten kod pokazuje, jak utworzyć MeteringPoint
:
Kotlin
// Use PreviewView.getMeteringPointFactory if PreviewView is used for preview. previewView.setOnTouchListener((view, motionEvent) -> { val meteringPoint = previewView.meteringPointFactory .createPoint(motionEvent.x, motionEvent.y) … } // Use DisplayOrientedMeteringPointFactory if SurfaceView / TextureView is used for // preview. Please note that if the preview is scaled or cropped in the View, // it’s the application's responsibility to transform the coordinates properly // so that the width and height of this factory represents the full Preview FOV. // And the (x,y) passed to create MeteringPoint might need to be adjusted with // the offsets. val meteringPointFactory = DisplayOrientedMeteringPointFactory( surfaceView.display, camera.cameraInfo, surfaceView.width, surfaceView.height ) // Use SurfaceOrientedMeteringPointFactory if the point is specified in // ImageAnalysis ImageProxy. val meteringPointFactory = SurfaceOrientedMeteringPointFactory( imageWidth, imageHeight, imageAnalysis)
startFocusAndMetering i FocusMeteringAction
Do wywołania
startFocusAndMetering()
aplikacje muszą utworzyć
FocusMeteringAction
,
składający się z co najmniej jednego elementu MeteringPoints
z opcjonalnym trybem pomiaru
kombinacje z
FLAG_AF
FLAG_AE
FLAG_AWB
.
jest to kod ilustrujący to użycie:
Kotlin
val meteringPoint1 = meteringPointFactory.createPoint(x1, x1) val meteringPoint2 = meteringPointFactory.createPoint(x2, y2) val action = FocusMeteringAction.Builder(meteringPoint1) // default AF|AE|AWB // Optionally add meteringPoint2 for AF/AE. .addPoint(meteringPoint2, FLAG_AF | FLAG_AE) // The action is canceled in 3 seconds (if not set, default is 5s). .setAutoCancelDuration(3, TimeUnit.SECONDS) .build() val result = cameraControl.startFocusAndMetering(action) // Adds listener to the ListenableFuture if you need to know the focusMetering result. result.addListener({ // result.get().isFocusSuccessful returns if the auto focus is successful or not. }, ContextCompat.getMainExecutor(this)
Jak pokazano w poprzednim kodzie,
startFocusAndMetering()
przyjmuje FocusMeteringAction
składające się z jednego MeteringPoint
dla AF/AE/AWB
w regionach pomiaru, a inny MeteringPoint – tylko w przypadku AF i AE.
Wewnętrznie AparatX przekształca go w Aparat 2.
MeteringRectangles
i ustawia odpowiednie wartości
CONTROL_AF_REGIONS
/
CONTROL_AE_REGIONS
/
CONTROL_AWB_REGIONS
do żądania przechwytywania.
Ponieważ nie każde urządzenie obsługuje AF/AE/AWB i wielu regionów, AparatX
FocusMeteringAction
. Aparat X używa maksymalnej liczby
z obsługiwanych punktów MeteringPoints w kolejności dodania punktów. Wszystkie
Punkty MeteringPoint dodane po maksymalnej liczbie punktów są ignorowane. Jeśli na przykład plik
FocusMeteringAction
jest wyposażony w 3 punkty MeteringPoints na platformie obsługującej
tylko 2, używane są tylko 2 pierwsze punkty MeteringPoint. Ostatni MeteringPoint
to
zignorowane przez aparatX.
Kompensacja ekspozycji
Kompensacja ekspozycji jest przydatna, gdy aplikacje muszą precyzyjnie dostosować ekspozycję (EV) poza wynikami automatycznej ekspozycji (AE). Kompensacja ekspozycji są łączone w następujący sposób, aby określić niezbędną ekspozycję dla bieżące warunki obrazu:
Exposure = ExposureCompensationIndex * ExposureCompensationStep
Aparat X udostępnia
Camera.CameraControl.setExposureCompensationIndex()
do ustawiania kompensacji ekspozycji jako wartości indeksu.
Dodatnie wartości indeksu powodują rozjaśnienie obrazu, a ujemne – przyciemnianie
. Aplikacje mogą wysyłać zapytania do obsługiwanego zakresu przez
CameraInfo.ExposureState.exposureCompensationRange()
opisane w następnej sekcji. Jeśli wartość jest obsługiwana, zwracana jest wartość
Działanie ListenableFuture
kończy się, gdy wartość zostanie włączona w kolumnie
żądania przechwytywania; jeśli podany indeks jest poza obsługiwanym zakresem,
setExposureCompensationIndex()
powoduje, że zwrócona wartość ListenableFuture
jest
możesz wykonać natychmiast z
nieudanym wynikiem.
CameraX zachowuje tylko najnowsze zapisane zdjęcia (setExposureCompensationIndex()
)
i wywoływanie funkcji wielokrotnie przed poprzednim żądaniem
skutkuje anulowaniem.
Poniższy fragment kodu ustawia indeks kompensacji ekspozycji i rejestruje zwrotny po zrealizowaniu żądania zmiany ekspozycji:
Kotlin
camera.cameraControl.setExposureCompensationIndex(exposureCompensationIndex) .addListener({ // Get the current exposure compensation index, it might be // different from the asked value in case this request was // canceled by a newer setting request. val currentExposureIndex = camera.cameraInfo.exposureState.exposureCompensationIndex … }, mainExecutor)
Camera.CameraInfo.getExposureState()
pobiera bieżącąExposureState
w tym:- Obsługa kontroli kompensacji ekspozycji.
- Bieżący indeks kompensacji ekspozycji.
- Zakres indeksu kompensacji ekspozycji.
- Krok kompensacji ekspozycji używany w wartości kompensacji ekspozycji obliczeń.
Na przykład ten kod inicjuje ustawienia ekspozycji
SeekBar
z obecnym ExposureState
wartości:
Kotlin
val exposureState = camera.cameraInfo.exposureState binding.seekBar.apply { isEnabled = exposureState.isExposureCompensationSupported max = exposureState.exposureCompensationRange.upper min = exposureState.exposureCompensationRange.lower progress = exposureState.exposureCompensationIndex }
Dodatkowe materiały
Więcej informacji o aparacie AparatX znajdziesz w tych dodatkowych materiałach.
Ćwiczenia z programowania
Przykładowy kod
Społeczność programistów
Grupa dyskusyjna dotyczące aparatu Android CameraX