eventcv_core/representation/
point_set.rs1use super::{event_index, Representation, RepresentationError};
2use crate::EventStream;
3
4#[derive(Clone, Copy, Debug, Default)]
5pub struct PointSet;
6
7#[derive(Clone, Debug, PartialEq)]
8pub struct EventPointSet {
9 data: Vec<f32>,
10 len: usize,
11}
12
13impl EventPointSet {
14 pub fn data(&self) -> &[f32] {
15 &self.data
16 }
17
18 pub fn shape(&self) -> (usize, usize) {
19 (self.len, 4)
20 }
21
22 pub fn columns(&self) -> (&'static str, &'static str, &'static str, &'static str) {
23 ("x", "y", "t", "p")
24 }
25}
26
27impl Representation for PointSet {
28 type Output = EventPointSet;
29
30 fn generate(&self, stream: &EventStream) -> Result<EventPointSet, RepresentationError> {
31 let (width, height) = stream.sensor_size();
32 let capacity = stream
33 .len()
34 .checked_mul(4)
35 .ok_or(RepresentationError::SizeOverflow)?;
36 let mut data = Vec::with_capacity(capacity);
37 let minimum_time = stream
38 .iter()
39 .map(|event| event.timestamp)
40 .min()
41 .unwrap_or(0);
42 let maximum_time = stream
43 .iter()
44 .map(|event| event.timestamp)
45 .max()
46 .unwrap_or(0);
47 let duration = maximum_time - minimum_time;
48
49 for event in stream.iter() {
50 event_index(event, width, height)?;
51 data.extend([
52 normalize_coordinate(event.x, width),
53 normalize_coordinate(event.y, height),
54 if duration == 0 {
55 0.0
56 } else {
57 (event.timestamp - minimum_time) as f32 / duration as f32
58 },
59 if event.polarity { 1.0 } else { -1.0 },
60 ]);
61 }
62
63 Ok(EventPointSet {
64 data,
65 len: stream.len(),
66 })
67 }
68}
69
70fn normalize_coordinate(coordinate: usize, length: usize) -> f32 {
71 if length <= 1 {
72 0.0
73 } else {
74 coordinate as f32 / (length - 1) as f32
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use ndarray::array;
81
82 use super::{PointSet, Representation};
83 use crate::EventStream;
84
85 #[test]
86 fn normalizes_points_without_reordering_events() {
87 let stream = EventStream::from_array2(
88 array![[1, 0, 30, 0], [0, 2, 10, 1], [1, 1, 20, 1]],
89 2,
90 3,
91 0.001,
92 );
93
94 let points = PointSet.generate(&stream).unwrap();
95
96 assert_eq!(points.shape(), (3, 4));
97 assert_eq!(
98 points.data(),
99 &[1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.5, 0.5, 1.0]
100 );
101 }
102
103 #[test]
104 fn zero_duration_streams_have_zero_normalized_time() {
105 let stream = EventStream::from_array2(array![[0, 0, 10, 1], [1, 0, 10, 0]], 2, 1, 0.001);
106
107 let points = PointSet.generate(&stream).unwrap();
108
109 assert_eq!(points.data()[2], 0.0);
110 assert_eq!(points.data()[6], 0.0);
111 }
112}