use std::iter::zip;
use super::new_fixed_vec;
pub trait Data {
fn get_frame_p_frame_data(&self) -> *mut u8;
fn get_frame_data_len(&self) -> usize;
fn get_min_depth_mm(&self) -> u16;
fn get_max_depth_mm(&self) -> u16;
fn current_frame_is_depth(&self) -> bool;
}
pub struct TouchDetector {
min_depth: u16,
max_depth: u16,
min_touch: f32,
max_touch: f32,
pixel_count: usize,
baseline_sample_size: usize,
sample_size: usize,
baseline_sample: usize,
sample: usize,
baseline_depth_sum: Vec<u32>,
depth_sum: Vec<u32>,
ring_buffer: Vec<u16>,
}
impl TouchDetector {
pub fn new<Device: Data>(
device: &Device,
min_touch: f32,
max_touch: f32,
baseline_sample_size: usize,
sample_size: usize,
pixel_count: usize,
) -> Self {
Self {
min_depth: device.get_min_depth_mm(),
max_depth: device.get_max_depth_mm(),
min_touch,
max_touch,
pixel_count,
baseline_sample_size,
sample_size,
baseline_sample: 0,
sample: 0,
baseline_depth_sum: new_fixed_vec(pixel_count, 0u32),
depth_sum: new_fixed_vec(pixel_count, 0u32),
ring_buffer: new_fixed_vec(sample_size * pixel_count, 0u16),
}
}
pub fn process<Device: Data>(
&mut self,
device: &Device,
touch_signal: &mut [u8],
distance: &mut [f32],
) {
if device.current_frame_is_depth() {
unsafe {
let p = match std::ptr::slice_from_raw_parts(
device.get_frame_p_frame_data(),
device.get_frame_data_len(),
)
.as_ref()
{
Some(ptr) => ptr,
None => return,
};
for (i, pi) in p.chunks_exact(2).enumerate() {
let depth_mm =
u16::from_le_bytes([pi[0], pi[1]]).clamp(self.min_depth, self.max_depth);
if self.baseline_sample < self.baseline_sample_size {
self.baseline_depth_sum[i] += depth_mm as u32;
}
let j = self.pixel_count * self.sample + i;
self.depth_sum[i] -= self.ring_buffer[j] as u32;
self.ring_buffer[j] = depth_mm;
self.depth_sum[i] += depth_mm as u32;
let diff = self.baseline_depth_sum[i] as f32 / self.baseline_sample_size as f32
- self.depth_sum[i] as f32 / self.sample_size as f32;
touch_signal[i] = if self.min_touch < diff && diff < self.max_touch {
255
} else {
0
};
distance[i] = diff;
}
}
self.sample = (self.sample + 1) % self.sample_size;
if self.baseline_sample < self.baseline_sample_size {
self.baseline_sample += 1;
}
}
}
pub fn get_normalized_average_depth(&self, average_depth: &mut [u8]) {
for (adi, dsi) in zip(average_depth, self.depth_sum.as_slice()) {
let d = *dsi as f32 / self.sample_size as f32;
*adi = ((d - self.min_depth as f32) * 255.0 / (self.max_depth - self.min_depth) as f32)
.floor() as u8;
}
}
pub fn get_baseline(&self) -> Vec<f32> {
let mut base_line = new_fixed_vec(self.baseline_depth_sum.len(), 0.0);
for (a, b) in zip(self.baseline_depth_sum.as_slice(), base_line.as_mut_slice()) {
*b = *a as f32 / self.baseline_sample_size as f32;
}
base_line
}
}