4.18. Múltiplos sensores¶
Algumas OpenMV Cams combinam dois sensores de imagem na mesma placa – mais comumente uma câmera colorida ao lado de um sensor térmico FLIR® Lepton®, mas o mesmo formato se aplica às placas de cor mais eventos e a qualquer hardware futuro de sensor duplo. Cada sensor tem sua própria matriz de pixels, seu próprio barramento de controle e executa seu próprio pipeline em sua própria taxa de quadros. A API CSI se estende para abrangê-los permitindo que a aplicação instancie um objeto CSI por sensor físico.
4.18.1. Selecionando qual sensor¶
O construtor de CSI recebe um argumento cid que nomeia um sensor específico na placa. cid=-1 (o padrão) seleciona o sensor primário; as constantes cid nomeadas selecionam um 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 sua própria configuração – formato de pixel, framesize, ajustes de exposição / ganho, pool de framebuffer – e é resetada, configurada e lida de forma independente da outra. As constantes para os sensores secundários suportados (LEPTON, GENX320 e as outras listadas na referência de CSI) nomeiam o chip que a aplicação espera na porta secundária; o driver faz a construção falhar se o chip real não corresponder.
4.18.2. Capturando de ambos os sensores¶
Cada sensor executa seu pipeline de captura de forma independente do outro – o sensor colorido pode entregar trinta quadros por segundo enquanto o Lepton® entrega nove. A maneira direta de lidar com essa diferença é deixar o sensor mais rápido conduzir o laço e ler o sensor mais lento de forma não bloqueante, pegando o que estiver pronto e pulando a iteração quando não houver 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 dita o ritmo do laço; o não bloqueante retorna o quadro térmico mais recente quando um novo chegou desde a chamada anterior, e None caso contrário. A aplicação continua executando na taxa de quadros do sensor colorido e obtém um quadro térmico sempre que o Lepton® produz um.
O padrão oposto – dois snapshots bloqueantes em sequência – também funciona, mas o laço passa a rodar na taxa do mais lento dos dois sensores, com o pipeline do sensor mais rápido travando entre as iterações. Escolha a taxa que o processamento subsequente da aplicação realmente quiser conduzir.
4.18.4. Selecionando a fonte do stream¶
Câmeras com dois sensores têm duas instâncias de CSI, mas ainda assim apenas um framebuffer de stream entre elas. Um argumento do construtor escolhe os quadros 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 nomeada a fonte. Sem um 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. Chamadas a snapshot() no sensor não selecionado ainda capturam quadros normalmente para os framebuffers daquele sensor – elas apenas não atualizam a pré-visualização.