use crate::trackers::sort::{PositionalMetricType, SortAttributesOptions};
use crate::trackers::spatio_temporal_constraints::SpatioTemporalConstraints;
use crate::trackers::visual_sort::metric::builder::VisualMetricBuilder;
use crate::trackers::visual_sort::metric::{VisualMetric, VisualSortMetricType};
use std::collections::HashMap;
use std::sync::RwLock;
#[derive(Debug, Clone)]
pub struct VisualSortOptions {
max_idle_epochs: usize,
kept_history_length: usize,
spatio_temporal_constraints: SpatioTemporalConstraints,
metric_builder: VisualMetricBuilder,
kalman_position_weight: f32,
kalman_velocity_weight: f32,
}
impl VisualSortOptions {
pub(crate) fn build(self) -> (SortAttributesOptions, VisualMetric) {
(
SortAttributesOptions::new(
Some(RwLock::new(HashMap::default())),
self.max_idle_epochs,
self.kept_history_length,
self.spatio_temporal_constraints,
self.kalman_position_weight,
self.kalman_velocity_weight,
),
self.metric_builder.build(),
)
}
pub fn max_idle_epochs(mut self, n: usize) -> Self {
self.max_idle_epochs = n;
self
}
pub fn kept_history_length(mut self, n: usize) -> Self {
assert!(n > 0, "History length must be a positive number");
self.kept_history_length = n;
self
}
pub fn visual_metric(mut self, metric: VisualSortMetricType) -> Self {
self.metric_builder = self.metric_builder.visual_metric(metric);
self
}
pub fn visual_min_votes(mut self, n: usize) -> Self {
self.metric_builder = self.metric_builder.visual_min_votes(n);
self
}
pub fn visual_max_observations(mut self, n: usize) -> Self {
self.metric_builder = self.metric_builder.visual_max_observations(n);
self
}
pub fn positional_min_confidence(mut self, conf: f32) -> Self {
self.metric_builder = self.metric_builder.positional_min_confidence(conf);
self
}
pub fn spatio_temporal_constraints(mut self, constraints: SpatioTemporalConstraints) -> Self {
self.spatio_temporal_constraints = constraints;
self
}
pub fn positional_metric(mut self, metric: PositionalMetricType) -> Self {
self.metric_builder = self.metric_builder.positional_metric(metric);
self
}
pub fn visual_minimal_track_length(mut self, length: usize) -> Self {
self.metric_builder = self.metric_builder.visual_minimal_track_length(length);
self
}
pub fn visual_minimal_area(mut self, area: f32) -> Self {
self.metric_builder = self.metric_builder.visual_minimal_area(area);
self
}
pub fn visual_minimal_quality_use(mut self, q: f32) -> Self {
self.metric_builder = self.metric_builder.visual_minimal_quality_use(q);
self
}
pub fn visual_minimal_quality_collect(mut self, q: f32) -> Self {
self.metric_builder = self.metric_builder.visual_minimal_quality_collect(q);
self
}
pub fn visual_minimal_own_area_percentage_use(mut self, area: f32) -> Self {
self.metric_builder = self
.metric_builder
.visual_minimal_own_area_percentage_use(area);
self
}
pub fn visual_minimal_own_area_percentage_collect(mut self, area: f32) -> Self {
self.metric_builder = self
.metric_builder
.visual_minimal_own_area_percentage_collect(area);
self
}
pub fn kalman_position_weight(mut self, weight: f32) -> Self {
self.kalman_position_weight = weight;
self
}
pub fn kalman_velocity_weight(mut self, weight: f32) -> Self {
self.kalman_velocity_weight = weight;
self
}
}
impl Default for VisualSortOptions {
fn default() -> Self {
Self {
max_idle_epochs: 2,
kept_history_length: 10,
metric_builder: VisualMetricBuilder::default(),
spatio_temporal_constraints: SpatioTemporalConstraints::default(),
kalman_position_weight: 1.0 / 20.0,
kalman_velocity_weight: 1.0 / 160.0,
}
}
}
#[cfg(feature = "python")]
pub mod python {
use crate::trackers::sort::python::PyPositionalMetricType;
use crate::trackers::spatio_temporal_constraints::python::PySpatioTemporalConstraints;
use crate::trackers::visual_sort::metric::python::PyVisualSortMetricType;
use super::VisualSortOptions;
use pyo3::prelude::*;
#[pyclass]
#[pyo3(name = "VisualSortOptions")]
pub struct PyVisualSortOptions(pub(crate) VisualSortOptions);
#[pymethods]
impl PyVisualSortOptions {
#[new]
pub(crate) fn new() -> Self {
Self(VisualSortOptions::default())
}
#[pyo3(text_signature = "($self, n)")]
pub(crate) fn max_idle_epochs(&mut self, n: i64) {
self.0.max_idle_epochs = n.try_into().expect("Parameter must be a positive number");
}
#[pyo3(text_signature = "($self, n)")]
pub(crate) fn kept_history_length(&mut self, n: i64) {
self.0.kept_history_length = n.try_into().expect("Parameter must be a positive number");
}
#[pyo3(text_signature = "($self, n)")]
pub(crate) fn visual_min_votes(&mut self, n: i64) {
self.0.metric_builder.set_visual_min_votes(n as _);
}
#[pyo3(text_signature = "($self, metric)")]
pub(crate) fn visual_metric(&mut self, metric: PyVisualSortMetricType) {
self.0.metric_builder.set_visual_kind(metric.0);
}
#[pyo3(text_signature = "($self, constraints)")]
pub(crate) fn spatio_temporal_constraints(
&mut self,
constraints: PySpatioTemporalConstraints,
) {
self.0.spatio_temporal_constraints = constraints.0;
}
#[pyo3(text_signature = "($self, metric)")]
pub(crate) fn positional_metric(&mut self, metric: PyPositionalMetricType) {
self.0.metric_builder.set_positional_kind(metric.0);
}
#[pyo3(text_signature = "($self, length)")]
pub(crate) fn visual_minimal_track_length(&mut self, length: i64) {
self.0.metric_builder.set_visual_minimal_track_length(
length
.try_into()
.expect("Parameter must be a positive number"),
);
}
#[pyo3(text_signature = "($self, area)")]
pub(crate) fn visual_minimal_area(&mut self, area: f32) {
self.0.metric_builder.set_visual_minimal_area(area);
}
#[pyo3(text_signature = "($self, q)")]
pub(crate) fn visual_minimal_quality_use(&mut self, q: f32) {
self.0.metric_builder.set_visual_minimal_quality_use(q);
}
#[pyo3(text_signature = "($self, conf)")]
pub(crate) fn positional_min_confidence(&mut self, conf: f32) {
self.0.metric_builder.set_positional_min_confidence(conf);
}
#[pyo3(text_signature = "($self, n)")]
pub(crate) fn visual_max_observations(&mut self, n: i64) {
self.0.metric_builder.set_visual_max_observations(
n.try_into().expect("Parameter must be a positive number"),
);
}
#[pyo3(text_signature = "($self, q)")]
pub(crate) fn visual_minimal_quality_collect(&mut self, q: f32) {
self.0.metric_builder.set_visual_minimal_quality_collect(q);
}
#[pyo3(text_signature = "($self, area)")]
pub(crate) fn visual_minimal_own_area_percentage_use(&mut self, area: f32) {
self.0
.metric_builder
.set_visual_minimal_own_area_percentage_use(area);
}
#[pyo3(text_signature = "($self, area)")]
pub(crate) fn visual_minimal_own_area_percentage_collect(&mut self, area: f32) {
self.0
.metric_builder
.set_visual_minimal_own_area_percentage_collect(area);
}
#[pyo3(text_signature = "($self, weight)")]
pub(crate) fn kalman_position_weight(&mut self, weight: f32) {
self.0.kalman_position_weight = weight;
}
#[pyo3(text_signature = "($self, weight)")]
pub(crate) fn kalman_velocity_weight(&mut self, weight: f32) {
self.0.kalman_velocity_weight = weight;
}
#[classattr]
const __hash__: Option<Py<PyAny>> = None;
fn __repr__(&self) -> String {
format!("{:?}", self.0)
}
fn __str__(&self) -> String {
format!("{:#?}", self.0)
}
}
}
#[cfg(test)]
mod tests {
use crate::trackers::sort::python::PyPositionalMetricType;
use crate::trackers::sort::PositionalMetricType;
use crate::trackers::spatio_temporal_constraints::python::PySpatioTemporalConstraints;
use crate::trackers::spatio_temporal_constraints::SpatioTemporalConstraints;
use crate::trackers::visual_sort::metric::python::PyVisualSortMetricType;
use crate::trackers::visual_sort::metric::VisualSortMetricType;
use crate::trackers::visual_sort::options::python::PyVisualSortOptions;
use crate::trackers::visual_sort::options::VisualSortOptions;
#[test]
fn visual_sort_options_builder() {
let (opts, metric) = dbg!(VisualSortOptions::default()
.max_idle_epochs(3)
.kept_history_length(10)
.visual_metric(VisualSortMetricType::Euclidean(100.0))
.positional_metric(PositionalMetricType::Mahalanobis)
.visual_minimal_track_length(3)
.visual_minimal_area(5.0)
.visual_minimal_quality_use(0.45)
.visual_minimal_quality_collect(0.5)
.visual_max_observations(25)
.visual_min_votes(5)
.positional_min_confidence(0.13)
.visual_minimal_own_area_percentage_use(0.1)
.visual_minimal_own_area_percentage_collect(0.2)
.spatio_temporal_constraints(
SpatioTemporalConstraints::default().constraints(&[(5, 7.0)])
)
.build());
let mut opts_builder = PyVisualSortOptions::new();
opts_builder.max_idle_epochs(3);
opts_builder.kept_history_length(10);
opts_builder.visual_metric(PyVisualSortMetricType::euclidean(100.0));
opts_builder.positional_metric(PyPositionalMetricType::maha());
opts_builder.visual_minimal_track_length(3);
opts_builder.visual_minimal_area(5.0);
opts_builder.visual_minimal_quality_use(0.45);
opts_builder.visual_minimal_quality_collect(0.5);
opts_builder.visual_max_observations(25);
opts_builder.positional_min_confidence(0.13);
opts_builder.visual_minimal_own_area_percentage_use(0.1);
opts_builder.visual_minimal_own_area_percentage_collect(0.2);
opts_builder.visual_min_votes(5);
let mut constraints = PySpatioTemporalConstraints::new();
constraints.add_constraints(vec![(5, 7.0)]);
opts_builder.spatio_temporal_constraints(constraints);
let (opts_py, metric_py) = dbg!(opts_builder.0.build());
assert_eq!(format!("{:?}", opts), format!("{:?}", opts_py));
assert_eq!(format!("{:?}", metric), format!("{:?}", metric_py));
}
}