Sie konfigurieren jeden CameraX-Anwendungsfall, um verschiedene Aspekte des Betriebs des Anwendungsfalls zu steuern.
Für den Anwendungsfall „Bilderfassung“ können Sie beispielsweise ein Zielseitenverhältnis festlegen und einen Blitzmodus. Der folgende Code zeigt ein Beispiel:
Kotlin
val imageCapture = ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build()
Java
ImageCapture imageCapture = new ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build();
Zusätzlich zu den Konfigurationsoptionen stellen einige Anwendungsfälle APIs bereit, mit denen sich Einstellungen nach dem Erstellen des Anwendungsfalls dynamisch ändern lassen. Informationen zu Konfiguration, die für den jeweiligen Anwendungsfall spezifisch ist, finden Sie unter Implementierung eines „preview“, „Analysieren“ Bilder und Bild aufnehmen.
CameraXConfig
Zur Vereinfachung gibt es in CameraX Standardkonfigurationen wie interne Executors und Handler, die für die meisten Anwendungsfälle geeignet sind. Wenn Ihre Anwendung jedoch spezielle Anforderungen hat oder Sie diese Konfigurationen lieber anpassen möchten, ist CameraXConfig
die richtige Oberfläche.
Mit CameraXConfig
kann eine Anwendung Folgendes tun:
- Optimieren Sie die Startlatenz mit
setAvailableCameraLimiter()
- Stellen Sie den Executor der Anwendung für CameraX mit
setCameraExecutor()
- Ersetzen Sie den Standard-Planer-Handler durch
setSchedulerHandler()
- Protokollierungsebene ändern mit
setMinimumLoggingLevel()
Nutzungsmodell
Im Folgenden wird die Verwendung von CameraXConfig
beschrieben:
- Erstellen Sie ein
CameraXConfig
-Objekt mit Ihren benutzerdefinierten Konfigurationen. - Implementiere die Schnittstelle
CameraXConfig.Provider
in deinemApplication
und gib dasCameraXConfig
-Objekt ingetCameraXConfig()
zurück. - Fügen Sie der Datei
AndroidManifest.xml
die KlasseApplication
hinzu als hier beschrieben.
Das folgende Codebeispiel beschränkt die CameraX-Protokollierung auf Fehler. Nur Nachrichten:
Kotlin
class CameraApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setMinimumLoggingLevel(Log.ERROR).build() } }
Speichern Sie eine lokale Kopie des CameraXConfig
-Objekts, wenn Ihre Anwendung
die Konfiguration von CameraX kennen.
Kamerabegrenzer
Beim ersten Aufruf von
ProcessCameraProvider.getInstance()
,
CameraX listet die Eigenschaften der auf der Kamera verfügbaren Kameras auf und fragt diese ab.
. Da CameraX mit Hardwarekomponenten kommunizieren muss, kann dieser Vorgang für jede Kamera relativ lange dauern, insbesondere auf Low-End-Geräten. Wenn Ihre Anwendung nur bestimmte Kameras auf dem Gerät verwendet, z. B. die Standard-Frontkamera, können Sie CameraX so einstellen, dass andere Kameras ignoriert werden. Dadurch kann die Startverzögerung für die von Ihrer Anwendung verwendeten Kameras reduziert werden.
Wenn die CameraSelector
, die an CameraXConfig.Builder.setAvailableCamerasLimiter()
übergeben wird, eine Kamera herausfiltert, verhält sich CameraX so, als würde diese Kamera nicht existieren. Mit dem folgenden Code wird beispielsweise festgelegt, dass die Anwendung nur die Standardrückkamera des Geräts verwendet:
Kotlin
class MainApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setAvailableCamerasLimiter(CameraSelector.DEFAULT_BACK_CAMERA) .build() } }
Threads
Viele der Plattform-APIs, auf denen CameraX basiert, erfordern eine blockierende Inter-Process-Kommunikation (IPC) mit Hardware, die manchmal Hunderte von Millisekunden für eine Antwort benötigt. Aus diesem Grund ruft CameraX diese APIs nur aus Hintergrundthreads auf, damit der Hauptthread nicht blockiert wird und die Benutzeroberfläche flüssig bleibt. CameraX verwaltet diese Hintergrundthreads intern, sodass dieses Verhalten transparent erscheint. Bei einigen Anwendungen ist jedoch eine strenge Steuerung der Threads erforderlich. Mit CameraXConfig
kann eine Anwendung die Hintergrundthreads festlegen
die durch
CameraXConfig.Builder.setCameraExecutor()
und
CameraXConfig.Builder.setSchedulerHandler()
Kamera-Executor
Der Camera Executor wird für alle internen API-Aufrufe der Kameraplattform sowie
Callbacks von diesen APIs: CameraX weist ein internes
Executor
, um diese Aufgaben auszuführen.
Wenn Ihre Anwendung jedoch eine strengere Steuerung von Threads erfordert, verwenden Sie
CameraXConfig.Builder.setCameraExecutor()
Planer-Handler
Mit dem Scheduler-Handler werden interne Aufgaben in festen Intervallen geplant,
z. B. einen neuen Versuch starten, die Kamera zu öffnen, wenn sie nicht verfügbar ist. Dieser Handler tut
keine Jobs ausführen und nur an den Kamera-Executor weitergeleitet werden. Es ist auch
werden manchmal auf Legacy-API-Plattformen verwendet, die eine
Handler
für Callbacks In diesen Fällen werden die Rückrufe weiterhin direkt an den Kameraausführer gesendet. CameraX weist und verwaltet eine interne HandlerThread
zu, um diese Aufgaben auszuführen. Sie können sie jedoch mit CameraXConfig.Builder.setSchedulerHandler()
überschreiben.
Protokollierung
Mit der CameraX-Protokollierung können Anwendungen Logcat-Nachrichten filtern. um ausführliche Meldungen in Ihrem Produktionscode zu vermeiden. CameraX unterstützt vier Logging-Ebenen, von der ausführlichsten bis zur striktesten:
Log.DEBUG
(Standard)Log.INFO
Log.WARN
Log.ERROR
Weitere Informationen finden Sie in der Android-Protokolldokumentation.
finden Sie detaillierte Beschreibungen dieser Protokollebenen. Verwenden Sie CameraXConfig.Builder.setMinimumLoggingLevel(int)
, um die richtige Logging-Ebene für Ihre Anwendung festzulegen.
Automatische Auswahl
CameraX bietet automatisch gerätespezifische Funktionen. auf denen Ihre App ausgeführt wird. CameraX ermittelt beispielsweise automatisch die beste Auflösung, wenn Sie keine Auflösung angeben oder die von Ihnen angegebene Auflösung nicht unterstützt wird. All dies wird von der Bibliothek übernommen, Sie müssen gerätespezifischen Code schreiben.
Das Ziel von CameraX ist es, eine Kamerasitzung erfolgreich zu initialisieren. Das bedeutet, dass CameraX bei der Auflösung und dem Seitenverhältnis Kompromisse eingeht, die auf den Gerätefunktionen basieren. Die Manipulation kann folgende Gründe haben:
- Das Gerät unterstützt die angeforderte Auflösung nicht.
- Das Gerät weist Kompatibilitätsprobleme auf, z. B. bei älteren Geräten, die für die ordnungsgemäße Funktion bestimmte Auflösungen erfordern.
- Auf einigen Geräten sind bestimmte Formate nur in bestimmten Seitenverhältnissen verfügbar Seitenverhältnissen.
- Das Gerät hat eine Präferenz für „nächstgelegenes mod16“. für JPEG oder Video
Codierung. Weitere Informationen finden Sie unter
SCALER_STREAM_CONFIGURATION_MAP
Auch wenn CameraX die Sitzung erstellt und verwaltet, sollten Sie die zurückgegebenen Bildgrößen in der Anwendungsfallausgabe in Ihrem Code immer prüfen und entsprechend anpassen.
Ausrichtung
Standardmäßig wird die Kameradrehung so eingestellt, dass sie der Drehung des Standarddisplays beim Erstellen des Anwendungsfalls entspricht. In diesem Standardfall gibt CameraX Ausgabedaten aus, damit die App den Erwartungen in der Vorschau entspricht. Sie können die Drehung in einen benutzerdefinierten Wert ändern, um Geräte mit mehreren Displays zu unterstützen. Geben Sie dazu beim Konfigurieren von Use-Case-Objekten die aktuelle Displayausrichtung an oder ändern Sie sie nach dem Erstellen dynamisch.
Ihre App kann die Zielrotation mithilfe von Konfigurationseinstellungen festlegen. Die Rotationseinstellungen können dann mithilfe der Methoden aus den Anwendungsfall-APIs (z. B. ImageAnalysis.setTargetRotation()
) aktualisiert werden, auch wenn der Lebenszyklus aktiv ist. Sie können diese Option verwenden, wenn die App im Hochformat gesperrt ist und daher beim Drehen keine Neukonfiguration erfolgt. Der Anwendungsfall für Fotos oder Analysen muss jedoch die aktuelle Drehung des Geräts berücksichtigen. Beispielsweise kann die Rotationserkennung erforderlich sein.
also
Gesichter sind für die Gesichtserkennung korrekt ausgerichtet oder Fotos sind im Querformat eingestellt
oder Hochformat.
Daten für erfasste Bilder werden möglicherweise ohne Rotationsinformationen gespeichert. EXIF-Daten enthalten Informationen zur Drehung, damit Galerieanwendungen das Bild nach dem Speichern in der richtigen Ausrichtung anzeigen können.
Wenn Sie Vorschaudaten mit der richtigen Ausrichtung anzeigen möchten, können Sie mithilfe der Metadatenausgabe von Preview.PreviewOutput()
Transformationen erstellen.
Im folgenden Codebeispiel wird gezeigt, wie die Drehung für ein Ausrichtungsereignis festgelegt wird:
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(); }
Basierend auf der festgelegten Rotation werden in jedem Anwendungsfall entweder die Bilddaten gedreht direkt oder stellt den Nutzern des nicht gedrehten Bildes Rotationsmetadaten bereit Daten.
- Vorschau: Die Metadatenausgabe wird so bereitgestellt, dass die Drehung der Zielauflösung mit
Preview.getTargetRotation()
bekannt ist. - ImageAnalysis: Die Metadatenausgabe wird für den Bildzwischenspeicher bereitgestellt. -Koordinaten relativ zu Anzeigekoordinaten bekannt sind.
- ImageCapture: Die Metadaten des EXIF-Bilds, der Zwischenspeicher oder beides. Metadaten werden so geändert, dass die Rotationseinstellung angegeben wird. Der geänderte Wert hängt von der HAL-Implementierung ab.
Rechteck zuschneiden
Standardmäßig ist das Zuschneide-Rechteck der vollständige Rect des Buffers. Sie können es mit ViewPort
und UseCaseGroup
anpassen. Nach Gruppierung
und beim Festlegen des Darstellungsbereichs sorgt CameraX dafür, dass der Zuschnitt
die Anwendungsfälle in der Gruppe auf denselben Bereich im Kamerasensor verweisen.
Das folgende Code-Snippet zeigt, wie diese beiden Klassen verwendet werden:
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
definiert das Zwischenspeicherrechteck, das für Endnutzer sichtbar ist. Anschließend berechnet CameraX anhand der Eigenschaften des Ansichtsbereichs und der angehängten Anwendungsfälle das größte mögliche Zuschneide-Rechteck. Normalerweise können Sie den Darstellungsbereich basierend auf dem Vorschau-Use-Case konfigurieren, um einen WYSIWYG-Effekt zu erzielen. Eine einfache Möglichkeit, den Darstellungsbereich abzurufen, ist die Verwendung von PreviewView
.
Die folgenden Code-Snippets zeigen, wie das ViewPort
-Objekt abgerufen wird:
Kotlin
val viewport = findViewById<PreviewView>(R.id.preview_view).viewPort
Java
ViewPort viewPort = ((PreviewView)findViewById(R.id.preview_view)).getViewPort();
Im vorherigen Beispiel wird der Inhalt der App von ImageAnalysis
und
ImageCapture
entspricht dem, was der Endnutzer in PreviewView
sieht, vorausgesetzt, der
Der Skalierungstyp von PreviewView
ist auf die Standardeinstellung FILL_CENTER
festgelegt. Nach dem Anwenden
Zuschnitt und Drehung zum Ausgabezwischenspeicher, das Bild aus allen Anwendungsfällen
mit unterschiedlicher Auflösung. Weitere Informationen zum Anwenden der Transformationsinformationen finden Sie unter Transformationsausgabe.
Kameraauswahl
CameraX wählt automatisch das beste Kameragerät für die Anforderungen und Anwendungsfälle. Wenn Sie ein anderes Gerät als das ausgewählte verwenden möchten, haben Sie folgende Möglichkeiten:
- Mit
CameraSelector.DEFAULT_FRONT_CAMERA
können Sie die Standard-Frontkamera anfordern. - Rufen Sie die Standardrückkamera mit
CameraSelector.DEFAULT_BACK_CAMERA
auf. - Filtern Sie die Liste der verfügbaren Geräte nach ihrer
CameraCharacteristics
mitCameraSelector.Builder.addCameraFilter()
.
Im folgenden Codebeispiel wird gezeigt, wie eine CameraSelector
erstellt wird, um die Geräteauswahl zu beeinflussen:
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)
Mehrere Kameras gleichzeitig auswählen
Ab CameraX 1.3 können Sie auch mehrere Kameras gleichzeitig auswählen. Sie können beispielsweise die Front- und Rückkamera verknüpfen, um Fotos oder Videos aus beiden Perspektiven gleichzeitig aufzunehmen.
Bei Verwendung der Funktion „Gleichzeitige Kamera“ können zwei Kameras bedient werden.
mit unterschiedlichen Objektiven gleichzeitig oder zwei Kameras auf der Rückseite
gleichzeitig. Im folgenden Codeblock wird gezeigt, wie Sie beim Aufrufen von bindToLifecycle
zwei Kameras festlegen und wie Sie beide Kameraobjekte aus dem zurückgegebenen ConcurrentCamera
-Objekt abrufen.
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);
Kameraauflösung
Sie können festlegen, dass KameraX die Bildauflösung anhand einer Kombination festlegen soll. der Gerätefunktionen, der unterstützten Hardware Level, Anwendungsfall und angegebenes Seitenverhältnis. Alternativ können Sie in Anwendungsfällen, die diese Konfiguration unterstützen, eine bestimmte Zielauflösung oder ein bestimmtes Seitenverhältnis festlegen.
Automatische Auflösung
CameraX kann die beste Auflösung automatisch anhand des
Anwendungsfälle, die in cameraProcessProvider.bindToLifecycle()
angegeben sind. Immer
geben Sie alle Anwendungsfälle an, die gleichzeitig in einem einzigen
Sitzung in einem einzelnen bindToLifecycle()
-Aufruf. CameraX bestimmt die Auflösung.
basierend auf den Anwendungsfällen, für die die unterstützte
Hardwareebene und unter Berücksichtigung gerätespezifischer Abweichungen (wenn ein Gerät
die Stream-Konfigurationen überschreitet oder nicht erfüllt
verfügbar).
Ziel ist es, die Anwendung auf einer Vielzahl von Geräten ausführen zu können und gleichzeitig gerätespezifische Codepfade zu minimieren.
Das Standardseitenverhältnis für Anwendungsfälle der Bildaufnahme und Bildanalyse ist 4:3.
Anwendungsfälle haben ein konfigurierbares Seitenverhältnis, über das die Anwendung festlegen kann das gewünschte Seitenverhältnis basierend auf dem UI-Design. Die CameraX-Ausgabe wird so erstellt, dass sie den angeforderten Seitenverhältnissen so nahe wie möglich kommt, was das Gerät unterstützt. Wenn keine Lösung mit exakter Übereinstimmung unterstützt wird, wird die Lösung ausgewählt, die die meisten Bedingungen erfüllt. Die Anwendung gibt also vor, wie die Kamera im App und CameraX ermittelt die beste Kameraauflösung, auf verschiedenen Geräten.
Eine App kann beispielsweise Folgendes tun:
- Geben Sie für einen Anwendungsfall eine Zielauflösung von 4:3 oder 16:9 an
- Geben Sie eine benutzerdefinierte Auflösung an, die CameraX versucht, die nächstgelegene Auflösung zu finden Übereinstimmung mit
- Seitenverhältnis für den Zuschnitt von
ImageCapture
angeben
CameraX wählt die Oberflächenauflösungen der internen Kamera2 automatisch aus. Die Folgende Tabelle zeigt die Auflösungen:
Anwendungsfall | Auflösung der Innenfläche | Auflösung der Ausgabedaten |
---|---|---|
Vorschau | Seitenverhältnis: Die Auflösung, die das Ziel am besten an die Einstellung anpasst. | Interne Oberflächenauflösung. Metadaten werden bereitgestellt, damit eine Ansicht für das Zielseitenverhältnis zugeschnitten, skaliert und gedreht werden kann. |
Standardauflösung:Höchste Vorschauauflösung oder höchste Auflösung des Geräts, die dem Seitenverhältnis der Vorschau entspricht. | ||
Maximale Auflösung:Vorschaugröße, die sich auf die beste Größe bezieht Bildschirmauflösung des Geräts oder 1080p (1920 x 1080) entsprechen, je nachdem, welcher Wert kleiner ist. | ||
Bildanalyse | Seitenverhältnis:Das ist die Auflösung, die am besten zum Ziel passt. Einstellung. | Auflösung der Oberfläche. |
Standardauflösung:Die Standardeinstellung für die Zielauflösung ist 640x480. Zielauflösung und entsprechendes Seitenverhältnis anpassen zu einer am besten unterstützten Auflösung führt. | ||
Maximale Auflösung:Die maximale Ausgabeauflösung der Kamera von
YUV_420_888-Format, das abgerufen wird aus
StreamConfigurationMap.getOutputSizes()
Die Zielauflösung ist standardmäßig auf 640 × 480 festgelegt. Wenn Sie eine Auflösung von mehr als 640 × 480 benötigen, müssen Sie setTargetResolution() und setTargetAspectRatio() verwenden, um die am besten geeignete Auflösung aus den unterstützten Auflösungen zu erhalten.
|
||
Bildaufnahme | Seitenverhältnis:Das am besten zur Einstellung passende Seitenverhältnis. | Interne Oberflächenauflösung. |
Standardauflösung:Höchste verfügbare oder höchste Auflösung Auflösung des Geräts, die dem Seitenverhältnis von ImageCapture entspricht. | ||
Maximale Auflösung: Die maximale Ausgabeauflösung der Kamera im JPEG-Format. Verwende StreamConfigurationMap.getOutputSizes() , um sie abzurufen.
|
Auflösung angeben
Sie können beim Erstellen von Use-Cases mit der Methode setTargetResolution(Size resolution)
bestimmte Auflösungen festlegen, wie im folgenden Codebeispiel gezeigt:
Kotlin
val imageAnalysis = ImageAnalysis.Builder() .setTargetResolution(Size(1280, 720)) .build()
Java
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder() .setTargetResolution(new Size(1280, 720)) .build();
Sie können nicht gleichzeitig das Zielseitenverhältnis und die Zielauflösung festlegen
Fall. Andernfalls wird beim Erstellen des Konfigurationsobjekts ein IllegalArgumentException
geworfen.
Geben Sie die Auflösung Size
in den Koordinaten an.
nachdem die unterstützten Größen durch die Zieldrehung gedreht wurden. Beispiel:
Gerät mit natürlicher Ausrichtung im Hochformat und natürlicher Zielrotation, das ein
Bild im Hochformat kann 480 x 640 Pixel und dasselbe Gerät, um 90 Grad gedreht, und
Querformat-Targeting kann 640 x 480 angeben.
Mit der Zielauflösung wird versucht, eine Mindestgrenze für das Bild festzulegen Problembehebung. Die tatsächliche Bildauflösung ist die nächstgelegene verfügbare Auflösung, die nicht kleiner als die Zielauflösung ist, die von der Kameraimplementierung bestimmt wird.
Wenn jedoch keine Auflösung vorhanden ist, die der Zielauflösung entspricht oder größer ist, wird die nächstniedrigere verfügbare Auflösung ausgewählt. Auflösungen mit demselben Seitenverhältnis wie die bereitgestellte Size
haben eine höhere Priorität als Auflösungen mit unterschiedlichen Seitenverhältnissen.
CameraX wendet die am besten geeignete Auflösung anhand der Anfragen an. Wenn die
Hauptanforderung besteht darin, das Seitenverhältnis zu erfüllen. Geben Sie nur setTargetAspectRatio
an.
und CameraX eine für das jeweilige Gerät passende Auflösung.
Wenn in der App hauptsächlich eine Auflösung angegeben werden muss, um die Bildverarbeitung effizienter zu gestalten (z. B. ein kleines oder mittelgroßes Bild basierend auf der Verarbeitungskapazität des Geräts), verwenden Sie setTargetResolution(Size resolution)
.
Falls für Ihre App eine genaue Lösung erforderlich ist, sehen Sie sich die Tabelle unter
createCaptureSession()
um zu ermitteln, welche maximalen Auflösungen von der jeweiligen Hardwarestufe unterstützt werden. Bis
welche Auflösungen vom aktuellen Gerät unterstützt werden, siehe
StreamConfigurationMap.getOutputSizes(int)
Wenn Ihre App unter Android 10 oder höher ausgeführt wird, können Sie mit isSessionConfigurationSupported()
eine bestimmte SessionConfiguration
bestätigen.
Kameraausgabe steuern
Sie können nicht nur die Kameraausgabe für jedes Gerät individuell konfigurieren, für individuelle Anwendungsfälle implementiert CameraX auch die folgenden Schnittstellen, um Kameravorgänge, die für alle gebundenen Anwendungsfälle typisch sind:
- Unter
CameraControl
können Sie gängige Kamerafunktionen konfigurieren. - Mit
CameraInfo
können Sie Abfragen die Status dieser gängigen Kamerafunktionen.
Folgende Kamerafunktionen werden von CameraControl unterstützt:
- Zoom
- Fackel
- Fokus und Belichtungsmessung (Zum Fokussieren tippen)
- Belichtungskorrektur
Instanzen von CameraControl und CameraInfo abrufen
Rufen Sie Instanzen von CameraControl
und CameraInfo
mithilfe der
Camera
-Objekt, das von zurückgegeben wird.
ProcessCameraProvider.bindToLifecycle()
Der folgende Code zeigt ein Beispiel:
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()
Sie können beispielsweise Zoom- und andere CameraControl
-Vorgänge senden, nachdem
bindToLifecycle()
wird angerufen. Nachdem Sie die zum Binden verwendete Aktivität beendet oder gelöscht haben
Kamerainstanz hat CameraControl
keine Vorgänge mehr ausführen und
gibt einen fehlgeschlagenen ListenableFuture
zurück.
Zoom
CameraControl bietet zwei Methoden zum Ändern des Zoomfaktors:
setZoomRatio()
legt den Zoom um das Zoomverhältnis fest.Das Verhältnis muss im
CameraInfo.getZoomState().getValue().getMinZoomRatio()
undCameraInfo.getZoomState().getValue().getMaxZoomRatio()
. Andernfalls Funktion gibt einen fehlgeschlagenenListenableFuture
zurück.Mit
setLinearZoom()
wird der aktuelle Zoom mit einem linearen Zoomwert zwischen 0 und 1,0 festgelegt.Der Vorteil des linearen Zooms besteht darin, dass das Sichtfeld mit Änderungen des Zooms skaliert wird. Das macht sie ideal für die Verwendung in einer
Slider
-Ansicht.
CameraInfo.getZoomState()
gibt LiveData des aktuellen Zoomstatus zurück. Der Wert ändert sich, wenn die Kamera
initialisiert ist oder die Zoomstufe mit setZoomRatio()
oder
setLinearZoom()
. Durch das Aufrufen einer der beiden Methoden werden die
ZoomState.getZoomRatio()
und
ZoomState.getLinearZoom()
Das ist hilfreich, wenn Sie neben einem Schieberegler Text zum Zoomverhältnis anzeigen möchten.
Beobachten Sie einfach die ZoomState
LiveData
, um beide zu aktualisieren, ohne eine Umwandlung vornehmen zu müssen.
Mit dem von beiden APIs zurückgegebenen ListenableFuture
können Anwendungen benachrichtigt werden, wenn eine wiederkehrende Anfrage mit dem angegebenen Zoomwert abgeschlossen ist. Wenn Sie während des vorherigen Vorgangs einen neuen Zoom-Wert festlegen,
wird noch ausgeführt, schlägt der ListenableFuture
des vorherigen Zoomvorgangs fehl.
sofort.
Taschenlampe
Mit CameraControl.enableTorch(boolean)
können Sie die Taschenlampe aktivieren oder deaktivieren.
Mit CameraInfo.getTorchState()
können Sie den aktuellen Taschenlampenstatus abfragen. Sie können den zurückgegebenen Wert
von
CameraInfo.hasFlashUnit()
um festzustellen, ob eine Taschenlampe verfügbar ist. Andernfalls wird durch das Aufrufen von CameraControl.enableTorch(boolean)
der zurückgegebene Wert ListenableFuture
sofort mit einem Fehler abgeschlossen und der Status der Taschenlampe wird auf TorchState.OFF
gesetzt.
Wenn die Taschenlampe aktiviert ist, bleibt sie unabhängig von der Einstellung „flashMode“ bei der Aufnahme von Fotos und Videos eingeschaltet. Die
flashMode
Zoll
ImageCapture
funktioniert nur, wenn die Taschenlampe deaktiviert ist.
Fokus und Belichtung
CameraControl.startFocusAndMetering()
löst den Autofokus und die Belichtungsmessung aus, indem AF-/AE-/AWB-Messbereiche basierend auf der angegebenen FocusMeteringAction festgelegt werden. Dies wird häufig verwendet, um die Schaltfläche
fokussieren“ in vielen Kamera-Apps.
MeteringPoint
Erstellen Sie zuerst eine MeteringPoint
mit MeteringPointFactory.createPoint(float x, float y, float
size)
.
Ein MeteringPoint
steht für einen einzelnen Punkt auf der Kamera Surface
. Sie wird in normalisierter Form gespeichert, damit sie leicht in Sensorkoordinaten umgewandelt werden kann, um AF-/AE-/AWB-Regionen anzugeben.
Die Größe von MeteringPoint
liegt zwischen 0 und 1, wobei die Standardgröße ist:
0.15f. Wenn MeteringPointFactory.createPoint(float x, float y, float
size)
aufgerufen wird, erstellt CameraX für die angegebene size
einen rechteckigen Bereich mit (x, y)
in der Mitte.
Der folgende Code zeigt, wie ein MeteringPoint
erstellt wird:
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 und FocusMeteringAction
Zum Aufrufen
startFocusAndMetering()
,
Anwendungen müssen eine
FocusMeteringAction
,
die aus mindestens einem MeteringPoints
mit optionalem Metering-Modus besteht
Kombinationen aus
FLAG_AF
,
FLAG_AE
,
FLAG_AWB
. Das folgende Codebeispiel veranschaulicht diese Verwendung:
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)
Wie im vorherigen Code zu sehen, nimmt startFocusAndMetering()
einen FocusMeteringAction
an, der aus einem MeteringPoint
für AF/AE/AWB-Messbereiche und einem weiteren Messpunkt nur für AF und AE besteht.
Intern wandelt CameraX sie in Camera2 MeteringRectangles
um und setzt die entsprechenden CONTROL_AF_REGIONS
-/CONTROL_AE_REGIONS
-/CONTROL_AWB_REGIONS
-Parameter in der Aufnahmeanfrage.
Da nicht jedes Gerät AF/AE/AWB und mehrere Regionen unterstützt, führt CameraX
nach besten Kräften die FocusMeteringAction
. CameraX verwendet die maximal unterstützte Anzahl von Belichtungspunkten in der Reihenfolge, in der sie hinzugefügt wurden. Alle MeteringPoints, die nach Erreichen der maximalen Anzahl hinzugefügt werden, werden ignoriert. Wenn beispielsweise für eine FocusMeteringAction
drei Messpunkte auf einer Plattform angegeben werden, die nur zwei unterstützt, werden nur die ersten beiden Messpunkte verwendet. Die letzte MeteringPoint
wird von CameraX ignoriert.
Belichtungskorrektur
Mit der Belichtungskorrektur können Anwendungen die Belichtung optimieren -Werte (LW) über das Ausgabeergebnis für die automatische Belichtung (AE) hinaus. Belichtungskorrektur werden folgendermaßen kombiniert, um die erforderliche Exposition für Aktuelle Bildbedingungen:
Exposure = ExposureCompensationIndex * ExposureCompensationStep
CameraX bietet die Funktion Camera.CameraControl.setExposureCompensationIndex()
, um die Belichtungskorrektur als Indexwert festzulegen.
Positive Indexwerte hellen das Bild auf, während negative Werte es abdunkeln. Anwendungen können den unterstützten Bereich abfragen, indem sie
CameraInfo.ExposureState.exposureCompensationRange()
die im nächsten Abschnitt beschrieben werden. Wenn der Wert unterstützt wird, wird der zurückgegebene ListenableFuture
-Wert abgeschlossen, wenn der Wert in der Erfassungsanfrage erfolgreich aktiviert wurde. Wenn der angegebene Index nicht im unterstützten Bereich liegt, führt setExposureCompensationIndex()
dazu, dass der zurückgegebene ListenableFuture
-Wert sofort mit einem Fehlerergebnis abgeschlossen wird.
CameraX speichert nur die letzte ausstehende setExposureCompensationIndex()
-Anfrage. Wenn die Funktion mehrmals aufgerufen wird, bevor die vorherige Anfrage ausgeführt wird, wird sie abgebrochen.
Das folgende Snippet legt einen Belichtungskompensationsindex fest und registriert einen Callback für die Ausführung der Anforderungsänderung:
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()
ruft den aktuellenExposureState
einschließlich:- Unterstützung der Belichtungskorrektur
- Der aktuelle Index für die Belichtungskorrektur.
- Der Indexbereich der Belichtungskorrektur.
- Der Schritt für die Belichtungskorrektur, der bei der Berechnung des Belichtungskorrekturwerts verwendet wird.
Im folgenden Code werden beispielsweise die Einstellungen für eine Belichtung SeekBar
mit den aktuellen ExposureState
-Werten initialisiert:
Kotlin
val exposureState = camera.cameraInfo.exposureState binding.seekBar.apply { isEnabled = exposureState.isExposureCompensationSupported max = exposureState.exposureCompensationRange.upper min = exposureState.exposureCompensationRange.lower progress = exposureState.exposureCompensationIndex }
Weitere Informationen
Weitere Informationen zu CameraX finden Sie in den folgenden zusätzlichen Ressourcen.
Codelab
Codebeispiel
Entwickler-Community
Diskussionsgruppe zu Android CameraX