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.