fn non_maximum_suppression(
    g: &ImageBuffer<Luma<f32>, Vec<f32>>,
    gx: &ImageBuffer<Luma<i16>, Vec<i16>>,
    gy: &ImageBuffer<Luma<i16>, Vec<i16>>,
) -> ImageBuffer<Luma<f32>, Vec<f32>> {
    const RADIANS_TO_DEGREES: f32 = 180f32 / std::f32::consts::PI;
    let mut out = ImageBuffer::from_pixel(g.width(), g.height(), Luma([0.0]));
    for y in 1..g.height() - 1 {
        for x in 1..g.width() - 1 {
            let x_gradient = gx[(x, y)][0] as f32;
            let y_gradient = gy[(x, y)][0] as f32;
            let mut angle = (y_gradient).atan2(x_gradient) * RADIANS_TO_DEGREES;
            if angle < 0.0 {
                angle += 180.0
            }
            // Clamp angle.
            let clamped_angle = if !(22.5..157.5).contains(&angle) {
                0
            } else if (22.5..67.5).contains(&angle) {
                45
            } else if (67.5..112.5).contains(&angle) {
                90
            } else if (112.5..157.5).contains(&angle) {
                135
            } else {
                unreachable!()
            };

            // Get the two perpendicular neighbors.
            let (cmp1, cmp2) = unsafe {
                match clamped_angle {
                    0 => (g.unsafe_get_pixel(x - 1, y), g.unsafe_get_pixel(x + 1, y)),
                    45 => (
                        g.unsafe_get_pixel(x + 1, y + 1),
                        g.unsafe_get_pixel(x - 1, y - 1),
                    ),
                    90 => (g.unsafe_get_pixel(x, y - 1), g.unsafe_get_pixel(x, y + 1)),
                    135 => (
                        g.unsafe_get_pixel(x - 1, y + 1),
                        g.unsafe_get_pixel(x + 1, y - 1),
                    ),
                    _ => unreachable!(),
                }
            };
            let pixel = *g.get_pixel(x, y);
            // If the pixel is not a local maximum, suppress it.
            if pixel[0] < cmp1[0] || pixel[0] < cmp2[0] {
                out.put_pixel(x, y, Luma([0.0]));
            } else {
                out.put_pixel(x, y, pixel);
            }
        }
    }
    out
}
/// Finds local maxima to make the edges thinner.
Finds local maxima to make the edges thinner.
Finds local maxima to make the edges thinner .
fn non_maximum_suppression(
    g: &ImageBuffer<Luma<f32>, Vec<f32>>,
    gx: &ImageBuffer<Luma<i16>, Vec<i16>>,
    gy: &ImageBuffer<Luma<i16>, Vec<i16>>,
) -> ImageBuffer<Luma<f32>, Vec<f32>> {
    const RADIANS_TO_DEGREES: f32 = 180f32 / std::f32::consts::PI;
    let mut out = ImageBuffer::from_pixel(g.width(), g.height(), Luma([0.0]));
    for y in 1..g.height() - 1 {
        for x in 1..g.width() - 1 {
            let x_gradient = gx[(x, y)][0] as f32;
            let y_gradient = gy[(x, y)][0] as f32;
            let mut angle = (y_gradient).atan2(x_gradient) * RADIANS_TO_DEGREES;
            if angle < 0.0 {
                angle += 180.0
            }
            // Clamp angle.
            let clamped_angle = if !(22.5..157.5).contains(&angle) {
                0
            } else if (22.5..67.5).contains(&angle) {
                45
            } else if (67.5..112.5).contains(&angle) {
                90
            } else if (112.5..157.5).contains(&angle) {
                135
            } else {
                unreachable!()
            };
            // Get the two perpendicular neighbors.
            let (cmp1, cmp2) = unsafe {
                match clamped_angle {
                    0 => (g.unsafe_get_pixel(x - 1, y), g.unsafe_get_pixel(x + 1, y)),
                    45 => (
                        g.unsafe_get_pixel(x + 1, y + 1),
                        g.unsafe_get_pixel(x - 1, y - 1),
                    ),
                    90 => (g.unsafe_get_pixel(x, y - 1), g.unsafe_get_pixel(x, y + 1)),
                    135 => (
                        g.unsafe_get_pixel(x - 1, y + 1),
                        g.unsafe_get_pixel(x + 1, y - 1),
                    ),
                    _ => unreachable!(),
                }
            };
            let pixel = *g.get_pixel(x, y);
            // If the pixel is not a local maximum, suppress it.
            if pixel[0] < cmp1[0] || pixel[0] < cmp2[0] {
                out.put_pixel(x, y, Luma([0.0]));
            } else {
                out.put_pixel(x, y, pixel);
            }
        }
    }
    out
}
fn non_maximum_suppression ( g : & ImageBuffer < Luma < f32 > , Vec < f32 > > , gx : & ImageBuffer < Luma < i16 > , Vec < i16 > > , gy : & ImageBuffer < Luma < i16 > , Vec < i16 > > , ) -> ImageBuffer < Luma < f32 > , Vec < f32 > > { const RADIANS_TO_DEGREES : f32 = 180f32 / std :: f32 :: consts :: PI ; let mut out = ImageBuffer :: from_pixel ( g . width ( ) , g . height ( ) , Luma ( [ 0.0 ] ) ) ; for y in 1 .. g . height ( ) - 1 { for x in 1 .. g . width ( ) - 1 { let x_gradient = gx [ ( x , y ) ] [ 0 ] as f32 ; let y_gradient = gy [ ( x , y ) ] [ 0 ] as f32 ; let mut angle = ( y_gradient ) . atan2 ( x_gradient ) * RADIANS_TO_DEGREES ; if angle < 0.0 { angle += 180.0 } // Clamp angle. let clamped_angle = if ! ( 22.5 .. 157.5 ) . contains ( & angle ) { 0 } else if ( 22.5 .. 67.5 ) . contains ( & angle ) { 45 } else if ( 67.5 .. 112.5 ) . contains ( & angle ) { 90 } else if ( 112.5 .. 157.5 ) . contains ( & angle ) { 135 } else { unreachable ! ( ) } ; // Get the two perpendicular neighbors. let ( cmp1 , cmp2 ) = unsafe { match clamped_angle { 0 => ( g . unsafe_get_pixel ( x - 1 , y ) , g . unsafe_get_pixel ( x + 1 , y ) ) , 45 => ( g . unsafe_get_pixel ( x + 1 , y + 1 ) , g . unsafe_get_pixel ( x - 1 , y - 1 ) , ) , 90 => ( g . unsafe_get_pixel ( x , y - 1 ) , g . unsafe_get_pixel ( x , y + 1 ) ) , 135 => ( g . unsafe_get_pixel ( x - 1 , y + 1 ) , g . unsafe_get_pixel ( x + 1 , y - 1 ) , ) , _ => unreachable ! ( ) , } } ; let pixel = * g . get_pixel ( x , y ) ; // If the pixel is not a local maximum, suppress it. if pixel [ 0 ] < cmp1 [ 0 ] || pixel [ 0 ] < cmp2 [ 0 ] { out . put_pixel ( x , y , Luma ( [ 0.0 ] ) ) ; } else { out . put_pixel ( x , y , pixel ) ; } } } out }
Finds local maxima to make the edges thinner.
Finds local maxima to make the edges thinner .
g
&ImageBuffer<Luma<f32>, Vec<f32>>
gx
&ImageBuffer<Luma<i16>, Vec<i16>>
gy
&ImageBuffer<Luma<i16>, Vec<i16>>
g
&ImageBuffer<Luma<f32>, Vec<f32>>
gx
&ImageBuffer<Luma<i16>, Vec<i16>>
gy
&ImageBuffer<Luma<i16>, Vec<i16>>