use rustnum as np;
fn main() -> np::Result<()> {
let mut rng = np::random::Rng::seed(7);
let axis = np::linspace(0.0, 255.0, 64);
let (xx, yy) = np::meshgrid(&axis, &axis);
let img = ((&xx + &yy) * 0.5 + rng.normal(0.0, 20.0, &[64, 64])).clip(0.0, 255.0);
println!(
"image shape = {:?}, min = {:.1}, max = {:.1}",
img.shape(),
img.min(),
img.max()
);
let lo = img.min();
let hi = img.max();
let norm = (&img - lo) / (hi - lo);
println!("normalized: min = {}, max = {}", norm.min(), norm.max());
let left_right = norm.flip(1);
let up_down = norm.flip(0);
let transposed = norm.t();
println!(
"flipped and transposed shapes: {:?} {:?} {:?}",
left_right.shape(),
up_down.shape(),
transposed.shape()
);
assert_eq!(left_right[[0, 0]], norm[[0, 63]]);
assert_eq!(up_down[[0, 0]], norm[[63, 0]]);
assert_eq!(transposed[[2, 5]], norm[[5, 2]]);
let mut acc = np::zeros::<f64>(&[62, 62]);
for di in 0..3isize {
for dj in 0..3isize {
acc += &norm.slice(&np::s![di..di + 62, dj..dj + 62]);
}
}
let blurred = acc / 9.0;
println!("blurred shape = {:?}", blurred.shape());
println!(
"std before = {:.4}, std after = {:.4}",
norm.std(),
blurred.std()
);
assert!(
blurred.std() < norm.std(),
"blur should reduce the spread of pixel values"
);
let patch = norm.slice(&np::s![0..3, 0..3]);
assert!((blurred[[0, 0]] - patch.mean()).abs() < 1e-12);
let path = std::env::temp_dir().join("rustnum_image_ops_blurred.npy");
let path = path.to_string_lossy().into_owned();
np::io::save_npy(&path, &blurred)?;
let loaded = np::io::load_npy::<f64>(&path)?;
assert!(loaded == blurred, "saved and loaded arrays differ");
println!("saved {path} and read it back unchanged");
Ok(())
}