Câmera de Eventos Multiespectral¶
O Módulo de Câmera de Eventos Multiespectral combina o sensor de eventos GENX320 com um sensor de cor PAG7936 de global-shutter de 1 MP em um único módulo — um pipeline sincronizado de eventos + cor para rastreamento de objetos em alta velocidade, rastreamento de LEDs, fluxo de fluidos e outras cenas dinâmicas.
Para o datasheet completo, fotos e informações de compra, consulte a página do produto Multispectral Event Camera.
Nota
Suportado apenas na OpenMV N6.
Destaques¶
Sensor de eventos de 320x320, faixa dinâmica >140 dB, histogramas a 375 Hz+
PAG7936 a cores: 1280x800 @ 120 FPS, 640x400 @ 240 FPS
Timestamps de eventos sincronizados com gatilho de exposição compartilhado
Enxerga abaixo de 5 lux sem exposição automática
Consumo a partir de ~3 mW para streaming de eventos
Voltado para rastreamento em alta velocidade, rastreamento de LEDs e fluxo de fluidos/partículas
Uso¶
O sensor de cor e o sensor de eventos GENX320 recebem cada um sua própria instância de csi.CSI. A primeira chamada usa por padrão o sensor primário (o PAG7936); a segunda se vincula ao GENX320 passando cid= csi.GENX320. Faça um hard-reset no sensor de cor com csi.CSI.reset (hard=True) para energizar o trilho, e configure o GENX320 com hard=False para que seu driver apenas reprograme o chip sem reativar o reset.
O GENX320 produz 320x320 em modo de histograma; o PAG7936 em csi.QVGA produz 320x200. A sobreposição básica abaixo recorta as 120 linhas inferiores do quadro do GENX320. Use a transformação de homografia (abaixo) para uma sobreposição ajustada ou um framesize maior do PAG7936.
Dois buffers de rascunho permanecem constantes ao longo do loop de quadros — uma paleta alfa de 256x1 armazenada como uma image.Image, de modo que os pixels do histograma na linha de base de cinza médio (128) se tornem transparentes e tanto os realces de eventos ON quanto as sombras de eventos OFF se tornem opacos, e um frame buffer do GENX320 pré-alocado com image.Image, para que csi.CSI.snapshot (blocking=False, image=...) possa preenchê-lo no lugar a cada iteração sem realocar:
import time
import csi
import image
import math
# V-shaped alpha: pixels far from the baseline 128 become opaque.
alpha_pal = image.Image(256, 1, image.GRAYSCALE)
for i in range(256):
alpha_pal[i] = int(math.pow(abs(i - 128) / 128.0, 2) * 255)
# Setup the color camera sensor.
csi0 = csi.CSI()
csi0.reset(hard=True) # force hardware reset.
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)
csi1 = csi.CSI(cid=csi.GENX320)
csi1.reset(hard=False) # no hardware reset - just configure GENX320
csi1.pixformat(csi.GRAYSCALE)
csi1.framesize((320, 320))
csi1.brightness(128) # histogram baseline (default)
csi1.contrast(64) # per-event step
clock = time.clock()
img1 = image.Image(csi1.width(), csi1.height(), csi1.pixformat())
while True:
clock.tick()
img0 = csi0.snapshot()
csi1.snapshot(blocking=False, image=img1)
img0.draw_image(img1, 0, 0, color_palette=image.PALETTE_EVT_LIGHT,
alpha_palette=alpha_pal,
hint=image.BILINEAR)
print(clock.fps())
Cada iteração captura um snapshot de cor com bloqueio e um snapshot do GENX320 sem bloqueio. Image.draw_image então compõe os dois: color_palette= image.PALETTE_EVT_LIGHT (ou image.PALETTE_EVT_DARK para um fundo escuro) mapeia o histograma em escala de cinza do GENX320 em uma rampa de cores, alpha_palette= mescla cada pixel usando o mapa alfa em forma de V para que as regiões silenciosas da cena deixem passar a imagem de cor, e hint= image.BILINEAR suaviza o aumento de escala quando o sensor de cor opera em resolução mais alta que o GENX320.
Os ioctls de presets de bias, filtro AFK, calibração de hot-pixel e filtro STC do GENX320 funcionam todos da mesma forma nesta configuração de câmera dupla — chame-os em csi1 após csi.CSI.reset. Veja as seções abaixo para detalhes.
Alinhamento acelerado por GPU¶
Image.draw_image aceita um argumento transform= — uma matriz de homografia 3x3 como um array 2-D de ulab.numpy. Na OpenMV N6, a GPU executa a projeção por pixel durante o mesmo desenho, de modo que o quadro do GENX320 pode ser realinhado à perspectiva da câmera de cor sem uma passagem de warp separada — útil quando os dois sensores têm óptica ou campos de visão ligeiramente diferentes, ou quando a câmera de cor opera em resolução mais alta. Calibre a matriz por câmera com a ferramenta GenX320 Overlay Calibration, que exibe um tabuleiro de xadrez piscante para que o sensor de eventos produza eventos de canto sem qualquer movimento físico:
import time
import csi
import image
from ulab import numpy as np
import math
# Calibration matrix from the GenX320 Overlay Calibration tool.
m = np.array([
[2.000000, 0.000000, 0.000000],
[0.000000, 2.000000, 80.000000],
[0.000000, 0.000000, 1.000000],
])
alpha_pal = image.Image(256, 1, image.GRAYSCALE)
for i in range(256):
alpha_pal[i] = int(math.pow(abs(i - 128) / 128.0, 2) * 255)
# Setup the color camera sensor.
csi0 = csi.CSI()
csi0.reset(hard=True)
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)
csi1 = csi.CSI(cid=csi.GENX320)
csi1.reset(hard=False)
csi1.pixformat(csi.GRAYSCALE)
csi1.framesize((320, 320))
csi1.brightness(128)
csi1.contrast(64)
clock = time.clock()
img1 = image.Image(csi1.width(), csi1.height(), csi1.pixformat())
while True:
clock.tick()
img0 = csi0.snapshot()
csi1.snapshot(blocking=False, image=img1)
img0.draw_image(img1, 0, 0, color_palette=image.PALETTE_EVT_LIGHT,
alpha_palette=alpha_pal,
hint=image.BILINEAR,
transform=m)
print(clock.fps())
Esta variante executa a câmera de cor em csi.VGA (640x480) e o GENX320 em sua resolução nativa de 320x320 — a homografia projeta o quadro menor do GENX320 dentro do quadro maior de cor como parte do desenho, de modo que o fator de aumento de escala é incorporado à própria matriz em vez de ser aplicado separadamente.
Detalhes da câmera de eventos¶
O GENX320 é um sensor de visão baseado em eventos — em vez de ler toda a matriz de 320x320 em um clock de quadro fixo, cada pixel reporta “eventos” assíncronos no instante em que detecta uma mudança de brilho. Cada evento carrega uma coordenada X/Y, uma polaridade ON/OFF (claro→escuro ou escuro→claro) e um timestamp em microssegundos. É daí que vêm a precisão temporal de microssegundos do sensor, a ausência de borramento por movimento, a faixa dinâmica muito alta e o consumo de energia proporcional à atividade. Cenas estáticas não geram dados.
O firmware da OpenMV expõe o GENX320 através de csi.CSI com cid= csi.GENX320. Dois modos de operação estão disponíveis:
Modo de histograma (padrão) — os eventos são acumulados no chip em bins por pixel e reportados como um quadro em escala de cinza de 320x320 a uma taxa configurável (~20-350 FPS). O sensor se comporta como uma câmera comum, de modo que todas as rotinas padrão de processamento de imagem (
Image.find_blobs, paletas, etc.) funcionam diretamente.Modo de evento — os eventos brutos são transmitidos para um
ndarraynumpy com timestamps completos em microssegundos, para aplicações que precisam do detalhe temporal em vez de um quadro pré-agrupado.
Modo de histograma¶
No modo de histograma, o GENX320 produz quadros em escala de cinza em que cada pixel codifica a atividade recente de eventos naquele local. Pixels acima da linha de base de brilho são eventos ON (brilho aumentando), abaixo são eventos OFF (brilho diminuindo). O brilho de linha de base padrão é 128 e o passo de contraste por evento é 16 — aumente o contraste para fazer os eventos se destacarem:
import csi
import time
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.pixformat(csi.GRAYSCALE)
csi0.framesize((320, 320))
csi0.brightness(128) # baseline (default 128)
csi0.contrast(16) # per-event step
csi0.framerate(50) # 20-350 FPS
clock = time.clock()
while True:
clock.tick()
img = csi0.snapshot()
print(clock.fps())
csi.CSI.brightness, csi.CSI.contrast e csi.CSI.framerate são os três botões que moldam a saída do histograma.
Saída colorizada¶
Defina csi.CSI.color_palette como image.PALETTE_EVT_LIGHT para um fundo claro ou image.PALETTE_EVT_DARK para um escuro — o driver emite quadros RGB565 usando a paleta diretamente:
csi0.color_palette(image.PALETTE_EVT_LIGHT)
Calibração de hot-pixel¶
Sensores de eventos acumulam “hot pixels” que disparam espuriamente. Execute csi.IOCTL_GENX320_CALIBRATE contra uma cena estática para desabilitá-los. O driver constrói uma contagem de acertos por pixel de 320x320, calcula a média e o desvio padrão, e desabilita qualquer pixel cuja contagem esteja acima de mean + sigma * stddev — então os pixels desabilitados param de emitir eventos no nível do sensor.
Dois parâmetros controlam a calibração:
event_count— quantos eventos contabilizar antes de calcular as estatísticas. O loop captura quadros até que o total acumulado de eventos ultrapasse esse orçamento. Contagens mais altas dão uma estimativa mais confiável ao custo de um tempo de calibração mais longo.10000é um ponto de partida razoável.sigma— multiplicador de limiar sobre o desvio padrão. Valores mais baixos são mais agressivos (mais pixels desabilitados); valores mais altos são mais conservadores.0.5é um bom padrão.
Aponte o sensor para uma cena estática primeiro, para que quaisquer eventos gerados por movimento não sejam contabilizados contra pixels que estão realmente em bom estado:
csi0.snapshot(time=5000) # let the user steady the camera
disabled = csi0.ioctl(csi.IOCTL_GENX320_CALIBRATE, 10000, 0.5)
print(f"disabled {disabled} hot pixels")
Filtro anti-cintilação (AFK)¶
Fontes de luz periódicas (fluorescentes, telas acionadas por LED) geram volumes enormes de eventos redundantes. O filtro AFK rejeita eventos cujo pixel alterna em uma frequência dentro de uma banda — habilite-o via csi.IOCTL_GENX320_SET_AFK com as bordas da banda em hertz:
csi0.ioctl(csi.IOCTL_GENX320_SET_AFK, 1, 130, 160) # 130-160 Hz
csi0.ioctl(csi.IOCTL_GENX320_SET_AFK, 0) # disable
Presets de bias¶
Cada pixel do GenX320 executa um front-end analógico com vários biases configuráveis. Eles governam em conjunto a sensibilidade, o ruído, a largura de banda do pixel e a taxa de eventos — a combinação certa depende da cena. Os biases individuais são:
DIFF_ON — o limiar de contraste do comparador positivo. Um pixel emite um evento ON quando sua log-iluminação aumentou nessa quantidade. Mais baixo = mais sensível a transições para mais claro.
DIFF_OFF — o limiar de contraste do comparador negativo (a contraparte simétrica para eventos OFF). Mais baixo = mais sensível a transições para mais escuro.
FO — a frequência de corte passa-baixas do pixel. Mais alto = largura de banda do pixel mais ampla (resposta mais rápida, menor latência), mas mais atividade de ruído de fundo.
HPF — a frequência de corte passa-altas. Mais alto = rejeição mais forte de mudanças lentas de brilho; apenas transições rápidas alcançam os comparadores. Útil para ignorar a deriva ambiente.
REFR — o período refratário. Após um pixel disparar, ele permanece em reset por esse tempo antes de poder disparar novamente. Mais alto = tempo morto mais longo, útil para limitar a taxa de eventos por pixel.
Após csi.CSI.reset, o driver aplica csi.GENX320_BIASES_LOW_NOISE, e não csi.GENX320_BIASES_DEFAULT — os padrões do datasheet emitem uma taxa de eventos de fundo muito mais alta, então LOW_NOISE é usado como ponto de partida para manter o stream silencioso. Chame csi.IOCTL_GENX320_SET_BIASES com um preset diferente quando a aplicação precisar de mais sensibilidade ou largura de banda.
csi.IOCTL_GENX320_SET_BIASES aplica um de cinco presets:
csi.GENX320_BIASES_DEFAULT— padrões do datasheet do GenX320. Sensibilidade, ruído e largura de banda equilibrados para cenas gerais.csi.GENX320_BIASES_LOW_LIGHT— ambos os limiares de contraste afrouxados para maior sensibilidade, FO reduzido para manter o ruído baixo, e HPF ajustado para 0 para que mudanças lentas de brilho ainda sejam registradas — uma cena de pouca luz gera poucos eventos por si só, então queremos que o maior número possível chegue até nós.csi.GENX320_BIASES_ACTIVE_MARKER— ajustado para rastrear LEDs piscantes de alto contraste. Limiares de contraste elevados para que apenas transições nítidas disparem; FO e HPF aumentados ao máximo para maximizar a largura de banda do pixel e rejeitar qualquer deriva ambiente lenta; REFR reduzido a 0 para que cada borda de piscada seja capturada consecutivamente. O resultado: um stream que é quase só bordas de LED, fácil de rastrear.csi.GENX320_BIASES_LOW_NOISE— padrão do driver. Ambos os limiares de contraste elevados em relação aDEFAULT(menos sensível) e FO reduzido (pixel mais lento = pixel mais silencioso). Melhor para cenas estáticas ou lentas onde eventos falsos dominariam de outra forma.csi.GENX320_BIASES_HIGH_SPEED— FO aumentado para que cada pixel possa responder mais rápido, HPF elevado para rejeitar deriva lenta de brilho, e REFR elevado para que uma única borda em movimento rápido não inunde a leitura — o tempo morto mais longo mantém o volume de eventos limitado sob movimento intenso.
Sobrescreva biases individuais com csi.IOCTL_GENX320_SET_BIAS mais um de csi.GENX320_BIAS_DIFF_ON, csi.GENX320_BIAS_DIFF_OFF, csi.GENX320_BIAS_FO, csi.GENX320_BIAS_HPF ou csi.GENX320_BIAS_REFR e um valor de DAC. Cada bias é definido de forma independente — escolha um preset como ponto de partida e depois ajuste os biases que sua cena precisar:
csi0.ioctl(csi.IOCTL_GENX320_SET_BIASES, csi.GENX320_BIASES_LOW_LIGHT)
csi0.ioctl(csi.IOCTL_GENX320_SET_BIAS, csi.GENX320_BIAS_HPF, 20)
Rastreamento¶
Como a saída do modo de histograma é apenas uma imagem em escala de cinza, o rastreamento de blobs comum funciona diretamente. Para rastrear um LED de marcador ativo, carregue o preset de bias de marcador ativo e encontre blobs na extremidade clara do histograma:
import csi
import time
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.pixformat(csi.GRAYSCALE)
csi0.framesize((320, 320))
csi0.brightness(128)
csi0.contrast(16)
csi0.framerate(200)
csi0.ioctl(csi.IOCTL_GENX320_SET_BIASES, csi.GENX320_BIASES_ACTIVE_MARKER)
clock = time.clock()
while True:
clock.tick()
img = csi0.snapshot()
for blob in img.find_blobs([(120, 140)], invert=True,
pixels_threshold=2, area_threshold=4,
merge=True):
img.draw_detection(blob)
print(clock.fps())
Modo de evento¶
O modo de evento contorna o histograma no chip e transmite eventos brutos para um ndarray numpy. Cada evento é uma linha de seis colunas uint16:
[0]tipo de evento — veja abaixo[1]timestamp em segundos[2]timestamp em milissegundos[3]timestamp em microssegundos[4]coordenada X, 0-319[5]coordenada Y, 0-319
O driver emite seis tipos de evento na coluna [0]:
csi.PIX_OFF_EVENT— um pixel detectou uma diminuição de brilho (o limiar do comparadorDIFF_OFFfoi cruzado). X/Y apontam para o pixel que disparou.csi.PIX_ON_EVENT— um pixel detectou um aumento de brilho (o limiarDIFF_ONfoi cruzado). X/Y apontam para o pixel.csi.EXT_TRIGGER_FALLING— o pino de gatilho externo do sensor viu uma borda de descida. X/Y não são usados.csi.EXT_TRIGGER_RISING— o pino de gatilho externo do sensor viu uma borda de subida. X/Y não são usados.csi.RST_TRIGGER_FALLING— gatilho de reset de pixel, borda de descida. X/Y não são usados. Não é gerado pelo firmware no momento.csi.RST_TRIGGER_RISING— gatilho de reset de pixel, borda de subida. X/Y não são usados. Não é gerado pelo firmware no momento.
A entrada de gatilho externo do GENX320 está conectada à linha de frame-sync da câmera, que também é roteada para P10 tanto no processador quanto no header de pinos — acione P10 para injetar bordas de sincronização no stream de eventos e capturá-las como eventos EXT_TRIGGER_RISING / EXT_TRIGGER_FALLING junto aos dados de pixel.
A maioria das aplicações só se importa com PIX_OFF_EVENT e PIX_ON_EVENT; os tipos de gatilho permitem correlacionar eventos com sinais de temporização externos.
Aloque o buffer de eventos com o formato (EVT_res, 6) onde EVT_res é uma potência de dois entre 1024 e 65536, depois entre no modo de evento através de csi.IOCTL_GENX320_SET_MODE com csi.GENX320_MODE_EVENT e o tamanho do buffer. Leia os eventos com csi.IOCTL_GENX320_READ_EVENTS, que preenche o buffer até sua capacidade e retorna o número de linhas válidas.
Image.draw_event_histogram rasteriza eventos em uma imagem em escala de cinza — para cada evento ON ele adiciona contrast ao bin; para cada evento OFF ele subtrai. clear=True redefine a imagem para brightness primeiro; clear=False acumula ao longo de muitas chamadas:
import csi
import image
import time
from ulab import numpy as np
img = image.Image(320, 320, image.GRAYSCALE)
events = np.zeros((2048, 6), dtype=np.uint16)
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT, events.shape[0])
clock = time.clock()
while True:
clock.tick()
n = csi0.ioctl(csi.IOCTL_GENX320_READ_EVENTS, events)
img.draw_event_histogram(events[:n], clear=True, brightness=128, contrast=64)
img.flush()
print(n, clock.fps())
Os ioctls de presets de bias do modo de histograma, filtro AFK e calibração de hot-pixel funcionam todos da mesma forma no modo de evento — chame-os após csi.IOCTL_GENX320_SET_MODE.
Filtragem por polaridade¶
Fatie o array de eventos com ulab para manter apenas eventos ON (movimento para um estado mais claro) ou apenas eventos OFF:
TARGET = csi.PIX_ON_EVENT # or csi.PIX_OFF_EVENT
events_slice = events[:n]
indices = np.nonzero(events_slice[:, 0] == TARGET)[0]
if len(indices):
target_events = np.take(events_slice, indices, axis=0)
img.draw_event_histogram(target_events, clear=True,
brightness=128, contrast=64)
Acumulação de longa exposição¶
Defina clear=False para continuar empilhando eventos na mesma imagem ao longo de muitos quadros — o resultado é uma visualização de rastro de movimento. Redefina periodicamente para iniciar uma nova exposição:
EXPOSURE_FRAMES = 30
i = 0
while True:
n = csi0.ioctl(csi.IOCTL_GENX320_READ_EVENTS, events)
clear = (i % EXPOSURE_FRAMES) == 0
img.draw_event_histogram(events[:n], clear=clear, brightness=128, contrast=64)
img.flush()
i += 1
Processamento em alta velocidade¶
Descarte a visualização para liberar CPU para o processamento de eventos. Imprima estatísticas apenas a cada N-ésima iteração — enviar uma linha de print a cada iteração se torna o gargalo em taxas de eventos altas:
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT, events.shape[0])
clock = time.clock()
i = 0
while True:
clock.tick()
n = csi0.ioctl(csi.IOCTL_GENX320_READ_EVENTS, events)
i += 1
if not i % 10:
print(f"{n} events {clock.fps()} fps")
Filtro de contraste espaço-temporal (STC)¶
Uma borda de contraste real em movimento tende a disparar uma rajada ruidosa de eventos no mesmo pixel dentro de uma curta janela de tempo — descasamento de pixel e ruído analógico produzem eventos extras em torno da transição genuína que não são úteis para a aplicação. O filtro STC é um pós-processamento no chip que mantém apenas um (ou alguns) eventos por rajada e descarta o restante.
Ele implementa três estratégias, selecionadas via csi.IOCTL_GENX320_SET_STC e uma constante GENX320_STC_*. Cada modo é definido por quais eventos ele encaminha de uma rajada:
Modo |
Mantém |
Descarta |
|---|---|---|
todos os eventos |
nada |
|
segundo evento de uma rajada |
primeiro + eventos posteriores |
|
primeiro evento de uma rajada |
eventos subsequentes |
|
primeiro + bordas subsequentes |
apenas ruído redundante |
Em detalhe:
csi.GENX320_STC_DISABLE— filtro desligado, todos os eventos passam (padrão).csi.GENX320_STC_ONLY— mantém o segundo evento de uma rajada. Parâmetro:stc_threshold(ms). Se um novo evento em um pixel chega dentro destc_thresholdde um evento anterior, ele é considerado o “segundo” de uma rajada e é encaminhado — o primeiro evento e quaisquer eventos subsequentes na mesma rajada são filtrados. Melhor quando você quer uma transição confirmada por ruído em vez do primeiro disparo.csi.GENX320_STC_TRAIL_ONLY— mantém o primeiro evento de uma rajada. Parâmetro:trail_threshold(ms). Após um pixel disparar, eventos subsequentes no mesmo pixel são descartados até quetrail_thresholdtenha decorrido. Preserva a temporização precisa da borda de ataque — útil quando o momento da troca de polaridade importa mais que a confirmação da rajada.csi.GENX320_STC_TRAIL— combina ambos. Parâmetros:stc_thresholdetrail_threshold(ambos em ms). Mantém a borda de ataque conforme o modo Trail mais as bordas subsequentes conforme o modo STC, de modo que múltiplos eventos de uma rajada ainda passam — maior throughput de eventos que os filtros de modo único, mas o sinal mais rico.
Os dois limiares devem permanecer dentro de uma razão de aproximadamente 13:1 — o sensor rejeita configurações onde um é mais de ~13x o outro:
csi0.ioctl(csi.IOCTL_GENX320_SET_STC, csi.GENX320_STC_TRAIL, 1, 2)
csi0.ioctl(csi.IOCTL_GENX320_SET_STC, csi.GENX320_STC_DISABLE)
Profundidade do buffer¶
Quando as taxas de eventos disparam, o pipeline padrão de triplo buffer favorece o quadro mais recente e descarta os antigos. Aumente a profundidade do FIFO via csi.CSI.framebuffers para enfileirar eventos em vez disso — ao custo de processar dados ligeiramente mais antigos quando o host fica para trás:
csi0.framebuffers(10) # FIFO depth, > 3 enables queueing
Streaming e visualização em desktop¶
Para visualização GUI em tempo real em um PC host, a ferramenta GenX320 Event Streaming no repositório openmv-projects combina a câmera com um front-end DearPyGui. A GUI do PC executa duas visualizações lado a lado: um canvas de acumulação de eventos (mesma ideia de Image.draw_event_histogram, mas com paletas selecionáveis e modos de janela deslizante vs. limpeza automática) e um mapa de frequência por pixel acionado por um filtro passa-banda IIR — útil para detectar sinais periódicos (ventiladores girando, LEDs piscando, etc.) diretamente no stream de eventos.
Ela vem com dois scripts de streaming na câmera:
Modo processado (
genx320_event_mode_streaming_on_cam.py) — a câmera decodifica os eventos comcsi.IOCTL_GENX320_READ_EVENTSe transmite cada linha como 12 bytes via USB ([0]tipo,[1]seg,[2]ms,[3]us,[4]x,[5]y). Fácil de consumir no PC porque o formato de transmissão corresponde ao formato ndarray na câmera.Modo bruto (
genx320_raw_event_mode_streaming_on_cam.py) — a câmera transmite as palavras de evento empacotadas nativas de 32 bits do chip através decsi.IOCTL_GENX320_READ_EVENTS_RAW. Isso são 4 bytes por evento contra 12 no modo processado (cerca de 3x menos dados via USB), portanto uma taxa de eventos alcançável ~3x mais alta quando o link é o gargalo. O PC decodifica as palavras empacotadas de volta para o mesmo layout de evento de 6 colunas usando numpy vetorizado, de modo que o código do visualizador a jusante é idêntico.
O modo bruto é o padrão na GUI porque o throughput de USB é a restrição limitante nas taxas que o GenX320 pode produzir; mude para o modo processado se você precisar conectar lógica de processamento ao script na câmera.