1 // This is brl/bseg/bsgm/bsgm_disparity_estimator.h
2 #ifndef bsgm_multiscale_disparity_estimator_h_
3 #define bsgm_multiscale_disparity_estimator_h_
4
5 #include <string>
6 #include <vector>
7 #include <set>
8 #include <iostream>
9 #include <sstream>
10 #include <utility>
11
12 #include <vul/vul_timer.h>
13 #include <vnl/vnl_math.h>
14 #include <vil/vil_image_view.h>
15 #include "vil/vil_resample_nearest.h"
16 #include "vil/vil_resample_bilin.h"
17 #include <vil/algo/vil_structuring_element.h>
18 #include <vil/algo/vil_sobel_3x3.h>
19 #include <vil/algo/vil_median.h>
20 #include <vil/algo/vil_binary_dilate.h>
21 #include <vil/algo/vil_gauss_reduce.h>
22
23 #include "bsgm_disparity_estimator.h"
24
25 //:
26 // \file
27 // \brief A multi-scale implementation of SGM.
28 // \author Thomas Pollard
29 // \date June 7, 2016
30 //
31 // Modifications
32 // Jun, 2016 Yi Dong - add input parameter for function 'compute'
33 // \endverbatim
34
35
36 class bsgm_multiscale_disparity_estimator
37 {
38 public:
39
40 //: Construct from parameters. Coarse scale SGM will run on images
41 // downsampled by 2^downscale_exponent
42 bsgm_multiscale_disparity_estimator(
43 const bsgm_disparity_estimator_params& params,
44 int img_width,
45 int img_height,
46 int num_disparities,
47 int num_active_disparities,
48 int downscale_exponent = 2 );
49
50 //: Destructor
51 ~bsgm_multiscale_disparity_estimator();
52
53 //: Run SGM twice, once at a lower resolution to determine the active
54 // disparity range, and again at full-res using the reduced disparity range.
55 // Should improve speed and quality with respect to single-scale approach if
56 // tight disparity bounds are unknown.
57 // mutli_scale_mode can be:
58 // 0 Single min disparity used for entire image
59 // 1 Single min disparity used within coarse image blocks
60 // 2 Different min disparity used at each pixel
61 template <class T>
62 bool compute(
63 const vil_image_view<T>& img_target,
64 const vil_image_view<T>& img_ref,
65 const vil_image_view<bool>& invalid_target,
66 int min_disparity,
67 float invalid_disparity,
68 int const& multi_scale_mode,
69 vil_image_view<float>& disp_target,
70 float dynamic_range_factor = 1.0f,
71 bool skip_error_check = false);
72
73 //: Same as above, except compute disparity maps for both images and use a
74 // full left-right consistency check to detect and fix errors in the
75 // disparity maps.
76 template <class T>
77 bool compute_both(
78 const vil_image_view<T>& img_target,
79 const vil_image_view<T>& img_ref,
80 const vil_image_view<bool>& invalid_target,
81 const vil_image_view<bool>& invalid_ref,
82 int min_disparity,
83 float invalid_disparity,
84 int const& multi_scale_mode,
85 vil_image_view<float>& disp_target,
86 vil_image_view<float>& disp_ref,
87 float dynamic_range_factor = 1.0f);
88
89 //: Write out the appearance or total cost volume as a set of images for
90 // debugging
91 void write_cost_debug_imgs(
92 const std::string& out_dir,
93 bool write_total_cost = false )
94 {
95 fine_de_->write_cost_debug_imgs(out_dir, write_total_cost);
96 }
97
98 protected:
99 int bsgm_compute_median_of_image(
100 const vil_image_view<float>& img,
101 const vil_image_view<bool>& invalid,
102 int start_x,
103 int end_x,
104 int start_y,
105 int end_y,
106 int min_img_val,
107 int num_img_vals,
108 float invalid_disparity );
109 //: Size of image
110 int coarse_w_, coarse_h_, fine_w_, fine_h_;
111
112 //: Downscaling parameters where downscale_factor_ = 2^downscale_exponent_
113 int downscale_exponent_;
114 int downscale_factor_;
115
116 int num_coarse_disparities_, num_fine_disparities_, num_active_disparities_;
117
118 //: Single-scale SGMs for coarse and fine scales
119 bsgm_disparity_estimator* coarse_de_;
120 bsgm_disparity_estimator* fine_de_;
121 bsgm_disparity_estimator_params params_;
122 };
123 template <class T>
compute(const vil_image_view<T> & img_tar,const vil_image_view<T> & img_ref,const vil_image_view<bool> & invalid_tar,int min_disp,float invalid_disp,int const & multi_scale_mode,vil_image_view<float> & disp_tar,float dynamic_range_factor,bool skip_error_check)124 bool bsgm_multiscale_disparity_estimator::compute(
125 const vil_image_view<T>& img_tar,
126 const vil_image_view<T>& img_ref,
127 const vil_image_view<bool>& invalid_tar,
128 int min_disp,
129 float invalid_disp,
130 int const& multi_scale_mode,
131 vil_image_view<float>& disp_tar,
132 float dynamic_range_factor,
133 bool skip_error_check)
134 {
135 //int multi_scale_mode = 1;
136
137 // Size of block used in mode 1
138 int block_size = 100;
139 disp_tar.set_size( fine_w_, fine_h_ );
140
141 // Validate images.
142 if( img_tar.ni() != fine_w_ || img_tar.nj() != fine_h_ ||
143 img_ref.ni() != fine_w_ || img_ref.nj() != fine_h_ ||
144 invalid_tar.ni() != fine_w_ || invalid_tar.nj() != fine_h_ )
145 return false;
146
147 // Downsample the images
148 vil_image_view<T> img_t_coarse, img_r_coarse,
149 temp_t_coarse, temp_r_coarse, working;
150
151 vil_gauss_reduce( img_tar, img_t_coarse, working );
152 vil_gauss_reduce( img_ref, img_r_coarse, working );
153
154 for( int s = 1; s < downscale_exponent_; s++ ){
155 vil_gauss_reduce( img_t_coarse, temp_t_coarse, working );
156 img_t_coarse.deep_copy( temp_t_coarse );
157 vil_gauss_reduce( img_r_coarse, temp_r_coarse, working );
158 img_r_coarse.deep_copy( temp_r_coarse );
159 }
160
161 // Downsample the invalid image and dilate to handle borders
162 vil_image_view<bool> invalid_t_resamp( coarse_w_, coarse_h_ );
163 vil_resample_nearest( invalid_tar, invalid_t_resamp, coarse_w_, coarse_h_ );
164 vil_image_view<bool> invalid_t_coarse( coarse_w_, coarse_h_ );
165 vil_structuring_element se; se.set_to_disk( 3.0 );
166 vil_binary_dilate( invalid_t_resamp, invalid_t_coarse, se );
167
168 vil_image_view<int> min_disp_img_coarse( coarse_w_, coarse_h_ );
169 vil_image_view<int> min_disp_img_fine( fine_w_, fine_h_ );
170
171 // Setup trivial coarse-scale min disparity image
172 int min_disp_coarse = min_disp / downscale_factor_;
173 min_disp_img_coarse.fill( min_disp_coarse );
174
175 float invalid_disp_coarse = invalid_disp / downscale_factor_;
176
177 // Run SGM on coarse scale images
178 vil_image_view<float> disp_t_coarse;
179 if( !coarse_de_->compute( img_t_coarse, img_r_coarse, invalid_t_coarse,
180 min_disp_img_coarse, invalid_disp_coarse, disp_t_coarse, dynamic_range_factor ) )
181 return false;
182
183 //DEBUG
184 //vil_save( disp_t_coarse, "D:/temp/sgm/mountain_pair/disp_t_coarse.tif");
185
186
187 // Mode 0 uses a constant min disparity for all pixels
188 if( multi_scale_mode == 0 ){
189
190 // Compute the median disparity for the
191 int med_ds = bsgm_compute_median_of_image(
192 disp_t_coarse, invalid_t_coarse, 0, coarse_w_, 0, coarse_h_,
193 min_disp_coarse, num_coarse_disparities_, invalid_disp_coarse );
194
195 // Setup fine-scale min disparity image
196 min_disp_img_fine.fill(
197 med_ds*downscale_factor_ - num_active_disparities_/2 );
198
199 // Mode 1 uses a fixed min disparity in large block regions
200 } else if( multi_scale_mode == 1 ) {
201
202 int coarse_block_size = block_size / downscale_factor_;
203
204 for( int start_y = 0; start_y < coarse_h_; start_y+=coarse_block_size ){
205 for( int start_x = 0; start_x < coarse_w_; start_x+=coarse_block_size ){
206
207 int end_x = std::min( coarse_w_, start_x+coarse_block_size );
208 int end_y = std::min( coarse_h_, start_y+coarse_block_size );
209
210 // Compute median of the box region
211 int med_ds = bsgm_compute_median_of_image( disp_t_coarse,
212 invalid_t_coarse, start_x, end_x, start_y, end_y,
213 min_disp_coarse, num_coarse_disparities_, invalid_disp_coarse );
214
215 // Set the min (fine-scale) disparity for each pixel in the box to a
216 // value centered on this median.
217 for( int by = start_y; by < end_y; by++ ){
218 for( int bx = start_x; bx < end_x; bx++ ){
219 min_disp_img_coarse(bx,by) =
220 med_ds*downscale_factor_ - num_active_disparities_/2;
221 }
222 }
223 }
224 }
225
226 // Upscale to full-res
227 vil_resample_bilin(
228 min_disp_img_coarse, min_disp_img_fine, fine_w_, fine_h_ );
229
230 // Mode 2 uses per pixel min disparity based on coarse disparity
231 } else {
232
233 // Set the min (fine-scale) disparity for each pixel to a value
234 // value centered on this median.
235 for( int y = 0; y < coarse_h_; y++ ){
236 for( int x = 0; x < coarse_w_; x++ ){
237 min_disp_img_coarse(x,y) =
238 disp_t_coarse(x,y)*downscale_factor_ - num_active_disparities_/2;
239 }
240 }
241
242 // Upscale to full-res
243 vil_resample_bilin(
244 min_disp_img_coarse, min_disp_img_fine, fine_w_, fine_h_ );
245 }
246
247 // Run fine-scale SGM
248 if( !fine_de_->compute( img_tar, img_ref, invalid_tar,
249 min_disp_img_fine, invalid_disp, disp_tar, dynamic_range_factor, skip_error_check ) )
250 return false;
251
252 //fine_de_->write_cost_debug_imgs( std::string("C:/data/results"), true );
253
254 return true;
255 }
256
257
258 //--------------------------------------------------------------
259 template <class T>
compute_both(const vil_image_view<T> & img_tar,const vil_image_view<T> & img_ref,const vil_image_view<bool> & invalid_tar,const vil_image_view<bool> & invalid_ref,int min_disparity,float invalid_disparity,int const & multi_scale_mode,vil_image_view<float> & disp_tar,vil_image_view<float> & disp_ref,float dynamic_range_factor)260 bool bsgm_multiscale_disparity_estimator::compute_both(
261 const vil_image_view<T>& img_tar,
262 const vil_image_view<T>& img_ref,
263 const vil_image_view<bool>& invalid_tar,
264 const vil_image_view<bool>& invalid_ref,
265 int min_disparity,
266 float invalid_disparity,
267 int const& multi_scale_mode,
268 vil_image_view<float>& disp_tar,
269 vil_image_view<float>& disp_ref,
270 float dynamic_range_factor)
271 {
272 // Compute disparity maps for both images
273 compute(img_tar, img_ref, invalid_tar, min_disparity,
274 invalid_disparity, multi_scale_mode, disp_tar, dynamic_range_factor, true);
275 compute(img_ref, img_tar, invalid_ref,
276 (-num_fine_disparities_-min_disparity+1),
277 invalid_disparity, multi_scale_mode, disp_ref, dynamic_range_factor,true);
278
279 // Compute error maps
280 vil_image_view<bool> error_tar, error_ref;
281 bsgm_check_leftright(disp_tar, disp_ref, invalid_tar, invalid_ref, error_tar);
282 bsgm_check_leftright(disp_ref, disp_tar, invalid_ref, invalid_tar, error_ref);
283
284 // Set bad pixels to invalid
285 for (size_t y = 0; y < img_tar.nj(); y++)
286 for (size_t x = 0; x < img_tar.ni(); x++)
287 if (error_tar(x, y)) disp_tar(x, y) = invalid_disparity;
288
289 for (size_t y = 0; y < img_ref.nj(); y++)
290 for (size_t x = 0; x < img_ref.ni(); x++)
291 if (error_ref(x, y)) disp_ref(x, y) = invalid_disparity;
292
293 // Interpolate
294 if (params_.error_check_mode > 1) {
295 bsgm_interpolate_errors(disp_tar, invalid_tar,
296 img_tar, invalid_disparity, params_.shadow_thresh);
297 bsgm_interpolate_errors(disp_ref, invalid_ref,
298 img_ref, invalid_disparity, params_.shadow_thresh);
299 }
300
301 return true;
302 }
303
304
305 #endif // bsgm_multiscale_disparity_estimator_h_
306