4.18. Sensori multipli¶
Alcune OpenMV Cam abbinano due sensori di immagine sulla stessa scheda – più comunemente una camera a colori affiancata a un sensore termico FLIR® Lepton®, ma la stessa struttura vale per le schede colore-più-eventi e per qualsiasi futuro hardware a doppio sensore. Ogni sensore ha la propria matrice di pixel, il proprio bus di controllo ed esegue la propria pipeline al proprio frame rate. L’API CSI si estende per gestirli consentendo all’applicazione di istanziare un oggetto CSI per ogni sensore fisico.
4.18.1. Selezione del sensore¶
Il costruttore CSI accetta un argomento cid che identifica un sensore specifico sulla scheda. cid=-1 (il valore predefinito) seleziona il sensore primario; le costanti cid denominate selezionano un secondario tramite chip ID:
import csi
csi_rgb = csi.CSI() # primary colour sensor
csi_thermal = csi.CSI(cid=csi.LEPTON) # FLIR® Lepton®
Ogni istanza possiede la propria configurazione – formato dei pixel, framesize, regolazioni di esposizione / guadagno, pool di framebuffer – e viene resettata, configurata e letta in modo indipendente dall’altra. Le costanti per i sensori secondari supportati (LEPTON, GENX320 e le altre elencate nel riferimento CSI) identificano il chip che l’applicazione si aspetta sulla porta secondaria; il driver fa fallire la costruzione se il chip effettivo non corrisponde.
4.18.2. Acquisizione da entrambi i sensori¶
Ogni sensore esegue la propria pipeline di acquisizione in modo indipendente dall’altro – il sensore a colori potrebbe fornire trenta frame al secondo mentre il Lepton® ne fornisce nove. Il modo più semplice per gestire questa discrepanza è lasciare che il sensore più veloce guidi il ciclo e leggere il sensore più lento in modo non bloccante, prendendo ciò che è pronto e saltando l’iterazione quando non c’è nulla:
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
Il metodo bloccante snapshot() scandisce il ritmo del ciclo; quello non bloccante restituisce il frame termico più recente quando ne è arrivato uno nuovo dalla chiamata precedente, e None altrimenti. L’applicazione continua a funzionare al frame rate del sensore a colori e ottiene un frame termico ogni volta che il Lepton® ne produce uno.
Il pattern opposto – due snapshot bloccanti consecutivi – funziona anch’esso, ma il ciclo gira allora alla velocità del più lento dei due sensori, con la pipeline del sensore più veloce in stallo tra le iterazioni. Scegli la velocità che l’elaborazione a valle dell’applicazione vuole effettivamente guidare.
4.18.4. Selezione della sorgente di streaming¶
Le camere con due sensori hanno due istanze CSI ma comunque un solo framebuffer di streaming tra di esse. Un argomento del costruttore sceglie i frame di quale sensore alimentano l’anteprima:
csi_rgb = csi.CSI() # primary
csi_thermal = csi.CSI(cid=csi.LEPTON,
stream=True) # preview source
stream=True rende l’istanza denominata la sorgente. Senza l’argomento stream= la sorgente è il sensore primario (cid=-1, il valore predefinito); le istanze costruite con cid= di un sensore secondario rimangono silenti sull’anteprima a meno che non venga passato esplicitamente stream=True. Le chiamate a snapshot() sul sensore non selezionato acquisiscono comunque i frame nei framebuffer di quel sensore normalmente – semplicemente non aggiornano l’anteprima.