use crate::image::Image;
pub fn huber<const CHANNELS: usize>(
image1: &Image<f32, CHANNELS>,
image2: &Image<f32, CHANNELS>,
delta: f32,
) -> f32 {
assert_eq!(image1.size(), image2.size());
ndarray::Zip::from(&image1.data)
.and(&image2.data)
.fold(0f32, |acc, &a, &b| {
let diff = a - b;
if diff.abs() <= delta {
acc + 0.5 * diff.powi(2)
} else {
acc + delta * (diff.abs() - 0.5 * delta)
}
})
/ (image1.data.len() as f32)
}
#[cfg(test)]
mod tests {
use crate::image::{Image, ImageSize};
use anyhow::Result;
#[test]
fn test_huber() -> Result<()> {
let image1 = Image::<_, 1>::new(
ImageSize {
width: 2,
height: 3,
},
vec![0f32, 1f32, 2f32, 3f32, 4f32, 5f32],
)?;
let image2 = Image::<_, 1>::new(
ImageSize {
width: 2,
height: 3,
},
vec![5f32, 4f32, 3f32, 2f32, 1f32, 0f32],
)?;
let huber = super::huber(&image1, &image2, 1.0);
assert_eq!(huber, 2.5);
Ok(())
}
}