GENX320-tapahtumakamera

GENX320 Event Camera Module on Prophesee-yhtiön tapahtumapohjainen näkösensori, jonka resoluutio on 320x320 ja jonka ajallinen tarkkuus on mikrosekuntiluokkaa.

GENX320-tapahtumakamera

Täydellisen datalehden, kuvat ja tilaustiedot löydät GENX320 Event Camera -tuotesivulta.

Muista

Tuettu malleissa OpenMV H7 Plus, RT1062 ja N6.

Kohokohdat

  • 320x320 tapahtumapohjainen näkösensori

  • 140 dB:n dynaaminen alue, ei liike-epäterävyyttä

  • 375 Hz+ tapahtumahistogrammien ulostulonopeus

  • Tehonkulutus skaalautuu näkymän aktiivisuuden mukaan — alkaa noin 3 mW:sta

  • Toimii alle 5 luksista kirkkaaseen auringonpaisteeseen ilman automaattista valotusta

  • Tuottaa harmaasävykehyksiä tai raakoja tapahtumavirtoja

Käyttö

GENX320 on tapahtumapohjainen näkösensori — sen sijaan, että koko 320x320-matriisi luettaisiin ulos kiinteällä kehyskellotaajuudella, jokainen pikseli raportoi asynkronisia ”tapahtumia” sillä hetkellä, kun se havaitsee kirkkauden muutoksen. Jokainen tapahtuma sisältää X/Y-koordinaatin, ON/OFF-polariteetin (kirkkaasta→tummaksi tai tummasta→kirkkaaksi) sekä mikrosekuntiaikaleiman. Tästä juontuvat sensorin mikrosekuntiluokan ajallinen tarkkuus, liike-epäterävyyden puuttuminen, erittäin laaja dynaaminen alue sekä aktiivisuuteen skaalautuva tehonkulutus. Staattiset näkymät eivät tuota lainkaan dataa.

OpenMV-laiteohjelmisto tuo GENX320:n käyttöön csi.CSI-luokan kautta arvolla cid= csi.GENX320. Käytettävissä on kaksi toimintatilaa:

  • Histogrammitila (oletus) — tapahtumat kerätään sirulla pikselikohtaisiin lokeroihin ja raportoidaan 320x320-harmaasävykehyksenä säädettävällä nopeudella (~20–350 FPS). Sensori käyttäytyy kuin tavallinen kamera, joten kaikki tavanomaiset kuvankäsittelyrutiinit (Image.find_blobs, paletit jne.) toimivat suoraan.

  • Tapahtumatila — raakatapahtumat virtaavat numpy-tyyppiseen ndarray-taulukkoon täysillä mikrosekuntiaikaleimoilla niitä sovelluksia varten, jotka tarvitsevat ajallisen yksityiskohdan esivalmistellun kehyksen sijaan.

Histogrammitila

Histogrammitilassa GENX320 tuottaa harmaasävykehyksiä, joissa kukin pikseli koodaa kyseisen sijainnin viimeaikaisen tapahtuma-aktiivisuuden. Kirkkauden perustason yläpuolella olevat pikselit ovat ON-tapahtumia (kirkkaus nousee), alapuolella olevat OFF-tapahtumia (kirkkaus laskee). Oletusperustason kirkkaus on 128 ja tapahtumakohtainen kontrastiaskel 16 — nosta kontrastia, jotta tapahtumat erottuvat selvemmin:

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 ja csi.CSI.framerate ovat ne kolme säädintä, jotka muokkaavat histogrammin ulostuloa.

Värillinen ulostulo

Aseta csi.CSI.color_palette arvoon image.PALETTE_EVT_LIGHT vaaleaa taustaa varten tai image.PALETTE_EVT_DARK tummaa taustaa varten — ajuri tuottaa RGB565-kehyksiä käyttäen palettia suoraan:

csi0.color_palette(image.PALETTE_EVT_LIGHT)

Kuumien pikselien kalibrointi

Tapahtumasensoreihin kertyy ”kuumia pikseleitä”, jotka laukeavat virheellisesti. Aja csi.IOCTL_GENX320_CALIBRATE staattista näkymää vasten poistaaksesi ne käytöstä. Ajuri rakentaa 320x320-pikselikohtaisen osumalaskurin, laskee keskiarvon ja keskihajonnan sekä poistaa käytöstä jokaisen pikselin, jonka laskuri ylittää arvon mean + sigma * stddev — tämän jälkeen käytöstä poistetut pikselit lakkaavat lähettämästä tapahtumia sensoritasolla.

Kaksi parametria ohjaa kalibrointia:

  • event_count — kuinka monta tapahtumaa lasketaan ennen tilastojen laskemista. Silmukka kaappaa kehyksiä, kunnes juokseva tapahtumien kokonaismäärä ylittää tämän budjetin. Suuremmat arvot antavat luotettavamman arvion pidemmän kalibrointiajan kustannuksella. 10000 on järkevä lähtökohta.

  • sigma — keskihajonnan kynnyskerroin. Pienemmät arvot ovat aggressiivisempia (enemmän pikseleitä poistetaan käytöstä); suuremmat arvot ovat varovaisempia. 0.5 on hyvä oletusarvo.

Suuntaa sensori ensin staattiseen näkymään, jotta liikkeen aiheuttamia tapahtumia ei lasketa niitä pikseleitä vastaan, jotka ovat itse asiassa kunnossa:

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

Vilkunnanesto-suodatin (AFK)

Jaksolliset valonlähteet (loisteputket, LED-ohjatut näytöt) tuottavat valtavia määriä turhia tapahtumia. AFK-suodatin hylkää tapahtumat, joiden pikseli vaihtelee tiettyyn taajuuskaistaan kuuluvalla taajuudella — ota se käyttöön komennolla csi.IOCTL_GENX320_SET_AFK antaen kaistan reunat hertseinä:

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

Bias-esiasetukset

Jokainen GenX320:n pikseli sisältää analogisen etuasteen useilla säädettävillä bias-arvoilla. Ne ohjaavat yhdessä herkkyyttä, kohinaa, pikselin kaistanleveyttä ja tapahtumanopeutta — oikea yhdistelmä riippuu näkymästä. Yksittäiset bias-arvot ovat:

  • DIFF_ON — positiivisen vertailijan kontrastikynnysarvo. Pikseli lähettää ON-tapahtuman, kun sen logaritminen valaistus on noussut tämän verran. Pienempi = herkempi kirkkaille muutoksille.

  • DIFF_OFF — negatiivisen vertailijan kontrastikynnysarvo (symmetrinen vastine OFF-tapahtumille). Pienempi = herkempi tummille muutoksille.

  • FO — pikselin alipäästön rajataajuus. Korkeampi = leveämpi pikselin kaistanleveys (nopeampi vaste, pienempi viive) mutta enemmän taustakohina-aktiivisuutta.

  • HPF — ylipäästön rajataajuus. Korkeampi = voimakkaampi hitaiden kirkkausmuutosten hylkäys; vain nopeat muutokset saavuttavat vertailijat. Hyödyllinen ympäristön ajautuman ohittamiseen.

  • REFR — palautumisaika. Pikselin lauettua se pysyy nollaustilassa tämän ajan, ennen kuin se voi laueta uudelleen. Korkeampi = pidempi kuolleen aika, hyödyllinen pikselikohtaisen tapahtumanopeuden rajaamiseen.

Komennon csi.CSI.reset jälkeen ajuri ottaa käyttöön asetukset csi.GENX320_BIASES_LOW_NOISE, ei asetuksia csi.GENX320_BIASES_DEFAULT — datalehden oletukset tuottavat paljon korkeamman taustatapahtumanopeuden, joten LOW_NOISE käytetään lähtökohtana virran pitämiseksi hiljaisena. Kutsu csi.IOCTL_GENX320_SET_BIASES eri esiasetuksella, kun sovellus tarvitsee enemmän herkkyyttä tai kaistanleveyttä.

csi.IOCTL_GENX320_SET_BIASES ottaa käyttöön yhden viidestä esiasetuksesta:

  • csi.GENX320_BIASES_DEFAULT — GenX320:n datalehden oletukset. Tasapainotettu herkkyys, kohina ja kaistanleveys yleisiin näkymiin.

  • csi.GENX320_BIASES_LOW_LIGHT — molempia kontrastikynnysarvoja löysennetty herkkyyden lisäämiseksi, FO laskettu kohinan pitämiseksi kurissa ja HPF asetettu nollaan, jotta hitaatkin kirkkausmuutokset rekisteröityvät — hämärä näkymä tuottaa itsessään vähän tapahtumia, joten haluamme niistä mahdollisimman monen läpi.

  • csi.GENX320_BIASES_ACTIVE_MARKER — viritetty korkeakontrastisten vilkkuvien LEDien seurantaan. Kontrastikynnysarvoja nostettu niin, että vain terävät muutokset laukaisevat; FO ja HPF kohotettu korkealle pikselin kaistanleveyden maksimoimiseksi ja hitaan ympäristön ajautuman hylkäämiseksi; REFR vedetty nollaan, jotta jokainen vilkkumisen reuna tallentuu peräkkäin. Tuloksena on virta, joka koostuu lähes pelkistä LEDien reunoista ja jota on helppo seurata.

  • csi.GENX320_BIASES_LOW_NOISE — ajurin oletus. Molemmat kontrastikynnysarvot nostettu verrattuna asetukseen DEFAULT (vähemmän herkkä) ja FO laskettu (hitaampi pikseli = hiljaisempi pikseli). Paras staattisille tai hitaille näkymille, joissa virheelliset tapahtumat muutoin hallitsisivat.

  • csi.GENX320_BIASES_HIGH_SPEED — FO nostettu, jotta kukin pikseli voi reagoida nopeammin, HPF nostettu hitaan kirkkausajautuman hylkäämiseksi ja REFR nostettu, jottei yksittäinen nopeasti liikkuva reuna tukkisi ulkolukua — pidempi kuollut aika pitää tapahtumamäärän rajattuna voimakkaan liikkeen aikana.

Ohita yksittäiset bias-arvot komennolla csi.IOCTL_GENX320_SET_BIAS yhdessä jonkin seuraavista kanssa: csi.GENX320_BIAS_DIFF_ON, csi.GENX320_BIAS_DIFF_OFF, csi.GENX320_BIAS_FO, csi.GENX320_BIAS_HPF tai csi.GENX320_BIAS_REFR, sekä DAC-arvo. Kukin bias asetetaan erikseen — valitse esiasetus lähtökohdaksi ja säädä sitten niitä bias-arvoja, joita näkymäsi tarvitsee:

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

Seuranta

Koska histogrammitilan ulostulo on vain harmaasävykuva, tavanomainen blob-seuranta toimii suoraan. Aktiivisen markkeri-LEDin seuraamiseksi lataa aktiivisen markkerin bias-esiasetus ja etsi blobeja histogrammin kirkkaasta päästä:

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

Tapahtumatila

Tapahtumatila ohittaa sirun histogrammin ja virtaa raakatapahtumat numpy-tyyppiseen ndarray-taulukkoon. Jokainen tapahtuma on rivi, jossa on kuusi uint16-saraketta:

  • [0] tapahtuman tyyppi — katso alta

  • [1] sekuntien aikaleima

  • [2] millisekuntien aikaleima

  • [3] mikrosekuntien aikaleima

  • [4] X-koordinaatti, 0–319

  • [5] Y-koordinaatti, 0–319

Ajuri lähettää kuutta tapahtumatyyppiä sarakkeessa [0]:

  • csi.PIX_OFF_EVENT — pikseli havaitsi kirkkauden vähenemisen (DIFF_OFF-vertailijan kynnysarvo ylittyi). X/Y osoittavat lauenneeseen pikseliin.

  • csi.PIX_ON_EVENT — pikseli havaitsi kirkkauden lisääntymisen (DIFF_ON-kynnysarvo ylittyi). X/Y osoittavat pikseliin.

  • csi.EXT_TRIGGER_FALLING — sensorin ulkoinen liipaisunasta havaitsi laskevan reunan. X/Y eivät ole käytössä.

  • csi.EXT_TRIGGER_RISING — sensorin ulkoinen liipaisunasta havaitsi nousevan reunan. X/Y eivät ole käytössä.

  • csi.RST_TRIGGER_FALLING — pikselin nollausliipaisin, laskeva reuna. X/Y eivät ole käytössä. Laiteohjelmisto ei tuota tätä tällä hetkellä.

  • csi.RST_TRIGGER_RISING — pikselin nollausliipaisin, nouseva reuna. X/Y eivät ole käytössä. Laiteohjelmisto ei tuota tätä tällä hetkellä.

GENX320:n ulkoinen liipaisutulo on kytketty kameran kehyssynkronointilinjaan, joka on myös reititetty nastaan P10 sekä prosessorissa että nastarimassa — ohjaa P10:tä syöttääksesi synkronointireunoja tapahtumavirtaan ja poimi ne EXT_TRIGGER_RISING / EXT_TRIGGER_FALLING -tapahtumina pikselidatan rinnalla.

Useimmat sovellukset välittävät vain tapahtumista PIX_OFF_EVENT ja PIX_ON_EVENT; liipaisutyyppien avulla voit yhdistää tapahtumat ulkoisiin ajoitussignaaleihin.

Varaa tapahtumapuskuri muodolla (EVT_res, 6), jossa EVT_res on kahden potenssi välillä 1024 ja 65536, ja siirry sitten tapahtumatilaan komennolla csi.IOCTL_GENX320_SET_MODE arvolla csi.GENX320_MODE_EVENT ja puskurin koolla. Lue tapahtumat komennolla csi.IOCTL_GENX320_READ_EVENTS, joka täyttää puskurin sen kapasiteettiin asti ja palauttaa kelvollisten rivien määrän.

Image.draw_event_histogram rasteroi tapahtumat harmaasävykuvaksi — jokaista ON-tapahtumaa kohti se lisää lokeroon arvon contrast ja jokaista OFF-tapahtumaa kohti vähentää sen. clear=True nollaa kuvan ensin arvoon brightness; clear=False kerää useiden kutsujen yli:

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

Histogrammitilan bias-esiasetukset, AFK-suodatin ja kuumien pikselien kalibroinnin ioctl-komennot toimivat kaikki samalla tavalla tapahtumatilassa — kutsu niitä komennon csi.IOCTL_GENX320_SET_MODE jälkeen.

Suodatus polariteetin mukaan

Viipaloi tapahtumataulukko ulabilla säilyttääksesi vain ON-tapahtumat (liike kirkkaampaan tilaan) tai vain OFF-tapahtumat:

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)

Pitkän valotuksen kertyminen

Aseta clear=False pinotaksesi tapahtumia samaan kuvaan useiden kehysten ajan — tuloksena on liikejälkien visualisointi. Nollaa ajoittain aloittaaksesi uuden valotuksen:

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

Suuren nopeuden käsittely

Pudota visualisointi vapauttaaksesi prosessoria tapahtumankäsittelyyn. Tulosta tilastot vain joka N:nnellä iteraatiolla — tulostusrivin työntäminen jokaisella iteraatiolla muodostuu pullonkaulaksi suurilla tapahtumanopeuksilla:

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

Tila-aikakontrastisuodatin (STC)

Todellinen liikkuva kontrastireuna laukaisee tyypillisesti kohinaisen tapahtumien purskeen samalla pikselillä lyhyen aikaikkunan sisällä — pikselien epätäsmäys ja analoginen kohina tuottavat ylimääräisiä tapahtumia aidon muutoksen ympärille, jotka eivät ole sovelluksen kannalta hyödyllisiä. STC-suodatin on sirulla suoritettava jälkikäsittely, joka säilyttää vain yhden (tai muutaman) tapahtuman purskeesta ja hylkää loput.

Se toteuttaa kolme strategiaa, jotka valitaan komennolla csi.IOCTL_GENX320_SET_STC ja vakiolla GENX320_STC_*. Kukin tila määritellään sen mukaan, mitkä tapahtumat se välittää purskeesta:

Tila

Säilyttää

Hylkää

csi.GENX320_STC_DISABLE

jokainen tapahtuma

ei mitään

csi.GENX320_STC_ONLY

purskeen toinen tapahtuma

ensimmäinen + myöhemmät tapahtumat

csi.GENX320_STC_TRAIL_ONLY

purskeen ensimmäinen tapahtuma

myöhemmät tapahtumat

csi.GENX320_STC_TRAIL

ensimmäinen + myöhemmät reunat

vain turha kohina

Yksityiskohtaisesti:

  • csi.GENX320_STC_DISABLE — suodatin pois, jokainen tapahtuma kulkee läpi (oletus).

  • csi.GENX320_STC_ONLY — säilyttää purskeen toisen tapahtuman. Parametri: stc_threshold (ms). Jos pikselin uusi tapahtuma saapuu stc_threshold-ajan sisällä edellisestä tapahtumasta, sitä pidetään purskeen ”toisena” tapahtumana ja se välitetään — ensimmäinen tapahtuma ja samaan purskeeseen kuuluvat myöhemmät tapahtumat suodatetaan pois. Paras silloin, kun haluat kohinalla varmennetun muutoksen aivan ensimmäisen osuman sijaan.

  • csi.GENX320_STC_TRAIL_ONLY — säilyttää purskeen ensimmäisen tapahtuman. Parametri: trail_threshold (ms). Pikselin lauettua samaa pikseliä koskevat myöhemmät tapahtumat hylätään, kunnes trail_threshold on kulunut. Säilyttää etureunan tarkan ajoituksen — hyödyllinen, kun polariteetin vaihtumishetki on tärkeämpi kuin purskeen varmistus.

  • csi.GENX320_STC_TRAIL — yhdistää molemmat. Parametrit: stc_threshold ja trail_threshold (molemmat ms). Säilyttää etureunan Trail-tilan mukaisesti sekä myöhemmät reunat STC-tilan mukaisesti, joten useita purskeen tapahtumia pääsee silti läpi — korkeampi tapahtumien läpäisykyky kuin yksitilaisilla suodattimilla, mutta rikkain signaali.

Kahden kynnysarvon on pysyttävä karkeasti suhteessa 13:1 — sensori hylkää konfiguraatiot, joissa toinen on yli noin 13-kertainen toiseen nähden:

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

Puskurin syvyys

Kun tapahtumanopeudet piikittävät, oletusarvoinen kolmoispuskuriputki suosii uusinta kehystä ja hylkää vanhat. Nosta FIFO-syvyyttä ominaisuudella csi.CSI.framebuffers jonottaaksesi tapahtumia sen sijaan — sen hinnalla, että käsiteltävä data on hieman vanhempaa silloin, kun isäntä jää jälkeen:

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

Työpöytäsuoratoisto ja visualisointi

Reaaliaikaiseen graafiseen visualisointiin isäntä-PC:llä GenX320 Event Streaming -työkalu openmv-projects-repossa yhdistää kameran DearPyGui-käyttöliittymään. PC:n graafinen käyttöliittymä näyttää kaksi visualisointia rinnakkain: tapahtumien kertymäkankaan (sama idea kuin Image.draw_event_histogram, mutta valittavilla paleteilla sekä liukuva-ikkuna- vai automaattinollaustiloilla) ja IIR-kaistanpäästösuodattimen ohjaaman pikselikohtaisen taajuuskartan — hyödyllinen jaksollisten signaalien (pyörivät tuulettimet, vilkkuvat LEDit jne.) havaitsemiseen suoraan tapahtumavirrasta.

Sen mukana toimitetaan kaksi kameralla ajettavaa suoratoistoskriptiä:

  • Käsitelty tila (genx320_event_mode_streaming_on_cam.py) — kamera purkaa tapahtumat komennolla csi.IOCTL_GENX320_READ_EVENTS ja suoratoistaa kunkin rivin 12 tavuna USB:n yli ([0] tyyppi, [1] s, [2] ms, [3] µs, [4] x, [5] y). Helppo käsitellä PC:llä, koska siirtomuoto vastaa kameran ndarray-muotoa.

  • Raakatila (genx320_raw_event_mode_streaming_on_cam.py) — kamera suoratoistaa sirun natiivit 32-bittiset pakatut tapahtumasanat komennolla csi.IOCTL_GENX320_READ_EVENTS_RAW. Se on 4 tavua tapahtumaa kohti verrattuna käsitellyn tilan 12 tavuun (noin 3 kertaa vähemmän dataa USB:n yli), joten noin 3 kertaa korkeampi saavutettavissa oleva tapahtumanopeus silloin, kun linkki on pullonkaula. PC purkaa pakatut sanat takaisin samaan 6-sarakkeiseen tapahtumamuotoon vektoroidulla numpylla, joten myöhemmän visualisoijan koodi on identtinen.

Raakatila on graafisen käyttöliittymän oletus, koska USB:n läpäisykyky on sitova rajoite niillä nopeuksilla, joita GenX320 pystyy tuottamaan; vaihda käsiteltyyn tilaan, jos sinun täytyy liittää käsittelylogiikkaa kameralla ajettavaan skriptiin.