Skip to main content

Python bindings for event camera utilities

Project description

evlib logo

evlib: Event Camera Data Processing Library

PyPI Version Python Versions Documentation Python Rust Platform License

An event camera processing library with a Rust backend and Python bindings, designed for scalable data processing with real-world event camera datasets.

Architecture

evlib keeps a thin Rust core and does all DataFrame work in Polars from Python:

  • Rust (evlib._evlib) handles only what cannot be expressed as DataFrame operations: binary format parsing (EVT2/EVT3/EVT2.1, AEDAT, AER, HDF5 with the ECF codec), construction of the Polars frame from decoded primitives, and the native dense scatter-add kernels that build RVT stacked-histogram representations (evlib.representations_rs.stacked_histogram_dense on the CPU, plus _cuda and _metal GPU kernels).
  • Python Polars handles all processing: loading filters, filtering (evlib.filtering), and representations (evlib.representations, evlib.rvt). Every query is a lazy Polars LazyFrame collected with a selectable engine, so the same code runs on the CPU streaming engine today and on the GPU via cudf-polars (collect(engine="gpu")) where CUDA is available.

evlib.load_events returns a LazyFrame and applies any time, spatial, or polarity filters as Polars expressions, so loading and filtering fuse into one GPU-collectable query.

Quick Start

xkcd

What are Event Cameras?

Event cameras (also called neuromorphic or dynamic vision sensors) operate asynchronously: each pixel independently reports brightness changes as they occur, rather than sampling frames at a fixed rate.

Each event is represented as a 4-tuple:

$$e = (x, y, t, p)$$

Where:

  • $x, y \in \mathbb{N}$: Pixel coordinates
  • $t \in \mathbb{R}^+$: Timestamp (microsecond precision)
  • $p \in {-1, +1}$ or ${0, 1}$: Polarity (brightness change direction)

An event fires when the logarithmic brightness change exceeds a threshold:

$$\log(L(x,y,t)) - \log(L(x,y,t_{\text{last}})) > \pm C$$

where $C$ is the contrast threshold. This yields microsecond temporal resolution, 120 dB+ dynamic range, and data sparsity proportional to scene motion.

For a deeper introduction, see the user guide.

event data visualisation

Basic Usage

import evlib

# Automatic format detection: returns a Polars LazyFrame
events = evlib.load_events("data/prophesee/samples/evt2/80_balls.raw")

df = events.collect(engine="streaming")
print(f"Loaded {len(df):,} events")
print(f"Resolution: {df['x'].max()} x {df['y'].max()}")
print(f"Duration:   {df['t'].max() - df['t'].min()}")

Chain Polars expressions for efficient filtering and representation extraction:

import evlib
import evlib.representations as evr
import polars as pl

events = evlib.load_events("data/prophesee/samples/hdf5/pedestrians.hdf5")

# Temporal + spatial + polarity filtering, lazily
filtered = events.filter(
    (pl.col("t").dt.total_microseconds() / 1_000_000).is_between(0.1, 0.5)
    & pl.col("x").is_between(100, 500)
    & (pl.col("polarity") == 1)
)

# Produce a stacked histogram ready for an RVT-style model
hist = evr.create_stacked_histogram(
    filtered.collect(),
    height=180, width=240,
    bins=5, window_duration_ms=50.0,
)

The transformation turns a raw asynchronous event stream into a dense, model-ready tensor. Below, the pedestrians sequence: on the left, 250ms of raw events (red +1, blue -1); on the right, the same window as a stacked histogram of five 50ms temporal bins, where the walking figures advance bin to bin:

evlib: pedestrians event stream transformed into a stacked-histogram representation, shown as five temporal bins

Both this and a fully reproducible 80_balls version (from the tracked EVT2 sample) are generated by python scripts/generate_representation_figures.py.

See the representations guide for voxel grids, time surfaces, and mixed density stacks.

RVT preprocessing backends

evlib.rvt.process_sequence(...) reproduces the RVT stacked-histogram preprocessing pipeline and offers four interchangeable backends via backend=:

  • "polars": Polars on the CPU, or on the cudf GPU engine when you pass an engine= of "gpu" or a pl.GPUEngine(...).
  • "rust": Rust dense scatter-add on the CPU.
  • "cuda": a custom CUDA scatter-add kernel on an NVIDIA GPU. It loads the nvcc-built librvt_scatter.so via the EVLIB_CUDA_LIB environment variable.
  • "metal": a Metal scatter-add kernel on Apple Silicon. Build it with CC=clang maturin develop --features metal.

The underlying native kernels are exposed directly as evlib.representations_rs.stacked_histogram_dense (CPU), stacked_histogram_dense_cuda, and stacked_histogram_dense_metal.

Performance

evlib is bit-validated against the reference implementations it competes with: RVT (PyTorch), tonic, OpenEB, and dv_processing. On the gen4_1mpx validation set (18 sequences, RTX 4090), the RVT preprocessing output is bit-identical to RVT torch bar a single roughly 1e-10 boundary quirk, and the timings are:

  • evlib CUDA: 283.6s, slightly ahead of RVT torch-GPU at 286.3s (parity-plus, about 1.01x).
  • evlib Rust-CPU: 406.2s, 1.32x faster than RVT torch-CPU at 534.2s.
  • evlib CUDA is 1.88x faster than RVT torch-CPU.

For the standalone representations (20M events, versus tonic NumPy): voxel_grid 1.35x, event_frame 2.9x, time_surface 2.1x.

The Polars GPU engine is not a free win for single operations, and the CUDA-versus-RVT-GPU margin is parity-plus rather than a large speedup. The biggest margins are evlib's CPU backends and the standalone representations.

[!Note]

State of the GPU and Metal work: the CUDA backend is the production GPU path and edges out RVT's torch-GPU pipeline. The Metal backend is bit-identical to the CPU kernel on an M2 Pro, but about 3x slower there: the workload is memory-bound and the M2 Pro's CPU cores win. Metal is a portability path (an on-device kernel where torch-CUDA cannot run), not a speed win on M2-class hardware; use backend="rust" for the fastest Apple-CPU path.

evlib vs RVT preprocessing on an RTX 4090: evlib is faster than RVT on both GPU and CPU, bit-identical

More plots: the full five-backend chart rvt_final_time.png (and rvt_final_memory.png for peak memory), plus tonic_bench_time.png for the representations-versus-tonic comparison.

Full documentation: https://tallamjr.github.io/evlib/

Installation

# Basic install
pip install evlib

# With PyTorch integration
pip install evlib[pytorch]

From source (requires Rust nightly and maturin):

git clone https://github.com/tallamjr/evlib.git
cd evlib
uv venv --python 3.12 && source .venv/bin/activate
uv pip install -e ".[dev]"
maturin develop                    # default minimal build
maturin develop --features hdf5    # opt-in HDF5 support (Linux/macOS)

[!Warning]

Known issue: --features hdf5 fails against Homebrew HDF5 2.x. The Rust binding (hdf5-metno-sys 0.10.1) only supports HDF5 1.8/1.10/1.12/1.14 and panics on a 2.x header with Invalid H5_VERSION: "2.1.1". Homebrew now ships 2.x, and even its hdf5@1.14 formula currently resolves to 2.1.1, so there is no Homebrew-based fix. To build the feature, point HDF5_DIR at a genuine 1.8-1.14 install from another source, for example conda-forge:

conda install -c conda-forge "hdf5=1.14"
HDF5_DIR="$CONDA_PREFIX" maturin develop --features hdf5

The default build (no --features hdf5) is unaffected: read HDF5 via h5py, or use the EVT2/EVT3 readers (which need no HDF5 feature). On Windows, HDF5 is always read through h5py.

Distributable wheels are built with the opt-in extension-module feature, e.g. maturin build --release --features python,polars,arrow,extension-module. That feature is deliberately off by default so cargo test and maturin develop build and run without linking errors.

GPU scatter-add kernels are opt-in features. For the CUDA backend, build the nvcc kernel and point EVLIB_CUDA_LIB at the resulting librvt_scatter.so. For the Metal backend on Apple Silicon, build with CC=clang maturin develop --features metal.

HDF5 is opt-in on Linux/macOS and unavailable on Windows; use h5py directly for HDF5 I/O on Windows. Full details and platform-specific notes live in the installation guide.

Documentation

Complete documentation is published at https://tallamjr.github.io/evlib/:

Examples

Runnable examples live in examples/:

python examples/simple_example.py
python examples/filtering_demo.py
python examples/stacked_histogram_demo.py

# Jupyter notebooks
pytest --nbmake examples/

Benchmarks live in benchmarks/: the Python suite (bench_rvt_dataset.py, bench_tonic.py) at the top level, and the Rust criterion benches under benchmarks/rust/.

Development

# Tests (both run directly, no special flags needed)
pytest                        # Python (test suite only)
cargo test                    # Rust
pytest --markdown-docs docs/  # doc examples (explicit)
pytest --nbmake examples/     # example notebooks (explicit)

# Formatting / linting
black python/ tests/ examples/
cargo fmt
ruff check python/ tests/
cargo clippy -- -D warnings

See CONTRIBUTING and the architecture overview for design details.

Community & Support

  • Issues: Report bugs and request features

xkcd

License

MIT License. See LICENSE.md for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

evlib-0.12.0-cp313-cp313-win_amd64.whl (17.5 MB view details)

Uploaded CPython 3.13Windows x86-64

evlib-0.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (16.6 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

evlib-0.12.0-cp313-cp313-macosx_11_0_arm64.whl (14.9 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

evlib-0.12.0-cp312-cp312-win_amd64.whl (17.5 MB view details)

Uploaded CPython 3.12Windows x86-64

evlib-0.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (16.6 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

evlib-0.12.0-cp312-cp312-macosx_11_0_arm64.whl (14.9 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

evlib-0.12.0-cp311-cp311-win_amd64.whl (17.5 MB view details)

Uploaded CPython 3.11Windows x86-64

evlib-0.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (16.6 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

evlib-0.12.0-cp311-cp311-macosx_11_0_arm64.whl (14.9 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

File details

Details for the file evlib-0.12.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: evlib-0.12.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 17.5 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for evlib-0.12.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 282972dc87a9a9e204624881ca96094e8e29eb75f5922d2145763af94d54be7c
MD5 56c381e391f73934f2ce404a13431c2d
BLAKE2b-256 90a190e1243f1f19ee5b80b52e8e0a5ada020ed8e8acd963e2ee197bbeb31c7b

See more details on using hashes here.

File details

Details for the file evlib-0.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for evlib-0.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 f0ddc0d1ae0a2420b9beb01ac96c6578beecbda01ce15380d667e1185d2eba4d
MD5 13ed05f0e5be0c299d57021e82bd9e87
BLAKE2b-256 2ea90f25d65788804162b5a32b4c4e0deb702cb507cb662df519183aaf9dbd4c

See more details on using hashes here.

File details

Details for the file evlib-0.12.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for evlib-0.12.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 69ea63df0654c43fb9861caa7855ad3b5db6c5d9f579b0758766b38f301f8171
MD5 3ab7918e5804a1042032020622b3e842
BLAKE2b-256 2b377f59253fcd8bf10a40393a51ba4b97513a924139097adacec0e79fe3a8b0

See more details on using hashes here.

File details

Details for the file evlib-0.12.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: evlib-0.12.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 17.5 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for evlib-0.12.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 bfcdd48d66e0bdcf64622e6d9e0d15336214b4700314b4ef42becfb9cf510bea
MD5 018c69a383e29073ffdf1cdb44d950e4
BLAKE2b-256 48f97c9024057f8d06c1d5096c5aa43163d33aee1066cb7cd732cef42ee10dba

See more details on using hashes here.

File details

Details for the file evlib-0.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for evlib-0.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b36bd3630bf7bb60ea69b66bb04c843691ecb94b879c98cccd6e19940a4aa0bf
MD5 9ae4e5173e0d360ce7c1979ea289f7db
BLAKE2b-256 bb389a24a7f17d3eac249aa6a6be230b74a23a67e171356accab1a378f7eff81

See more details on using hashes here.

File details

Details for the file evlib-0.12.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for evlib-0.12.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b242a9f39f786f49435ad0c764d32ce7eb2d4836dc5222eef85384f4e69aaebd
MD5 4c861acd5ce4ecad1e2ccdeed8b58e28
BLAKE2b-256 eeb8905be8449e9a8e2282d056d9f8ae319858071602c4ebc279247e32fa833a

See more details on using hashes here.

File details

Details for the file evlib-0.12.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: evlib-0.12.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 17.5 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for evlib-0.12.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 e4f512ff3fb95bf3c19fcf7766e7cb42d224faff3e4abbde52a11e097b04f0c5
MD5 302bedbce68092eb0e50ac5335e148db
BLAKE2b-256 249affe51df3e6db6724c587273828753e002eebc674b1d6c4b94db1c386a699

See more details on using hashes here.

File details

Details for the file evlib-0.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for evlib-0.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 8a1d28661ea1ce2ecc3df066bb4c027b552f559b8170086b933281304659b04d
MD5 c06ce2589a8bee6c7a896bb199b29e04
BLAKE2b-256 043bbd7105fe844f7d3c36748802daab96effb7c17af7b95af1d959f035f8bf1

See more details on using hashes here.

File details

Details for the file evlib-0.12.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for evlib-0.12.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 54903bb94301115ed9b4406eafa9f208115caeed429188bb19c8736ee264cc8e
MD5 da20ba9b72235733d3eedc26bb6bf6b9
BLAKE2b-256 02f4f9f6ffa2cd6234b85ce92ced82a0b2fdf803549102357e540458d269f857

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page