1
1
use super :: generic_model:: * ;
2
2
3
+ use image:: { DynamicImage , GenericImageView , GrayImage , ImageBuffer } ;
3
4
use nalgebra as na;
4
5
use rayon:: prelude:: * ;
5
6
@@ -44,7 +45,7 @@ pub fn init_undistort_map(
44
45
. into_par_iter ( )
45
46
. flat_map ( |y| {
46
47
( 0 ..new_w_h. 0 )
47
- . into_par_iter ( )
48
+ . into_iter ( )
48
49
. map ( |x| {
49
50
rmat_inv * na:: Vector3 :: new ( ( x as f64 - cx) / fx, ( y as f64 - cy) / fy, 1.0 )
50
51
} )
@@ -53,7 +54,7 @@ pub fn init_undistort_map(
53
54
. collect ( ) ;
54
55
let p2ds = camera_model. project ( & p3ds) ;
55
56
let ( xvec, yvec) : ( Vec < f32 > , Vec < f32 > ) = p2ds
56
- . par_iter ( )
57
+ . iter ( )
57
58
. map ( |xy| {
58
59
if let Some ( xy) = xy {
59
60
( xy[ 0 ] as f32 , xy[ 1 ] as f32 )
@@ -67,6 +68,123 @@ pub fn init_undistort_map(
67
68
( xmap, ymap)
68
69
}
69
70
71
+ #[ inline]
72
+ fn interpolate_bilinear_weight ( x : f32 , y : f32 ) -> ( u32 , u32 ) {
73
+ if x < 0.0 || x > 65535.0 {
74
+ panic ! ( "x not in [0-65535]" ) ;
75
+ }
76
+ if y < 0.0 || y > 65535.0 {
77
+ panic ! ( "y not in [0-65535]" ) ;
78
+ }
79
+ const UPPER : f32 = u8:: MAX as f32 ;
80
+ let x_weight = ( UPPER * ( x. ceil ( ) - x) ) as u32 ;
81
+ let y_weight = ( UPPER * ( y. ceil ( ) - y) ) as u32 ;
82
+ // 0-255
83
+ ( x_weight, y_weight)
84
+ }
85
+
86
+ pub fn compute_for_fast_remap (
87
+ xmap : & na:: DMatrix < f32 > ,
88
+ ymap : & na:: DMatrix < f32 > ,
89
+ ) -> Vec < ( u32 , u32 , u32 , u32 ) > {
90
+ let xy_pos_weight_vec: Vec < _ > = xmap
91
+ . iter ( )
92
+ . zip ( ymap. iter ( ) )
93
+ . map ( |( & x, & y) | {
94
+ let ( xw, yw) = interpolate_bilinear_weight ( x, y) ;
95
+ let x0 = x. floor ( ) as u32 ;
96
+ let y0 = y. floor ( ) as u32 ;
97
+ ( x0, y0, xw, yw)
98
+ } )
99
+ . collect ( ) ;
100
+ xy_pos_weight_vec
101
+ }
102
+
103
+ fn reinterpret_vec ( input : Vec < [ u8 ; 3 ] > ) -> Vec < u8 > {
104
+ let len = input. len ( ) * 3 ;
105
+ let capacity = input. capacity ( ) * 3 ;
106
+ let ptr = input. as_ptr ( ) as * mut u8 ;
107
+ std:: mem:: forget ( input) ; // prevent dropping original vec
108
+ unsafe { Vec :: from_raw_parts ( ptr, len, capacity) }
109
+ }
110
+
111
+ pub fn fast_remap (
112
+ img : & DynamicImage ,
113
+ new_w_h : ( u32 , u32 ) ,
114
+ xy_pos_weight_vec : & [ ( u32 , u32 , u32 , u32 ) ] ,
115
+ ) -> DynamicImage {
116
+ let remaped = match img {
117
+ DynamicImage :: ImageLuma8 ( image_buffer) => {
118
+ let val: Vec < u8 > = xy_pos_weight_vec
119
+ . par_iter ( )
120
+ . map ( |& ( x0, y0, xw0, yw0) | {
121
+ let p00 = unsafe { image_buffer. unsafe_get_pixel ( x0, y0) [ 0 ] as u32 } ;
122
+ let p10 = unsafe { image_buffer. unsafe_get_pixel ( x0 + 1 , y0) [ 0 ] as u32 } ;
123
+ let p01 = unsafe { image_buffer. unsafe_get_pixel ( x0, y0 + 1 ) [ 0 ] as u32 } ;
124
+ let p11 = unsafe { image_buffer. unsafe_get_pixel ( x0 + 1 , y0 + 1 ) [ 0 ] as u32 } ;
125
+ let xw1 = 255 - xw0;
126
+ let yw1 = 255 - yw0;
127
+ const UPPER_UPPER : u32 = 255 * 255 ;
128
+ let p =
129
+ ( ( p00 * xw0 * yw0 + p10 * xw1 * yw0 + p01 * xw0 * yw1 + p11 * xw1 * yw1)
130
+ / UPPER_UPPER ) as u8 ;
131
+ p
132
+ } )
133
+ . collect ( ) ;
134
+ let img = GrayImage :: from_vec ( new_w_h. 0 , new_w_h. 1 , val) . unwrap ( ) ;
135
+ DynamicImage :: ImageLuma8 ( img)
136
+ }
137
+ DynamicImage :: ImageRgb8 ( image_buffer) => {
138
+ let val: Vec < [ u8 ; 3 ] > = xy_pos_weight_vec
139
+ . par_iter ( )
140
+ . map ( |& ( x0, y0, xw0, yw0) | {
141
+ let p00 = unsafe { image_buffer. unsafe_get_pixel ( x0, y0) } ;
142
+ let p10 = unsafe { image_buffer. unsafe_get_pixel ( x0 + 1 , y0) } ;
143
+ let p01 = unsafe { image_buffer. unsafe_get_pixel ( x0, y0 + 1 ) } ;
144
+ let p11 = unsafe { image_buffer. unsafe_get_pixel ( x0 + 1 , y0 + 1 ) } ;
145
+ let mut v = [ 0 , 1 , 2 ] ;
146
+ v. iter_mut ( ) . for_each ( |i| {
147
+ let xw1 = 255 - xw0;
148
+ let yw1 = 255 - yw0;
149
+ let c = * i as usize ;
150
+ const UPPER_UPPER : u32 = 255 * 255 ;
151
+ * i = ( ( p00. 0 [ c] as u32 * xw0 * yw0
152
+ + p10. 0 [ c] as u32 * xw1 * yw0
153
+ + p01. 0 [ c] as u32 * xw0 * yw1
154
+ + p11. 0 [ c] as u32 * xw1 * yw1)
155
+ / UPPER_UPPER ) as u8 ;
156
+ } ) ;
157
+ v
158
+ } )
159
+ . collect ( ) ;
160
+ let img = ImageBuffer :: from_vec ( new_w_h. 0 , new_w_h. 1 , reinterpret_vec ( val) ) . unwrap ( ) ;
161
+ DynamicImage :: ImageRgb8 ( img)
162
+ }
163
+ DynamicImage :: ImageLuma16 ( image_buffer) => {
164
+ let val: Vec < u16 > = xy_pos_weight_vec
165
+ . par_iter ( )
166
+ . map ( |& ( x0, y0, xw0, yw0) | {
167
+ let p00 = unsafe { image_buffer. unsafe_get_pixel ( x0, y0) [ 0 ] as u32 } ;
168
+ let p10 = unsafe { image_buffer. unsafe_get_pixel ( x0 + 1 , y0) [ 0 ] as u32 } ;
169
+ let p01 = unsafe { image_buffer. unsafe_get_pixel ( x0, y0 + 1 ) [ 0 ] as u32 } ;
170
+ let p11 = unsafe { image_buffer. unsafe_get_pixel ( x0 + 1 , y0 + 1 ) [ 0 ] as u32 } ;
171
+ let xw1 = 255 - xw0;
172
+ let yw1 = 255 - yw0;
173
+ const UPPER_UPPER : u32 = 255 * 255 ;
174
+ let p =
175
+ ( ( p00 * xw0 * yw0 + p10 * xw1 * yw0 + p01 * xw0 * yw1 + p11 * xw1 * yw1)
176
+ / UPPER_UPPER ) as u16 ;
177
+ p
178
+ } )
179
+ . collect ( ) ;
180
+ let img = ImageBuffer :: from_vec ( new_w_h. 0 , new_w_h. 1 , val) . unwrap ( ) ;
181
+ DynamicImage :: ImageLuma16 ( img)
182
+ }
183
+ _ => panic ! ( "Only mono8, mono16, and rgb8 support fast remap." ) ,
184
+ } ;
185
+ remaped
186
+ }
187
+
70
188
/// Returns xmap and ymap for remaping
71
189
///
72
190
/// # Arguments
0 commit comments