@@ -2,7 +2,7 @@ use crate::core::*;
2
2
use crate :: processing:: * ;
3
3
use core:: mem:: MaybeUninit ;
4
4
use core:: ops:: Neg ;
5
- use ndarray:: { prelude:: * , s, DataMut , OwnedRepr } ;
5
+ use ndarray:: { prelude:: * , s, DataMut , OwnedRepr , Zip } ;
6
6
use num_traits:: { cast:: FromPrimitive , real:: Real , Num , NumAssignOps } ;
7
7
use std:: marker:: Sized ;
8
8
61
61
for r in 0 ..res_shape. 0 {
62
62
for c in 0 ..res_shape. 1 {
63
63
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 )
65
65
+ v_deriv[ [ r, c, channel] ] . powi ( 2 ) )
66
66
. sqrt ( ) ;
67
- if temp > T :: one ( ) {
68
- temp = T :: one ( ) ;
69
- }
70
67
unsafe {
71
68
* result. uget_mut ( [ r, c, channel] ) = MaybeUninit :: new ( temp) ;
72
69
}
@@ -81,10 +78,15 @@ where
81
78
82
79
let mut magnitude = h_deriv. mapv ( |x| x. powi ( 2 ) ) + v_deriv. mapv ( |x| x. powi ( 2 ) ) ;
83
80
magnitude. mapv_inplace ( |x| x. sqrt ( ) ) ;
84
- magnitude. mapv_inplace ( |x| if x > T :: one ( ) { T :: one ( ) } else { x } ) ;
85
81
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 ( ) } ;
88
90
89
91
Ok ( ( magnitude, rotation) )
90
92
}
@@ -109,3 +111,54 @@ where
109
111
. map ( |( m, r) | ( Image :: from_data ( m) , Image :: from_data ( r) ) )
110
112
}
111
113
}
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