#![warn(missing_docs)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::similar_names)]
#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::cast_sign_loss)]
#![allow(clippy::cast_precision_loss)]
#![allow(clippy::cast_lossless)]
#![allow(clippy::cast_possible_wrap)]
#![allow(clippy::many_single_char_names)]
#![allow(clippy::too_many_lines)]
#![allow(clippy::needless_range_loop)]
#![allow(clippy::missing_panics_doc)]
#![allow(clippy::unused_self)]
#![allow(clippy::items_after_statements)]
#![allow(clippy::manual_memcpy)]
#![allow(clippy::unnecessary_wraps)]
#![allow(clippy::trivially_copy_pass_by_ref)]
#![allow(clippy::single_match_else)]
#![allow(clippy::must_use_candidate)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::manual_swap)]
#![allow(clippy::doc_markdown)]
#![allow(dead_code)]
pub mod action_beat;
pub mod activity;
pub mod adaptive_scene;
pub mod aesthetic;
pub mod audio_visual_correlation;
#[path = "camera_motion/mod.rs"]
pub mod camera_motion;
pub mod classification;
pub mod classify;
pub mod color_temperature;
pub mod complexity_detector;
pub mod composition;
pub mod content_moderation;
pub mod continuity_check;
pub mod crowd_density;
pub mod depth_of_field;
pub mod detect;
pub mod emotion_recognition;
pub mod error;
pub mod event;
pub mod face_landmark;
pub mod features;
pub mod lighting_analysis;
pub mod location;
pub mod mood;
pub mod motion_energy;
pub mod object_tracker;
pub mod pacing;
pub mod saliency;
pub mod scene_boundary;
pub mod scene_captioning;
pub mod scene_graph;
pub mod scene_metadata;
pub mod scene_score;
pub mod scene_stats;
pub mod scene_tags;
pub mod segment;
pub mod segmentation;
pub mod shot_type;
pub mod storyboard;
pub mod summarization;
pub mod temporal_graph;
pub mod text_detect;
pub mod thumbnail_selector;
pub mod transition;
pub mod visual_quality_map;
pub mod visual_rhythm;
pub use error::{SceneError, SceneResult};
pub mod common {
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct Point {
pub x: f32,
pub y: f32,
}
impl Point {
#[must_use]
pub const fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
#[must_use]
pub fn distance(&self, other: &Self) -> f32 {
let dx = self.x - other.x;
let dy = self.y - other.y;
(dx * dx + dy * dy).sqrt()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct Rect {
pub x: f32,
pub y: f32,
pub width: f32,
pub height: f32,
}
impl Rect {
#[must_use]
pub const fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
Self {
x,
y,
width,
height,
}
}
#[must_use]
pub const fn area(&self) -> f32 {
self.width * self.height
}
#[must_use]
pub const fn center(&self) -> Point {
Point {
x: self.x + self.width / 2.0,
y: self.y + self.height / 2.0,
}
}
#[must_use]
pub const fn contains(&self, point: &Point) -> bool {
point.x >= self.x
&& point.x <= self.x + self.width
&& point.y >= self.y
&& point.y <= self.y + self.height
}
#[must_use]
pub fn iou(&self, other: &Self) -> f32 {
let x1 = self.x.max(other.x);
let y1 = self.y.max(other.y);
let x2 = (self.x + self.width).min(other.x + other.width);
let y2 = (self.y + self.height).min(other.y + other.height);
if x2 <= x1 || y2 <= y1 {
return 0.0;
}
let intersection = (x2 - x1) * (y2 - y1);
let union = self.area() + other.area() - intersection;
if union == 0.0 {
0.0
} else {
intersection / union
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Confidence(f32);
impl Confidence {
#[must_use]
pub fn new(value: f32) -> Self {
Self(value.clamp(0.0, 1.0))
}
#[must_use]
pub const fn value(&self) -> f32 {
self.0
}
#[must_use]
pub const fn meets_threshold(&self, threshold: f32) -> bool {
self.0 >= threshold
}
}
impl From<f32> for Confidence {
fn from(value: f32) -> Self {
Self::new(value)
}
}
impl From<Confidence> for f32 {
fn from(conf: Confidence) -> Self {
conf.0
}
}
}
#[cfg(test)]
mod tests {
use super::common::*;
#[test]
fn test_point_distance() {
let p1 = Point::new(0.0, 0.0);
let p2 = Point::new(3.0, 4.0);
assert!((p1.distance(&p2) - 5.0).abs() < f32::EPSILON);
}
#[test]
fn test_rect_area() {
let rect = Rect::new(0.0, 0.0, 10.0, 20.0);
assert!((rect.area() - 200.0).abs() < f32::EPSILON);
}
#[test]
fn test_rect_center() {
let rect = Rect::new(0.0, 0.0, 10.0, 20.0);
let center = rect.center();
assert!((center.x - 5.0).abs() < f32::EPSILON);
assert!((center.y - 10.0).abs() < f32::EPSILON);
}
#[test]
fn test_rect_contains() {
let rect = Rect::new(0.0, 0.0, 10.0, 20.0);
assert!(rect.contains(&Point::new(5.0, 10.0)));
assert!(!rect.contains(&Point::new(15.0, 10.0)));
}
#[test]
fn test_rect_iou() {
let rect1 = Rect::new(0.0, 0.0, 10.0, 10.0);
let rect2 = Rect::new(5.0, 5.0, 10.0, 10.0);
let iou = rect1.iou(&rect2);
assert!((iou - 0.1428571).abs() < 0.001);
}
#[test]
fn test_confidence() {
let conf = Confidence::new(0.75);
assert!((conf.value() - 0.75).abs() < f32::EPSILON);
assert!(conf.meets_threshold(0.5));
assert!(!conf.meets_threshold(0.8));
let conf_high = Confidence::new(1.5);
assert!((conf_high.value() - 1.0).abs() < f32::EPSILON);
let conf_low = Confidence::new(-0.5);
assert!((conf_low.value() - 0.0).abs() < f32::EPSILON);
}
}