use crate::error::{Error, Result};
const IMAGENET_MEAN: [f32; 3] = [0.48145466, 0.4578275, 0.40821073];
const IMAGENET_STD: [f32; 3] = [0.26862954, 0.261_302_6, 0.275_777_1];
pub fn preprocess_image(bytes: &[u8], image_size: usize) -> Result<Vec<f32>> {
let img = image::load_from_memory(bytes).map_err(|e| Error::ModelError {
reason: format!("failed to decode image: {e}"),
})?;
let resized = img.resize_exact(
image_size as u32,
image_size as u32,
image::imageops::FilterType::Triangle,
);
let rgb = resized.to_rgb8();
let total = 3 * image_size * image_size;
let mut output = Vec::with_capacity(total);
for c in 0..3 {
for y in 0..image_size {
for x in 0..image_size {
let pixel = rgb.get_pixel(x as u32, y as u32);
let val = pixel[c] as f32 / 255.0;
let normalized = (val - IMAGENET_MEAN[c]) / IMAGENET_STD[c];
output.push(normalized);
}
}
}
Ok(output)
}
pub fn preprocess_image_custom(
bytes: &[u8],
image_size: usize,
mean: [f32; 3],
std: [f32; 3],
) -> Result<Vec<f32>> {
let img = image::load_from_memory(bytes).map_err(|e| Error::ModelError {
reason: format!("failed to decode image: {e}"),
})?;
let resized = img.resize_exact(
image_size as u32,
image_size as u32,
image::imageops::FilterType::Triangle,
);
let rgb = resized.to_rgb8();
let total = 3 * image_size * image_size;
let mut output = Vec::with_capacity(total);
for c in 0..3 {
for y in 0..image_size {
for x in 0..image_size {
let pixel = rgb.get_pixel(x as u32, y as u32);
let val = pixel[c] as f32 / 255.0;
let normalized = (val - mean[c]) / std[c];
output.push(normalized);
}
}
}
Ok(output)
}