Bilder streamen (experimentell)

Der Bild-Stream ist experimentell (ab v2.3.0). Seine Knoten können sich noch ändern. Verwenden Sie ihn zur Evaluierung, und prüfen Sie ihn mit Ihrer Kamera, bevor Sie sich darauf verlassen.

capture liefert ein Bild pro Request, und jeder Request wartet, bis sein Bild eingetroffen ist. Bei der von uns getesteten Kamera ergibt das etwa 34 Bilder pro Sekunde, deutlich weniger, als die Kamera selbst liefern kann: Die nächste Belichtung kann nicht beginnen, bevor das vorherige Bild ausgelesen und gesendet wurde.

Der Bild-Stream arbeitet umgekehrt. Solange er läuft, veröffentlicht der Cam Driver jedes Bild, das die Kamera liefert, auf <camera name>/control/publish/output/stream/frame. Ihr Programm abonniert diesen Knoten und erhält jedes Bild, sobald es eintrifft - mit seiner Größe, seinem Pixelformat und seiner Herkunft, siehe Was jeder Frame enthält.

Der Stream wird durch eine Funktion ein- und ausgeschaltet, control/publish: Setzen Sie ihre Eingaben, und rufen Sie dann control/publish/execute auf, um sie anzuwenden. Siehe Einen Stream betreiben.

Das allgemeine Stream-Konzept - Produzenten, Konsumenten und die Lineage ihrer Ergebnisse - ist in Streams beschrieben. Diese Seite beschreibt den Stream des Cam Driver.

Der Cam Driver triggert die Kamera nicht von selbst. Ein Bild kommt, wenn die Kamera getriggert wird - durch ein Signal an ihrem Trigger-Eingang oder durch control/trigger/execute - oder, bei ausgeschaltetem Trigger-Modus der Kamera, so schnell, wie die Kamera läuft. Siehe Die Kamera triggern.

Tabelle 1. Was ein Abonnent erhält
Data Layer Bilder, die ein Abonnent von control/publish/output/stream/frame erhält

ctrlX Data Layer (ctrlX OS)

Jedes Bild, in Reihenfolge, sobald es veröffentlicht wird, unabhängig vom Publish-Intervall des Abonnements. Bilder werden nur verworfen, wenn der Data Layer weit zurückfällt.

LumiScan Keryx (PC)

Jedes Bild, in Reihenfolge. Der Data Layer verwirft Bilder nur, wenn ein Abonnent weit zurückfällt.

Jeder Frame trägt seine Nummer im Stream, sodass ein Abonnent ein verworfenes Bild als Lücke erkennt. Ein Lesen von control/publish/output/stream/frame liefert immer das neueste Bild.

Adressen

Alle Adressen unten beginnen mit hdvisionsystems/lumiscan-cam-driver/<camera name>/. Sie folgen der Regel jeder execute-Methode: Die Methode besitzt ihre Knoten, control/publish/execute, control/publish/input/…​ und control/publish/output/…​.

Tabelle 2. Die Methode und ihre Eingaben
Adresse Typ Standard Bedeutung

control/publish/execute

Methode

Wendet die folgenden Eingaben gemeinsam an. Eine Eingabe allein zu schreiben ändert nichts. Kehrt sofort zurück: Der Stream startet oder stoppt innerhalb des nächsten Zyklus des Cam Driver, und control/publish/output/stream/active zeigt an, wann er läuft. Wird mit DL_RESOURCE_UNAVAILABLE abgelehnt, während der Cam Driver beendet wird oder nachdem seine Einstellungen auf dem Data Layer geändert wurden (system/restart-required). Wird mit DL_CREATION_FAILED abgelehnt, wenn ein geändertes tag nicht gespeichert werden kann: Dann ändert sich nichts.

control/publish/input/enable

bool

false

true lässt den Stream laufen, solange die Kamera verbunden ist; false stoppt ihn.

control/publish/input/keep-latest-output

bool

false

true kopiert jedes gestreamte Bild zusätzlich nach output/image: data, width, height, pixel-type und timestamp (die Zeit, zu der das Bild eingetroffen ist), und erhöht dann output/package-identifier um eins, wie capture es tut. Jede Kopie kostet Zeit, was einen schnellen Stream verlangsamt. Wird auf einen laufenden Stream angewendet, ohne ihn neu zu starten. Siehe Capture, während der Stream läuft.

control/publish/input/tag

string

stream.tag der Modulkonfigurationsdatei, oder leer

Das Tag auf den Bildern des Moduls: Der Schritt der Kamera in ihrer Lineage trägt es, und ebenso die Ergebnisse jeder Anwendung, die sie verarbeitet. Leer: der Kameraname, zum Beispiel camera1. Geben Sie ein anderes an, zum Beispiel die Station, auf die die Kamera blickt, um es in jedem Ergebnis zu sehen. Wird auf einen laufenden Stream angewendet, ohne ihn neu zu starten. Siehe Das Tag.

Was execute angewendet hat, wird nicht gespeichert, außer dem Tag: Nach dem Start des Cam Driver ist der Stream aus, bis control/publish/execute mit enable true aufgerufen wird.

Tabelle 3. Die Ausgaben der Methode, unter control/publish/
Adresse Typ Bedeutung

output/stream/active

bool

true, solange der Stream läuft.

output/stream/frame

flatbuffers (stream_image)

Jedes gestreamte Bild: die Pixel, ihre Größe und ihr Format sowie die Lineage des Bildes. Abonnieren Sie ihn, um die Bilder zu erhalten. Siehe Was jeder Frame enthält.

output/stream/width, output/stream/height

uint64

Größe der gestreamten Bilder in Pixeln, zum Nachsehen. Jeder Frame trägt seine eigene.

output/stream/pixel-type

string

Pixelformat der gestreamten Bilder, zum Nachsehen. Jeder Frame trägt sein eigenes.

output/stream/statistics/…​

uint64

Zähler des aktuellen oder letzten Streams, siehe Die Statistik lesen.

Tabelle 4. Neben der Methode
Adresse Typ Bedeutung

setting/settings-hash

string

Der Hash der Einstellungen, mit denen die Bilder aufgenommen werden, als 16 Hexadezimalziffern. Siehe Der Einstellungs-Hash.

setting/stream/tag

string

Das Tag, das control/publish/execute zuletzt angewendet hat, wie die Bilder es tragen. Leer: Die Bilder tragen den Kameranamen.

Das Tag

Ein geändertes control/publish/input/tag wird als stream.tag in der Modulkonfigurationsdatei gespeichert, bevor control/publish/execute es anwendet; der Rest der Datei bleibt, wie er war. So tragen die Bilder es auch nach einem Neustart, und control/publish/input/tag beginnt damit. Kann die Datei nicht geschrieben werden, antwortet control/publish/execute mit DL_CREATION_FAILED, und weder das Tag noch die anderen Eingaben ändern sich. Ein unverändertes Tag wird nicht gespeichert, sodass ein Modul, dessen Datei nicht geschrieben werden kann, trotzdem streamt.

Das Tag ist nicht Teil des Einstellungs-Hashs: Es benennt die Bilder, es verändert sie nicht.

Die Kamera triggern

Jeder Trigger, den die Kamera erhält, liefert ein Bild auf control/publish/output/stream/frame. Stellen Sie den Trigger-Modus der Kamera ein, bevor Sie den Stream starten, über ihre Feature-Knoten unter features oder in einer Feature-Datei.

Bilder kommen Kameraeinstellungen Was zu tun ist

Bei einem Hardware-Trigger

TriggerMode On, TriggerSource ein Trigger-Eingang, zum Beispiel Line0

Senden Sie für jedes Bild einen Impuls an den Trigger-Eingang.

Auf Anforderung

TriggerMode On, TriggerSource Software

Rufen Sie für jedes Bild einmal control/trigger/execute auf. Der Cam Driver sendet den Software-Trigger der Kamera, wie das Feature-Mapping von hdv ihn benennt.

Kontinuierlich

TriggerMode Off

Nichts. Die Kamera liefert so schnell, wie sie läuft, oder mit ihrer AcquisitionFrameRate, wo diese aktiviert ist.

Eine Kamera ohne Software-Trigger-Modus - eine simulierte Kamera, die einen Ordner mit Bildern abspielt, oder eine Plugin- Kamera ohne TriggerSoftware - nimmt ebenfalls bei jedem Aufruf von control/trigger/execute ein Bild auf.

control/trigger/execute antwortet, wenn der Trigger gesendet wurde, nicht, wenn sein Bild eingetroffen ist. Eine Kamera, die noch mit dem vorherigen Bild beschäftigt ist, kann einen Trigger ignorieren, ohne es zu melden, siehe Für die höchste Bildrate: TriggerOverlap.

Für die höchste Bildrate: TriggerOverlap

Ist das GenICam-Feature TriggerOverlap auf Off gesetzt, nimmt eine Kamera das nächste Bild erst auf, wenn das vorherige ausgelesen wurde, und ignoriert einen Trigger, der früher kommt. Ein Overlap lässt die nächste Belichtung beginnen, während das vorherige Bild noch ausgelesen oder gesendet wird, was die Bildrate erhöht, die die Kamera erreicht.

Um mit der höchsten Bildrate zu streamen, darf TriggerOverlap nicht Off sein. Setzen Sie es auf einen Overlap, den Ihre Kamera unterstützt - PreviousFrame oder ReadOut, siehe ihre Dokumentation - in einer Feature-Datei des Kameramoduls, ein Feature pro Zeile:

TriggerOverlap PreviousFrame

Tragen Sie die Datei in cameras[].featureFiles des Moduls ein. Der Cam Driver wendet sie jedes Mal an, wenn er die Kamera verbindet, bevor die Aufnahme beginnt, sodass sie auch für capture gilt. Ein Feature-Knoten unter features funktioniert ebenfalls, aber manche Kameras lehnen Trigger-Features ab, während sie aufnehmen, und der Wert geht verloren, wenn die Kamera erneut verbunden wird.

Was jeder Frame enthält

control/publish/output/stream/frame enthält eine FlatBuffers-Tabelle vom Typ stream_image, auf dem Data Layer registriert als types/hdvisionsystems/lumiscan-cam-driver/stream_image. Ihr kompiliertes Schema wird als bfbs/stream_image.bfbs installiert.

Feld Bedeutung

image.data

Die Pixel, Zeile für Zeile, ohne Padding.

image.width, image.height

Die Bildgröße in Pixeln.

image.pixel_type

Das Pixelformat, zum Beispiel Mono8.

lineage.steps

Woher das Bild stammt. Bei einem Kamerabild ist das ein Schritt, der der Kamera selbst:

* producer: die Adresse der Kamera, hdvisionsystems/lumiscan-cam-driver/<camera name>. * tag: das Tag des Moduls, setting/stream/tag, oder der Kameraname, wenn es leer ist. Siehe Das Tag. * run: wann der Stream gestartet wurde, in Mikrosekunden seit 1970. Jeder Start des Streams ist ein neuer Lauf. * sequence: die Nummer des Bildes im Lauf, ab 1. Eine Lücke bedeutet, dass Bilder unterwegs verloren gingen. * external_id: die eigene Bildnummer der Kamera (die GigE-Vision-Block-ID). Eine Lücke hier ohne Lücke in sequence bedeutet, dass Bilder zwischen Kamera und Cam Driver verloren gingen. * time_us: wann das Bild veröffentlicht wurde, in Mikrosekunden seit 1970. * settings_hash: die Einstellungen, mit denen das Bild aufgenommen wurde, siehe Der Einstellungs-Hash.

Die Anwendungen, die den Stream verarbeiten - AI Object Matching, Calibration - übernehmen die Lineage dessen, was sie empfangen, und fügen einen eigenen Schritt mit ihrem eigenen Tag hinzu. Ihre Ergebnisse benennen deshalb weiterhin das Kamerabild, aus dem sie stammen, über producer, run und sequence, und jeder Schritt sagt über sein tag, welches Modul ihn erzeugt hat.

Der Einstellungs-Hash

setting/settings-hash und der settings_hash jedes Frames identifizieren die Einstellungen, mit denen die Kamera arbeitet. Der Hash ändert sich, wenn sich eine davon ändert:

  • die Moduleinstellungen und die Feature-Dateien, mit denen die Kamera verbunden wurde;

  • jedes Kamera-Feature, das geschrieben wird, während die Kamera verbunden ist, zum Beispiel ExposureTime über input/exposure-time oder einen Feature-Knoten unter features, mit dem Wert, den die Kamera angenommen hat;

  • die Version des Cam Driver.

Einstellungen, die nur den Transport der Bilder betreffen, wie das Timeout oder die Paketgröße, ändern den Hash nicht. Wenn ein Hash zum ersten Mal auftritt, schreibt der Cam Driver die Einstellungen, für die er steht, nach settings-history/<camera name>-<hash>.json in seinem Konfigurationsordner, sodass ein in einem Ergebnis gefundener Hash später nachgeschlagen werden kann.

Eine Kamera nimmt die Bilder, die bereits unterwegs sind, mit den alten Einstellungen auf. Die Bilder, die direkt nach dem Schreiben eines Features eintreffen, können den neuen Hash tragen, obwohl sie vor der Änderung aufgenommen wurden.

Was der Hash nicht sagt

  • Dass, nicht was. Ein Frame trägt nur den Hash. Ein anderer Hash sagt, dass sich etwas geändert hat, womit die Bilder aufgenommen werden, nicht was sich geändert hat. Um das herauszufinden, vergleichen Sie die beiden Dateien in settings-history, die die Hashes benennen, von Hand. Die Dateien liegen auf dem Gerät, auf dem der Cam Driver lief.

  • Nur, was durch den Cam Driver geht. Der Hash folgt einem Feature-Knoten unter features, input/exposure-time und den Einstellungen und Feature-Dateien, mit denen die Kamera verbunden wurde. Er folgt nicht Werten, die die Kamera selbst ändert: Bei eingeschaltetem ExposureAuto folgt der Hash der Einstellung ExposureAuto, nicht den Belichtungszeiten, die die Kamera wählt.

Dass der Hash einer Änderung eines Kamera-Features folgt, wurde bisher nur in Unit-Tests geprüft, mit einem Ersatz für die Kamera, nicht mit einer echten Kamera. Bis das geschehen ist, verlassen Sie sich nicht allein auf den Einstellungs-Hash der Kamera, um zu erkennen, dass sich ein Kamera-Feature geändert hat.

Einen Stream betreiben

  1. Verbinden Sie die Kamera mit dem Handshake connect-camera. Siehe Verbindungsschritte.

  2. Setzen Sie die benötigten Kamera-Features, wie die Belichtungszeit, den Trigger-Modus und TriggerOverlap, bevor Sie den Stream starten. Siehe Die Kamera triggern.

  3. Abonnieren Sie control/publish/output/stream/frame.

  4. Setzen Sie control/publish/input/enable auf true und control/publish/input/keep-latest-output auf true, wenn Sie jedes Bild auch auf output/image haben möchten.

  5. Rufen Sie control/publish/execute auf, und warten Sie, bis control/publish/output/stream/active true ist.

  6. Triggern Sie die Kamera. Jedes Bild trifft auf control/publish/output/stream/frame ein.

  7. Zum Stoppen setzen Sie control/publish/input/enable auf false und rufen erneut control/publish/execute auf. control/publish/output/stream/active wird innerhalb des nächsten Zyklus false.

  8. Bevor Sie wieder aufnehmen, warten Sie, bis control/capture/ready true ist. Siehe Nach dem Stream.

Gut zu wissen:

  • Die Eingaben wirken erst bei execute, alle gemeinsam. Ein Programm kann sie daher in beliebiger Reihenfolge setzen, und nichts ändert sich halb.

  • Was execute angewendet hat, bleibt bis zum nächsten execute: Der Stream läuft, solange enable als true angewendet wurde und die Kamera verbunden ist. Wird er angewendet, während die Kamera getrennt ist, startet der Stream, sobald die Kamera verbunden ist.

  • connect-camera, disconnect-camera und reset stoppen einen laufenden Stream. Wurde enable als true angewendet, startet der Stream erneut, sobald die Kamera verbunden ist.

  • Kann der Stream nicht starten, bleibt control/publish/output/stream/active false, und der Grund wird in das Protokoll geschrieben. Es wird kein neuer Versuch unternommen, bis control/publish/execute erneut aufgerufen wird.

  • Eine Kamera ignoriert Trigger, die schneller kommen, als sie Bilder aufnehmen kann, ohne es zu melden. Wenn statistics/frames langsamer wächst als die Zahl der gesendeten Trigger, triggern Sie seltener oder setzen Sie einen Overlap, siehe Für die höchste Bildrate: TriggerOverlap.

  • Die Belichtungszeit auf input/exposure-time und das Inter-Packet-Delay werden nicht angewendet, solange der Stream läuft. Ändern Sie Kamera-Features nur, solange der Stream gestoppt ist.

Capture, während der Stream läuft

Der Stream und capture nutzen die Kamera auf unterschiedliche Weise, deshalb laufen sie nie gleichzeitig:

  • control/capture/ready ist false, solange der Stream läuft, sodass ein Programm, das den Handshake verwendet, wartet.

  • control/capture/execute antwortet mit DL_INVALID_OPERATION_MODE, solange der Stream läuft, und mit DL_TOO_MANY_OPERATIONS, während der Stream startet oder stoppt. Wiederholen Sie DL_INVALID_OPERATION_MODE nicht in einer Schleife. Stoppen Sie stattdessen den Stream und warten Sie auf capture/ready. Siehe Eine Methode ausführen.

  • Ein Capture-Request, der den Cam Driver erreicht, während der Stream läuft, wird mit Status -3 (invalidInput) abgelehnt, mit dem Text "capture refused: the image stream (experimental) is active". Er speichert keinen Fehler, es ist also kein reset nötig.

  • Ein Stream, der eingeschaltet wird, während ein Capture läuft, startet, sobald dieses Capture abgeschlossen ist. Er bricht ein Capture nie ab.

Gestreamte Bilder werden auf control/publish/output/stream/frame veröffentlicht. Sie erreichen output/image nur, solange keep-latest-output als true angewendet ist: Dann ersetzt jedes das dortige Bild, und output/package-identifier zählt es, wie es ein Capture zählt, fortlaufend ab der Nummer des letzten Capture. save speichert auch dann weiterhin das letzte Bild, das mit capture oder load aufgenommen wurde.

Nach dem Stream

Während des Streamings liefert die Kamera ihre Bilder in einem anderen Aufnahmemodus als dem, den capture verwendet. Um zurückzuschalten, trennt der Cam Driver die Kamera und verbindet sie erneut, wenn der Stream stoppt, und wendet dabei jede Verbindungseinstellung an, wie connect-camera es tut. capture/ready wird true, sobald das abgeschlossen ist. Bis dahin antwortet capture/execute mit DL_TOO_MANY_OPERATIONS.

Starten und Stoppen dauern deshalb unterschiedlich lang. Bei der von uns getesteten Kamera:

Schritt Dauer Hauptsächlich verwendet für

Stream starten

etwa 0,35 s

Umschalten des Aufnahmemodus der Kamera.

Stream stoppen, bis capture/ready wieder true ist

etwa 2,2 s

Erneutes Verbinden der Kamera: Öffnen des Geräts (etwa 0,8 s) und Lesen aller seiner GenICam- Features für den Data Layer (etwa 0,8 s).

Wechseln Sie deshalb so selten wie möglich zwischen Streaming und Capture. Ein Programm, das während des Streamings einzelne Bilder benötigt, kann sie von control/publish/output/stream/frame nehmen, statt den Stream zu stoppen, oder keep-latest-output anwenden und output/image lesen, wenn sich output/package-identifier ändert.

Gemessene Bildraten

Diese Werte wurden mit einer LUCID PHX016S (1440 x 1080, Mono8, Belichtung 1 ms) und LumiScan Keryx auf einem PC gemessen. Sie zeigen nur die Größenordnung: Ihre Kamera, Belichtungszeit, Ihr Netzwerk und Ihr Data Layer entscheiden, was Sie erreichen.

Sie wurden gemessen, als der Cam Driver die Kamera noch selbst triggerte, mit fester Rate. Ein Hardware-Trigger oder eine kontinuierlich laufende Kamera sollte dasselbe ergeben. Das Triggern mit control/trigger/execute fügt einen Methodenaufruf pro Bild hinzu; das wurde noch nicht gemessen.

Methode Gelieferte Bilder pro Sekunde

capture/execute in einer Schleife

etwa 34

Stream, TriggerOverlap Off

bis zu 63, jedes Bild geliefert

Stream, TriggerOverlap PreviousFrame

bis zu 66, jedes Bild geliefert

Was die Kamera selbst liefern kann (AcquisitionFrameRate)

71,7

Die Statistik lesen

Die Zähler unter control/publish/output/stream/statistics/ beginnen bei jedem Start des Streams bei null und werden etwa viermal pro Sekunde aktualisiert, solange er läuft.

Zähler Bedeutung

elapsed-ms

Millisekunden seit dem Start des Streams, gemessen vom Cam Driver. Teilen Sie einen Zähler dadurch, um eine Rate zu erhalten.

frames

Vollständige Bilder, die die Kamera geliefert hat.

incomplete-frames

Bilder, die die Kamera unvollständig geliefert hat. Sie werden nicht veröffentlicht.

lost-frames

Bilder, die den Cam Driver nie erreicht haben, ermittelt aus Lücken in den Bildnummern der Kamera.

published-frames

Bilder, die auf control/publish/output/stream/frame geschrieben wurden.