Merge pull request #427 from vbasky/pr/measured-ae-fidelity

This commit is contained in:
Claude committed 2026-10-10 12:50:18 +00:00
commit 37cff1f547
3 files changed
+52

No files matched your search

+47
View File
@@ -0,0 +1,47 @@
//! Deterministic rendered-frame comparison helpers for the fidelity corpus.
use effectcraft_raster::Image;
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct FrameScore {
pub compared_pixels: usize,
pub mean_absolute_error: f64,
pub max_error: f32,
}
/// Compare two premultiplied rendered frames. A size mismatch is reported as an error instead of
/// silently producing a misleading score.
pub fn compare_frames(actual: &Image, reference: &Image) -> Result<FrameScore, String> {
if actual.width != reference.width || actual.height != reference.height {
return Err(format!("frame size mismatch: {}x{} vs {}x{}", actual.width, actual.height, reference.width, reference.height));
}
let mut sum = 0.0f64;
let mut max = 0.0f32;
for (a, b) in actual.data.iter().zip(&reference.data) {
for (&x, &y) in a.iter().zip(b) {
let error = (x - y).abs();
sum += f64::from(error);
max = max.max(error);
}
}
let compared_pixels = actual.data.len();
let samples = compared_pixels.saturating_mul(4).max(1);
Ok(FrameScore { compared_pixels, mean_absolute_error: sum / samples as f64, max_error: max })
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn reports_pixel_error_and_rejects_size_mismatch() {
let mut actual = Image::filled(2, 1, [0.0, 0.0, 0.0, 1.0]);
let reference = Image::filled(2, 1, [0.0, 0.0, 0.0, 1.0]);
actual.data[1][0] = 0.5;
let score = compare_frames(&actual, &reference).expect("same size");
assert_eq!(score.compared_pixels, 2);
assert!((score.mean_absolute_error - 0.0625).abs() < f64::EPSILON);
assert_eq!(score.max_error, 0.5);
assert!(compare_frames(&actual, &Image::new(1, 1)).is_err());
}
}
+1
View File
@@ -21,6 +21,7 @@ mod color2;
mod color3;
mod color_fx;
pub mod controls;
pub mod fidelity;
mod distort;
mod distort2;
mod distort3;
+4
View File
@@ -52,6 +52,10 @@ the 168 live AE samples.
## Still unmeasured
Rendered frame comparisons now have a deterministic `effectcraft_effects::fidelity::compare_frames`
helper. Corpus runners can use it with locally generated host/reference frames and fail on either a
mean or maximum channel error without committing proprietary renders.
Mixed interpolation sides, non-unit durations, automatic/continuous Bezier, spatial speeds and paths,
time remapping, expressions, actual rendered motion and other effects need separate corpus cases.
The initial probe makes no claim about those features.