use crate::config::{IMAGE_MEAN, IMAGE_STD};
pub fn preprocess_rgb(rgb: &[u8], in_h: usize, in_w: usize, out: usize) -> Vec<f32> {
let mut planes = [
vec![0f32; in_h * in_w],
vec![0f32; in_h * in_w],
vec![0f32; in_h * in_w],
];
for i in 0..in_h * in_w {
for (c, plane) in planes.iter_mut().enumerate() {
plane[i] = rgb[i * 3 + c] as f32;
}
}
let mut out_planes = Vec::with_capacity(3);
for plane in &planes {
let tmp = resample_axis(plane, in_h, in_w, out, true); let res = resample_axis(&tmp, in_h, out, out, false); out_planes.push(res);
}
let mut pixel = vec![0f32; 3 * out * out];
for c in 0..3 {
let mean = IMAGE_MEAN[c];
let std = IMAGE_STD[c];
for i in 0..out * out {
let v = out_planes[c][i] / 255.0;
pixel[c * out * out + i] = (v - mean) / std;
}
}
pixel
}
fn cubic(x: f64) -> f64 {
let a = -0.5;
let x = x.abs();
if x < 1.0 {
((a + 2.0) * x - (a + 3.0)) * x * x + 1.0
} else if x < 2.0 {
(((x - 5.0) * x + 8.0) * x - 4.0) * a
} else {
0.0
}
}
fn resample_axis(
data: &[f32],
rows: usize,
cols: usize,
out_size: usize,
horizontal: bool,
) -> Vec<f32> {
const SUPPORT: f64 = 2.0; let in_size = if horizontal { cols } else { rows };
let scale = in_size as f64 / out_size as f64;
let filterscale = scale.max(1.0);
let support = SUPPORT * filterscale;
let mut starts = Vec::with_capacity(out_size);
let mut weights: Vec<Vec<f64>> = Vec::with_capacity(out_size);
for xx in 0..out_size {
let center = (xx as f64 + 0.5) * scale;
let mut xmin = (center - support + 0.5).floor() as isize;
if xmin < 0 {
xmin = 0;
}
let mut xmax = (center + support + 0.5).floor() as isize;
if xmax > in_size as isize {
xmax = in_size as isize;
}
let (xmin, xmax) = (xmin as usize, xmax as usize);
let mut w = Vec::with_capacity(xmax - xmin);
let mut sum = 0f64;
for x in xmin..xmax {
let val = cubic((x as f64 - center + 0.5) / filterscale);
w.push(val);
sum += val;
}
if sum != 0.0 {
for v in &mut w {
*v /= sum;
}
}
starts.push(xmin);
weights.push(w);
}
if horizontal {
let mut out = vec![0f32; rows * out_size];
for r in 0..rows {
let src = &data[r * cols..(r + 1) * cols];
for xx in 0..out_size {
let xmin = starts[xx];
let mut acc = 0f64;
for (k, &wk) in weights[xx].iter().enumerate() {
acc += src[xmin + k] as f64 * wk;
}
out[r * out_size + xx] = acc as f32;
}
}
out
} else {
let mut out = vec![0f32; out_size * cols];
for yy in 0..out_size {
let ymin = starts[yy];
for col in 0..cols {
let mut acc = 0f64;
for (k, &wk) in weights[yy].iter().enumerate() {
acc += data[(ymin + k) * cols + col] as f64 * wk;
}
out[yy * cols + col] = acc as f32;
}
}
out
}
}