4.18. Több érzékelő

Néhány OpenMV Cam két képérzékelőt párosít ugyanazon a kártyán – leggyakrabban egy színes kamerát egy FLIR® Lepton® hőérzékelő mellett, de ugyanez a forma érvényes a színes-plusz-esemény kártyákra és bármely jövőbeli kétérzékelős hardverre is. Minden érzékelőnek saját képpontmátrixa, saját vezérlőbusza van, és saját képkockasebességén futtatja saját folyamatát. A CSI API úgy bővül ki rájuk, hogy lehetővé teszi az alkalmazás számára, hogy fizikai érzékelőnként egy-egy CSI objektumot példányosítson.

4.18.1. Az érzékelő kiválasztása

A CSI konstruktor egy cid argumentumot vesz át, amely egy adott érzékelőt nevez meg a kártyán. A cid=-1 (az alapértelmezett) az elsődleges érzékelőt választja ki; a megnevezett cid konstansok chip-azonosító alapján választanak ki egy másodlagosat:

import csi

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

Minden példány saját konfigurációval rendelkezik – pixelformátum, framesize, expozíciós / erősítési vezérlők, képkocka-puffer készlet –, és a másiktól függetlenül kerül visszaállításra, konfigurálásra és kiolvasásra. A támogatott másodlagos érzékelők konstansai (LEPTON, GENX320 és a többi, amelyek a CSI referenciában szerepelnek) azt a chipet nevezik meg, amelyet az alkalmazás a másodlagos porton elvár; a meghajtó meghiúsítja a létrehozást, ha a tényleges chip nem egyezik.

4.18.2. Rögzítés mindkét érzékelőből

Minden érzékelő a másiktól függetlenül futtatja rögzítési folyamatát – a színes érzékelő másodpercenként harminc képkockát szállíthat, miközben a Lepton® kilencet. A legegyszerűbb módja ennek az eltérésnek a kezelésére az, ha a gyorsabb érzékelő hajtja a ciklust, a lassabb érzékelőt pedig nem blokkolóan olvassuk, átvéve azt, ami éppen kész, és kihagyva az iterációt, amikor semmi sincs:

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

A blokkoló snapshot() ütemezi a ciklust; a nem blokkoló a legutóbbi hőképkockát adja vissza, ha az előző hívás óta egy friss érkezett, egyébként pedig None értéket. Az alkalmazás a színes érzékelő képkockasebességén fut tovább, és kap egy hőképkockát, valahányszor a Lepton® előállít egyet.

Az ellentétes minta – két blokkoló pillanatkép közvetlenül egymás után – szintén működik, de a ciklus ekkor a két érzékelő közül a lassabb sebességén fut, miközben a gyorsabb érzékelő folyamata megáll az iterációk között. Válaszd azt a sebességet, amelyet az alkalmazás utólagos feldolgozása valóban hajtani akar.

4.18.3. Visszaállítás közös tápsínek esetén

Egyes kétérzékelős kártyák mindkét chipet egyetlen tápsínről futtatják, vagy közös visszaállítóvonalon osztoznak. Ezeken az első reset() felhozza a sínt és impulzust ad a közös jelnek; a többi CSI példányon végzett későbbi visszaállításoknak a hard=False értéket kell átadniuk, hogy csak a saját chipjüket programozzák újra anélkül, hogy a szomszédot is végighúznák egy visszaállításon:

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

Egy hard=True egy másodlagoson ebben a formában mellékhatásként újra visszaállítaná az elsődlegeset, semmissé téve minden beállítást, amelyet az alkalmazás már átadott. Az egyes kétérzékelős kártyák referenciaoldala kiemeli, hogy a sínek közösek-e.

4.18.4. A folyam forrásának kiválasztása

A két érzékelővel rendelkező kamerák két CSI példánnyal bírnak, de még mindig csak egyetlen folyam képkocka-pufferrel közöttük. Egy konstruktorargumentum választja ki, hogy melyik érzékelő képkockái táplálják az előnézetet:

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

A stream=True a megnevezett példányt teszi forrássá. A stream= argumentum nélkül az elsődleges érzékelő (cid=-1, az alapértelmezett) a forrás; a másodlagos érzékelő cid= értékével létrehozott példányok némán maradnak az előnézeten, hacsak nem adjuk át kifejezetten a stream=True értéket. A nem kiválasztott érzékelőn végzett snapshot() hívások továbbra is normál módon rögzítik a képkockákat az adott érzékelő képkocka-puffereibe – csak éppen nem frissítik az előnézetet.