Konfigurationsoptionen

Sie konfigurieren jeden CameraX-Anwendungsfall so, dass unterschiedliche Aspekte der Verwendung gesteuert werden. die Vorgänge in der Anfrage auszuführen.

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

Neben den Konfigurationsoptionen werden in einigen Anwendungsfällen APIs auch für Einstellungen nach der Erstellung des Anwendungsfalls ändern. Informationen zu eine Konfiguration, die für den jeweiligen Anwendungsfall spezifisch ist, finden Sie unter Implementierung eines „preview“, „Analysieren“ Bilder und Bild aufnehmen.

CameraXConfig

Der Einfachheit halber hat CameraX Standardkonfigurationen, z. B. interne Executors. und Handler, die für die meisten Nutzungsszenarien geeignet sind. Wenn Ihre Anwendung spezielle Anforderungen hat oder diese anpassen möchte Konfigurationen, CameraXConfig ist die Schnittstelle für diesen Zweck.

Mit CameraXConfig kann eine Anwendung Folgendes tun:

Nutzungsmodell

Im Folgenden wird die Verwendung von CameraXConfig beschrieben:

  1. Erstellen Sie ein CameraXConfig-Objekt mit Ihren benutzerdefinierten Konfigurationen.
  2. Implementieren Sie die CameraXConfig.Provider in der Application und CameraXConfig-Objekt zurückgeben in getCameraXConfig()
  3. Fügen Sie der Datei AndroidManifest.xml die Klasse Application 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 für jede Kamera sehr viel Zeit in Anspruch nehmen, insbesondere Low-End-Geräte. Wenn Ihre App nur bestimmte Kameras auf dem Gerät verwendet, wie der Standard-Frontkamera, können Sie CameraX so einstellen, dass andere Kameras ignoriert werden. wodurch die Startlatenz für die von Ihrer Anwendung verwendeten Kameras reduziert werden kann.

Wenn CameraSelector bestanden wurde bis CameraXConfig.Builder.setAvailableCamerasLimiter() filtert eine Kamera heraus, verhält sich CameraX so, als wäre diese Kamera nicht vorhanden. Für Beispiel: Der folgende Code schränkt ein, dass die App nur die Standard-Rückkamera:

Kotlin

class MainApplication : Application(), CameraXConfig.Provider {
   override fun getCameraXConfig(): CameraXConfig {
       return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig())
              .setAvailableCamerasLimiter(CameraSelector.DEFAULT_BACK_CAMERA)
              .build()
   }
}

Threads

Viele Plattform-APIs, auf denen CameraX basiert, müssen blockiert werden. Interprocess Communication (IPC) mit Hardware kann manchmal Hunderte von Millisekunden, um zu antworten. Aus diesem Grund ruft CameraX diese APIs nur von Hintergrundthreads, damit der Hauptthread nicht blockiert wird bleibt flüssig. CameraX verwaltet diese Hintergrundthreads intern, das Verhalten transparent zu sein scheint. Einige Anwendungen erfordern jedoch eine strenge Kontrolle. von Threads. 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 Callbacks werden weiterhin nur direkt an den Camera Executor gesendet. KameraX teilt und verwaltet ein internes HandlerThread zum Ausführen dieser Aufgaben aber Sie können ihn 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 Protokollierungsstufen, von der ausführlichsten bis zur schwerwiegendsten:

  • 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 entsprechende Logging-Ebene für Ihre Anwendung festzulegen.

Automatische Auswahl

CameraX bietet automatisch gerätespezifische Funktionen. auf denen Ihre App ausgeführt wird. Beispielsweise erkennt CameraX automatisch, ist die beste Auflösung, wenn du keine Auflösung angibst wird nicht unterstützt. 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, Bei CameraX werden Auflösung und Seitenverhältnisse je nach Gerätefähigkeit gefährden. Das kann folgende Gründe haben:

  • Das Gerät unterstützt die angeforderte Auflösung nicht.
  • Das Gerät hat Kompatibilitätsprobleme, z. B. ältere Geräte, für die eine damit alles korrekt funktioniert.
  • 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ächstgelegene 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 in jedem Fall die zurückgegebene Bildgrößen in der Ausgabe des Anwendungsfalls in Ihrem Code und passen Sie sie entsprechend an.

Ausrichtung

Standardmäßig ist die Kameradrehung so eingestellt, dass sie der Drehung des Standarddisplays entspricht bei der Erstellung des Anwendungsfalls. In diesem Standardfall erstellt CameraX damit die App dem entspricht, was Sie in der in der Vorschau ansehen. Sie können die Rotation in einen benutzerdefinierten Wert ändern, um Multi-Display-Anzeigen zu unterstützen Geräte durch Übergeben der aktuellen Displayausrichtung beim Konfigurieren des Anwendungsfalls oder dynamisch, nachdem sie erstellt wurden.

Ihre App kann die Zielrotation mithilfe von Konfigurationseinstellungen festlegen. Es kann dann Rotationseinstellungen mithilfe der Methoden aus den APIs für Anwendungsfälle (z. B. ImageAnalysis.setTargetRotation()), auch wenn der Lebenszyklus ausgeführt ist. Sie können diese Funktion nutzen, ist auf Hochformat eingestellt – eine Neukonfiguration findet gedreht werden soll. Der Anwendungsfall von Foto oder Analyse muss jedoch die aktuelle Drehung des Geräts. 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 enthält Rotationsinformationen, sodass Galerieanwendungen das Bild in nach dem Speichern in die richtige Ausrichtung.

Um Vorschaudaten mit der richtigen Ausrichtung anzuzeigen, können Sie die Metadaten verwenden Ausgabe von Preview.PreviewOutput() um Transformationen zu erstellen.

Das folgende Codebeispiel zeigt, wie die Rotation 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 bereitgestellt, sodass die Rotation des Ziels ist die Verwendung von Preview.getTargetRotation()
  • 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 entspricht das Rechteck zuschneiden dem vollständigen Zwischenspeicher. Sie können sie anpassen mit ViewPort und UseCaseGroup 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. Dann berechnet CameraX Größtmögliches Zuschneide-Rechteck basierend auf den Eigenschaften des Darstellungsbereichs und des angehängten Anwendungsfälle. Um einen WYSIWYG-Effekt zu erzielen, können Sie Darstellungsbereich basierend auf dem Anwendungsfall der Vorschau. Eine einfache Methode zum Abrufen des Darstellungsbereichs , um PreviewView zu verwenden.

Die folgenden Code-Snippets zeigen, wie das Objekt ViewPort 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 Informationen zum Anwenden der Transformationsinformationen finden Sie unter Transformieren Output

Kameraauswahl

CameraX wählt automatisch das beste Kameragerät für die Anforderungen und Anwendungsfälle. Wenn Sie ein anderes Gerät als dieses verwenden möchten stehen Ihnen mehrere Optionen zur Verfügung:

Das folgende Codebeispiel zeigt, wie Sie eine CameraSelector erstellen, um Geräteauswahl 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 eine Bindung an eine Front- und Rückkamera herstellen, um Fotos oder Aufnahmen zu machen aus beiden Perspektiven gleichzeitig ansehen.

Bei Verwendung der Funktion „Gleichzeitige Kamera“ können zwei Kameras bedient werden. mit unterschiedlichen Objektiven gleichzeitig oder zwei Kameras auf der Rückseite gleichzeitig. Der folgende Codeblock zeigt, wie zwei Kameras eingerichtet werden, bindToLifecycle aufrufen und beide Camera-Objekte aus der zurückgegebenen ConcurrentCamera-Objekt.

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 ein bestimmtes die Zielauflösung oder ein bestimmtes Seitenverhältnis haben. Konfiguration.

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). Die App soll auf einer Vielzahl von Geräten laufen, und minimieren gerätespezifische Codepfade.

Das Standardseitenverhältnis für die Bilderfassung und ‐analyse beträgt 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 Ausgabe von CameraX wird Sie müssen den angeforderten Seitenverhältnissen so genau wie das Gerät entsprechen. Wenn es keine genaue Übereinstimmung unterstützt, die die meisten Bedingungen erfüllt ausgewählt ist. 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 für ImageCapture angeben

CameraX wählt die Oberflächenauflösungen von Camera2 automatisch aus. Die Folgende Tabelle zeigt die Auflösungen:

Anwendungsfall Interne Oberflächenauflösung Auflösung der Ausgabedaten
Vorschau Seitenverhältnis: Das ist die Auflösung, die am besten für das Ziel und den Einstellung. Interne Oberflächenauflösung. Metadaten werden bereitgestellt, damit eine Ansicht das Zuschneiden, das für das gewünschte Seitenverhältnis skalieren und drehen.
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. Interne Oberflächenauflösung.
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 x 480 festgelegt. Wenn Sie also eine höhere Auflösung als 640 x 480 wünschen, müssen Sie setTargetResolution() und setTargetAspectRatio() um die beste Auflösung zu finden.
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 in im JPEG-Format. Verwenden Sie StreamConfigurationMap.getOutputSizes() um diese Informationen abzurufen.

Auflösung angeben

Beim Erstellen von Anwendungsfällen können Sie mithilfe der setTargetResolution(Size resolution)-Methode, wie im folgenden Code dargestellt Beispiel:

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. Dadurch wird beim Erstellen der Konfiguration ein IllegalArgumentException ausgelöst -Objekt enthält.

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 entspricht der aktuellen verfügbaren Auflösung die nicht kleiner als die Zielauflösung ist. Kameraimplementierung

Wenn jedoch keine Auflösung vorhanden ist, die gleich oder größer als die Zielauflösung ist, ist die nächste verfügbare Auflösung kleiner als wird die angestrebte Auflösung ausgewählt. Auflösungen mit demselben Seitenverhältnis von haben die angegebenen Size eine höhere Priorität als verschiedene Auflösungen Seitenverhältnissen.

CameraX wendet je nach den Anforderungen die am besten geeignete Auflösung 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 für die App vor allem die Auflösung zum Erstellen von Bildern erforderlich ist effizienter zu verarbeiten (z. B. ein kleines oder mittelgroßes Bild basierend auf Geräteverarbeitungsfunktionen), 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 läuft, können Sie isSessionConfigurationSupported() um eine bestimmte SessionConfiguration zu 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:

  • Mit CameraControl können Sie 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 der Zoomstufe:

  • setZoomRatio() legt den Zoom um das Zoomverhältnis fest.

    Das Verhältnis muss im CameraInfo.getZoomState().getValue().getMinZoomRatio() und CameraInfo.getZoomState().getValue().getMaxZoomRatio(). Andernfalls Funktion gibt einen fehlgeschlagenen ListenableFuture zurück.

  • setLinearZoom() legt die aktuelle Zoomstufe mit einem linearen Zoomwert zwischen 0 und 1,0 fest.

    Der Vorteil des linearen Zooms besteht darin, dass das Sichtfeld mit Änderungen des Zoomfaktors skalieren. Daher eignet sie sich ideal für Slider-Ansicht.

CameraInfo.getZoomState() gibt LiveData des aktuellen Zoom-Zustands 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() Dies ist hilfreich, wenn Sie Text für das Zoomverhältnis neben einem Schieberegler anzeigen lassen möchten. Sehen Sie sich einfach das ZoomState LiveData an, um beide zu aktualisieren, ohne dass Conversion.

Die von beiden APIs zurückgegebene ListenableFuture bietet die Option für Anwendungen wird benachrichtigt, wenn eine wiederkehrende Anfrage mit dem angegebenen Zoomwert abgeschlossen. 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.

Fackel

CameraControl.enableTorch(boolean) die Taschenlampe aktiviert oder deaktiviert.

CameraInfo.getTorchState() kann verwendet werden, um den aktuellen Taschenlampenstatus abzufragen. Sie können den zurückgegebenen Wert von CameraInfo.hasFlashUnit() um festzustellen, ob eine Taschenlampe verfügbar ist. Wenn nicht, rufen Sie CameraControl.enableTorch(boolean) führt dazu, dass die zurückgegebene ListenableFuture in sofort mit dem Fehlschlagen des Ergebnisses abgeschlossen und den Taschenlampenstatus auf TorchState.OFF

Wenn die Taschenlampe aktiviert ist, bleibt sie bei Foto- und Videoaufnahmen eingeschaltet. unabhängig von der flashMode-Einstellung. Die flashMode Zoll ImageCapture funktioniert nur, wenn die Taschenlampe deaktiviert ist.

Fokus und Belichtung

CameraControl.startFocusAndMetering() löst die Autofokus- und Belichtungsmessung aus, indem AF/AE/AWB-Messbereiche festgelegt werden basierend auf der gegebenen FocusMeteringAction. Dies wird häufig verwendet, um die Schaltfläche in vielen Kamera-Apps verwenden.

Messpunkt

Erstellen Sie zunächst eine MeteringPoint verwendet MeteringPointFactory.createPoint(float x, float y, float size) Ein MeteringPoint steht für einen einzelnen Punkt auf der Kamera Surface Sie werden in einer normalisierten Form gespeichert. sodass sie leicht in Sensorkoordinaten konvertiert werden können, AF/AE/AWB-Regionen.

Die Größe von MeteringPoint liegt zwischen 0 und 1, wobei die Standardgröße ist: 0.15f. Beim Aufrufen von MeteringPointFactory.createPoint(float x, float y, float size) erstellt CameraX einen rechteckigen Bereich, der bei (x, y) für das angegebene Objekt zentriert ist. size

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. Die folgen Sie dem Code, um diese Verwendung zu demonstrieren:

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 der vorherige Code zeigt, startFocusAndMetering() nimmt eine FocusMeteringAction bestehend aus einer MeteringPoint für AF/AE/AWB. nur für AF und AE verfügbar.

KameraX wandelt sie intern in Camera2 um. MeteringRectangles und legt die entsprechenden CONTROL_AF_REGIONS / CONTROL_AE_REGIONS / CONTROL_AWB_REGIONS. -Parameter zur Erfassungsanfrage hinzu.

Da nicht jedes Gerät AF/AE/AWB und mehrere Regionen unterstützt, führt CameraX die FocusMeteringAction nach bestem Wissen und Gewissen. CameraX verwendet die maximale Anzahl der unterstützten Messpunkte in der Reihenfolge, in der die Punkte hinzugefügt wurden. Alle Messpunkte, die nach der maximalen Anzahl hinzugefügt werden, werden ignoriert. Wenn zum Beispiel ein Bei FocusMeteringAction sind 3 MeteringPoints auf einer Plattform vorhanden, die nur 2 auswählen, werden nur die ersten beiden MeteringPoints verwendet. Der letzte MeteringPoint ist 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 Camera.CameraControl.setExposureCompensationIndex() zum Festlegen der Belichtungskorrektur als Indexwert.

Positive Indexwerte machen das Bild heller, während negative Werte das Bild dimmen Bild. 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 Wert ListenableFuture wird abgeschlossen, wenn der Wert im Anforderung erfassen; wenn der angegebene Index außerhalb des unterstützten Bereichs liegt, setExposureCompensationIndex() bewirkt, dass ListenableFuture sofort mit einem fehlgeschlagenen Ergebnis abschließen.

CameraX behält nur die neuesten ausstehenden setExposureCompensationIndex() bei und die Funktion mehrmals vor der vorherigen Anfrage aufrufen. ausgeführt wird, führt zu deren Abbruch.

Mit dem folgenden Snippet wird ein Belichtungskompensationsindex festgelegt und ein 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 aktuellen ExposureState einschließlich:

    • Die Unterstützung für die Belichtungskorrektur.
    • Der aktuelle Belichtungskompensationsindex.
    • Der Belichtungskompensationsindexbereich.
    • Der Belichtungskorrekturschritt, der als Belichtungskorrekturwert verwendet wird Berechnung.

Mit dem folgenden Code werden beispielsweise die Einstellungen für einen Kontakt SeekBar mit der aktuellen ExposureState Werte:

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 Ressourcen.

Codelab

  • <ph type="x-smartling-placeholder"></ph> Erste Schritte mit CameraX
  • Codebeispiel

  • <ph type="x-smartling-placeholder"></ph> Beispiel-Apps für CameraX
  • Entwickler-Community

    Diskussionsgruppe zu Android CameraX