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)
Table of Contents
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 Stream API that offer a higher level of abstraction as explained in the following section.
Using SDK Stream C++ API
The SDK Stream 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.
See also
It is also possible to use the C++ class CameraStreamSlicer
that slices a stream of events
and triggers according to a given condition (a fixed number of events, a fixed duration or a mix of both).
This class is illustrated in the metavision_camera_stream_slicer C++ sample.
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 easiest 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
See also
It is also possible to use the Python class CameraStreamSlicer
that slices a stream of events and triggers according to a given condition (a fixed number of events, a fixed duration or a mix of both).
This class is illustrated in the metavision_camera_stream_slicer Python sample.
Using HAL Python API
If you want to use the lower level HAL API, you can check
the metavision_hal_get_started sample
that shows how to load events using get_latest_raw_data()
function.