4.18. Múltiples sensores¶
Unas pocas OpenMV Cam combinan dos sensores de imagen en la misma placa – lo más habitual es una cámara de color junto a un sensor térmico FLIR® Lepton®, pero el mismo esquema se aplica a las placas de color más eventos y a cualquier futuro hardware de doble sensor. Cada sensor tiene su propia matriz de píxeles, su propio bus de control y ejecuta su propia canalización a su propia frecuencia de fotogramas. La API CSI se amplía para cubrirlos permitiendo que la aplicación instancie un objeto CSI por cada sensor físico.
4.18.1. Seleccionar qué sensor¶
El constructor CSI recibe un argumento cid que nombra un sensor específico de la placa. cid=-1 (el valor predeterminado) selecciona el sensor principal; las constantes cid con nombre seleccionan un secundario por ID de chip:
import csi
csi_rgb = csi.CSI() # primary colour sensor
csi_thermal = csi.CSI(cid=csi.LEPTON) # FLIR® Lepton®
Cada instancia es propietaria de su propia configuración – formato de píxel, tamaño de fotograma, controles de exposición / ganancia, grupo de búferes de fotogramas – y se reinicia, configura y lee independientemente de la otra. Las constantes para los sensores secundarios admitidos (LEPTON, GENX320 y las demás que figuran en la referencia de CSI) nombran el chip que la aplicación espera en el puerto secundario; el controlador falla la construcción si el chip real no coincide.
4.18.2. Capturar desde ambos sensores¶
Cada sensor ejecuta su canalización de captura independientemente del otro – el sensor de color podría entregar treinta fotogramas por segundo mientras que el Lepton® entrega nueve. La forma directa de gestionar ese desajuste es dejar que el sensor más rápido gobierne el bucle y leer el sensor más lento de manera no bloqueante, tomando lo que esté listo y omitiendo la iteración cuando no haya nada:
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
La snapshot() bloqueante marca el ritmo del bucle; la no bloqueante devuelve el fotograma térmico más reciente cuando ha llegado uno nuevo desde la llamada anterior, y None en caso contrario. La aplicación sigue ejecutándose a la frecuencia de fotogramas del sensor de color y obtiene un fotograma térmico cada vez que el Lepton® produce uno.
El patrón opuesto – dos capturas bloqueantes una tras otra – también funciona, pero entonces el bucle se ejecuta a la frecuencia del más lento de los dos sensores, y la canalización del sensor más rápido se detiene entre iteraciones. Elija la frecuencia que el procesamiento posterior de la aplicación realmente quiera gobernar.
4.18.4. Seleccionar la fuente del flujo¶
Las cámaras con dos sensores tienen dos instancias de CSI pero aun así un solo búfer de fotogramas de flujo entre ambas. Un argumento del constructor elige qué fotogramas de sensor alimentan la vista previa:
csi_rgb = csi.CSI() # primary
csi_thermal = csi.CSI(cid=csi.LEPTON,
stream=True) # preview source
stream=True convierte a la instancia nombrada en la fuente. Sin el argumento stream=, el sensor principal (cid=-1, el valor predeterminado) es la fuente; las instancias construidas con cid= de un sensor secundario permanecen silenciosas en la vista previa a menos que se pase explícitamente stream=True. Las llamadas a snapshot() en el sensor no seleccionado siguen capturando fotogramas en los búferes de fotogramas de ese sensor con normalidad – simplemente no actualizan la vista previa.