Beim Anwendungsfall Bildanalyse erhält Ihre Anwendung ein über die CPU zugängliches Bild, auf dem Sie Bildverarbeitung, maschinelles Sehen oder Inferenzen durch maschinelles Lernen ausführen können. Die Anwendung implementiert die Methode analyze()
, die für jeden Frame ausgeführt wird.
Informationen zum Einbinden des ML Kits von Google in die CameraX-App finden Sie unter ML Kit Analyzer.
Betriebsmodi
Wenn die Analysepipeline der Anwendung nicht mit den Framerate-Anforderungen von CameraX mithalten kann, kann CameraX so konfiguriert werden, dass Frames auf eine der folgenden Arten entfernt werden:
Nicht blockierend (Standardeinstellung): In diesem Modus speichert der Executor immer das neueste Image in einem Image-Zwischenspeicher (ähnlich einer Warteschlange mit einer Tiefe von eins), während die Anwendung das vorherige Image analysiert. Wenn CameraX ein neues Bild empfängt, bevor die Anwendung die Verarbeitung abgeschlossen hat, wird das neue Bild in demselben Zwischenspeicher gespeichert und das vorherige Bild überschrieben. Beachten Sie, dass
ImageAnalysis.Builder.setImageQueueDepth()
in diesem Szenario keine Auswirkungen hat und der Zwischenspeicherinhalt immer überschrieben wird. Sie können diesen nicht blockierenden Modus aktivieren, indem SiesetBackpressureStrategy()
mitSTRATEGY_KEEP_ONLY_LATEST
aufrufen. Weitere Informationen zu Auswirkungen des Executors finden Sie in der Referenzdokumentation zuSTRATEGY_KEEP_ONLY_LATEST
.blocking: In diesem Modus kann der interne Executor der internen Image-Warteschlange mehrere Images hinzufügen und beginnt erst dann mit dem Löschen von Frames, wenn die Warteschlange voll ist. Die Blockierung betrifft die gesamte Kamerageräte: Wenn das Kameragerät mehrere gebundene Anwendungsfälle hat, werden alle diese Anwendungsfälle blockiert, während CameraX diese Bilder verarbeitet. Wenn beispielsweise sowohl die Vorschau als auch die Bildanalyse an ein Kameragerät gebunden sind, wird die Vorschau ebenfalls blockiert, während CameraX die Bilder verarbeitet. Sie können den Blockierungsmodus aktivieren, indem Sie
STRATEGY_BLOCK_PRODUCER
ansetBackpressureStrategy()
übergeben. Sie können die Tiefe der Bildwarteschlange auch mithilfe von ImageAnalysis.Builder.setImageQueueDepth() konfigurieren.
Mit einem Analysetool für niedrige Latenz und hoher Leistung, bei dem die Gesamtzeit für die Analyse eines Bildes kürzer als die Dauer eines CameraX-Frames (z. B. 16 ms für 60 fps) ist, sorgen beide Betriebsmodi für ein reibungsloses Gesamterlebnis. Der Blockiermodus kann in einigen Szenarien weiterhin hilfreich sein, z. B. beim Umgang mit sehr kurzen Systemjitter.
Bei einer hohen Latenz und einem Hochleistungs-Analysetool ist der Blockierungsmodus mit einer längeren Warteschlange erforderlich, um die Latenz auszugleichen. Die Anwendung kann jedoch weiterhin alle Frames verarbeiten.
Mit einer hohen Latenz und einem zeitaufwendigen Analysetool (das Analysetool kann nicht alle Frames verarbeiten), ist ein nicht blockierender Modus möglicherweise die bessere Wahl, da Frames für den Analysepfad entfernt werden müssen, aber bei anderen gleichzeitig gebundenen Anwendungsfällen weiterhin alle Frames angezeigt werden können.
Implementierung
So verwenden Sie die Bildanalyse in Ihrer Anwendung:
- Erstellen Sie einen
ImageAnalysis
-Anwendungsfall. - Erstellen Sie eine
ImageAnalysis.Analyzer
. - Stellen Sie das Analysetool auf
ImageAnalysis
ein. - Binden Sie den Lebenszyklusinhaber, die Kameraauswahl und den
ImageAnalysis
-Anwendungsfall an den Lebenszyklus.
Sofort nach der Bindung sendet CameraX Bilder an Ihr registriertes Analysegerät.
Rufen Sie nach Abschluss der Analyse ImageAnalysis.clearAnalyzer()
auf oder heben Sie die Verknüpfung mit dem Anwendungsfall ImageAnalysis
auf, um die Analyse zu beenden.
Anwendungsfall „ImageAnalysis erstellen“
ImageAnalysis
verbindet das Analysetool (ein Bildnutzer) mit CameraX, einem Bildersteller.
Anwendungen können ImageAnalysis.Builder
verwenden, um ein ImageAnalysis
-Objekt zu erstellen. Mit dem ImageAnalysis.Builder
kann die Anwendung Folgendes konfigurieren:
- Parameter für die Bildausgabe:
- Format: CameraX unterstützt
YUV_420_888
undRGBA_8888
bissetOutputImageFormat(int)
. Das Standardformat istYUV_420_888
. - Auflösung und Seitenverhältnis: Sie können beide Parameter festlegen, aber nicht beide Werte gleichzeitig.
- Rotation:
- Zielname: Verwenden Sie diesen Parameter zu Fehlerbehebungszwecken.
- Format: CameraX unterstützt
- Steuerelemente für den Bildfluss:
In Anwendungen kann entweder die Auflösung oder das Seitenverhältnis festgelegt werden, aber nicht beides. Die genaue Ausgabeauflösung hängt von der von der Anwendung angeforderten Größe (oder Seitenverhältnis) und den Hardwarefunktionen ab und kann von der angeforderten Größe oder vom angeforderten Seitenverhältnis abweichen. Informationen zum Algorithmus zum Auflösungsabgleich finden Sie in der Dokumentation zu setTargetResolution()
.
In einer Anwendung können die Ausgabebildpixel als YUV- (Standard) oder RGBA-Farbräume konfiguriert werden. Beim Festlegen eines RGBA-Ausgabeformats wandelt CameraX die Bilder intern vom YUV in den RGBA-Farbraum um und packt Bildbits in der ByteBuffer
der ersten Ebene von ImageProxy (die anderen beiden Ebenen werden nicht verwendet) mit der folgenden Reihenfolge:
ImageProxy.getPlanes()[0].buffer[0]: alpha
ImageProxy.getPlanes()[0].buffer[1]: red
ImageProxy.getPlanes()[0].buffer[2]: green
ImageProxy.getPlanes()[0].buffer[3]: blue
...
Bei komplizierten Bildanalysen, bei denen das Gerät die Framerate nicht mithalten kann, können Sie CameraX so konfigurieren, dass Frames mit den im Abschnitt Betriebsmodi dieses Themas beschriebenen Strategien ausgelassen werden.
Analysetool erstellen
Anwendungen können Analysetools erstellen, indem die ImageAnalysis.Analyzer
-Schnittstelle implementiert und analyze(ImageProxy image)
überschrieben wird.
In jedem Analyzer erhalten die Anwendungen ein ImageProxy
, das ein Wrapper für Media.Image ist.
Das Bildformat kann mit ImageProxy.getFormat()
abgefragt werden.
Das Format ist einer der folgenden Werte, die die Anwendung ImageAnalysis.Builder
bereitstellt:
ImageFormat.RGBA_8888
, wenn die AppOUTPUT_IMAGE_FORMAT_RGBA_8888
angefordert hat.ImageFormat.YUV_420_888
, wenn die AppOUTPUT_IMAGE_FORMAT_YUV_420_888
angefordert hat.
Informationen zu Farbraumkonfigurationen und zum Abrufen der Pixelbyte finden Sie unter Anwendungsfall "ImageAnalysis erstellen".
In einem Analysetool sollte die Anwendung folgende Aktionen ausführen:
- Analysiere einen bestimmten Frame so schnell wie möglich, am besten innerhalb des vorgegebenen Framerate-Zeitlimits (z. B. weniger als 32 ms bei 30 fps). Wenn die Anwendung einen Frame nicht schnell genug analysieren kann, sollten Sie einen der unterstützten Verfahren zum Löschen von Frames in Betracht ziehen.
- Lassen Sie
ImageProxy
durch Aufrufen vonImageProxy.close()
in CameraX los. Die Schließen-Funktion (Media.Image.close()
) des umschlossenen Media.Image sollte nicht aufgerufen werden.
Anwendungen können das umschlossene Media.Image
direkt in ImageProxy verwenden.
Rufen Sie nur nicht Media.Image.close()
für das umschlossene Bild auf, da dies den Bildfreigabemechanismus in CameraX beeinträchtigen würde. Verwenden Sie stattdessen ImageProxy.close()
, um die zugrunde liegende Media.Image
für CameraX freizugeben.
Analysetool für ImageAnalysis konfigurieren
Nachdem Sie ein Analysetool erstellt haben, können Sie es mit ImageAnalysis.setAnalyzer()
registrieren und mit der Analyse beginnen. Wenn Sie mit der Analyse fertig sind, verwenden Sie ImageAnalysis.clearAnalyzer()
, um das registrierte Analysetool zu entfernen.
Für die Bildanalyse kann nur ein aktives Analysetool konfiguriert werden. Durch das Aufrufen von ImageAnalysis.setAnalyzer()
wird das registrierte Analyse-Tool ersetzt, falls es bereits vorhanden ist. Anwendungen können vor oder nach der Bindung des Anwendungsfalls jederzeit ein neues Analysetool festlegen.
ImageAnalysis an einen Lebenszyklus binden
Es wird dringend empfohlen, den ImageAnalysis
mit der Funktion ProcessCameraProvider.bindToLifecycle()
an einen vorhandenen AndroidX-Lebenszyklus zu binden. Die Funktion bindToLifecycle()
gibt das ausgewählte Camera
-Gerät zurück, mit dem erweiterte Einstellungen wie die Belichtung und andere Elemente abgestimmt werden können. Weitere Informationen zur Steuerung der Kameraausgabe findest du in diesem Leitfaden.
Im folgenden Beispiel werden alle vorherigen Schritte kombiniert, um Anwendungsfälle für CameraX ImageAnalysis
und Preview
an einen lifeCycle
-Inhaber zu binden:
Kotlin
val imageAnalysis = ImageAnalysis.Builder() // enable the following line if RGBA output is needed. // .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888) .setTargetResolution(Size(1280, 720)) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build() imageAnalysis.setAnalyzer(executor, ImageAnalysis.Analyzer { imageProxy -> val rotationDegrees = imageProxy.imageInfo.rotationDegrees // insert your code here. ... // after done, release the ImageProxy object imageProxy.close() }) cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, imageAnalysis, preview)
Java
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder() // enable the following line if RGBA output is needed. //.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888) .setTargetResolution(new Size(1280, 720)) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build(); imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() { @Override public void analyze(@NonNull ImageProxy imageProxy) { int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees(); // insert your code here. ... // after done, release the ImageProxy object imageProxy.close(); } }); cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, imageAnalysis, preview);
Weitere Informationen
Weitere Informationen zu CameraX finden Sie in den folgenden zusätzlichen Ressourcen.
Codelab
Codebeispiel