use crate::error::Result;
use crate::feature::{array_to_image, image_to_array};
use image::{DynamicImage, GrayImage};
use scirs2_core::ndarray::Array2;
#[allow(dead_code)]
pub fn prewitt_edges(img: &DynamicImage, threshold: f32) -> Result<GrayImage> {
let array = image_to_array(img)?;
let (height, width) = array.dim();
let mut edges = Array2::zeros(array.dim());
for y in 1..(height - 1) {
for x in 1..(width - 1) {
let gx = -array[[y - 1, x - 1]]
+ 0.0 * array[[y - 1, x]]
+ 1.0 * array[[y - 1, x + 1]]
+ -array[[y, x - 1]]
+ 0.0 * array[[y, x]]
+ 1.0 * array[[y, x + 1]]
+ -array[[y + 1, x - 1]]
+ 0.0 * array[[y + 1, x]]
+ 1.0 * array[[y + 1, x + 1]];
let gy = -array[[y - 1, x - 1]]
+ -array[[y - 1, x]]
+ -array[[y - 1, x + 1]]
+ 0.0 * array[[y, x - 1]]
+ 0.0 * array[[y, x]]
+ 0.0 * array[[y, x + 1]]
+ 1.0 * array[[y + 1, x - 1]]
+ 1.0 * array[[y + 1, x]]
+ 1.0 * array[[y + 1, x + 1]];
let magnitude = (gx * gx + gy * gy).sqrt();
if magnitude > threshold {
edges[[y, x]] = 1.0;
}
}
}
array_to_image(&edges)
}
#[allow(dead_code)]
pub fn prewitt_gradients(img: &DynamicImage) -> Result<(Array2<f32>, Array2<f32>)> {
let array = image_to_array(img)?;
let (height, width) = array.dim();
let mut magnitude = Array2::zeros(array.dim());
let mut direction = Array2::zeros(array.dim());
for y in 1..(height - 1) {
for x in 1..(width - 1) {
let gx = -array[[y - 1, x - 1]]
+ 1.0 * array[[y - 1, x + 1]]
+ -array[[y, x - 1]]
+ 1.0 * array[[y, x + 1]]
+ -array[[y + 1, x - 1]]
+ 1.0 * array[[y + 1, x + 1]];
let gy = -array[[y - 1, x - 1]]
+ -array[[y - 1, x]]
+ -array[[y - 1, x + 1]]
+ 1.0 * array[[y + 1, x - 1]]
+ 1.0 * array[[y + 1, x]]
+ 1.0 * array[[y + 1, x + 1]];
magnitude[[y, x]] = (gx * gx + gy * gy).sqrt();
direction[[y, x]] = gy.atan2(gx);
}
}
Ok((magnitude, direction))
}
#[cfg(test)]
mod tests {
use super::*;
use image::Luma;
#[test]
fn test_prewitt_on_simple_edge() {
let mut img = GrayImage::new(10, 10);
for y in 0..10 {
for x in 0..10 {
let value = if x < 5 { 0 } else { 255 };
img.put_pixel(x, y, Luma([value]));
}
}
let dynamic_img = DynamicImage::ImageLuma8(img);
let result = prewitt_edges(&dynamic_img, 0.1);
assert!(result.is_ok());
let edges = result.expect("Operation failed");
let mut has_edge = false;
for y in 1..9 {
for x in 4..7 {
if edges.get_pixel(x, y)[0] > 0 {
has_edge = true;
break;
}
}
}
assert!(has_edge, "Should detect vertical edge");
}
#[test]
fn test_prewitt_gradients() {
let img = GrayImage::new(10, 10);
let dynamic_img = DynamicImage::ImageLuma8(img);
let result = prewitt_gradients(&dynamic_img);
assert!(result.is_ok());
let (magnitude, direction) = result.expect("Operation failed");
assert_eq!(magnitude.dim(), (10, 10));
assert_eq!(direction.dim(), (10, 10));
}
#[test]
fn test_prewitt_vs_sobel_difference() {
let mut img = GrayImage::new(10, 10);
for y in 0..10 {
for x in 0..10 {
let value = if x > y { 255 } else { 0 };
img.put_pixel(x, y, Luma([value]));
}
}
let dynamic_img = DynamicImage::ImageLuma8(img);
let prewitt = prewitt_edges(&dynamic_img, 0.1).expect("Operation failed");
let mut has_diagonal = false;
for i in 2..8 {
if prewitt.get_pixel(i, i)[0] > 0 {
has_diagonal = true;
break;
}
}
assert!(has_diagonal, "Should detect diagonal edge");
}
}