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