pub struct EventStream { /* private fields */ }Expand description
A stream of events stored column-wise (struct-of-arrays). Columns compress and
transform far better than interleaved rows, and timestamps use i64 (µs) so
real multi-second recordings fit. See TASKS.md §3.
The columns are shared, not owned: a transform that rewrites one column hands the other three
on untouched, and clone is four refcount bumps rather than a copy of the whole recording.
Arc<Vec<T>> rather than Arc<[T]> because the latter cannot reuse a Vec’s allocation (the
refcount header sits in the same block), so every EventStreamBuilder::build — every reader
slice, every subsetting transform — would copy all four columns; and because Arc::make_mut
gives copy-on-write for free on a Vec and is not available on an unsized [T].
Implementations§
Source§impl EventStream
impl EventStream
Sourcepub fn event_rate(&self, bin_us: i64) -> EventRate
pub fn event_rate(&self, bin_us: i64) -> EventRate
Bins the stream into fixed-width intervals of bin_us and counts events in each.
Bins span the stream’s own extent — from the earliest to the latest timestamp — so an empty
stream produces no bins and a stream that does not divide evenly gets a final short bin that
is still counted. A bin_us below 1 is clamped, since a zero-width bin has no rate.
Does not require sorted input: bins are indexed arithmetically from the minimum timestamp
rather than by walking in order, so this is safe to call before sort_by_time.
Source§impl EventStream
impl EventStream
Sourcepub fn random_flip_x(&self, p: f64, seed: u64) -> EventStream
pub fn random_flip_x(&self, p: f64, seed: u64) -> EventStream
Mirrors the stream left-right with probability p.
Sourcepub fn random_flip_y(&self, p: f64, seed: u64) -> EventStream
pub fn random_flip_y(&self, p: f64, seed: u64) -> EventStream
Mirrors the stream top-bottom with probability p.
Sourcepub fn random_polarity_flip(&self, p: f64, seed: u64) -> EventStream
pub fn random_polarity_flip(&self, p: f64, seed: u64) -> EventStream
Inverts every polarity with probability p.
Draws once for the stream, not once per event: flipping a random subset of polarities is label noise, whereas flipping all of them is the physically meaningful augmentation (the same scene with the contrast direction reversed).
Sourcepub fn random_crop(&self, width: usize, height: usize, seed: u64) -> EventStream
pub fn random_crop(&self, width: usize, height: usize, seed: u64) -> EventStream
Takes a random width × height crop. A window at least as large as the sensor is the
identity, so this is safe to leave in a pipeline that also runs on smaller recordings.
Sourcepub fn event_drop(&self, p: f64, seed: u64) -> EventStream
pub fn event_drop(&self, p: f64, seed: u64) -> EventStream
Drops each event independently with probability p, thinning the stream without changing its
geometry or duration. p <= 0 is the identity; p >= 1 empties the stream.
Sourcepub fn pixel_dropout(&self, p: f64, seed: u64) -> EventStream
pub fn pixel_dropout(&self, p: f64, seed: u64) -> EventStream
Silences a random p fraction of pixels for the whole stream.
Unlike EventStream::event_drop, which thins events independently, this removes every event
from the chosen pixels — the failure mode of a real sensor with dead pixels, and a much harder
augmentation for a model to average away.
Sourcepub fn spatial_jitter(&self, sigma: f64, seed: u64) -> EventStream
pub fn spatial_jitter(&self, sigma: f64, seed: u64) -> EventStream
Jitters each event’s position by a rounded gaussian offset with standard deviation sigma
pixels. Events pushed off the sensor are dropped, so a large sigma also thins the stream.
Sourcepub fn time_jitter(&self, sigma: f64, seed: u64) -> EventStream
pub fn time_jitter(&self, sigma: f64, seed: u64) -> EventStream
Jitters each event’s timestamp by a rounded gaussian offset with standard deviation sigma
(same units as the stored timestamps, i.e. µs).
Re-sorts afterwards: jitter can reorder neighbouring events, and the correlation-based filters
(background_activity_filter, refractory_filter) require ascending time.
Sourcepub fn time_reversal(&self, p: f64, seed: u64) -> EventStream
pub fn time_reversal(&self, p: f64, seed: u64) -> EventStream
Plays the stream backwards with probability p, inverting polarity to match.
Reversing time without inverting polarity would be physically wrong: an edge that brightened as it passed darkens when the same motion is run in reverse. Timestamps are mirrored within the stream’s own span, so the result starts and ends where the original did.
Source§impl EventStream
impl EventStream
Sourcepub fn iwe(
&self,
model: WarpModel,
params: &[f64],
) -> Result<EventFrame, CmaxError>
pub fn iwe( &self, model: WarpModel, params: &[f64], ) -> Result<EventFrame, CmaxError>
Accumulates the image of warped events for an explicit motion.
The picture the objective actually scores, returned so it can be looked at — a blurred IWE with the “right” parameters is the clearest sign that a warp model does not fit the scene.
Sourcepub fn contrast_maximise(
&self,
model: WarpModel,
config: CmaxConfig,
) -> Result<CmaxResult, CmaxError>
pub fn contrast_maximise( &self, model: WarpModel, config: CmaxConfig, ) -> Result<CmaxResult, CmaxError>
Finds the motion that makes the warped events sharpest.
Returns the recovered parameters along with the score at rest, so the caller can tell a real
estimate from the optimiser wandering on a flat landscape — see CmaxResult::improvement.
Source§impl EventStream
impl EventStream
Sourcepub fn efast(&self) -> EventStream
pub fn efast(&self) -> EventStream
eFAST event corner detector (Mueggler et al., Fast Event-based Corner Detection,
BMVC 2017). For each event it updates its polarity’s SAE, then tests two Bresenham rings
(radius 3 and 4) around the pixel: an event is a corner when, on both rings, the most
recent timestamps form a contiguous arc within the INNER_ARC/OUTER_ARC bounds — the
signature of a moving corner rather than a straight edge. Events too close to the border to
evaluate the outer ring are dropped. Returns the corner events as a new stream.
Sourcepub fn harris_corners(&self, threshold: f64) -> EventStream
pub fn harris_corners(&self, threshold: f64) -> EventStream
Harris corner score on the Surface of Active Events. For each event it updates a
merged SAE of raw latest timestamps, then computes the normalised Harris response
det(M)/trace(M)² - k of the structure tensor M = Σ ∇T ∇Tᵀ of the SAE’s spatial
gradient over a 9×9 window. Because the SAE is a local time ramp, a straight moving edge
has a constant gradient direction (rank-1 M, R < 0) while a corner mixes gradient
directions (rank-2 M, R > 0) — so the default threshold = 0 keeps corners and rejects
edges. The score is bounded to [-k, 0.25 - k] = [-0.04, 0.21], so raising threshold
within that range is what makes it stricter; anything above 0.21 keeps nothing. Returns
the corner events as a new stream; a score-based complement to Self::efast.
Source§impl EventStream
impl EventStream
Sourcepub fn background_activity_filter(&self, dt: i64) -> EventStream
pub fn background_activity_filter(&self, dt: i64) -> EventStream
Background-activity (nearest-neighbour) noise filter. Keeps an event only if some pixel in
its 3×3 neighbourhood fired within dt (raw timestamp units, as Self::time_window):
uncorrelated noise, which has no recent neighbours, is dropped. Assumes ascending time.
See Self::background_activity_filter_with to use the 4-neighbour cross instead, which
rejects uncorrelated noise more cleanly.
Sourcepub fn background_activity_filter_with(
&self,
dt: i64,
neighbourhood: Neighbourhood,
) -> EventStream
pub fn background_activity_filter_with( &self, dt: i64, neighbourhood: Neighbourhood, ) -> EventStream
Self::background_activity_filter over a chosen Neighbourhood.
Sourcepub fn refractory_filter(&self, dt: i64) -> EventStream
pub fn refractory_filter(&self, dt: i64) -> EventStream
Refractory-period filter: after a pixel fires, suppress its events for dt (raw timestamp
units). Keeps an event only when at least dt has elapsed since that pixel’s last kept
event; dropped events do not refresh the dead time. Assumes ascending time.
That rule is RefreshOn::Kept, the hardware definition of a dead time. tonic and evlib
instead restart the clock on every arriving event — see
Self::refractory_filter_with to reproduce them.
Sourcepub fn refractory_filter_with(&self, dt: i64, refresh: RefreshOn) -> EventStream
pub fn refractory_filter_with(&self, dt: i64, refresh: RefreshOn) -> EventStream
Self::refractory_filter under a chosen RefreshOn rule.
Sourcepub fn hot_pixel_filter(&self, n_std: f64) -> EventStream
pub fn hot_pixel_filter(&self, n_std: f64) -> EventStream
Hot-pixel removal: drops every event from stuck pixels whose total event count exceeds
mean + n_std·std, with the mean and standard deviation taken over the active pixels
(those with at least one event). A uniform or empty stream removes nothing.
Sourcepub fn hot_pixel_mask(&self, n_std: f64) -> Vec<bool>
pub fn hot_pixel_mask(&self, n_std: f64) -> Vec<bool>
The hot-pixel mask this stream would remove: true at each pixel whose total event count
exceeds mean + n_std·std (statistics over the active pixels), row-major width·height.
Degenerate sensors give an empty mask. Exposed on its own so a reader can compute the mask
once over a whole recording and apply it to every slice with Self::drop_masked_pixels
— a per-slice hot_pixel_filter instead re-thresholds each window, so hot pixels survive at
long accumulation times.
Sourcepub fn add_pixel_counts(&self, counts: &mut [u64])
pub fn add_pixel_counts(&self, counts: &mut [u64])
Adds this stream’s per-pixel event counts into counts (row-major width·height for this
stream’s sensor); a mismatched buffer is left untouched. Lets a reader tally a whole
recording chunk-by-chunk — feeding Self::hot_pixel_mask_from_counts — without ever
materialising the full file, so the pre-scan stays within bounded memory.
Sourcepub fn hot_pixel_mask_from_counts(counts: &[u64], n_std: f64) -> Vec<bool>
pub fn hot_pixel_mask_from_counts(counts: &[u64], n_std: f64) -> Vec<bool>
The hot-pixel mask for pre-tallied per-pixel counts: true where a count exceeds
mean + n_std·std taken over the active (non-zero) pixels. All-zero counts flag nothing.
The chunked-scan counterpart of Self::hot_pixel_mask.
Sourcepub fn drop_masked_pixels(&self, mask: &[bool]) -> EventStream
pub fn drop_masked_pixels(&self, mask: &[bool]) -> EventStream
Drops every event whose pixel is flagged true in mask (row-major width·height, as
Self::hot_pixel_mask returns), keeping (x, y, p, t) and order. A mask that does not
match the sensor grid (e.g. the empty mask of a degenerate sensor) removes nothing, so a
reader can carry one whole-recording mask and apply it to every slice unconditionally.
Source§impl EventStream
impl EventStream
Sourcepub fn optical_flow(&self, window: usize) -> Result<EventFrame, FlowError>
pub fn optical_flow(&self, window: usize) -> Result<EventFrame, FlowError>
Estimates dense optical flow by Lucas-Kanade on the time surface. window is the
half-width of the least-squares neighbourhood (a (2·window+1)² patch); it must be at
least 1. Returns a two-channel f32 frame — channel 0 flow_x, channel 1 flow_y, in
pixels/ms — zero wherever flow is undefined.
Source§impl EventStream
impl EventStream
Sourcepub fn filter_polarity(&self, polarity: bool) -> EventStream
pub fn filter_polarity(&self, polarity: bool) -> EventStream
Keeps only events of the given polarity.
Sourcepub fn invert_polarity(&self) -> EventStream
pub fn invert_polarity(&self) -> EventStream
Flips every event’s polarity. Sensor and timestamps unchanged.
Sourcepub fn sort_by_time(&self) -> EventStream
pub fn sort_by_time(&self) -> EventStream
Returns a copy reordered by ascending timestamp (stable for equal timestamps).
Sourcepub fn concat(&self, others: &[&EventStream]) -> EventStream
pub fn concat(&self, others: &[&EventStream]) -> EventStream
Concatenates several streams into one (in argument order, not time-sorted). The sensor
size is the element-wise maximum of the inputs; the timestamp scale comes from self.
Source§impl EventStream
impl EventStream
Sourcepub fn crop(&self, x0: i64, y0: i64, w: usize, h: usize) -> EventStream
pub fn crop(&self, x0: i64, y0: i64, w: usize, h: usize) -> EventStream
Keeps events inside the w×h window at (x0, y0) and shifts them to a new origin.
The result is a w×h stream.
Sourcepub fn flip_x(&self) -> EventStream
pub fn flip_x(&self) -> EventStream
Mirrors horizontally (x → width-1-x). Sensor size unchanged.
Sourcepub fn flip_y(&self) -> EventStream
pub fn flip_y(&self) -> EventStream
Mirrors vertically (y → height-1-y). Sensor size unchanged.
Sourcepub fn rotate90(&self, k: i32) -> EventStream
pub fn rotate90(&self, k: i32) -> EventStream
Rotates by k * 90° clockwise. k is taken mod 4; quarter turns swap the sensor dims.
A quarter turn swaps the two coordinate columns before rewriting one of them, so it copies one column rather than four.
Sourcepub fn transpose(&self) -> EventStream
pub fn transpose(&self) -> EventStream
Reflects across the main diagonal ((x, y) → (y, x)); swaps the sensor dims.
Sourcepub fn translate(&self, dx: i64, dy: i64) -> EventStream
pub fn translate(&self, dx: i64, dy: i64) -> EventStream
Translates by (dx, dy); events shifted off the sensor are dropped. Sensor unchanged.
Sourcepub fn resize(&self, w: usize, h: usize) -> EventStream
pub fn resize(&self, w: usize, h: usize) -> EventStream
Resizes the sensor grid to w×h, rebinning each coordinate proportionally (floored —
the destination bin, no interpolation). Every event maps into [0, w)×[0, h), so the
count is conserved; on downscale several events may share a pixel (lossless).
Sourcepub fn scale(&self, sx: f64, sy: f64) -> EventStream
pub fn scale(&self, sx: f64, sy: f64) -> EventStream
Scales the sensor by (sx, sy), rounding the new dimensions. See Self::resize.
Sourcepub fn warp_affine(&self, m: [[f64; 3]; 2]) -> EventStream
pub fn warp_affine(&self, m: [[f64; 3]; 2]) -> EventStream
Applies a 2×3 affine matrix [[a,b,c],[d,e,f]] (x' = a·x+b·y+c, rounded). Sensor
size unchanged; events warped off the sensor are dropped.
Sourcepub fn warp_perspective(&self, m: [[f64; 3]; 3]) -> EventStream
pub fn warp_perspective(&self, m: [[f64; 3]; 3]) -> EventStream
Applies a 3×3 perspective (homography) matrix, dividing by the homogeneous coordinate. Events whose denominator is zero, or that warp off the sensor, are dropped.
Sourcepub fn undistort(&self, camera: &Camera) -> EventStream
pub fn undistort(&self, camera: &Camera) -> EventStream
Rectifies events with a Camera’s intrinsics + distortion, mapping each event from its
distorted pixel to the undistorted location on the same grid. Builds a per-pixel lookup
once (the sensor grid is small), then remaps every event through it; events landing off
the sensor after rectification are dropped. Sensor size unchanged.
Source§impl EventStream
impl EventStream
Sourcepub fn time_window(&self, t0: i64, t1: i64) -> EventStream
pub fn time_window(&self, t0: i64, t1: i64) -> EventStream
Keeps events whose timestamp lies in the half-open window [t0, t1).
In a time-ordered stream — what every reader and the simulator produce — the window is a contiguous range, so this is two binary searches and a slice rather than a predicate per event; a window covering the whole stream copies nothing at all. The scan that establishes the ordering is one pass over the timestamps and vectorises, and an unordered stream falls back to the general path rather than being silently mis-windowed.
Sourcepub fn time_shift(&self, dt: i64) -> EventStream
pub fn time_shift(&self, dt: i64) -> EventStream
Shifts every timestamp by dt (same units as the stored timestamps).
Sourcepub fn time_scale(&self, factor: f64) -> EventStream
pub fn time_scale(&self, factor: f64) -> EventStream
Scales every timestamp by factor (rounded), e.g. to change playback speed.
Sourcepub fn normalize_time(&self) -> EventStream
pub fn normalize_time(&self) -> EventStream
Shifts timestamps so the earliest event starts at zero. A no-op on an empty stream.
Sourcepub fn decimate(&self, k: usize) -> EventStream
pub fn decimate(&self, k: usize) -> EventStream
Keeps every k-th event by index (k = 1 is the identity); k = 0 is treated as 1.
Source§impl EventStream
impl EventStream
pub fn len(&self) -> usize
pub fn is_empty(&self) -> bool
pub fn sensor_size(&self) -> (usize, usize)
pub fn timestamp_scale_ms(&self) -> f64
pub fn xs(&self) -> &[u16]
pub fn ys(&self) -> &[u16]
pub fn ts(&self) -> &[i64]
pub fn ps(&self) -> &[bool]
pub fn iter(&self) -> impl Iterator<Item = Event> + '_
Trait Implementations§
Source§impl Clone for EventStream
impl Clone for EventStream
Source§fn clone(&self) -> EventStream
fn clone(&self) -> EventStream
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for EventStream
impl RefUnwindSafe for EventStream
impl Send for EventStream
impl Sync for EventStream
impl Unpin for EventStream
impl UnsafeUnpin for EventStream
impl UnwindSafe for EventStream
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more