The EventCV Library for Event-Based Robotic Vision
Adam D. Hines, Michael Milford, Tobias Fischer
cs.RO
2026-09-18
QUT's EventCV unifies event-camera pipelines in OpenCV-style Python; on Jetson it builds representations 2.8–3.7× faster than existing libraries.
A USB webcam plus OpenCV is one function call. Event cameras still are not. Each pixel fires on its own when log intensity changes, emitting (x, y, t, p) at microsecond resolution, with dynamic range past 120 dB and a data rate that tracks scene activity. That is the right sensor for fast robots and harsh lighting.
The software never caught up. iniVation and Prophesee ship incompatible SDKs; USB does not install a driver by itself. Recordings sit in AEDAT, EVT3 RAW, HDF5, and ROS bags that most libraries cannot all read. Geometry, corners, motion, and tracking live in different packages. An offline script often cannot be pointed at a live camera through the same API. jAER covers the most ground, but a Java stack does not import into a PyTorch environment.
This is a plumbing gap. The algorithms (odometry, flow, recognition, localization) have been around for a decade.
QUT Centre for Robotics put the heavy work in a Rust core, eventcv-core: slice indexing, decoding, camera threads, representation building, filters, and estimators. The Python front end copies OpenCV's shape. Functions and bound methods are equivalent, so stream.voxel(bins=5) and ecv.voxel(stream, bins=5) do the same thing.
Live cameras go through Neuromorphic Drivers: Prophesee EVK3 HD and EVK4, iniVation DVXplorer and DAVIS346, SilkyEvCam HD, IDS uEye XCP-E. Nine file formats share one call: HDF5, ROS bags of dvsmsgs, AEDAT 2.0/4.0, Prophesee DAT and EVT2/EVT3 RAW, NumPy, delimited text. ecv.load pulls everything into memory; ecv.open plans slice-by-slice reads, which is the path for multi-GB recordings. Whatever it reads, it can write.
Processing acts on event coordinates, not on a raster first:
For deployment, ONNX Runtime consumes camera windows directly. ROS 2 goes through hiroz, a pure-Rust Zenoh stack, so the wheel does not link ROS C libraries. Prebuilt packages cover Linux x86-64 and aarch64, Apple silicon, and Windows x86-64. Jetson does not need a source build.
All timings ran on a Jetson Orin AGX, median of nine runs after two warm-ups, file in the page cache. Inputs: a 3.0 s, 1280×720 EVT3 clip (116.3 M events) and a 651 s, 346×260 HDF5 recording (707.6 M events). Baselines: Tonic 1.6.0, evlib 0.13.2, dv-processing 2.0.4, Expelliarmus 1.1.7. Everything is CPU.
Building representations from a 1.22 M-event slice:
| Representation | EventCV | Tonic | evlib | vs next-fastest |
| Polarity frame (2 ch.) | 23.78 ms | 136.36 | 67.22 | 2.8× |
| Voxel grid (5 bins) | 26.50 ms | 124.44 | 97.23 | 3.7× |
| Time surface | 21.33 ms | 59.16 | 80.76 | 2.8× |
Geometric mean is 3.4× faster than evlib and 4.2× faster than Tonic. Representations that neither baseline implements take 8.56–74.85 ms.
Single-thread decode: EVT3 53.8 Mev/s (Expelliarmus 33.5, 1.6×); AEDAT 4.0 85.4 (dv-processing 77.0 on its own LZ4 file, 1.1×); HDF5 16.3 (evlib 5.1, 3.2×). AEDAT 4.0 on twelve cores reaches 631.6 Mev/s. The abstract's 1.1× to 3.7× span is the decode floor and the representation ceiling.
Lazy I/O is the larger practical win. Eager-reading the 707.6 M-event HDF5 peaks at 8.87 GB (13.5 bytes per event). Opening it lazily takes 0.11 s, exposes 19,737 windows of 33 ms, and peaks at 273 MB while serving 200 random windows: 33× less RAM, 8.6 ms per window (16.0 ms at p99).
Three rebuilt pipelines. Prophesee's ev-ultralytics YOLO26 detector, OpenEB swapped for EventCV: both hit the network tensor in about 10.5 ms and finish a window in about 28 ms, of which YOLO26 inference is about 17.5 ms. EventCV matches, it does not win. The gap is install cost: seven lines of user code versus OpenEB Python bindings from a third-party apt repo of 44 packages, tied to system Python, with no ARM wheels. SuperEvent keypoints on a live Prophesee EVK4, 50 ms windows: 44.9–71.7 ms end to end (14–22 Hz), up to 170 points. Event-LAB, the group's localization benchmark, had more than 2,700 lines of custom formatting including CUDA representation code. EventCV on CPU matches that CUDA path on indoor/outdoor DAVIS346 and outdoor DVXplorer recordings, so this stage no longer needs a GPU.
A hot-pixel filter on a 3.9 GB DAVIS346 recording found 22 pixels that accounted for 15.4% of all events; a 33 ms slice dropped from 26,677 to 24,584 events.
For anyone putting an event camera on a robot: pip / conda / pixi, then stream. Offline and live share one API. aarch64 wheels are the Jetson-relevant part. Faster representations and decodes are incremental. Packing nine formats, filters, features, motion, simulation, ONNX, and ROS 2 into one package is the actual saving.
This is not a new-algorithm paper. eFAST, FEAST, contrast maximization, and v2e are re-implementations. The bet is OpenCV-shaped density, not a leaderboard. Vendor SDKs remain deeper on their own sensors. If a Metavision or dv-processing stack already works, the reason to switch is cross-vendor and cross-format work, not accuracy.
The authors list three. Event processing itself stays CPU-bound; the GPU path only hands representations to PyTorch or ONNX Runtime. ROS 2 rides Zenoh, so a stock DDS deployment still needs zenoh-bridge-ros2dds. Feature learning and motion estimation were not checked against their reference implementations.
A few more. The capability table gives EventCV three check marks everywhere; those scores are the authors' own. jAER is still more mature on bias, device control, and real-time tracking, and the paper says so. The YOLO case is a tie; the speed story lives in offline representations and file decode. The Event-LAB CUDA comparison reports "comparable" without Mev/s numbers. The simulator has no event-quality check against ESIM or original v2e.