4.18. Mehrere Sensoren

Einige wenige OpenMV Cams kombinieren zwei Bildsensoren auf demselben Board – am häufigsten eine Farbkamera neben einem FLIR® Lepton® Thermalsensor, aber dieselbe Form gilt für die Color-plus-Event-Boards und jede künftige Hardware mit zwei Sensoren. Jeder Sensor hat sein eigenes Pixelarray, seinen eigenen Steuerbus und betreibt seine eigene Pipeline mit seiner eigenen Bildrate. Die CSI-API erweitert sich auf diese Konfiguration, indem sie die Anwendung pro physischem Sensor ein CSI-Objekt instanziieren lässt.

4.18.1. Auswahl des Sensors

Der CSI-Konstruktor nimmt ein cid-Argument entgegen, das einen bestimmten Sensor auf dem Board benennt. cid=-1 (der Standard) wählt den primären Sensor; die benannten cid-Konstanten wählen einen sekundären Sensor anhand der Chip-ID:

import csi

csi_rgb     = csi.CSI()                    # primary colour sensor
csi_thermal = csi.CSI(cid=csi.LEPTON)      # FLIR® Lepton®

Jede Instanz besitzt ihre eigene Konfiguration – Pixelformat, Framesize, Belichtungs- / Verstärkungsregler, Framebuffer-Pool – und wird unabhängig von der anderen zurückgesetzt, konfiguriert und ausgelesen. Die Konstanten für die unterstützten sekundären Sensoren (LEPTON, GENX320 und die anderen, die in der CSI-Referenz aufgeführt sind) benennen den Chip, den die Anwendung am sekundären Port erwartet; der Treiber lässt die Konstruktion fehlschlagen, wenn der tatsächliche Chip nicht übereinstimmt.

4.18.2. Aufnahme von beiden Sensoren

Jeder Sensor betreibt seine Aufnahme-Pipeline unabhängig vom anderen – der Farbsensor könnte dreißig Einzelbilder pro Sekunde liefern, während der Lepton® neun liefert. Der unkomplizierte Weg, mit dieser Diskrepanz umzugehen, besteht darin, den schnelleren Sensor die Schleife antreiben zu lassen und den langsameren Sensor nicht-blockierend auszulesen, wobei man nimmt, was bereit ist, und die Iteration überspringt, wenn nichts vorliegt:

import csi

csi_rgb     = csi.CSI()
csi_thermal = csi.CSI(cid=csi.LEPTON)

csi_rgb.reset()                        # powers the rail, pulses RESET
csi_rgb.pixformat(csi.RGB565)
csi_rgb.framesize(csi.QVGA)

csi_thermal.reset(hard=False)          # I2C reconfigure only
csi_thermal.pixformat(csi.GRAYSCALE)
csi_thermal.framesize(csi.QQVGA)

while True:
    rgb_img     = csi_rgb.snapshot()                  # blocks for next colour frame
    thermal_img = csi_thermal.snapshot(blocking=False)  # returns None if not ready
    if thermal_img is not None:
        # process aligned colour + thermal pair
        pass
    else:
        # process colour only on this iteration
        pass

Der blockierende snapshot() taktet die Schleife; der nicht-blockierende gibt das aktuellste Thermal-Einzelbild zurück, wenn seit dem vorherigen Aufruf ein frisches eingetroffen ist, und andernfalls None. Die Anwendung läuft weiter mit der Bildrate des Farbsensors und erhält ein Thermal-Einzelbild, wann immer der Lepton® eines produziert.

Das umgekehrte Muster – zwei blockierende Schnappschüsse hintereinander – funktioniert ebenfalls, aber die Schleife läuft dann mit der langsameren der beiden Sensorraten, wobei die Pipeline des schnelleren Sensors zwischen den Iterationen stockt. Wähle die Rate, die die nachgelagerte Verarbeitung der Anwendung tatsächlich antreiben soll.

4.18.3. Reset bei gemeinsamen Spannungsversorgungen

Manche Boards mit zwei Sensoren betreiben beide Chips an einer einzigen Spannungsversorgung oder teilen sich eine Reset-Leitung. Auf diesen bringt der erste reset() die Versorgung hoch und gibt einen Impuls auf das gemeinsame Signal; nachfolgende Resets auf den anderen CSI-Instanzen sollten hard=False übergeben, sodass sie nur ihren eigenen Chip neu programmieren, ohne den Nachbarn durch einen Reset zu ziehen:

csi_rgb.reset()                        # primary -- powers the rail, pulses RESET
csi_thermal.reset(hard=False)          # secondary -- I2C reconfigure only

Ein hard=True auf einem sekundären Sensor in dieser Konfiguration würde als Nebeneffekt den primären erneut zurücksetzen und jede Einrichtung rückgängig machen, die die Anwendung bereits vorgenommen hatte. Die Referenzseite für jedes Board mit zwei Sensoren weist darauf hin, ob die Versorgungen gemeinsam genutzt werden.

4.18.4. Auswahl der Stream-Quelle

Kameras mit zwei Sensoren haben zwei CSI-Instanzen, aber dennoch nur einen einzigen Stream-Framebuffer zwischen ihnen. Ein Konstruktorargument wählt aus, welche Einzelbilder des Sensors die Vorschau speisen:

csi_rgb     = csi.CSI()                    # primary
csi_thermal = csi.CSI(cid=csi.LEPTON,
                      stream=True)         # preview source

stream=True macht die benannte Instanz zur Quelle. Ohne stream=-Argument ist der primäre Sensor (cid=-1, der Standard) die Quelle; Instanzen, die mit cid= eines sekundären Sensors erstellt wurden, bleiben in der Vorschau stumm, sofern nicht stream=True explizit übergeben wird. Aufrufe von snapshot() auf dem nicht ausgewählten Sensor nehmen weiterhin normal Einzelbilder in die Framebuffer dieses Sensors auf – sie aktualisieren lediglich nicht die Vorschau.