eventcv_core/representation/
count.rs1use super::{
2 event_index, frame_len, EventFrame, EventFrameData, Representation, RepresentationError,
3 RepresentationKind,
4};
5use crate::EventStream;
6
7#[derive(Clone, Copy, Debug, Default)]
12pub struct EventCount {
13 normalize: bool,
14}
15
16impl EventCount {
17 pub fn new(normalize: bool) -> Self {
18 Self { normalize }
19 }
20
21 pub fn is_normalized(&self) -> bool {
22 self.normalize
23 }
24}
25
26impl Representation for EventCount {
27 type Output = EventFrame;
28
29 fn generate(&self, stream: &EventStream) -> Result<EventFrame, RepresentationError> {
30 let (width, height, length) = frame_len(stream, 1)?;
31 let mut counts = vec![0_u64; length];
32
33 for event in stream.iter() {
34 counts[event_index(event, width, height)?] += 1;
35 }
36
37 let data = if self.normalize {
38 EventFrameData::U8(normalize_u8(&counts))
39 } else {
40 EventFrameData::U64(counts)
41 };
42
43 Ok(EventFrame {
44 data,
45 channels: 1,
46 width,
47 height,
48 kind: RepresentationKind::Count,
49 channel_names: vec!["count".to_owned()],
50 })
51 }
52}
53
54fn normalize_u8(counts: &[u64]) -> Vec<u8> {
56 let maximum = counts.iter().copied().max().unwrap_or(0);
57 if maximum == 0 {
58 return vec![0; counts.len()];
59 }
60 counts
61 .iter()
62 .map(|&count| {
63 let scaled = count * u64::from(u8::MAX);
64 ((scaled + maximum / 2) / maximum) as u8
65 })
66 .collect()
67}
68
69#[cfg(test)]
70mod tests {
71 use ndarray::array;
72
73 use super::{EventCount, Representation};
74 use crate::{representation::EventFrameData, EventStream};
75
76 #[test]
77 fn sums_both_polarities_into_one_plane() {
78 let stream = EventStream::from_array2(
79 array![[0, 0, 1, 1], [0, 0, 2, 0], [1, 1, 3, 1]],
80 2,
81 2,
82 0.001,
83 );
84
85 let frame = EventCount::default().generate(&stream).unwrap();
86
87 assert_eq!(frame.shape(), (1, 2, 2));
88 assert_eq!(frame.data(), &EventFrameData::U64(vec![2, 0, 0, 1]));
89 }
90
91 #[test]
92 fn normalizes_the_busiest_pixel_to_full_scale() {
93 let stream = EventStream::from_array2(
94 array![[0, 0, 1, 1], [0, 0, 2, 0], [1, 0, 3, 1]],
95 2,
96 1,
97 0.001,
98 );
99
100 let frame = EventCount::new(true).generate(&stream).unwrap();
101
102 assert_eq!(frame.data(), &EventFrameData::U8(vec![255, 128]));
103 }
104
105 #[test]
106 fn rejects_out_of_bounds_events() {
107 let stream = EventStream::from_array2(array![[2, 0, 10, 1]], 2, 2, 0.001);
108
109 let error = EventCount::default().generate(&stream).unwrap_err();
110
111 assert_eq!(
112 error.to_string(),
113 "event coordinate (2, 0) exceeds sensor size 2x2"
114 );
115 }
116}