1use std::fs;
2use std::path::Path;
3use std::time::Duration;
4
5use yscv_detect::BoundingBox;
6use yscv_tensor::Tensor;
7
8use crate::error::AppError;
9
10pub fn duration_to_ms(duration: Duration) -> f64 {
11 duration.as_secs_f64() * 1000.0
12}
13
14pub fn ensure_parent_dir(path: &Path) -> Result<(), std::io::Error> {
15 if let Some(parent) = path.parent()
16 && !parent.as_os_str().is_empty()
17 {
18 fs::create_dir_all(parent)?;
19 }
20 Ok(())
21}
22
23pub fn face_min_area(frame_width: usize, frame_height: usize) -> usize {
24 let frame_area = frame_width.saturating_mul(frame_height);
25 ((frame_area as f32 * 0.003).round() as usize).max(4)
26}
27
28pub fn embedding_from_bbox(
29 bbox: BoundingBox,
30 frame_width: f32,
31 frame_height: f32,
32) -> Result<Tensor, AppError> {
33 let cx = ((bbox.x1 + bbox.x2) * 0.5) / frame_width;
34 let cy = ((bbox.y1 + bbox.y2) * 0.5) / frame_height;
35 let area = bbox.area() / (frame_width * frame_height);
36 Ok(Tensor::from_vec(vec![3], vec![cx, cy, area])?)
37}