Skip to content

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: t in microseconds, x the column, y the row, p the polarity. Any array with those four fields at exactly those dtypes works; extra fields are ignored.
  • sensor_size is (width, height), and the frame it produces is (height, width), as NumPy images are.
  • ingest() validated the array, accumulated it into the event_count kernel's state and, because it was the first call, published a snapshot. Later calls publish at most once per snapshot_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 read snapshot() 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) or frames2py.TimestampDecay(10_000.0).