4.18. Wiele sensorów#
Garstka kamer OpenMV Cam łączy dwa sensory obrazu na tej samej płytce – najczęściej kamerę kolorową obok termicznego sensora FLIR® Lepton®, ale ten sam schemat dotyczy płytek typu kolor plus zdarzenia oraz dowolnego przyszłego sprzętu z dwoma sensorami. Każdy sensor ma własną matrycę pikseli, własną magistralę sterującą i obsługuje własny potok z własną częstotliwością ramek. API CSI rozszerza się, aby je obsłużyć, pozwalając aplikacji utworzyć po jednym obiekcie CSI dla każdego fizycznego sensora.
4.18.1. Wybór sensora#
Konstruktor CSI przyjmuje argument cid, który nazywa konkretny sensor na płytce. cid=-1 (wartość domyślna) wybiera sensor podstawowy; nazwane stałe cid wybierają sensor dodatkowy według identyfikatora układu:
import csi
csi_rgb = csi.CSI() # primary colour sensor
csi_thermal = csi.CSI(cid=csi.LEPTON) # FLIR® Lepton®
Każda instancja posiada własną konfigurację – format pikseli, rozmiar ramki, pokrętła ekspozycji / wzmocnienia, pulę bufora ramki – i jest resetowana, konfigurowana oraz odczytywana niezależnie od pozostałych. Stałe dla obsługiwanych sensorów dodatkowych (LEPTON, GENX320 oraz inne wymienione w dokumentacji CSI) nazywają układ, którego aplikacja oczekuje na porcie dodatkowym; sterownik przerywa konstrukcję, jeśli faktyczny układ się nie zgadza.
4.18.2. Przechwytywanie z obu sensorów#
Każdy sensor obsługuje swój potok przechwytywania niezależnie od drugiego – sensor kolorowy może dostarczać trzydzieści ramek na sekundę, podczas gdy Lepton® dostarcza dziewięć. Najprostszym sposobem obsługi tej rozbieżności jest pozwolenie, by pętlą sterował szybszy sensor, a wolniejszy sensor odczytywać w trybie nieblokującym, biorąc to, co jest gotowe, i pomijając iterację, gdy nic nie ma:
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
Blokujący snapshot() nadaje tempo pętli; wersja nieblokująca zwraca najnowszą ramkę termiczną, gdy świeża pojawiła się od czasu poprzedniego wywołania, a w przeciwnym razie None. Aplikacja działa nadal z częstotliwością ramek sensora kolorowego i otrzymuje ramkę termiczną zawsze, gdy Lepton® ją wyprodukuje.
Przeciwny wzorzec – dwa blokujące zrzuty obrazu jeden po drugim – również działa, ale pętla działa wtedy z wolniejszą z częstotliwości obu sensorów, a potok szybszego sensora zacina się pomiędzy iteracjami. Wybierz tę częstotliwość, którą faktycznie ma sterować dalsze przetwarzanie w aplikacji.
4.18.4. Wybór źródła strumienia#
Kamery z dwoma sensorami mają dwie instancje CSI, ale wciąż tylko jeden wspólny bufor ramki strumienia. Argument konstruktora wybiera, których ramek sensora używa podgląd:
csi_rgb = csi.CSI() # primary
csi_thermal = csi.CSI(cid=csi.LEPTON,
stream=True) # preview source
stream=True ustawia nazwaną instancję jako źródło. Bez argumentu stream= źródłem jest sensor podstawowy (cid=-1, wartość domyślna); instancje zbudowane z cid= sensora dodatkowego pozostają milczące na podglądzie, chyba że stream=True zostanie przekazane jawnie. Wywołania snapshot() na niewybranym sensorze nadal przechwytują ramki do buforów ramki tego sensora w normalny sposób – po prostu nie aktualizują podglądu.