cecile_supercool_tracker/trackers/visual_sort/
options.rs1use crate::trackers::sort::{PositionalMetricType, SortAttributesOptions};
2use crate::trackers::spatio_temporal_constraints::SpatioTemporalConstraints;
3use crate::trackers::visual_sort::metric::builder::VisualMetricBuilder;
4use crate::trackers::visual_sort::metric::{VisualMetric, VisualSortMetricType};
5use std::collections::HashMap;
6use std::sync::RwLock;
7
8#[derive(Debug, Clone)]
10pub struct VisualSortOptions {
11 max_idle_epochs: usize,
12 kept_history_length: usize,
13 spatio_temporal_constraints: SpatioTemporalConstraints,
14 metric_builder: VisualMetricBuilder,
15 kalman_position_weight: f32,
16 kalman_velocity_weight: f32,
17}
18
19impl VisualSortOptions {
20 pub(crate) fn build(self) -> (SortAttributesOptions, VisualMetric) {
21 (
22 SortAttributesOptions::new(
23 Some(RwLock::new(HashMap::default())),
24 self.max_idle_epochs,
25 self.kept_history_length,
26 self.spatio_temporal_constraints,
27 self.kalman_position_weight,
28 self.kalman_velocity_weight,
29 ),
30 self.metric_builder.build(),
31 )
32 }
33
34 pub fn max_idle_epochs(mut self, n: usize) -> Self {
43 self.max_idle_epochs = n;
44 self
45 }
46
47 pub fn kept_history_length(mut self, n: usize) -> Self {
57 assert!(n > 0, "History length must be a positive number");
58 self.kept_history_length = n;
59 self
60 }
61
62 pub fn visual_metric(mut self, metric: VisualSortMetricType) -> Self {
68 self.metric_builder = self.metric_builder.visual_metric(metric);
69 self
70 }
71
72 pub fn visual_min_votes(mut self, n: usize) -> Self {
87 self.metric_builder = self.metric_builder.visual_min_votes(n);
88 self
89 }
90
91 pub fn visual_max_observations(mut self, n: usize) -> Self {
96 self.metric_builder = self.metric_builder.visual_max_observations(n);
97 self
98 }
99
100 pub fn positional_min_confidence(mut self, conf: f32) -> Self {
104 self.metric_builder = self.metric_builder.positional_min_confidence(conf);
105 self
106 }
107
108 pub fn spatio_temporal_constraints(mut self, constraints: SpatioTemporalConstraints) -> Self {
113 self.spatio_temporal_constraints = constraints;
114 self
115 }
116
117 pub fn positional_metric(mut self, metric: PositionalMetricType) -> Self {
122 self.metric_builder = self.metric_builder.positional_metric(metric);
123 self
124 }
125
126 pub fn visual_minimal_track_length(mut self, length: usize) -> Self {
133 self.metric_builder = self.metric_builder.visual_minimal_track_length(length);
134 self
135 }
136
137 pub fn visual_minimal_area(mut self, area: f32) -> Self {
141 self.metric_builder = self.metric_builder.visual_minimal_area(area);
142 self
143 }
144
145 pub fn visual_minimal_quality_use(mut self, q: f32) -> Self {
149 self.metric_builder = self.metric_builder.visual_minimal_quality_use(q);
150 self
151 }
152
153 pub fn visual_minimal_quality_collect(mut self, q: f32) -> Self {
157 self.metric_builder = self.metric_builder.visual_minimal_quality_collect(q);
158 self
159 }
160
161 pub fn visual_minimal_own_area_percentage_use(mut self, area: f32) -> Self {
166 self.metric_builder = self
167 .metric_builder
168 .visual_minimal_own_area_percentage_use(area);
169 self
170 }
171
172 pub fn visual_minimal_own_area_percentage_collect(mut self, area: f32) -> Self {
177 self.metric_builder = self
178 .metric_builder
179 .visual_minimal_own_area_percentage_collect(area);
180 self
181 }
182
183 pub fn kalman_position_weight(mut self, weight: f32) -> Self {
184 self.kalman_position_weight = weight;
185 self
186 }
187
188 pub fn kalman_velocity_weight(mut self, weight: f32) -> Self {
189 self.kalman_velocity_weight = weight;
190 self
191 }
192}
193
194impl Default for VisualSortOptions {
195 fn default() -> Self {
196 Self {
197 max_idle_epochs: 2,
198 kept_history_length: 10,
199 metric_builder: VisualMetricBuilder::default(),
200 spatio_temporal_constraints: SpatioTemporalConstraints::default(),
201 kalman_position_weight: 1.0 / 20.0,
202 kalman_velocity_weight: 1.0 / 160.0,
203 }
204 }
205}
206
207#[cfg(feature = "python")]
208pub mod python {
209 use crate::trackers::sort::python::PyPositionalMetricType;
210 use crate::trackers::spatio_temporal_constraints::python::PySpatioTemporalConstraints;
211 use crate::trackers::visual_sort::metric::python::PyVisualSortMetricType;
212
213 use super::VisualSortOptions;
214 use pyo3::prelude::*;
215
216 #[pyclass]
217 #[pyo3(name = "VisualSortOptions")]
218 pub struct PyVisualSortOptions(pub(crate) VisualSortOptions);
219
220 #[pymethods]
221 impl PyVisualSortOptions {
222 #[new]
223 pub(crate) fn new() -> Self {
224 Self(VisualSortOptions::default())
225 }
226
227 #[pyo3(text_signature = "($self, n)")]
228 pub(crate) fn max_idle_epochs(&mut self, n: i64) {
229 self.0.max_idle_epochs = n.try_into().expect("Parameter must be a positive number");
230 }
231
232 #[pyo3(text_signature = "($self, n)")]
233 pub(crate) fn kept_history_length(&mut self, n: i64) {
234 self.0.kept_history_length = n.try_into().expect("Parameter must be a positive number");
235 }
236
237 #[pyo3(text_signature = "($self, n)")]
238 pub(crate) fn visual_min_votes(&mut self, n: i64) {
239 self.0.metric_builder.set_visual_min_votes(n as _);
240 }
241
242 #[pyo3(text_signature = "($self, metric)")]
243 pub(crate) fn visual_metric(&mut self, metric: PyVisualSortMetricType) {
244 self.0.metric_builder.set_visual_kind(metric.0);
245 }
246
247 #[pyo3(text_signature = "($self, constraints)")]
248 pub(crate) fn spatio_temporal_constraints(
249 &mut self,
250 constraints: PySpatioTemporalConstraints,
251 ) {
252 self.0.spatio_temporal_constraints = constraints.0;
253 }
254
255 #[pyo3(text_signature = "($self, metric)")]
256 pub(crate) fn positional_metric(&mut self, metric: PyPositionalMetricType) {
257 self.0.metric_builder.set_positional_kind(metric.0);
258 }
259
260 #[pyo3(text_signature = "($self, length)")]
261 pub(crate) fn visual_minimal_track_length(&mut self, length: i64) {
262 self.0.metric_builder.set_visual_minimal_track_length(
263 length
264 .try_into()
265 .expect("Parameter must be a positive number"),
266 );
267 }
268
269 #[pyo3(text_signature = "($self, area)")]
270 pub(crate) fn visual_minimal_area(&mut self, area: f32) {
271 self.0.metric_builder.set_visual_minimal_area(area);
272 }
273
274 #[pyo3(text_signature = "($self, q)")]
275 pub(crate) fn visual_minimal_quality_use(&mut self, q: f32) {
276 self.0.metric_builder.set_visual_minimal_quality_use(q);
277 }
278
279 #[pyo3(text_signature = "($self, conf)")]
280 pub(crate) fn positional_min_confidence(&mut self, conf: f32) {
281 self.0.metric_builder.set_positional_min_confidence(conf);
282 }
283
284 #[pyo3(text_signature = "($self, n)")]
285 pub(crate) fn visual_max_observations(&mut self, n: i64) {
286 self.0.metric_builder.set_visual_max_observations(
287 n.try_into().expect("Parameter must be a positive number"),
288 );
289 }
290
291 #[pyo3(text_signature = "($self, q)")]
292 pub(crate) fn visual_minimal_quality_collect(&mut self, q: f32) {
293 self.0.metric_builder.set_visual_minimal_quality_collect(q);
294 }
295
296 #[pyo3(text_signature = "($self, area)")]
297 pub(crate) fn visual_minimal_own_area_percentage_use(&mut self, area: f32) {
298 self.0
299 .metric_builder
300 .set_visual_minimal_own_area_percentage_use(area);
301 }
302
303 #[pyo3(text_signature = "($self, area)")]
304 pub(crate) fn visual_minimal_own_area_percentage_collect(&mut self, area: f32) {
305 self.0
306 .metric_builder
307 .set_visual_minimal_own_area_percentage_collect(area);
308 }
309
310 #[pyo3(text_signature = "($self, weight)")]
311 pub(crate) fn kalman_position_weight(&mut self, weight: f32) {
312 self.0.kalman_position_weight = weight;
313 }
314
315 #[pyo3(text_signature = "($self, weight)")]
316 pub(crate) fn kalman_velocity_weight(&mut self, weight: f32) {
317 self.0.kalman_velocity_weight = weight;
318 }
319
320 #[classattr]
321 const __hash__: Option<Py<PyAny>> = None;
322
323 fn __repr__(&self) -> String {
324 format!("{:?}", self.0)
325 }
326
327 fn __str__(&self) -> String {
328 format!("{:#?}", self.0)
329 }
330 }
331}
332
333#[cfg(test)]
334mod tests {
335 use crate::trackers::sort::python::PyPositionalMetricType;
336 use crate::trackers::sort::PositionalMetricType;
337 use crate::trackers::spatio_temporal_constraints::python::PySpatioTemporalConstraints;
338 use crate::trackers::spatio_temporal_constraints::SpatioTemporalConstraints;
339 use crate::trackers::visual_sort::metric::python::PyVisualSortMetricType;
340 use crate::trackers::visual_sort::metric::VisualSortMetricType;
341 use crate::trackers::visual_sort::options::python::PyVisualSortOptions;
342 use crate::trackers::visual_sort::options::VisualSortOptions;
343
344 #[test]
345 fn visual_sort_options_builder() {
346 let (opts, metric) = dbg!(VisualSortOptions::default()
347 .max_idle_epochs(3)
348 .kept_history_length(10)
349 .visual_metric(VisualSortMetricType::Euclidean(100.0))
350 .positional_metric(PositionalMetricType::Mahalanobis)
351 .visual_minimal_track_length(3)
352 .visual_minimal_area(5.0)
353 .visual_minimal_quality_use(0.45)
354 .visual_minimal_quality_collect(0.5)
355 .visual_max_observations(25)
356 .visual_min_votes(5)
357 .positional_min_confidence(0.13)
358 .visual_minimal_own_area_percentage_use(0.1)
359 .visual_minimal_own_area_percentage_collect(0.2)
360 .spatio_temporal_constraints(
361 SpatioTemporalConstraints::default().constraints(&[(5, 7.0)])
362 )
363 .build());
364
365 let mut opts_builder = PyVisualSortOptions::new();
366 opts_builder.max_idle_epochs(3);
367 opts_builder.kept_history_length(10);
368 opts_builder.visual_metric(PyVisualSortMetricType::euclidean(100.0));
369 opts_builder.positional_metric(PyPositionalMetricType::maha());
370 opts_builder.visual_minimal_track_length(3);
371 opts_builder.visual_minimal_area(5.0);
372 opts_builder.visual_minimal_quality_use(0.45);
373 opts_builder.visual_minimal_quality_collect(0.5);
374 opts_builder.visual_max_observations(25);
375 opts_builder.positional_min_confidence(0.13);
376 opts_builder.visual_minimal_own_area_percentage_use(0.1);
377 opts_builder.visual_minimal_own_area_percentage_collect(0.2);
378 opts_builder.visual_min_votes(5);
379 let mut constraints = PySpatioTemporalConstraints::new();
380 constraints.add_constraints(vec![(5, 7.0)]);
381 opts_builder.spatio_temporal_constraints(constraints);
382 let (opts_py, metric_py) = dbg!(opts_builder.0.build());
383
384 assert_eq!(format!("{:?}", opts), format!("{:?}", opts_py));
385 assert_eq!(format!("{:?}", metric), format!("{:?}", metric_py));
386 }
387}