Událostní kamera GENX320

Modul událostní kamery GENX320 je událostní senzor strojového vidění od společnosti Prophesee s rozlišením 320x320 a mikrosekundovou časovou přesností.

Událostní kamera GENX320

Kompletní datasheet, fotografie a možnosti objednání naleznete na stránce produktu událostní kamera GENX320.

Poznámka

Podporováno na OpenMV H7 Plus, RT1062 a N6.

Hlavní vlastnosti

  • Událostní senzor strojového vidění s rozlišením 320x320

  • Dynamický rozsah 140 dB, bez rozmazání pohybem

  • Výstupní rychlost událostního histogramu 375 Hz+

  • Spotřeba se škáluje podle aktivity scény — začíná na ~3 mW

  • Funguje od <5 lux po jasné sluneční světlo bez automatické expozice

  • Vystupuje snímky ve stupních šedi nebo surové proudy událostí

Použití

GENX320 je událostní senzor strojového vidění — místo vyčítání celého pole 320x320 podle pevného snímkového hodinového signálu hlásí každý pixel asynchronní „události“ ve chvíli, kdy detekuje změnu jasu. Každá událost nese souřadnici X/Y, polaritu ON/OFF (světlé→tmavé nebo tmavé→světlé) a mikrosekundovou časovou značku. Odtud pochází mikrosekundová časová přesnost senzoru, absence rozmazání pohybem, velmi vysoký dynamický rozsah a spotřeba škálovaná podle aktivity. Statické scény negenerují žádná data.

Firmware OpenMV zpřístupňuje GENX320 prostřednictvím csi.CSI s cid= csi.GENX320. K dispozici jsou dva provozní režimy:

  • Režim histogramu (výchozí) — události se na čipu akumulují do binů po jednotlivých pixelech a jsou hlášeny jako snímek 320x320 ve stupních šedi s konfigurovatelnou rychlostí (~20-350 FPS). Senzor se chová jako běžná kamera, takže všechny standardní rutiny pro zpracování obrazu (Image.find_blobs, palety atd.) fungují přímo.

  • Režim událostí — surové události proudí do numpy ndarray s plnými mikrosekundovými časovými značkami, pro aplikace, které potřebují časový detail spíše než předem binovaný snímek.

Režim histogramu

V režimu histogramu vystupuje GENX320 snímky ve stupních šedi, kde každý pixel kóduje nedávnou událostní aktivitu na daném místě. Pixely nad jasovou základnou jsou události ON (jas roste), pod ní jsou události OFF (jas klesá). Výchozí jas základny je 128 a kontrastní krok na událost je 16 — zvyšte kontrast, aby události vynikly:

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 a csi.CSI.framerate jsou tři ovládací prvky, které tvarují výstup histogramu.

Barevný výstup

Nastavte csi.CSI.color_palette na image.PALETTE_EVT_LIGHT pro světlé pozadí nebo image.PALETTE_EVT_DARK pro tmavé — ovladač vytváří snímky RGB565 přímo pomocí palety:

csi0.color_palette(image.PALETTE_EVT_LIGHT)

Kalibrace horkých pixelů

Událostní senzory akumulují „horké pixely“, které spouštějí falešně. Spuštěním csi.IOCTL_GENX320_CALIBRATE proti statické scéně je zakážete. Ovladač sestaví počet zásahů na pixel pro pole 320x320, vypočítá průměr a směrodatnou odchylku a zakáže každý pixel, jehož počet je nad mean + sigma * stddev — poté zakázané pixely přestanou vysílat události na úrovni senzoru.

Kalibraci řídí dva parametry:

  • event_count — kolik událostí spočítat před výpočtem statistik. Smyčka snímá snímky, dokud běžící součet událostí nepřekročí tento rozpočet. Vyšší hodnoty poskytují spolehlivější odhad za cenu delší doby kalibrace. 10000 je rozumný výchozí bod.

  • sigma — prahový násobitel směrodatné odchylky. Nižší hodnoty jsou agresivnější (zakáže se více pixelů); vyšší hodnoty jsou konzervativnější. 0.5 je dobrá výchozí hodnota.

Nejprve namiřte senzor na statickou scénu, aby se žádné události způsobené pohybem nezapočítaly proti pixelům, které jsou ve skutečnosti v pořádku:

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")

Filtr proti blikání (AFK)

Periodické zdroje světla (zářivky, displeje řízené LED) generují obrovské množství nadbytečných událostí. Filtr AFK odmítá události, jejichž pixel přepíná na frekvenci uvnitř pásma — povolte jej pomocí csi.IOCTL_GENX320_SET_AFK s okraji pásma v hertzích:

csi0.ioctl(csi.IOCTL_GENX320_SET_AFK, 1, 130, 160)  # 130-160 Hz
csi0.ioctl(csi.IOCTL_GENX320_SET_AFK, 0)            # disable

Přednastavení biasů

Každý pixel v GenX320 obsahuje analogový vstupní stupeň s několika konfigurovatelnými biasy. Společně řídí citlivost, šum, šířku pásma pixelu a rychlost událostí — správná kombinace závisí na scéně. Jednotlivé biasy jsou:

  • DIFF_ON — kladný kontrastní práh komparátoru. Pixel vyšle událost ON, když jeho logaritmické osvětlení vzrostlo o tuto hodnotu. Nižší = citlivější na světlé přechody.

  • DIFF_OFF — záporný kontrastní práh komparátoru (symetrický protějšek pro události OFF). Nižší = citlivější na tmavé přechody.

  • FO — mezní frekvence dolní propusti pixelu. Vyšší = širší šířka pásma pixelu (rychlejší odezva, nižší latence), ale více aktivity způsobené šumem pozadí.

  • HPF — mezní frekvence horní propusti. Vyšší = silnější potlačení pomalých změn jasu; ke komparátorům se dostanou jen rychlé přechody. Užitečné pro ignorování driftu okolního světla.

  • REFR — refrakterní perioda. Poté, co pixel spustí, zůstává po tuto dobu v resetu, než může spustit znovu. Vyšší = delší mrtvá doba, užitečné pro omezení rychlosti událostí na pixel.

Po csi.CSI.reset ovladač aplikuje csi.GENX320_BIASES_LOW_NOISE, nikoliv csi.GENX320_BIASES_DEFAULT — výchozí hodnoty z datasheetu vysílají mnohem vyšší rychlost událostí pozadí, takže LOW_NOISE se používá jako výchozí bod, aby byl proud tichý. Když aplikace potřebuje větší citlivost nebo šířku pásma, zavolejte csi.IOCTL_GENX320_SET_BIASES s jiným přednastavením.

csi.IOCTL_GENX320_SET_BIASES aplikuje jedno z pěti přednastavení:

  • csi.GENX320_BIASES_DEFAULT — výchozí hodnoty z datasheetu GenX320. Vyvážená citlivost, šum a šířka pásma pro obecné scény.

  • csi.GENX320_BIASES_LOW_LIGHT — oba kontrastní prahy uvolněny pro vyšší citlivost, FO sníženo pro udržení nízkého šumu a HPF nastaveno na 0, aby se pomalé změny jasu stále zaznamenávaly — scéna se slabým osvětlením generuje sama o sobě málo událostí, takže chceme, aby jich co nejvíce prošlo.

  • csi.GENX320_BIASES_ACTIVE_MARKER — vyladěno pro sledování vysoce kontrastních blikajících LED. Kontrastní prahy zvýšeny tak, aby spouštěly jen ostré přechody; FO a HPF nastaveny vysoko pro maximalizaci šířky pásma pixelu a potlačení jakéhokoliv pomalého driftu okolního světla; REFR staženo na 0, takže každá hrana bliknutí je zachycena těsně za sebou. Výsledkem je proud, který tvoří téměř výhradně hrany LED, snadno sledovatelný.

  • csi.GENX320_BIASES_LOW_NOISE — výchozí nastavení ovladače. Oba kontrastní prahy zvýšeny oproti DEFAULT (nižší citlivost) a FO sníženo (pomalejší pixel = tišší pixel). Nejlepší pro statické nebo pomalé scény, kde by jinak dominovaly falešné události.

  • csi.GENX320_BIASES_HIGH_SPEED — FO zvýšeno, aby každý pixel mohl reagovat rychleji, HPF zvýšeno pro potlačení pomalého driftu jasu a REFR zvýšeno, aby jediná rychle se pohybující hrana nezahltila vyčítání — delší mrtvá doba udržuje objem událostí omezený při intenzivním pohybu.

Přepište jednotlivé biasy pomocí csi.IOCTL_GENX320_SET_BIAS plus jednoho z csi.GENX320_BIAS_DIFF_ON, csi.GENX320_BIAS_DIFF_OFF, csi.GENX320_BIAS_FO, csi.GENX320_BIAS_HPF nebo csi.GENX320_BIAS_REFR a hodnoty DAC. Každý bias se nastavuje nezávisle — vyberte přednastavení jako výchozí bod a poté upravte ty biasy, které vaše scéna potřebuje:

csi0.ioctl(csi.IOCTL_GENX320_SET_BIASES, csi.GENX320_BIASES_LOW_LIGHT)
csi0.ioctl(csi.IOCTL_GENX320_SET_BIAS, csi.GENX320_BIAS_HPF, 20)

Sledování

Protože výstup režimu histogramu je jen obraz ve stupních šedi, běžné sledování blobů funguje přímo. Pro sledování LED aktivního markeru načtěte přednastavení biasů pro aktivní marker a najděte bloby na jasném konci histogramu:

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())

Režim událostí

Režim událostí obchází histogram na čipu a streamuje surové události do numpy ndarray. Každá událost je řádek o šesti sloupcích typu uint16:

  • [0] typ události — viz níže

  • [1] časová značka v sekundách

  • [2] časová značka v milisekundách

  • [3] časová značka v mikrosekundách

  • [4] souřadnice X, 0-319

  • [5] souřadnice Y, 0-319

Ovladač vysílá ve sloupci [0] šest typů událostí:

  • csi.PIX_OFF_EVENT — pixel detekoval pokles jasu (byl překročen kontrastní práh komparátoru DIFF_OFF). X/Y ukazují na pixel, který spustil.

  • csi.PIX_ON_EVENT — pixel detekoval nárůst jasu (byl překročen práh DIFF_ON). X/Y ukazují na pixel.

  • csi.EXT_TRIGGER_FALLING — externí spouštěcí pin senzoru zaznamenal sestupnou hranu. X/Y se nepoužívají.

  • csi.EXT_TRIGGER_RISING — externí spouštěcí pin senzoru zaznamenal vzestupnou hranu. X/Y se nepoužívají.

  • csi.RST_TRIGGER_FALLING — spouštěč resetu pixelů, sestupná hrana. X/Y se nepoužívají. V tuto chvíli firmware negeneruje.

  • csi.RST_TRIGGER_RISING — spouštěč resetu pixelů, vzestupná hrana. X/Y se nepoužívají. V tuto chvíli firmware negeneruje.

Externí spouštěcí vstup GENX320 je připojen k linii frame-sync kamery, která je rovněž vedena na P10 jak na procesoru, tak na pinové liště — přiveďte signál na P10, abyste do proudu událostí vložili synchronizační hrany, a vyzvedněte je jako události EXT_TRIGGER_RISING / EXT_TRIGGER_FALLING spolu s daty pixelů.

Většina aplikací se stará pouze o PIX_OFF_EVENT a PIX_ON_EVENT; typy spouštěčů umožňují korelovat události s externími časovacími signály.

Alokujte buffer událostí s tvarem (EVT_res, 6), kde EVT_res je mocnina dvou mezi 1024 a 65536, poté přejděte do režimu událostí prostřednictvím csi.IOCTL_GENX320_SET_MODE s csi.GENX320_MODE_EVENT a velikostí bufferu. Čtěte události pomocí csi.IOCTL_GENX320_READ_EVENTS, které naplní buffer až do jeho kapacity a vrátí počet platných řádků.

Image.draw_event_histogram rasterizuje události do obrazu ve stupních šedi — pro každou událost ON přidá do binu contrast; pro každou událost OFF odečte. clear=True nejprve resetuje obraz na brightness; clear=False akumuluje přes mnoho volání:

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())

Přednastavení biasů, filtr AFK a ioctly pro kalibraci horkých pixelů z režimu histogramu fungují stejným způsobem i v režimu událostí — zavolejte je po csi.IOCTL_GENX320_SET_MODE.

Filtrování podle polarity

Slicujte pole událostí pomocí ulab, abyste si ponechali pouze události ON (pohyb do jasnějšího stavu) nebo pouze události 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)

Akumulace s dlouhou expozicí

Nastavte clear=False, abyste pokračovali v hromadění událostí do stejného obrazu přes mnoho snímků — výsledkem je vizualizace stopy pohybu. Pro zahájení nové expozice periodicky resetujte:

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

Vysokorychlostní zpracování

Vynechte vizualizaci, abyste uvolnili CPU pro zpracování událostí. Tiskněte statistiky pouze každou N-tou iteraci — vkládání řádku s tiskem v každé iteraci se při vysokých rychlostech událostí stává úzkým hrdlem:

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")

Časoprostorový kontrastní (STC) filtr

Skutečná pohybující se kontrastní hrana má tendenci spustit šumivý shluk událostí na stejném pixelu během krátkého časového okna — neshoda pixelů a analogový šum produkují kolem skutečného přechodu další události, které nejsou pro aplikaci užitečné. Filtr STC je následné zpracování na čipu, které si ponechá jen jednu (nebo několik) událostí na shluk a zbytek zahodí.

Implementuje tři strategie, vybírané pomocí csi.IOCTL_GENX320_SET_STC a konstanty GENX320_STC_*. Každý režim je definován tím, které události ze shluku přeposílá:

Režim

Ponechává

Zahazuje

csi.GENX320_STC_DISABLE

každou událost

nic

csi.GENX320_STC_ONLY

druhou událost shluku

první + pozdější události

csi.GENX320_STC_TRAIL_ONLY

první událost shluku

následné události

csi.GENX320_STC_TRAIL

první + následné hrany

pouze nadbytečný šum

Podrobně:

  • csi.GENX320_STC_DISABLE — filtr vypnut, každá událost prochází (výchozí).

  • csi.GENX320_STC_ONLY — ponechává druhou událost shluku. Parametr: stc_threshold (ms). Pokud nová událost na pixelu přijde do stc_threshold od předchozí události, je považována za „druhou“ ve shluku a je přeposlána — první událost a všechny následné události ve stejném shluku jsou odfiltrovány. Nejlepší, když chcete šumem potvrzený přechod spíše než úplně první zásah.

  • csi.GENX320_STC_TRAIL_ONLY — ponechává první událost shluku. Parametr: trail_threshold (ms). Poté, co pixel spustí, jsou následné události na stejném pixelu zahazovány, dokud neuplyne trail_threshold. Zachovává přesné časování náběžné hrany — užitečné, když na okamžiku změny polarity záleží více než na potvrzení shluku.

  • csi.GENX320_STC_TRAIL — kombinuje obojí. Parametry: stc_threshold a trail_threshold (oba ms). Ponechává náběžnou hranu podle režimu Trail plus následné hrany podle režimu STC, takže ze shluku stále projde více událostí — vyšší propustnost událostí než filtry s jediným režimem, ale nejbohatší signál.

Oba prahy musí zůstat zhruba v poměru 13:1 — senzor odmítá konfigurace, kde je jeden více než ~13x větší než druhý:

csi0.ioctl(csi.IOCTL_GENX320_SET_STC, csi.GENX320_STC_TRAIL, 1, 2)
csi0.ioctl(csi.IOCTL_GENX320_SET_STC, csi.GENX320_STC_DISABLE)

Hloubka bufferu

Když rychlosti událostí prudce vzrostou, výchozí pipeline s trojitým bufferem upřednostňuje nejnovější snímek a staré zahazuje. Zvyšte hloubku FIFO pomocí csi.CSI.framebuffers, abyste místo toho události zařazovali do fronty — za cenu zpracování o něco starších dat, když host zaostává:

csi0.framebuffers(10)  # FIFO depth, > 3 enables queueing

Streamování a vizualizace na desktopu

Pro vizualizaci v reálném čase v GUI na hostitelském PC spáruje nástroj GenX320 Event Streaming v repozitáři openmv-projects kameru s front-endem DearPyGui. GUI na PC spouští dvě vizualizace vedle sebe: plátno akumulace událostí (stejná myšlenka jako Image.draw_event_histogram, ale s volitelnými paletami a režimy posuvného okna vs. automatického mazání) a mapu frekvence po pixelech řízenou pásmovou propustí typu IIR — užitečné pro odhalování periodických signálů (rotující ventilátory, blikající LED atd.) přímo v proudu událostí.

Dodává dva streamovací skripty běžící na kameře:

  • Zpracovaný režim (genx320_event_mode_streaming_on_cam.py) — kamera dekóduje události pomocí csi.IOCTL_GENX320_READ_EVENTS a streamuje každý řádek jako 12 bajtů přes USB ([0] typ, [1] sek, [2] ms, [3] us, [4] x, [5] y). Snadné ke zpracování na PC, protože formát na lince odpovídá formátu ndarray na kameře.

  • Surový režim (genx320_raw_event_mode_streaming_on_cam.py) — kamera streamuje nativní 32bitová zabalená událostní slova čipu prostřednictvím csi.IOCTL_GENX320_READ_EVENTS_RAW. To jsou 4 bajty na událost oproti 12 ve zpracovaném režimu (asi 3x méně dat přes USB), takže ~3x vyšší dosažitelná rychlost událostí, když je linka úzkým hrdlem. PC dekóduje zabalená slova zpět do stejného šestisloupcového rozložení událostí pomocí vektorizovaného numpy, takže navazující kód vizualizéru je identický.

Surový režim je v GUI výchozí, protože propustnost USB je vázaným omezením při rychlostech, které GenX320 dokáže produkovat; přepněte na zpracovaný režim, pokud potřebujete do skriptu na kameře zapojit logiku zpracování.