Skip to main content

eventcv_core/representation/
tencode.rs

1use super::{
2    age_ms, event_index, frame_len, reference_time, validate_positive, EventFrame, EventFrameData,
3    Representation, RepresentationError, RepresentationKind,
4};
5use crate::EventStream;
6
7#[derive(Clone, Copy, Debug)]
8pub struct Tencode {
9    window_ms: f64,
10}
11
12impl Tencode {
13    pub fn new(window_ms: f64) -> Self {
14        Self { window_ms }
15    }
16}
17
18impl Default for Tencode {
19    fn default() -> Self {
20        Self::new(30.0)
21    }
22}
23
24impl Representation for Tencode {
25    type Output = EventFrame;
26
27    fn generate(&self, stream: &EventStream) -> Result<EventFrame, RepresentationError> {
28        validate_positive(self.window_ms, "window_ms")?;
29        let (width, height, length) = frame_len(stream, 3)?;
30        let plane_len = width * height;
31        let mut latest = vec![None; plane_len];
32        let mut values = vec![0_u8; length];
33
34        if let Some(reference) = reference_time(stream) {
35            for (order, event) in stream.iter().enumerate() {
36                if age_ms(stream, reference, event.timestamp) > self.window_ms {
37                    continue;
38                }
39                let index = event_index(event, width, height)?;
40                if latest[index].is_none_or(|(timestamp, previous_order, _)| {
41                    event.timestamp > timestamp
42                        || (event.timestamp == timestamp && order > previous_order)
43                }) {
44                    latest[index] = Some((event.timestamp, order, event.polarity));
45                }
46            }
47
48            for (index, event) in latest.into_iter().enumerate() {
49                if let Some((timestamp, _, polarity)) = event {
50                    if polarity {
51                        values[index] = u8::MAX;
52                    } else {
53                        values[2 * plane_len + index] = u8::MAX;
54                    }
55                    values[plane_len + index] = (255.0 * age_ms(stream, reference, timestamp)
56                        / self.window_ms)
57                        .round()
58                        .clamp(0.0, 255.0) as u8;
59                }
60            }
61        }
62
63        Ok(EventFrame {
64            data: EventFrameData::U8(values),
65            channels: 3,
66            width,
67            height,
68            kind: RepresentationKind::Tencode,
69            channel_names: vec![
70                "positive".to_owned(),
71                "age".to_owned(),
72                "negative".to_owned(),
73            ],
74        })
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use ndarray::array;
81
82    use super::{Representation, Tencode};
83    use crate::{representation::EventFrameData, EventStream};
84
85    #[test]
86    fn encodes_latest_polarity_and_age() {
87        let stream = EventStream::from_array2(
88            array![[0, 0, 10_000, 1], [1, 0, 30_000, 1], [1, 0, 30_000, 0]],
89            2,
90            1,
91            0.001,
92        );
93
94        let frame = Tencode::new(30.0).generate(&stream).unwrap();
95
96        assert_eq!(
97            frame.data(),
98            &EventFrameData::U8(vec![255, 0, 170, 0, 0, 255])
99        );
100    }
101}