4.18. Múltiplos sensores#
Algumas OpenMV Cams combinam dois sensores de imagem na mesma placa – mais frequentemente uma câmara a cores juntamente com um sensor térmico FLIR® Lepton®, mas o mesmo padrão aplica-se às placas de cor mais eventos e a qualquer hardware futuro com dois sensores. Cada sensor tem o seu próprio array de pixels, o seu próprio barramento de controlo, e executa o seu próprio pipeline à sua própria cadência de fotogramas. A API CSI estende-se para os cobrir, permitindo que a aplicação instancie um objeto CSI por sensor físico.
4.18.1. Selecionar o sensor#
O construtor de CSI aceita um argumento cid que identifica um sensor específico na placa. cid=-1 (o padrão) seleciona o sensor primário; as constantes cid com nome identificam um sensor secundário pelo ID do chip:
import csi
csi_rgb = csi.CSI() # primary colour sensor
csi_thermal = csi.CSI(cid=csi.LEPTON) # FLIR® Lepton®
Cada instância possui a sua própria configuração – formato de pixel, resolução, controlos de exposição/ganho, pool de framebuffer – e é reiniciada, configurada e lida de forma independente das restantes. As constantes para os sensores secundários suportados (LEPTON, GENX320, e os demais listados na referência de CSI) identificam o chip que a aplicação espera na porta secundária; o driver falha na construção se o chip real não corresponder.
4.18.2. Capturar a partir de ambos os sensores#
Cada sensor executa o seu pipeline de captura de forma independente do outro – o sensor de cores pode entregar trinta fotogramas por segundo enquanto o Lepton® entrega nove. A forma mais direta de lidar com essa diferença é deixar o sensor mais rápido conduzir o ciclo e ler o sensor mais lento de forma não bloqueante, tomando o que estiver disponível e saltando a iteração quando não há 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
O snapshot() bloqueante define o ritmo do ciclo; o não bloqueante devolve o fotograma térmico mais recente quando um novo chegou desde a chamada anterior, ou None caso contrário. A aplicação continua a executar à cadência de fotogramas do sensor de cores e obtém um fotograma térmico sempre que o Lepton® produz um.
O padrão inverso – dois snapshots bloqueantes seguidos – também funciona, mas o ciclo passa então a executar à velocidade do mais lento dos dois sensores, com o pipeline do sensor mais rápido a parar entre iterações. Escolha a cadência que o processamento subsequente da aplicação realmente precisa de conduzir.
4.18.4. Selecionar a fonte de streaming#
As câmaras com dois sensores têm duas instâncias de CSI, mas ainda partilham um único framebuffer de streaming entre elas. Um argumento do construtor escolhe os fotogramas de qual sensor alimentam a pré-visualização:
csi_rgb = csi.CSI() # primary
csi_thermal = csi.CSI(cid=csi.LEPTON,
stream=True) # preview source
stream=True torna a instância identificada a fonte. Sem argumento stream=, o sensor primário (cid=-1, o padrão) é a fonte; instâncias construídas com cid= de um sensor secundário permanecem silenciosas na pré-visualização, a menos que stream=True seja passado explicitamente. As chamadas a snapshot() no sensor não selecionado continuam a capturar fotogramas para os framebuffers desse sensor normalmente – apenas não atualizam a pré-visualização.