@@ -2,7 +2,7 @@ use crate::core::*;
22use crate :: processing:: * ;
33use core:: mem:: MaybeUninit ;
44use core:: ops:: Neg ;
5- use ndarray:: { prelude:: * , s, DataMut , OwnedRepr } ;
5+ use ndarray:: { prelude:: * , s, DataMut , OwnedRepr , Zip } ;
66use num_traits:: { cast:: FromPrimitive , real:: Real , Num , NumAssignOps } ;
77use std:: marker:: Sized ;
88
6161 for r in 0 ..res_shape. 0 {
6262 for c in 0 ..res_shape. 1 {
6363 for channel in 0 ..res_shape. 2 {
64- let mut temp = ( h_deriv[ [ r, c, channel] ] . powi ( 2 )
64+ let temp = ( h_deriv[ [ r, c, channel] ] . powi ( 2 )
6565 + v_deriv[ [ r, c, channel] ] . powi ( 2 ) )
6666 . sqrt ( ) ;
67- if temp > T :: one ( ) {
68- temp = T :: one ( ) ;
69- }
7067 unsafe {
7168 * result. uget_mut ( [ r, c, channel] ) = MaybeUninit :: new ( temp) ;
7269 }
@@ -81,10 +78,15 @@ where
8178
8279 let mut magnitude = h_deriv. mapv ( |x| x. powi ( 2 ) ) + v_deriv. mapv ( |x| x. powi ( 2 ) ) ;
8380 magnitude. mapv_inplace ( |x| x. sqrt ( ) ) ;
84- magnitude. mapv_inplace ( |x| if x > T :: one ( ) { T :: one ( ) } else { x } ) ;
8581
86- let mut rotation = v_deriv / h_deriv;
87- rotation. mapv_inplace ( |x| x. atan ( ) ) ;
82+ let dim = h_deriv. dim ( ) ;
83+ let mut rotation = Array3 :: uninit ( ( dim. 0 , dim. 1 , dim. 2 ) ) ;
84+ Zip :: from ( & mut rotation)
85+ . and ( & h_deriv)
86+ . and ( & v_deriv)
87+ . for_each ( |r, & h, & v| * r = MaybeUninit :: new ( h. atan2 ( v) ) ) ;
88+
89+ let rotation = unsafe { rotation. assume_init ( ) } ;
8890
8991 Ok ( ( magnitude, rotation) )
9092 }
@@ -109,3 +111,54 @@ where
109111 . map ( |( m, r) | ( Image :: from_data ( m) , Image :: from_data ( r) ) )
110112 }
111113}
114+
115+ #[ cfg( test) ]
116+ mod tests {
117+ use super :: * ;
118+ use approx:: * ;
119+
120+ #[ test]
121+ fn simple ( ) {
122+ let mut image: Image < f64 , Gray > = ImageBase :: new ( 11 , 11 ) ;
123+ image. data . slice_mut ( s ! [ 4 ..7 , 4 ..7 , ..] ) . fill ( 1.0 ) ;
124+ image. data . slice_mut ( s ! [ 3 ..8 , 5 , ..] ) . fill ( 1.0 ) ;
125+ image. data . slice_mut ( s ! [ 5 , 3 ..8 , ..] ) . fill ( 1.0 ) ;
126+
127+ let sobel = image. full_sobel ( ) . unwrap ( ) ;
128+
129+ // Did a calculation of sobel_mag[1..9, 1..9, ..] in a spreadsheet
130+ #[ rustfmt:: skip]
131+ let mag = vec ! [ 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ,
132+ 0.0 , 0.0 , 0.0 , 1.41421356237301 , 2.0 , 1.41421356237301 , 0.0 , 0.0 , 0.0 ,
133+ 0.0 , 0.0 , 1.41421356237301 , 4.24264068711929 , 4.0 , 4.24264068711929 , 1.4142135623731 , 0.0 , 0.0 ,
134+ 0.0 , 1.4142135623731 , 4.24264068711929 , 4.24264068711929 , 2.0 , 4.24264068711929 , 4.24264068711929 , 1.4142135623731 , 0.0 ,
135+ 0.0 , 2.0 , 4.0 , 2.0 , 0.0 , 2.0 , 4.0 , 2.0 , 0.0 ,
136+ 0.0 , 1.4142135623731 , 4.24264068711929 , 4.24264068711929 , 2.0 , 4.24264068711929 , 4.24264068711929 , 1.4142135623731 , 0.0 ,
137+ 0.0 , 0.0 , 1.4142135623731 , 4.24264068711929 , 4.0 , 4.24264068711929 , 1.4142135623731 , 0.0 ,
138+ 0.0 , 0.0 , 0.0 , 0.0 , 1.4142135623731 , 2.0 , 1.4142135623731 , 0.0 , 0.0 ,
139+ 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ,
140+ ] ;
141+
142+ let mag = Array :: from_shape_vec ( ( 9 , 9 ) , mag) . unwrap ( ) ;
143+
144+ assert_abs_diff_eq ! ( sobel. 0 . data. slice( s![ 1 ..10 , 1 ..10 , 0 ] ) , mag, epsilon = 1e-5 ) ;
145+
146+ let only_mag = image. apply_sobel ( ) . unwrap ( ) ;
147+ assert_abs_diff_eq ! ( sobel. 0 . data, only_mag. data) ;
148+
149+ // Did a calculation of sobel_rot[1..9, 1..9, ..] in a spreadsheet
150+ #[ rustfmt:: skip]
151+ let rot = vec ! [ 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 ,
152+ 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , -2.35619449019234 , 3.14159265358979 , 2.35619449019234 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 ,
153+ 0.00000000000000 , 0.00000000000000 , -2.35619449019234 , -2.35619449019234 , 3.14159265358979 , 2.35619449019234 , 2.35619449019234 , 0.00000000000000 , 0.00000000000000 ,
154+ 0.00000000000000 , -2.35619449019234 , -2.35619449019234 , -2.35619449019234 , 3.14159265358979 , 2.35619449019234 , 2.35619449019234 , 2.35619449019234 , 0.00000000000000 ,
155+ 0.00000000000000 , -1.57079632679490 , -1.57079632679490 , -1.57079632679490 , 0.00000000000000 , 1.57079632679490 , 1.57079632679490 , 1.57079632679490 , 0.00000000000000 ,
156+ 0.00000000000000 , -0.78539816339745 , -0.78539816339745 , -0.78539816339745 , 0.00000000000000 , 0.78539816339745 , 0.78539816339745 , 0.78539816339745 , 0.00000000000000 ,
157+ 0.00000000000000 , 0.00000000000000 , -0.78539816339745 , -0.78539816339745 , 0.00000000000000 , 0.78539816339745 , 0.78539816339745 , 0.00000000000000 , 0.00000000000000 ,
158+ 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , -0.78539816339745 , 0.00000000000000 , 0.78539816339745 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 ,
159+ 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 , 0.00000000000000 ] ;
160+ let rot = Array :: from_shape_vec ( ( 9 , 9 ) , rot) . unwrap ( ) ;
161+
162+ assert_abs_diff_eq ! ( sobel. 1 . data. slice( s![ 1 ..10 , 1 ..10 , 0 ] ) , rot, epsilon = 1e-5 ) ;
163+ }
164+ }
0 commit comments