API Reference¶
The Python API lives in the top-level eventcv package. Every operation exists both as
a method on EventStream / EventFrame and as an
OpenCV-style free function (listed under Functional API
below); the free functions are generated from the methods, so the two forms stay in sync.
Loading & saving¶
- eventcv.load(path: str, *, sensor_size: tuple[int, int] | None = None, time_unit: str | None = None, order: str = 'txyp', topic: str | None = None, max_events: int | None = None) EventStream[source]¶
Load events from any supported file, detected by its extension.
Supported today:
.npz(N-ImageNet),.txt/.csv(e.g. EV-IMOt x y p),.bag(ROSdvs_msgs/EventArray),.hdf5/.h5,.aedat(AEDAT 2.0, jAER/DAVIS), and.dat(Prophesee CD events).sensor_sizeandtime_unitare auto-detected when omitted and only act as overrides: rosbags carry both in the message; HDF5/text infer the time unit from the timestamps (a fractional text value means seconds) and the resolution from the coordinate range. Passingsensor_sizefor HDF5 also skips that scan.time_unitisseconds/milliseconds/microseconds/nanoseconds(orauto);order(txyp/xytp) applies to text.topicselects the rosbag topic (default/davis/left/events).max_eventscaps how many events are read, handy for previewing very large files.
- eventcv.open(path: str, *, dt_ms: float | None = None, repr: str | None = None, sensor_size: tuple[int, int] | None = None, time_unit: str | None = None, order: str = 'txyp', topic: str | None = None) EventReader[source]¶
Open a file for lazy slicing without loading it whole.
Where
load()is OpenCV’simread(read the entire stream eagerly),openis itsVideoCapture: it returns anEventReaderthat points at the original file and fetches a slice on demand. For HDF5 this binary-searches the on-disk timestamps, so a slice of a multi-gigabyte recording costs a handful of reads — the file is never fully materialised. Other formats are loaded once and sliced in memory.Pass
dt_msto treat the recording as a sequence of fixed-duration frames: the reader reportsn_slicesandreader.slice(n)returns then-th frame (reader[n]works too). Framenis measured from the recording start, so you never deal with absolute timestamps (which may be epoch-based). Withoutdt_ms, slice by explicit time/count window instead.sensor_sizeandtime_unitare auto-detected when omitted (seeload());order/topicmatchload(). For a multi-GB HDF5, passsensor_sizeto skip the one-time coordinate scan resolution inference needs.Pass
repr(a representation name —"count","voxel","tsurf","flow"for optical flow, …) to make the reader a PyTorch-style map dataset:len(reader) == n_slices,reader[i]returns the dense[C, H, W]array for framei, andreader.batch(indices)stacks a[B, C, H, W]batch — so aDataLoadercan collate the reader directly. Usereader.with_repr(name, **opts)to set per-representation options (e.g.bins=5, orwindow=5for"flow"). Withoutrepr,reader[i]stays a rawEventStream; to still batch those through aDataLoaderpasscollate_fn=eventcv.collate(each batch is alist[EventStream], since sparse streams can’t stack into a tensor).Phase 5 algorithms apply per slice:
reader.efast()/reader.harris_corners(thr)return a new reader whose every slice is the corner sub-stream, composing withslice/windows/with_repr. To render an algorithm as a video, map it overwindows()and hand the frames toexport_png()(then assemble with ffmpeg).Note
reprgoverns the array/dataset path (reader[i]→ NumPy). To view a slice interactively,slice(i)returns the rawEventStream, so name the representation on the stream:data.slice(1000).view("flow")(or.slice(1000).optical_flow().view()).Example:
r = eventcv.open("rec.hdf5", dt_ms=30) # resolution + time unit auto-detected r.n_slices # how many 30 ms frames r.slice(50).mcts().view() # the 50th 30 ms frame for frame in r.windows(): # walk every frame (step defaults to dt_ms) voxel = frame.voxel() # As a training dataset: ds = eventcv.open("rec.hdf5", dt_ms=30, repr="count") loader = torch.utils.data.DataLoader(ds, batch_size=32, shuffle=True) # Corner-detection video (one PNG per frame): corners = eventcv.open("rec.hdf5", dt_ms=30).efast() eventcv.export_png((w.count() for w in corners.windows()), "corners/", colormap="turbo") # Optical-flow video: eventcv.export_png((w.optical_flow() for w in r.windows()), "flow/")
- eventcv.save(obj, path: str, *, topic: str | None = None) None[source]¶
Save an
EventStreamorEventFrametopath.The mirror of
load(): the format is chosen by the file extension. Streams go to.npz/.txt/.h5/.bag(npz, HDF5, and rosbag round-trip exactly; txt storest x y pand recovers the sensor size/unit on load via inference or options). Frames (computed representations) go to.npzor.h5, preserving shape, dtype,kind, andchannel_names.topicnames the rosbag connection. Equivalent toobj.save(path).
- eventcv.load_frame(path: str) EventFrame[source]¶
Load an
EventFramewritten bysave()(.npzor.h5).Restores the representation’s shape, dtype,
kind, andchannel_names.
- eventcv.export_png(frames, out_dir: str, *, colormap: str = 'viridis', normalize: bool = True, prefix: str = 'frame_', start: int = 0, digits: int = 5)[source]¶
Write one or many
EventFrames to numbered.pngfiles — the “frame sequence → video frames” export.framesis a singleEventFrameor any iterable of them (e.g. a generator over a reader’s windows), so a whole recording renders lazily without materialising every frame at once:r = eventcv.open("rec.hdf5", dt_ms=30) eventcv.export_png((w.count() for w in r.windows()), "out/", colormap="turbo")
Each frame is colormapped through the same path as
frame.save("x.png")(colormap:viridis/turbo/grayscale/redblue;normalizeauto-contrasts). Files are named{prefix}{index:0{digits}d}.pngcounting fromstart. Returns the list of written paths (assemble a video with, e.g.,ffmpeg -i out/frame_%05d.png out.mp4).
- eventcv.collate(batch)[source]¶
collate_fnfortorch.utils.data.DataLoaderover anEventReader.A reader opened with a representation (
open(repr=…)) yields dense[C, H, W]arrays that torch’s default collate stacks into a[B, C, H, W]tensor with no help — so you only need this for a reader opened withoutrepr, whosereader[i]is a rawEventStream. Those are variable-length and sparse, so they can’t stack into a tensor; this returns the batch as a plainlistof streams instead (dense/array batches still defer to torch’s default collate). Pass it explicitly:loader = torch.utils.data.DataLoader(reader, batch_size=32, collate_fn=eventcv.collate) for batch in loader: # batch is a list[EventStream] batch[0].view()
Core types¶
- class eventcv.EventStream¶
Bases:
object- atsurf(*, tau_ms=30.0)¶
Averaged time surface — the per-pixel mean of exp(-age/tau_ms) over all events (two polarity channels, float32). Brighter where activity recurs; see tsurf.
- background_activity_filter(dt)¶
Background-activity (nearest-neighbour) noise filter: keeps an event only if a 3×3 neighbour fired within dt (raw timestamp units, e.g. microseconds).
- concat(others)¶
Concatenates this stream with others (argument order; sensor = element-wise max).
- count(*, normalize=True)¶
Event-count image — one channel of total events per pixel (both polarities). uint64 counts, or uint8 rescaled to the busiest pixel when normalize=True.
- crop(x0, y0, w, h)¶
Keeps events inside the w`×`h window at (x0, y0), shifted to a new origin.
- decimate(k)¶
Keeps every k-th event by index.
- efast()¶
eFAST event corner detector (Mueggler et al., BMVC 2017). Keeps the events sitting on a moving corner, tested on two Bresenham rings over the per-polarity surface of active events.
- filter_polarity(polarity)¶
Keeps only events of the given polarity (nonzero / True = ON, 0 / False = OFF).
- flip_x()¶
Mirrors horizontally (x → width-1-x).
- flip_y()¶
Mirrors vertically (y → height-1-y).
- harris_corners(threshold=0.0)¶
Harris corner score on the Surface of Active Events: keeps events whose Harris response det - k·trace² of the SAE-ramp structure tensor exceeds threshold. The default threshold=0 keeps corners (rank-2, R>0) and rejects straight edges (rank-1, R<0); raise it to be stricter.
- hot_pixel_filter(n_std=3.0)¶
Hot-pixel removal: drops pixels whose event count exceeds mean + n_std·std over the active pixels (default n_std=3.0).
- invert_polarity()¶
Flips every event’s polarity.
- mask(mask)¶
Keeps events where the (H, W) boolean mask is True.
- normalize_time()¶
Shifts timestamps so the earliest event starts at zero.
- optical_flow(*, window=3)¶
Dense Lucas-Kanade optical flow on the time surface. Returns a two-channel (flow_x, flow_y) frame in pixels/ms; window is the half-width of the least-squares neighbourhood.
- refractory_filter(dt)¶
Refractory-period filter: suppresses a pixel’s events for dt after it fires.
- repr¶
The default representation name carried from open(repr=…) / with_repr (what view()/flatten() render), or None for a raw stream.
- resize(width, height)¶
Event-domain resize to a width`×`height grid (rebinned, not interpolated).
- rotate90(k)¶
Rotates by k * 90° clockwise (quarter turns swap the sensor dims).
- save(path, *, topic=None)¶
Saves the stream to path, format chosen by extension (.npz/.txt/.h5/.bag) — the counterpart of eventcv.load. npz/HDF5/rosbag round-trip exactly; topic names the rosbag connection.
- scale(sx, sy)¶
Scales the sensor by (sx, sy).
- sort_by_time()¶
Returns a copy reordered by ascending timestamp (stable).
- time_scale(factor)¶
Scales every timestamp by factor (rounded).
- time_shift(dt)¶
Shifts every timestamp by dt microseconds.
- time_window(t0, t1)¶
Keeps events whose timestamp lies in the half-open window [t0, t1) (microseconds).
- translate(dx, dy)¶
Translates by (dx, dy); events shifted off the sensor are dropped.
- transpose()¶
Reflects across the main diagonal ((x, y) → (y, x)); swaps the sensor dims.
- undistort(camera)¶
Rectifies events with a Camera’s intrinsics + distortion (lens undistortion).
- view(representation=None, *, colormap='viridis', normalize=True)¶
Opens the interactive viewer on this stream. Pass a representation name to choose what to show — stream.view(“flow”), stream.view(“count”), stream.view(“voxel”), … — or omit it to use the stream’s stored representation (from open(repr=…)), falling back to the polarity image. (Equivalent to stream.<repr>().view().)
- warp_affine(matrix)¶
Applies a 2×3 affine matrix [[a,b,c],[d,e,f]] (rounded, no interpolation).
- warp_perspective(matrix)¶
Applies a 3×3 perspective (homography) matrix.
- class eventcv.EventFrame¶
Bases:
object- connected_components(*, connectivity=8)¶
Connected-component labelling (Phase 5): treats any non-zero pixel as foreground and labels each 4- or 8-connected blob 1..=k, background 0. Returns a single-channel u64 frame.
- resize(width, height, *, pooling='average')¶
Resize spatial dimensions using average or sum pooling on shrinking axes.
- save(path, *, colormap='viridis', normalize=True)¶
Saves the frame to path. .npz/.h5 store the raw array (shape, dtype, kind, channel_names) for eventcv.load_frame; .png writes a colormapped 2-D view (colormap = viridis/turbo/grayscale/redblue; normalize auto-contrasts).
- view(*, colormap='viridis', normalize=True)¶
Opens the interactive GPU viewer. Image reprs are shown colour-mapped (colormap: viridis/turbo/grayscale/redblue; normalize auto-contrasts); volumetric reprs become an orbitable 3-D point cloud (drag to rotate, Esc to close).
- class eventcv.EventReader¶
Bases:
objectLazy, seekable handle over a file’s events — the VideoCapture to load’s imread. Slices are fetched on demand (HDF5 by binary-searching its timestamps on disk), so multi-GB files never need to be fully resident. Opening with dt_ms fixes a frame duration so slice(n) returns the n-th frame (like seeking a video).
- batch(indices)¶
Renders slice indices into one dense [B, C, H, W] array — the explicit-batch path for training. Requires a representation (open(repr=…) / with_repr). indices is any int sequence (list / range / …); each is a dt_ms frame index.
- dt_ms¶
The fixed slice duration set at open, or None if it was not given.
- efast()¶
Returns a new reader whose every slice is passed through [EventStream::efast], so the reader yields corner sub-streams (chain .count() / with_repr to visualise them).
- harris_corners(threshold=0.0)¶
Returns a new reader whose every slice is passed through [EventStream::harris_corners].
- n_slices¶
Number of fixed dt_ms slices spanning the recording (requires open(dt_ms=…)).
- repr¶
The per-slice representation name set at open/with_repr, or None (raw streams).
- slice(index=None, *, t0_ms=None, t1_ms=None)¶
One slice as an EventStream. With a positional index n (requires open(dt_ms=…)), returns the n-th fixed dt_ms frame measured from the recording start — [t_min + n·dt, t_min + (n+1)·dt); negative n counts from the end. Otherwise returns the half-open time window [t0_ms, t1_ms), with omitted bounds extending to the recording’s start / end.
- slice_count(i0, i1)¶
Events whose index lies in [i0, i1) (clamped to the file).
- windows(*, step_ms=None, span_ms=None)¶
Lazy iterator of consecutive windows: each is [start, start + span_ms) and start advances by step_ms. step_ms defaults to the dt_ms set at open (so windows() walks every slice(n)), and span_ms defaults to step_ms (non-overlapping). Streams a multi-GB file window-by-window without loading it.
- with_repr(repr, *, bins=None, window_ms=None, tau_ms=None, max_window_ms=None, window=None, normalize=True)¶
Returns a new reader over the same file that renders each slice with repr (unset params take their method defaults). The dataset-mode counterpart of open(repr=…), but with per-representation options: e.g. reader.with_repr(“voxel”, bins=5).
- class eventcv.Camera(fx, fy, cx, cy, *, k1=0.0, k2=0.0, p1=0.0, p2=0.0, k3=0.0)¶
Bases:
objectPinhole intrinsics + Brown–Conrady distortion, e.g. an EV-IMO calib.txt (fx fy cx cy k1 k2 p1 p2). Pass to stream.undistort(camera).
- undistort_point(u, v)¶
Maps a distorted pixel (u, v) to its undistorted location.
Functional (OpenCV-style) API¶
Each function below forwards to the identically named method on a stream or frame — e.g.
eventcv.voxel(stream, bins=5) is stream.voxel(bins=5). They are generated by
introspecting the compiled types, so this list always matches the methods above.
- eventcv.atsurf(obj, *args, **kwargs)¶
Averaged time surface — the per-pixel mean of exp(-age/tau_ms) over all events
Free-function form of
obj.atsurf(*args, **kwargs).
- eventcv.background_activity_filter(obj, *args, **kwargs)¶
Background-activity (nearest-neighbour) noise filter: keeps an event only if a 3×3
Free-function form of
obj.background_activity_filter(*args, **kwargs).
- eventcv.concat(obj, *args, **kwargs)¶
Concatenates this stream with others (argument order; sensor = element-wise max).
Free-function form of
obj.concat(*args, **kwargs).
- eventcv.connected_components(obj, *args, **kwargs)¶
Connected-component labelling (Phase 5): treats any non-zero pixel as foreground and labels
Free-function form of
obj.connected_components(*args, **kwargs).
- eventcv.count(obj, *args, **kwargs)¶
Event-count image — one channel of total events per pixel (both polarities). uint64
Free-function form of
obj.count(*args, **kwargs).
- eventcv.crop(obj, *args, **kwargs)¶
Keeps events inside the w`×`h window at (x0, y0), shifted to a new origin.
Free-function form of
obj.crop(*args, **kwargs).
- eventcv.decimate(obj, *args, **kwargs)¶
Keeps every k-th event by index.
Free-function form of
obj.decimate(*args, **kwargs).
- eventcv.efast(obj, *args, **kwargs)¶
eFAST event corner detector (Mueggler et al., BMVC 2017). Keeps the events sitting on a
Free-function form of
obj.efast(*args, **kwargs).
- eventcv.filter_polarity(obj, *args, **kwargs)¶
Keeps only events of the given polarity (nonzero / True = ON, 0 / False = OFF).
Free-function form of
obj.filter_polarity(*args, **kwargs).
- eventcv.flatten(obj, *args, **kwargs)¶
Calls
obj.flatten(...).Free-function form of
obj.flatten(*args, **kwargs).
- eventcv.flip_x(obj, *args, **kwargs)¶
Mirrors horizontally (x → width-1-x).
Free-function form of
obj.flip_x(*args, **kwargs).
- eventcv.flip_y(obj, *args, **kwargs)¶
Mirrors vertically (y → height-1-y).
Free-function form of
obj.flip_y(*args, **kwargs).
- eventcv.harris_corners(obj, *args, **kwargs)¶
Harris corner score on the Surface of Active Events: keeps events whose Harris response
Free-function form of
obj.harris_corners(*args, **kwargs).
- eventcv.hot_pixel_filter(obj, *args, **kwargs)¶
Hot-pixel removal: drops pixels whose event count exceeds mean + n_std·std over the
Free-function form of
obj.hot_pixel_filter(*args, **kwargs).
- eventcv.invert_polarity(obj, *args, **kwargs)¶
Flips every event’s polarity.
Free-function form of
obj.invert_polarity(*args, **kwargs).
- eventcv.mask(obj, *args, **kwargs)¶
Keeps events where the (H, W) boolean mask is True.
Free-function form of
obj.mask(*args, **kwargs).
- eventcv.mcts(obj, *args, **kwargs)¶
Calls
obj.mcts(...).Free-function form of
obj.mcts(*args, **kwargs).
- eventcv.normalize_time(obj, *args, **kwargs)¶
Shifts timestamps so the earliest event starts at zero.
Free-function form of
obj.normalize_time(*args, **kwargs).
- eventcv.numpy(obj, *args, **kwargs)¶
Calls
obj.numpy(...).Free-function form of
obj.numpy(*args, **kwargs).
- eventcv.optical_flow(obj, *args, **kwargs)¶
Dense Lucas-Kanade optical flow on the time surface. Returns a two-channel `(flow_x,
Free-function form of
obj.optical_flow(*args, **kwargs).
- eventcv.pset(obj, *args, **kwargs)¶
Calls
obj.pset(...).Free-function form of
obj.pset(*args, **kwargs).
- eventcv.refractory_filter(obj, *args, **kwargs)¶
Refractory-period filter: suppresses a pixel’s events for dt after it fires.
Free-function form of
obj.refractory_filter(*args, **kwargs).
- eventcv.resize(obj, *args, **kwargs)¶
Event-domain resize to a width`×`height grid (rebinned, not interpolated).
Free-function form of
obj.resize(*args, **kwargs).
- eventcv.rotate90(obj, *args, **kwargs)¶
Rotates by k * 90° clockwise (quarter turns swap the sensor dims).
Free-function form of
obj.rotate90(*args, **kwargs).
- eventcv.scale(obj, *args, **kwargs)¶
Scales the sensor by (sx, sy).
Free-function form of
obj.scale(*args, **kwargs).
- eventcv.sort_by_time(obj, *args, **kwargs)¶
Returns a copy reordered by ascending timestamp (stable).
Free-function form of
obj.sort_by_time(*args, **kwargs).
- eventcv.tencode(obj, *args, **kwargs)¶
Calls
obj.tencode(...).Free-function form of
obj.tencode(*args, **kwargs).
- eventcv.time_scale(obj, *args, **kwargs)¶
Scales every timestamp by factor (rounded).
Free-function form of
obj.time_scale(*args, **kwargs).
- eventcv.time_shift(obj, *args, **kwargs)¶
Shifts every timestamp by dt microseconds.
Free-function form of
obj.time_shift(*args, **kwargs).
- eventcv.time_window(obj, *args, **kwargs)¶
Keeps events whose timestamp lies in the half-open window [t0, t1) (microseconds).
Free-function form of
obj.time_window(*args, **kwargs).
- eventcv.translate(obj, *args, **kwargs)¶
Translates by (dx, dy); events shifted off the sensor are dropped.
Free-function form of
obj.translate(*args, **kwargs).
- eventcv.transpose(obj, *args, **kwargs)¶
Reflects across the main diagonal ((x, y) → (y, x)); swaps the sensor dims.
Free-function form of
obj.transpose(*args, **kwargs).
- eventcv.tsurf(obj, *args, **kwargs)¶
Calls
obj.tsurf(...).Free-function form of
obj.tsurf(*args, **kwargs).
- eventcv.undistort(obj, *args, **kwargs)¶
Rectifies events with a Camera’s intrinsics + distortion (lens undistortion).
Free-function form of
obj.undistort(*args, **kwargs).
- eventcv.view(obj, *args, **kwargs)¶
Opens the interactive viewer on this stream. Pass a representation name to choose what
Free-function form of
obj.view(*args, **kwargs).
- eventcv.voxel(obj, *args, **kwargs)¶
Calls
obj.voxel(...).Free-function form of
obj.voxel(*args, **kwargs).
- eventcv.warp_affine(obj, *args, **kwargs)¶
Applies a 2×3 affine matrix [[a,b,c],[d,e,f]] (rounded, no interpolation).
Free-function form of
obj.warp_affine(*args, **kwargs).
- eventcv.warp_perspective(obj, *args, **kwargs)¶
Applies a 3×3 perspective (homography) matrix.
Free-function form of
obj.warp_perspective(*args, **kwargs).