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.