GENX320 eseményalapú kamera¶
A GENX320 eseményalapú kameramodul egy Prophesee eseményalapú látásérzékelő 320x320 felbontással és mikroszekundumos időbeli pontossággal.
A teljes adatlapot, fényképeket és rendelési információkat lásd a GENX320 eseményalapú kamera termékoldalán.
Megjegyzés
Az OpenMV H7 Plus, RT1062 és N6 modelleken támogatott.
Kiemelt jellemzők¶
320x320 eseményalapú látásérzékelő
140 dB dinamikatartomány, mozgásból eredő elmosódás nélkül
375 Hz feletti esemény-hisztogram kimeneti sebesség
A fogyasztás a jelenet aktivitásával skálázódik — ~3 mW-tól indul
<5 luxtól az erős napfényig működik automatikus expozíció nélkül
Szürkeárnyalatos képkockákat vagy nyers eseményfolyamokat ad ki
Használat¶
A GENX320 egy eseményalapú látásérzékelő — ahelyett, hogy a teljes 320x320-as tömböt egy rögzített képkocka-órajelen olvasná ki, minden képpont aszinkron „eseményeket” jelent abban a pillanatban, amikor fényerő-változást észlel. Minden esemény egy X/Y koordinátát, egy ON/OFF polaritást (világos→sötét vagy sötét→világos) és egy mikroszekundumos időbélyeget hordoz. Innen ered az érzékelő mikroszekundumos időbeli pontossága, a mozgásból eredő elmosódás hiánya, a nagyon nagy dinamikatartomány és az aktivitással skálázódó fogyasztás. A statikus jelenetek nem generálnak adatot.
Az OpenMV firmware a GENX320-at a csi.CSI-n keresztül teszi elérhetővé cid= csi.GENX320 beállítással. Két működési mód érhető el:
Hisztogram mód (alapértelmezett) — az események a chipen képpontonkénti tárolókba halmozódnak, és egy konfigurálható sebességgel (~20-350 FPS) 320x320-as szürkeárnyalatos képkockaként jelennek meg. Az érzékelő úgy viselkedik, mint egy közönséges kamera, így az összes szabványos képfeldolgozó rutin (
Image.find_blobs, paletták stb.) közvetlenül működik.Esemény mód — a nyers események egy numpy
ndarraytömbbe áramlanak teljes mikroszekundumos időbélyegekkel, olyan alkalmazásokhoz, amelyeknek az időbeli részletességre van szükségük egy előre tárolókba sorolt képkocka helyett.
Hisztogram mód¶
Hisztogram módban a GENX320 szürkeárnyalatos képkockákat ad ki, ahol minden képpont az adott helyen lévő közelmúltbeli eseményaktivitást kódolja. A fényerő-alapvonal feletti képpontok ON események (emelkedő fényerő), az alattiak OFF események (csökkenő fényerő). Az alapértelmezett alapvonal-fényerő 128, az eseményenkénti kontrasztlépés pedig 16 — növeld a kontrasztot, hogy az események jobban kiemelkedjenek:
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())
A csi.CSI.brightness, a csi.CSI.contrast és a csi.CSI.framerate az a három szabályozó, amely a hisztogram kimenetet alakítja.
Színezett kimenet¶
Állítsd a csi.CSI.color_palette értéket image.PALETTE_EVT_LIGHT-ra világos háttérhez, vagy image.PALETTE_EVT_DARK-ra sötéthez — a meghajtó RGB565 képkockákat bocsát ki közvetlenül a paletta felhasználásával:
csi0.color_palette(image.PALETTE_EVT_LIGHT)
Forrópont-kalibráció¶
Az eseményérzékelők „forró képpontokat” halmoznak fel, amelyek hamis jelzéseket adnak. Futtasd a csi.IOCTL_GENX320_CALIBRATE-et egy statikus jelenetre irányítva, hogy letiltsd őket. A meghajtó épít egy 320x320-as képpontonkénti találatszámlálót, kiszámítja az átlagot és a szórást, majd letilt minden olyan képpontot, amelynek a számlálója mean + sigma * stddev felett van — ezután a letiltott képpontok az érzékelő szintjén leállnak az események kibocsátásával.
Két paraméter vezérli a kalibrációt:
event_count— hány eseményt számoljon össze a statisztika kiszámítása előtt. A ciklus addig rögzít képkockákat, amíg a folyamatos eseményösszeg át nem lépi ezt a keretet. A magasabb számok megbízhatóbb becslést adnak hosszabb kalibrációs idő árán. A10000ésszerű kiindulópont.sigma— a szóráson alkalmazott küszöbszorzó. Az alacsonyabb értékek agresszívabbak (több képpont letiltva); a magasabb értékek óvatosabbak. A0.5jó alapértelmezés.
Először irányítsd az érzékelőt egy statikus jelenetre, hogy a mozgás által kiváltott események ne számítsanak be olyan képpontok ellen, amelyek valójában rendben vannak:
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")
Villogásgátló (AFK) szűrő¶
A periodikus fényforrások (fénycsövek, LED-vezérelt kijelzők) hatalmas mennyiségű redundáns eseményt generálnak. Az AFK szűrő elutasítja azokat az eseményeket, amelyek képpontja egy sávon belüli frekvencián vált — engedélyezd a csi.IOCTL_GENX320_SET_AFK-n keresztül a sávhatárokkal hertzben megadva:
csi0.ioctl(csi.IOCTL_GENX320_SET_AFK, 1, 130, 160) # 130-160 Hz
csi0.ioctl(csi.IOCTL_GENX320_SET_AFK, 0) # disable
Bias-előbeállítások¶
A GenX320 minden képpontja egy analóg bemeneti fokozatot futtat több konfigurálható bias-szal. Ezek együttesen szabályozzák az érzékenységet, a zajt, a képpont-sávszélességet és az eseménysebességet — a megfelelő kombináció a jelenettől függ. Az egyes bias-ok a következők:
DIFF_ON — a pozitív komparátor kontrasztküszöbe. Egy képpont ON eseményt bocsát ki, ha a logaritmikus megvilágítása ennyivel megemelkedett. Alacsonyabb = érzékenyebb a világos átmenetekre.
DIFF_OFF — a negatív komparátor kontrasztküszöbe (az OFF események szimmetrikus megfelelője). Alacsonyabb = érzékenyebb a sötét átmenetekre.
FO — a képpont aluláteresztő vágási frekvenciája. Magasabb = szélesebb képpont-sávszélesség (gyorsabb válasz, kisebb késleltetés), de több háttérzaj-aktivitás.
HPF — a felüláteresztő vágási frekvencia. Magasabb = erősebb elutasítása a lassú fényerő-változásoknak; csak a gyors átmenetek érik el a komparátorokat. Hasznos a környezeti elcsúszás figyelmen kívül hagyásához.
REFR — a refrakter periódus. Miután egy képpont jelzett, ennyi ideig visszaállított állapotban marad, mielőtt újra jelezhetne. Magasabb = hosszabb holtidő, hasznos a képpontonkénti eseménysebesség korlátozásához.
A csi.CSI.reset után a meghajtó a csi.GENX320_BIASES_LOW_NOISE-t alkalmazza, nem a csi.GENX320_BIASES_DEFAULT-ot — az adatlap szerinti alapértelmezések sokkal magasabb háttér-eseménysebességet bocsátanak ki, így a LOW_NOISE szolgál kiindulópontként a folyam csendben tartásához. Hívd a csi.IOCTL_GENX320_SET_BIASES-t egy másik előbeállítással, ha az alkalmazásnak nagyobb érzékenységre vagy sávszélességre van szüksége.
A csi.IOCTL_GENX320_SET_BIASES az öt előbeállítás egyikét alkalmazza:
csi.GENX320_BIASES_DEFAULT— a GenX320 adatlap szerinti alapértelmezések. Kiegyensúlyozott érzékenység, zaj és sávszélesség általános jelenetekhez.csi.GENX320_BIASES_LOW_LIGHT— mindkét kontrasztküszöb fellazítva a nagyobb érzékenységért, az FO lecsökkentve a zaj alacsonyan tartásához, a HPF pedig 0-ra állítva, hogy a lassú fényerő-változások is regisztrálódjanak — egy gyengén megvilágított jelenet önmagában kevés eseményt generál, ezért azt akarjuk, hogy minél több jusson át.csi.GENX320_BIASES_ACTIVE_MARKER— nagy kontrasztú villogó LED-ek követéséhez hangolva. A kontrasztküszöbök megemelve, így csak az éles átmenetek váltanak ki eseményt; az FO és a HPF magasra állítva a képpont-sávszélesség maximalizálásához és a lassú környezeti elcsúszás elutasításához; a REFR 0-ra húzva, hogy minden villanásél egymás után rögzüljön. Az eredmény: egy folyam, amely szinte teljes egészében LED-élekből áll, könnyen követhető.csi.GENX320_BIASES_LOW_NOISE— a meghajtó alapértelmezése. Mindkét kontrasztküszöb megemelve aDEFAULT-hoz képest (kevésbé érzékeny), az FO pedig lecsökkentve (lassabb képpont = csendesebb képpont). A legjobb statikus vagy lassú jelenetekhez, ahol a hamis események egyébként dominálnának.csi.GENX320_BIASES_HIGH_SPEED— az FO megemelve, hogy minden képpont gyorsabban reagálhasson, a HPF megemelve a lassú fényerő-elcsúszás elutasításához, a REFR pedig megemelve, hogy egyetlen gyorsan mozgó él ne árassza el a kiolvasást — a hosszabb holtidő erős mozgás esetén korlátok között tartja az eseménymennyiséget.
Az egyes bias-okat a csi.IOCTL_GENX320_SET_BIAS-szal írhatod felül a csi.GENX320_BIAS_DIFF_ON, csi.GENX320_BIAS_DIFF_OFF, csi.GENX320_BIAS_FO, csi.GENX320_BIAS_HPF vagy csi.GENX320_BIAS_REFR egyikével és egy DAC értékkel. Minden bias függetlenül állítható — válassz egy előbeállítást kiindulópontként, majd finomítsd azokat a bias-okat, amelyekre a jelenetednek szüksége van:
csi0.ioctl(csi.IOCTL_GENX320_SET_BIASES, csi.GENX320_BIASES_LOW_LIGHT)
csi0.ioctl(csi.IOCTL_GENX320_SET_BIAS, csi.GENX320_BIAS_HPF, 20)
Követés¶
Mivel a hisztogram módú kimenet csak egy szürkeárnyalatos kép, a közönséges foltkövetés közvetlenül működik. Egy aktív jelölő LED követéséhez töltsd be az aktív jelölő bias-előbeállítást, és keress foltokat a hisztogram világos végén:
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())
Esemény mód¶
Az esemény mód megkerüli a chipen lévő hisztogramot, és a nyers eseményeket egy numpy ndarray tömbbe áramoltatja. Minden esemény egy sor hat uint16 oszloppal:
[0]eseménytípus — lásd lent[1]másodperc időbélyeg[2]ezredmásodperc időbélyeg[3]mikroszekundum időbélyeg[4]X koordináta, 0-319[5]Y koordináta, 0-319
A meghajtó hat eseménytípust bocsát ki a [0] oszlopban:
csi.PIX_OFF_EVENT— egy képpont fényerő-csökkenést észlelt (aDIFF_OFFkomparátorküszöböt átlépte). Az X/Y a jelző képpontra mutat.csi.PIX_ON_EVENT— egy képpont fényerő-növekedést észlelt (aDIFF_ONküszöböt átlépte). Az X/Y a képpontra mutat.csi.EXT_TRIGGER_FALLING— az érzékelő külső trigger lába lefutó élt látott. Az X/Y nincs használatban.csi.EXT_TRIGGER_RISING— az érzékelő külső trigger lába felfutó élt látott. Az X/Y nincs használatban.csi.RST_TRIGGER_FALLING— képpont-visszaállító trigger, lefutó él. Az X/Y nincs használatban. A firmware jelenleg nem generálja.csi.RST_TRIGGER_RISING— képpont-visszaállító trigger, felfutó él. Az X/Y nincs használatban. A firmware jelenleg nem generálja.
A GENX320 külső trigger bemenete a kamera képkocka-szinkron vonalához van kötve, amely szintén a P10-re van irányítva mind a processzoron, mind a tűsoron — vezéreld a P10-et, hogy szinkronéleket injektálj az eseményfolyamba, és EXT_TRIGGER_RISING / EXT_TRIGGER_FALLING eseményekként vedd fel őket a képpontadatok mellett.
A legtöbb alkalmazás csak a PIX_OFF_EVENT és a PIX_ON_EVENT eseményekkel törődik; a trigger típusok lehetővé teszik, hogy az eseményeket külső időzítési jelekkel korreláld.
Foglald le az eseménypuffert (EVT_res, 6) alakkal, ahol az EVT_res egy kettő hatványa 1024 és 65536 között, majd lépj esemény módba a csi.IOCTL_GENX320_SET_MODE-on keresztül a csi.GENX320_MODE_EVENT-tel és a puffer méretével. Olvasd az eseményeket a csi.IOCTL_GENX320_READ_EVENTS-szel, amely a kapacitásáig feltölti a puffert, és visszaadja az érvényes sorok számát.
Az Image.draw_event_histogram az eseményeket szürkeárnyalatos képpé raszterizálja — minden ON eseményhez hozzáadja a contrast értéket a tárolóhoz; minden OFF eseménynél kivonja. A clear=True először visszaállítja a képet a brightness értékre; a clear=False sok híváson keresztül halmoz:
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())
A hisztogram módú bias-előbeállítások, az AFK szűrő és a forrópont-kalibrációs ioctl-ek mind ugyanúgy működnek esemény módban — hívd őket a csi.IOCTL_GENX320_SET_MODE után.
Szűrés polaritás szerint¶
Szeleteld fel az események tömbjét az ulab-bal, hogy csak az ON eseményeket (mozgás világosabb állapotba) vagy csak az OFF eseményeket tartsd meg:
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)
Hosszú expozíciós halmozás¶
Állítsd a clear=False értéket, hogy sok képkockán keresztül ugyanabba a képbe halmozd az eseményeket — az eredmény egy mozgásnyom-vizualizáció. Időnként állítsd vissza egy új expozíció indításához:
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
Nagy sebességű feldolgozás¶
Hagyd el a vizualizációt, hogy CPU-t szabadíts fel az eseményfeldolgozáshoz. Csak minden N-edik iterációnál írj ki statisztikát — minden iterációnál egy nyomtatási sor kiküldése válik a szűk keresztmetszetté nagy eseménysebességeknél:
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")
Tér-időbeli kontraszt (STC) szűrő¶
Egy valódi mozgó kontrasztél hajlamos arra, hogy egy zajos kitörést váltson ki eseményekből ugyanazon a képponton egy rövid időablakon belül — a képpont-eltérés és az analóg zaj extra eseményeket produkál a valódi átmenet körül, amelyek nem hasznosak az alkalmazás számára. Az STC szűrő egy chipen lévő utófeldolgozás, amely kitörésenként csak egy (vagy néhány) eseményt tart meg, a többit pedig eldobja.
Három stratégiát valósít meg, amelyeket a csi.IOCTL_GENX320_SET_STC-vel és egy GENX320_STC_* konstanssal lehet kiválasztani. Minden módot az határoz meg, hogy egy kitörésből mely eseményeket továbbítja:
Mód |
Megtartja |
Eldobja |
|---|---|---|
minden eseményt |
semmit |
|
egy kitörés második eseményét |
az elsőt + a későbbi eseményeket |
|
egy kitörés első eseményét |
a következő eseményeket |
|
az elsőt + a következő éleket |
csak a redundáns zajt |
Részletesen:
csi.GENX320_STC_DISABLE— szűrő ki, minden esemény átjut (alapértelmezett).csi.GENX320_STC_ONLY— egy kitörés második eseményét tartja meg. Paraméter:stc_threshold(ms). Ha egy képponton egy új esemény egy korábbi eseményhez képeststc_thresholdidőn belül érkezik, akkor a kitörés „második” eseményének tekintendő, és továbbításra kerül — az első esemény és az ugyanazon kitörés bármely következő eseménye kiszűrésre kerül. A legjobb, ha egy zaj által megerősített átmenetet szeretnél a legelső találat helyett.csi.GENX320_STC_TRAIL_ONLY— egy kitörés első eseményét tartja meg. Paraméter:trail_threshold(ms). Miután egy képpont jelzett, az ugyanazon a képponton lévő következő események eldobásra kerülnek, amíg el nem telik atrail_threshold. Megőrzi a vezető él pontos időzítését — hasznos, amikor a polaritásváltás pillanata fontosabb, mint a kitörés megerősítése.csi.GENX320_STC_TRAIL— mindkettőt kombinálja. Paraméterek:stc_thresholdéstrail_threshold(mindkettő ms). Megtartja a vezető élt a Trail mód szerint, valamint a következő éleket az STC mód szerint, így egy kitörésből több esemény is átjut — magasabb esemény-átviteli teljesítmény, mint az egymódú szűrőknél, de a leggazdagabb jel.
A két küszöbnek nagyjából egy 13:1 arányon belül kell maradnia — az érzékelő elutasítja azokat a konfigurációkat, ahol az egyik a másiknál több mint ~13-szor nagyobb:
csi0.ioctl(csi.IOCTL_GENX320_SET_STC, csi.GENX320_STC_TRAIL, 1, 2)
csi0.ioctl(csi.IOCTL_GENX320_SET_STC, csi.GENX320_STC_DISABLE)
Puffermélység¶
Amikor az eseménysebesség megugrik, az alapértelmezett hármaspuffer-folyamat a legújabb képkockát részesíti előnyben, és a régieket eldobja. Növeld a FIFO mélységét a csi.CSI.framebuffers-en keresztül, hogy ehelyett az eseményeket sorba állítsd — annak árán, hogy kissé régebbi adatokat dolgozol fel, amikor a gazdagép lemarad:
csi0.framebuffers(10) # FIFO depth, > 3 enables queueing
Asztali streamelés és vizualizáció¶
Egy gazda PC-n történő valós idejű grafikus vizualizációhoz az openmv-projects tárolóban lévő GenX320 eseménystreamelő eszköz párosítja a kamerát egy DearPyGui kezelőfelülettel. A PC-s grafikus felület két vizualizációt futtat egymás mellett: egy eseményhalmozó vásznat (ugyanaz az elv, mint az Image.draw_event_histogram, de választható palettákkal és csúszóablakos vs. automatikus-törlés módokkal) és egy képpontonkénti frekvenciatérképet, amelyet egy IIR sáváteresztő szűrő hajt — hasznos a periodikus jelek (forgó ventilátorok, villogó LED-ek stb.) közvetlen felismeréséhez az eseményfolyamban.
Két kamerán futó streamelő szkriptet tartalmaz:
Feldolgozott mód (
genx320_event_mode_streaming_on_cam.py) — a kamera acsi.IOCTL_GENX320_READ_EVENTS-szel dekódolja az eseményeket, és minden sort 12 bájtként streamel USB-n keresztül ([0]típus,[1]mp,[2]ms,[3]us,[4]x,[5]y). Könnyen feldolgozható a PC-n, mert a vezetékformátum megegyezik a kamerán lévő ndarray formátummal.Nyers mód (
genx320_raw_event_mode_streaming_on_cam.py) — a kamera a chip natív 32 bites csomagolt eseményszavait streameli acsi.IOCTL_GENX320_READ_EVENTS_RAW-on keresztül. Ez 4 bájt eseményenként a feldolgozott mód 12 bájtjával szemben (kb. 3-szor kevesebb adat USB-n), tehát ~3-szor magasabb elérhető eseménysebesség, amikor a kapcsolat a szűk keresztmetszet. A PC a csomagolt szavakat visszadekódolja ugyanarra a 6 oszlopos eseményelrendezésre vektorizált numpy segítségével, így a downstream vizualizáló kód azonos.
A nyers mód az alapértelmezett a grafikus felületen, mert az USB átviteli teljesítmény a kötő korlát azokon a sebességeken, amelyeket a GenX320 elő tud állítani; válts feldolgozott módra, ha feldolgozási logikát kell beépítened a kamerán futó szkriptbe.