cecile_supercool_tracker/
examples.rs1pub mod iou;
2
3use crate::distance::euclidean;
4use crate::track::utils::FromVec;
5use crate::track::{
6 Feature, MetricOutput, MetricQuery, NoopLookup, Observation, ObservationAttributes,
7 ObservationMetric, ObservationsDb, TrackAttributes, TrackAttributesUpdate, TrackStatus,
8};
9use crate::utils::bbox::BoundingBox;
10use anyhow::Result;
11use rand::distributions::Uniform;
12use rand::prelude::ThreadRng;
13use rand::Rng;
14use std::time::{Duration, SystemTime, UNIX_EPOCH};
15use thiserror::Error;
16
17#[derive(Debug, Error)]
18pub enum AppError {
19 #[error("Only single feature vector can be set")]
20 SetError,
21 #[error("Incompatible attributes")]
22 Incompatible,
23}
24
25#[derive(Debug, Clone, Default)]
26pub struct SimpleAttrs {
27 set: bool,
28}
29
30#[derive(Default, Clone)]
31pub struct SimpleAttributeUpdate;
32
33impl TrackAttributesUpdate<SimpleAttrs> for SimpleAttributeUpdate {
34 fn apply(&self, attrs: &mut SimpleAttrs) -> Result<()> {
35 if attrs.set {
36 return Err(AppError::SetError.into());
37 }
38 attrs.set = true;
39 Ok(())
40 }
41}
42
43impl TrackAttributes<SimpleAttrs, f32> for SimpleAttrs {
44 type Update = SimpleAttributeUpdate;
45 type Lookup = NoopLookup<SimpleAttrs, f32>;
46
47 fn compatible(&self, other: &SimpleAttrs) -> bool {
48 self.set && other.set
49 }
50
51 fn merge(&mut self, other: &SimpleAttrs) -> Result<()> {
52 if self.compatible(other) {
53 Ok(())
54 } else {
55 Err(AppError::Incompatible.into())
56 }
57 }
58
59 fn baked(&self, _observations: &ObservationsDb<f32>) -> Result<TrackStatus> {
60 if self.set {
61 Ok(TrackStatus::Ready)
62 } else {
63 Ok(TrackStatus::Pending)
64 }
65 }
66}
67
68#[derive(Default, Clone)]
69pub struct SimpleMetric;
70
71impl ObservationMetric<SimpleAttrs, f32> for SimpleMetric {
72 fn metric(&self, mq: &MetricQuery<'_, SimpleAttrs, f32>) -> MetricOutput<f32> {
73 let (e1, e2) = (mq.candidate_observation, mq.track_observation);
74 Some((
75 f32::calculate_metric_object(&e1.attr().as_ref(), &e2.attr().as_ref()),
76 match (e1.feature().as_ref(), e2.feature().as_ref()) {
77 (Some(x), Some(y)) => Some(euclidean(x, y)),
78 _ => None,
79 },
80 ))
81 }
82
83 fn optimize(
84 &mut self,
85 _feature_class: u64,
86 _merge_history: &[u64],
87 _attrs: &mut SimpleAttrs,
88 _features: &mut Vec<Observation<f32>>,
89 _prev_length: usize,
90 _is_merge: bool,
91 ) -> Result<()> {
92 Ok(())
93 }
94}
95
96#[derive(Debug, Clone, Default)]
97pub struct UnboundAttrs;
98
99#[derive(Default, Clone)]
100pub struct UnboundAttributeUpdate;
101
102impl TrackAttributesUpdate<UnboundAttrs> for UnboundAttributeUpdate {
103 fn apply(&self, _attrs: &mut UnboundAttrs) -> Result<()> {
104 Ok(())
105 }
106}
107
108impl TrackAttributes<UnboundAttrs, f32> for UnboundAttrs {
109 type Update = UnboundAttributeUpdate;
110 type Lookup = NoopLookup<UnboundAttrs, f32>;
111
112 fn compatible(&self, _other: &UnboundAttrs) -> bool {
113 true
114 }
115
116 fn merge(&mut self, _other: &UnboundAttrs) -> Result<()> {
117 Ok(())
118 }
119
120 fn baked(&self, _observations: &ObservationsDb<f32>) -> Result<TrackStatus> {
121 Ok(TrackStatus::Ready)
122 }
123}
124
125#[derive(Default, Clone)]
126pub struct UnboundMetric;
127
128impl ObservationMetric<UnboundAttrs, f32> for UnboundMetric {
129 fn metric(&self, mq: &MetricQuery<'_, UnboundAttrs, f32>) -> MetricOutput<f32> {
130 let (e1, e2) = (mq.candidate_observation, mq.track_observation);
131 Some((
132 f32::calculate_metric_object(&e1.attr().as_ref(), &e2.attr().as_ref()),
133 match (e1.feature().as_ref(), e2.feature().as_ref()) {
134 (Some(x), Some(y)) => Some(euclidean(x, y)),
135 _ => None,
136 },
137 ))
138 }
139
140 fn optimize(
141 &mut self,
142 _feature_class: u64,
143 _merge_history: &[u64],
144 _attrs: &mut UnboundAttrs,
145 _features: &mut Vec<Observation<f32>>,
146 _prev_length: usize,
147 _is_merge: bool,
148 ) -> Result<()> {
149 Ok(())
150 }
151}
152
153pub fn vec2(x: f32, y: f32) -> Feature {
154 Feature::from_vec(vec![x, y])
155}
156
157pub struct FeatGen2 {
158 x: f32,
159 y: f32,
160 gen: ThreadRng,
161 dist: Uniform<f32>,
162}
163
164impl FeatGen2 {
165 pub fn new(x: f32, y: f32, drift: f32) -> Self {
166 Self {
167 x,
168 y,
169 gen: rand::thread_rng(),
170 dist: Uniform::new(-drift, drift),
171 }
172 }
173}
174
175impl Iterator for FeatGen2 {
176 type Item = Observation<f32>;
177
178 fn next(&mut self) -> Option<Self::Item> {
179 self.x += self.gen.sample(self.dist);
180 self.y += self.gen.sample(self.dist);
181 Some(Observation::new(
182 Some(self.gen.sample(self.dist) + 0.7),
183 Some(vec2(self.x, self.y)),
184 ))
185 }
186}
187
188pub struct BoxGen2 {
189 x: f32,
190 y: f32,
191 width: f32,
192 height: f32,
193 gen: ThreadRng,
194 dist_pos: Uniform<f32>,
195 dist_box: Uniform<f32>,
196}
197
198impl BoxGen2 {
199 pub fn new(x: f32, y: f32, width: f32, height: f32, pos_drift: f32, box_drift: f32) -> Self {
200 Self {
201 x,
202 y,
203 width,
204 height,
205 gen: rand::thread_rng(),
206 dist_pos: Uniform::new(-pos_drift, pos_drift),
207 dist_box: Uniform::new(-box_drift, box_drift),
208 }
209 }
210 pub fn new_monotonous(
211 x: f32,
212 y: f32,
213 width: f32,
214 height: f32,
215 pos_drift: f32,
216 box_drift: f32,
217 ) -> Self {
218 Self {
219 x,
220 y,
221 width,
222 height,
223 gen: rand::thread_rng(),
224 dist_pos: Uniform::new(0.0, pos_drift),
225 dist_box: Uniform::new(-box_drift, box_drift),
226 }
227 }
228}
229
230impl Iterator for BoxGen2 {
231 type Item = BoundingBox;
232
233 fn next(&mut self) -> Option<Self::Item> {
234 self.x += self.gen.sample(self.dist_pos);
235 self.y += self.gen.sample(self.dist_pos);
236
237 self.width += self.gen.sample(self.dist_box);
238 self.height += self.gen.sample(self.dist_box);
239
240 if self.width < 1.0 {
241 self.width = 1.0;
242 }
243 if self.height < 1.0 {
244 self.height = 1.0;
245 }
246
247 Some(BoundingBox::new(self.x, self.y, self.width, self.height))
248 }
249}
250
251#[inline]
252pub fn current_time_span() -> Duration {
253 SystemTime::now().duration_since(UNIX_EPOCH).unwrap()
254}
255
256#[inline]
257pub fn current_time_ms() -> u128 {
258 current_time_span().as_millis()
259}
260
261#[inline]
262pub fn current_time_sec() -> u64 {
263 current_time_span().as_secs()
264}
265
266pub struct FeatGen {
267 x: f32,
268 len: usize,
269 gen: ThreadRng,
270 dist: Uniform<f32>,
271}
272
273impl FeatGen {
274 pub fn new(x: f32, len: usize, drift: f32) -> Self {
275 Self {
276 x,
277 len,
278 gen: rand::thread_rng(),
279 dist: Uniform::new(-drift, drift),
280 }
281 }
282}
283
284impl Iterator for FeatGen {
285 type Item = Observation<()>;
286
287 fn next(&mut self) -> Option<Self::Item> {
288 let v = (0..self.len)
289 .map(|_| self.x + self.gen.sample(self.dist))
290 .collect::<Vec<_>>();
291 Some(Observation::<()>::new(None, Some(Feature::from_vec(v))))
292 }
293}