Reading Events from a Device

Once you opened a camera or an event file, the next thing you will likely do is to read the events.

Note

All the examples in the following sections are valid for both cameras and event files. When we use the term “device”, it covers both cases (similarly as a HAL device can be either a file or a camera)

Using HAL C++ API

For a good example on how to stream events from a device with HAL API in C++, you can check out the sample metavision_hal_showcase that demonstrate the mechanisms to open a device and fetch the CD events along with some more advanced camera functionalities configuration.

The main concept to fetch the CD events is to register a callback on the CD event decoder, so that when the events are fetched from the camera, they are automatically handled by this callback.

This code snippet from metavision_hal_showcase shows how to register the callback once you opened the device:

Metavision::I_EventDecoder<Metavision::EventCD> *i_cddecoder =
    device->get_facility<Metavision::I_EventDecoder<Metavision::EventCD>>();

if (i_cddecoder) {
    // Register a lambda function to be called on every CD events
    i_cddecoder->add_event_buffer_callback(
        [&event_analyzer](const Metavision::EventCD *begin, const Metavision::EventCD *end) {
            event_analyzer.process_events(begin, end);
        });
};

You will also need a stream decoder that will receive raw data from your device, and dispatch parts of the buffer to instances of I_EventDecoder for specific event types:

Metavision::I_EventsStreamDecoder *i_eventsstreamdecoder = device->get_facility<Metavision::I_EventsStreamDecoder>();

Then you need to call i_eventsstream->start() for the device to start streaming:

Metavision::I_EventsStream *i_eventsstream = device->get_facility<Metavision::I_EventsStream>();
i_eventsstream->start()

And finally, you need to fetch the buffers of events with i_eventsstream->get_latest_raw_data() and trigger the decoding by calls to i_eventsstreamdecoder->decode() that will call the CD events callback defined earlier.

while (!stop_decoding) {
    uint8_t *raw_data = i_eventsstream->get_latest_raw_data(n_bytes);
    i_eventsstreamdecoder->decode(raw_data, raw_data + n_bytes);
    }
});

Those functions can be useful to have a fine-grained management of device, but for most of the application it can be more convenient to use SDK Core and SDK Driver API that offer a higher level of abstraction as explained in the following section.

Using SDK Driver C++ API

The SDK driver module relies on HAL to provide a high level class that simplifies and enhances some operations for device streaming. It also provides other related functionalities such as camera settings serialization, file input/output support for other event based formats, etc.

Note that since this module originally predates the HAL concept, some functionalities are duplicated with what HAL provides today and will be cleaned/refactored in the future. The module name will probably change to better reflect those modifications.

So, to have access to the events from a device, we first need to create a function that will be associated to the camera callback on those events:

void my_function(const Metavision::EventCD *begin, const Metavision::EventCD *end) {
    // this loop allows us to get access to each event received in this callback
    for (const Metavision::EventCD *ev = begin; ev != end; ++ev) {
        // e.g. print coordinates of each event
        std::cout << "Event received: coordinates (" << ev->x << ", " << ev->y << ")" << std::endl;
    }
}

And then we should associate this function to the events of the camera objects and start the camera:

// add a callback that will be called periodically to give access to the latest events
cam.cd().add_callback(my_function);
// start the camera
cam.start();

To see this in action, check the Get Started using C++ page.

Using SDK Core Python API

Metavision SDK also provides a Python API which is a mix of Python bindings of the C++ classes and some pure Python modules. As we have seen in the guide on connecting to cameras with SDK Python API and reading events from a file with SDK Python API, the best way to connect to a device is to leverage the EventsIterator class.

Reading events with EventsIterator

Retrieving the events from an EventsIterator is as simple as iterating over this object:

mv_iterator = EventsIterator("")
for events in mv_iterator:
    if events.size != 0:
        print(events['x'][0], events['y'][0])   # Coordinates of the first event of the buffer

As shown in the API documentation of EventsIterator, there are three modes to read events using this iterator:

  • delta_t: data are loaded by timeslices

  • n_events: data are loaded by number of events

  • mixed: data are loaded choosing the first met criterion about the previous two

By default, the EventsIterator will use delta_t with timeslice of 10ms. Here is how to retrieve events from a RAW file by buffers covering 1 millions events:

mv_iterator = EventsIterator("/path/to/my_file.raw", mode="n_events", n_events=1000000)
for events in mv_iterator:
    // events will contain 1 million events

The events served by the iterator are stored in a numpy structured array. This means you can conveniently access each attribute of the events (\(x\),\(y\), polarity \(p\) and timestamp \(t\)) as a numpy array. It also allows to use native numpy operators such as slicing or boolean masking

Here are some usage examples:

# We can access different fields in this one dimensional array
# this shows only the timestamps of events
print(events['t'])
# which would return something similar to [0 0 0 0 0 0 1 1 1 1]

# To count the events of positive polarity you can do:
np.sum(events['p'] == 1)

To see the EventsIterator in action, check the Get Started using Python page.

Reading events with RawReader

In some cases, using an iterator might not be convenient, so it is possible to use another class from SDK Core Python API: RawReader. Similarly as EventsIterator this class can be used on both cameras and event files.

Here is a simple example showing how to retrieve events by slice of 50k events from a RAW file:

from metavision_core.event_io.raw_reader import RawReader
raw_stream = RawReader("/path/to/my_file.raw")
while not raw_stream.is_done():
    events = raw_stream.load_n_events(1000000)
    // do stuff with events

Here is another example with a live camera built from a device (allowing to tune the camera with the facilities) on which we read events by timeslice of 10ms:

from metavision_core.event_io.raw_reader import initiate_device
from metavision_core.event_io.raw_reader import RawReader
device = initiate_device("")
raw_stream = RawReader.from_device(device=device)
while not raw_stream.is_done():
    events = raw_stream.load_delta_t(10000)
    // do stuff with events