use crate::dynmatrix::DynMatrix;
use crate::traits::FloatScalar;
use super::border::BorderMode;
use super::filters::{gaussian_blur, sobel_gradients};
pub fn harris_corners<T: FloatScalar>(
src: &DynMatrix<T>,
sigma: T,
k: T,
border: BorderMode<T>,
) -> DynMatrix<T> {
let (sxx, sxy, syy) = structure_tensor(src, sigma, border);
let h = src.nrows();
let w = src.ncols();
let mut out = DynMatrix::<T>::zeros(h, w);
for j in 0..w {
for i in 0..h {
let a = sxx[(i, j)];
let b = sxy[(i, j)];
let c = syy[(i, j)];
let det = a * c - b * b;
let tr = a + c;
out[(i, j)] = det - k * tr * tr;
}
}
out
}
pub fn shi_tomasi_corners<T: FloatScalar>(
src: &DynMatrix<T>,
sigma: T,
border: BorderMode<T>,
) -> DynMatrix<T> {
let (sxx, sxy, syy) = structure_tensor(src, sigma, border);
let h = src.nrows();
let w = src.ncols();
let half = T::from(0.5_f64).unwrap();
let four = T::from(4.0_f64).unwrap();
let zero = T::zero();
let mut out = DynMatrix::<T>::zeros(h, w);
for j in 0..w {
for i in 0..h {
let a = sxx[(i, j)];
let b = sxy[(i, j)];
let c = syy[(i, j)];
let diff = a - c;
let disc = (diff * diff + four * b * b).sqrt();
let lam_min = half * (a + c - disc);
out[(i, j)] = if lam_min < zero { zero } else { lam_min };
}
}
out
}
fn structure_tensor<T: FloatScalar>(
src: &DynMatrix<T>,
sigma: T,
border: BorderMode<T>,
) -> (DynMatrix<T>, DynMatrix<T>, DynMatrix<T>) {
let (gx, gy) = sobel_gradients(src, border);
let h = src.nrows();
let w = src.ncols();
let ixx = DynMatrix::from_fn(h, w, |i, j| gx[(i, j)] * gx[(i, j)]);
let ixy = DynMatrix::from_fn(h, w, |i, j| gx[(i, j)] * gy[(i, j)]);
let iyy = DynMatrix::from_fn(h, w, |i, j| gy[(i, j)] * gy[(i, j)]);
let sxx = gaussian_blur(&ixx, sigma, border);
let sxy = gaussian_blur(&ixy, sigma, border);
let syy = gaussian_blur(&iyy, sigma, border);
(sxx, sxy, syy)
}