Quickstart¶
Synthetic events in, a snapshot out. No camera, file or GUI needed.
quickstart.py
import numpy as np
import frames2py
# 10,000 synthetic events on a 640x480 sensor, one every microsecond.
rng = np.random.default_rng(seed=0)
events = np.zeros(10_000, dtype=frames2py.EVENT_DTYPE)
events["t"] = np.arange(10_000) # timestamps, µs
events["x"] = rng.integers(0, 640, 10_000) # column
events["y"] = rng.integers(0, 480, 10_000) # row
events["p"] = rng.integers(0, 2, 10_000) # polarity: 0 is OFF, anything else ON
engine = frames2py.Engine((640, 480), "event_count") # sensor_size is (width, height)
engine.ingest(events) # the first ingest() always publishes
snapshot = engine.snapshot() # the latest publication: shared, read-only
print(snapshot.frame.shape, snapshot.frame.dtype)
print("events counted:", int(snapshot.frame.sum()))
print("watermark:", snapshot.meta.watermark, "sequence:", snapshot.meta.sequence)
print("ingested:", engine.stats.events_ingested, "out of bounds:", engine.stats.events_out_of_bounds)
Output
(480, 640) uint32
events counted: 10000
watermark: 9999 sequence: 1
ingested: 10000 out of bounds: 0
What happened:
- Events are a 1-D NumPy structured array of
EVENT_DTYPE:tin microseconds,xthe column,ythe row,pthe polarity. Any array with those four fields at exactly those dtypes works; extra fields are ignored. sensor_sizeis(width, height), and the frame it produces is(height, width), as NumPy images are.ingest()validated the array, accumulated it into theevent_countkernel's state and, because it was the first call, published a snapshot. Later calls publish at most once persnapshot_interval_ms(16 ms by default).snapshot()returned that publication: the frame, shared and read-only, plus its metadata. The watermark is the largest timestamp accumulated so far; the sequence counts publications.
Next¶
- A producer thread and a consumer. This is what the Engine is for: the producer calls
ingest()in its own loop, and consumers readsnapshot()whenever they like. See Writing a consumer for a runnable example. - Watch it. The viewer shows an Engine's snapshots in a
window:
viewer.run(engine.snapshot)on the main thread, with the producer on another. - Real data. Read a recording with a file adapter, or feed your
camera SDK's buffers converted to
EVENT_DTYPE. - Other representations. Swap
"event_count"for another kernel:"polarity","time_surface",frames2py.ExpDecay(0.9)orframes2py.TimestampDecay(10_000.0).