//! Trained face models for face tracking, behind one swappable interface.
//!
//! - [`FaceModel`]: what the face tracker (`effectcraft-track`) asks of a model: find a face in a
//! region of a frame, then follow it from frame to frame. A model reports its own points (a
//! mesh, for MediaPipe) plus a [`Topology`] saying which of them are the tracker's named
//! landmarks and which trace the face outline, so the tracker never depends on one model's
//! layout. The classical tracker stays built in as the fallback when no model is chosen.
//! - [`Roi`] and [`crop`]: the rotated square crops face models look at.
use crate::{ModelInfo, Result};
/// Which of a model's points are the tracker's landmarks and its face outline.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Topology {
/// The points tracing the face outline, in order around the face.
pub outline: &'static [usize],
/// (landmark id, as the tracker names them, e.g. `leftEyeInner`; point index). "Left" is
/// image-left. Chin and jaw come from the outline.
pub landmarks: &'static [(&'static str, usize)],
}
/// A face in a frame: the model's points (frame pixels) and its confidence (0–1).
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Face {
pub points: Vec<[f32; 2]>,
pub score: f32,
}
/// A trained face model (swappable: the face tracker only uses this interface). Frames are
/// straight RGB 0–1, row-major `w×h`, coordinates frame pixels.
pub trait FaceModel: Send + Sync {
fn info(&self) -> &'static ModelInfo;
fn topology(&self) -> &'static Topology;
/// The most confident face whose centre lies in `region` (`[x0, y0, x1, y1]`).
fn find(&self, rgb: &[[f32; 3]], w: usize, h: usize, region: [f32; 4]) -> Result