mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-31 07:38:24 +00:00
#1539: keep Show Object empty when its tracked matte is missing
This commit is contained in:
1 parent
31307d15dc
commit
b148397d4e
1 file changed
+55
-7
@@ -457,20 +457,24 @@ impl Chain {
|
||||
}
|
||||
|
||||
/// What Show Object asks for at frame `f`: `None` shows the whole matte (all objects, a single object, or a frame
|
||||
/// the tracker did not follow); an object the instance does not have shows nothing.
|
||||
/// the tracker did not follow); a missing object on a tracked frame shows nothing.
|
||||
fn shown_object(&self, f: i64) -> Option<Arc<FrameSeg>> {
|
||||
let o = self.show_object.checked_sub(1)?;
|
||||
let objects = self.data.objects();
|
||||
if objects.len() < 2 {
|
||||
return None;
|
||||
}
|
||||
if !objects.contains(&o) {
|
||||
let sc = self.opts.scale;
|
||||
let [w, h] =
|
||||
self.saved.as_ref().map(|t| t.cache.size).or_else(|| self.keys.get(&f).and_then(|k| cached(tracked_key(*k), sc)).map(|s| [s.w, s.h]))?;
|
||||
return Some(Arc::new(FrameSeg::empty(w, h)));
|
||||
if objects.contains(&o)
|
||||
&& let Some(seg) = self.object_seg(f, o)
|
||||
{
|
||||
return Some(seg);
|
||||
}
|
||||
self.object_seg(f, o)
|
||||
let sc = self.opts.scale;
|
||||
let tracked = self.saved_seg(f, sc).or_else(|| {
|
||||
let key = tracked_key(*self.keys.get(&f)?);
|
||||
cached(key, sc).or_else(|| cached(key, 1.0).map(|seg| Arc::new(downscale(&seg, sc))))
|
||||
})?;
|
||||
Some(Arc::new(FrameSeg::empty(tracked.w, tracked.h)))
|
||||
}
|
||||
|
||||
/// The tracker's trust in frame `f`: from the saved tracking, else from this session's tracking.
|
||||
@@ -1469,6 +1473,50 @@ mod tests {
|
||||
assert!(cached(object_key(other[&1], 1), 1.0).is_none(), "the other model's cache holds none of it");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn showing_a_missing_tracked_object_never_falls_back_to_other_objects() {
|
||||
let mut d = RotoData::default();
|
||||
for object in 0..2 {
|
||||
d.add(Stroke { kind: StrokeKind::Fg, frame: 0, radius: 1.0, points: vec![[1.0, 1.0]], object }, 1, [0, 1]);
|
||||
}
|
||||
let union = Arc::new(FrameSeg { w: 4, h: 2, matte: vec![255; 8], refine: vec![0; 8], ..Default::default() });
|
||||
for saved in [false, true] {
|
||||
for scale in [1.0, 0.5] {
|
||||
let mut params = params_with(&d);
|
||||
params.values.insert("version".into(), Value::Scalar(0.0));
|
||||
params.values.insert(INPUT_KEY.into(), Value::Str(format!("missing-object-{saved}-{scale}")));
|
||||
let keys = d.chain_keys(seed(¶ms, [4.0, 2.0], 25.0));
|
||||
if saved {
|
||||
let matte = rle::encode(&union.matte);
|
||||
let refine = rle::encode(&union.refine);
|
||||
let cache = TrackCache {
|
||||
key: tracks_key(&keys),
|
||||
model: effectcraft_segment::CLASSICAL.into(),
|
||||
size: [4, 2],
|
||||
frames: [(0, TrackFrame { m: matte.clone(), r: refine.clone(), ..Default::default() })].into_iter().collect(),
|
||||
objects: [(0, [(0, ObjectFrame { m: matte, r: refine })].into_iter().collect())].into_iter().collect(),
|
||||
};
|
||||
params.values.insert(TRACKED.into(), Value::Str(cache.to_json()));
|
||||
} else {
|
||||
store(tracked_key(keys[&0]), 1.0, union.clone());
|
||||
store(object_key(keys[&0], 0), 1.0, union.clone());
|
||||
}
|
||||
let mut chain = Chain::new(¶ms, [4.0, 2.0], 25.0, scale);
|
||||
let expected = downscale(&union, scale);
|
||||
for object in [2, 7] {
|
||||
chain.show_object = object;
|
||||
let shown = chain.ensure(0, &mut |_| None, &|| false).expect("tracked frame");
|
||||
assert_eq!((shown.w, shown.h, shown.area()), (expected.w, expected.h, 0), "saved={saved}, scale={scale}, object={object}");
|
||||
}
|
||||
assert!(chain.shown_object(1).is_none(), "untracked frames keep their existing fallback");
|
||||
for object in [0, 1] {
|
||||
chain.show_object = object;
|
||||
assert_eq!(chain.ensure(0, &mut |_| None, &|| false).unwrap().matte, expected.matte);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn saved_tracking_decoders_validate_dimensions_and_plane_lengths() {
|
||||
let valid = rle::encode(&[255, 0, 255, 0]);
|
||||
|
||||
Reference in new issue
Block a user