4.18. Više senzora

Šačica OpenMV Cam kamera spaja dva slikovna senzora na istoj pločici – najčešće senzor u boji uz FLIR® Lepton® termalni senzor, ali isti se oblik primjenjuje na pločice s bojom i događajima te bilo koji budući hardver s dva senzora. Svaki senzor ima vlastito polje piksela, vlastitu upravljačku sabirnicu i pokreće vlastiti cjevovod pri vlastitoj brzini sličica. CSI API proširuje se da ih pokrije tako da aplikaciji dopušta instanciranje jednog CSI objekta po fizičkom senzoru.

4.18.1. Odabir senzora

Konstruktor CSI prima argument cid koji imenuje određeni senzor na pločici. cid=-1 (zadana vrijednost) odabire primarni senzor; imenovane konstante cid odabiru sekundarni prema ID-u čipa:

import csi

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

Svaka instanca posjeduje vlastitu konfiguraciju – format piksela, veličinu sličice, postavke ekspozicije / pojačanja, skup međuspremnika slike – te se resetira, konfigurira i čita neovisno o drugoj. Konstante za podržane sekundarne senzore (LEPTON, GENX320 i ostale navedene u referenci CSI) imenuju čip koji aplikacija očekuje na sekundarnom priključku; upravljački program ne uspijeva u izgradnji ako stvarni čip ne odgovara.

4.18.2. Snimanje s oba senzora

Svaki senzor pokreće svoj cjevovod snimanja neovisno o drugome – senzor u boji možda isporučuje trideset sličica u sekundi dok Lepton® isporučuje devet. Izravan način da se nosi s tim nesrazmjerom jest pustiti brži senzor da pokreće petlju i čitati sporiji senzor neblokirajuće, uzimajući ono što je spremno i preskačući iteraciju kada nema ničega:

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

Blokirajući snapshot() tempira petlju; neblokirajući vraća najnoviju termalnu sličicu kada je nova stigla od prethodnog poziva, a inače None. Aplikacija nastavlja raditi pri brzini sličica senzora u boji i dobiva termalnu sličicu kad god je Lepton® proizvede.

Suprotan obrazac – dvije blokirajuće snimke jedna za drugom – također radi, ali petlja tada radi pri sporijoj od brzina dvaju senzora, dok cjevovod bržeg senzora zastaje između iteracija. Odaberite onu brzinu koju zapravo želi pokretati naredna obrada u aplikaciji.

4.18.3. Reset na dijeljenim naponskim vodovima

Neke pločice s dva senzora pokreću oba čipa s jednog naponskog voda ili dijele liniju za reset. Na njima prvi reset() podiže napon na vodu i šalje impuls na dijeljeni signal; naknadni resetovi na ostalim instancama CSI trebaju proslijediti hard=False kako bi reprogramirali samo vlastiti čip bez povlačenja susjeda kroz reset:

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

hard=True na sekundarnom u ovom obliku ponovno bi resetirao primarni kao nuspojavu, poništavajući svaku postavku koju je aplikacija već uspostavila. Referentna stranica za svaku pločicu s dva senzora navodi jesu li naponski vodovi dijeljeni.

4.18.4. Odabir izvora toka

Kamere s dva senzora imaju dvije instance CSI, ali i dalje samo jedan međuspremnik slike toka između njih. Argument konstruktora bira čije sličice hrane pretpregled:

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

stream=True čini imenovanu instancu izvorom. Bez argumenta stream= izvor je primarni senzor (cid=-1, zadana vrijednost); instance izgrađene s cid= sekundarnog senzora ostaju nečujne na pretpregledu osim ako se izričito ne proslijedi stream=True. Pozivi snapshot() na neodabranom senzoru i dalje normalno snimaju sličice u međuspremnike slike tog senzora – samo ne ažuriraju pretpregled.