RSLightFields
Disparity map estimator from 3D light fields
rslf_fine_to_coarse.hpp
Go to the documentation of this file.
1 #ifndef _RSLF_FINE_TO_COARSE
2 #define _RSLF_FINE_TO_COARSE
3 
4 
6 
7 
8 #define _MIN_SPATIAL_DIM 10
9 
10 
17 namespace rslf
18 {
19 
20 /*
21  * *****************************************************************
22  * FineToCoarse
23  * *****************************************************************
24  */
25 
26 template<typename DataType>
28 {
29 public:
31  (
32  const Vec<Mat>& epis,
33  float d_min,
34  float d_max,
35  int dim_d,
36  float epi_scale_factor = -1,
38  int max_pyr_depth = -1,
39  bool accept_all_last_scale = true
40  );
41  ~FineToCoarse();
42 
46  void run();
47 
51  void get_results(Vec<Mat>& out_map_s_v_u_, Vec<Mat>& out_validity_s_v_u_);
52 
56  void get_coloured_depth_maps(Vec<Mat>& out_plot_depth_s_v_u_, int cv_colormap = cv::COLORMAP_JET, bool saturate = true);
57 
61  void get_coloured_depth_maps_and_imgs(Vec<Mat>& out_plot_depth_s_v_u_, int cv_colormap = cv::COLORMAP_JET, bool saturate = true);
62 
66  void get_coloured_epi_pyr(Vec<Mat>& out_plot_epi_pyr_p_s_u_, int v = -1, int cv_colormap = cv::COLORMAP_JET, bool saturate = true);
67 
71  void get_coloured_depth_pyr(Vec<Mat>& out_plot_depth_pyr_p_v_u_, int s = -1, int cv_colormap = cv::COLORMAP_JET, bool saturate = true);
72 
73  //~ Mat get_coloured_epi(int v = -1, int cv_colormap = cv::COLORMAP_JET);
74  //~ Mat get_disparity_map(int s = -1, int cv_colormap = cv::COLORMAP_JET);
75 
76 private:
77  Vec<Depth2DComputer<DataType>* > m_computers;
78  Vec<Depth1DParameters<DataType>* > m_parameter_instances;
79  bool m_accept_all_last_scale;
80 };
81 
82 
83 /*
84  * Aliases
85  */
86 
91 
96 
97 
100 
101 
102 template<typename DataType>
104 (
105  const Vec<Mat>& epis,
106  float d_min,
107  float d_max,
108  int dim_d,
109  float epi_scale_factor,
110  const Depth1DParameters<DataType>& parameters,
111  int max_pyr_depth,
112  bool accept_all_last_scale
113 )
114 {
115  Vec<Mat> tmp_epis = epis;
116 
117  int start_dim_v = tmp_epis.size();
118  int start_dim_u = tmp_epis[0].cols;
119 
120  int dim_v = tmp_epis.size();
121  int dim_u = tmp_epis[0].cols;
122 
123  if (max_pyr_depth < 1)
124  max_pyr_depth = std::numeric_limits<int>::max();
125 
126  int counter = 0;
127 
128  while (dim_v > _MIN_SPATIAL_DIM && dim_u > _MIN_SPATIAL_DIM && counter < max_pyr_depth)
129  {
130  counter++;
131 
132  std::cout << "Creating Depth2DComputer with sizes (" << dim_v << ", " << dim_u << ")" << std::endl;
133 
134  Depth1DParameters<DataType>* new_parameters = new Depth1DParameters<DataType>(parameters);
135 
136  // Compute scale factor
137  new_parameters->par_slope_factor = (0.0 + dim_u) / start_dim_u;
138 
139  // Create a new Depth2DComputer
140  Depth2DComputer<DataType>* computer = new Depth2DComputer<DataType>(tmp_epis, d_min, d_max, dim_d, epi_scale_factor, *new_parameters);
141 
142  // Downsample
143  Vec<Mat> downsampled_epis;
144  downsample_EPIs(tmp_epis, downsampled_epis);
145  tmp_epis = downsampled_epis;
146 
147  dim_v = tmp_epis.size();
148  dim_u = tmp_epis[0].cols;
149 
150  m_computers.push_back(computer);
151  m_parameter_instances.push_back(new_parameters);
152  }
153 
154  // The last level should accept all disparity measures
155  if (accept_all_last_scale)
156  m_computers.back()->set_accept_all(true);
157 }
158 
159 template<typename DataType>
161 {
162  for (int p=0; p<m_computers.size(); p++)
163  {
164  delete m_computers[p];
165  delete m_parameter_instances[p];
166  }
167 }
168 
169 template<typename DataType>
171 {
172  for (int p=0; p<m_computers.size(); p++)
173  {
174  m_computers[p]->run();
175  if (p < m_computers.size() - 1)
176  {
177  std::cout << "Setting new depth bounds..." << std::endl;
178 
179  // Depth map
180  Vec<Mat> depth_map_up = m_computers[p]->get_depths_s_v_u();
181  Vec<Mat> depth_map_down = m_computers[p+1]->get_depths_s_v_u();
182  // Validity mask
183  Vec<Mat> mask_up = m_computers[p]->get_valid_depths_mask_s_v_u();
184  Vec<Mat> mask_down = m_computers[p+1]->get_valid_depths_mask_s_v_u();
185 
186  // dmin map
187  Vec<Mat> dmin_map = m_computers[p+1]->edit_dmin();
188  // dmax map
189  Vec<Mat> dmax_map = m_computers[p+1]->edit_dmax();
190 
191  int dim_s = depth_map_up.size();
192 
193  int dim_v_up = depth_map_up[0].rows;
194  int dim_u_up = depth_map_up[0].cols;
195 
196  int dim_v_down = depth_map_down[0].rows;
197  int dim_u_down = depth_map_down[0].cols;
198 
199  // Edit the min/max d's
200 #pragma omp parallel for
201  for (int s=0; s<dim_s; s++)
202  {
203  for (int v=0; v<dim_v_down; v++)
204  {
205  for (int u=0; u<dim_u_down; u++)
206  {
207  Vec<float> candidate_ds;
208  // 1st line
209  // Get the upscaled u, v
210  int v_up = std::min(2 * v, dim_v_up - 1);
211  int u_up = std::min(2 * u, dim_u_up - 1);
212  // Get the point at the left
213  int u_left = u_up;
214  float d_left = nan_type<float>();
215  while (u_left > 1)
216  {
217  u_left -= 1;
218  if (mask_up[s].at<uchar>(v_up, u_left) > 0)
219  {
220  d_left = depth_map_up[s].at<float>(v_up, u_left);
221  break;
222  }
223  }
224  int u_right = u_up;
225  float d_right = nan_type<float>();
226  while (u_right < dim_u_up-1)
227  {
228  u_right += 1;
229  if (mask_up[s].at<uchar>(v_up, u_right) > 0)
230  {
231  d_right = depth_map_up[s].at<float>(v_up, u_right);
232  break;
233  }
234  }
235  //~ if (!is_nan_type<float>(d_left) && !is_nan_type<float>(d_right))
236  //~ {
237  //~ dmin_map[s].at<float>(v, u) = std::min(d_left, d_right);
238  //~ dmax_map[s].at<float>(v, u) = std::max(d_left, d_right);//candidate_ds[mid_idx+1];
239  //~ }
240  if (!is_nan_type<float>(d_left) && !is_nan_type<float>(d_right))
241  {
242  candidate_ds.push_back(d_left);
243  candidate_ds.push_back(d_right);
244  }
245 
246  // 2nd line
247  if (v_up+1 < dim_v_up)
248  {
249  // Get the upscaled u, v
250  v_up += 1;
251  int u_up = std::min(2 * u, dim_u_up - 1);
252  // Get the point at the left
253  int u_left = u_up;
254  float d_left = nan_type<float>();
255  while (u_left > 1)
256  {
257  u_left -= 1;
258  if (mask_up[s].at<uchar>(v_up, u_left) > 0)
259  {
260  d_left = depth_map_up[s].at<float>(v_up, u_left);
261  break;
262  }
263  }
264  int u_right = u_up;
265  float d_right = nan_type<float>();
266  while (u_right < dim_u_up-1)
267  {
268  u_right += 1;
269  if (mask_up[s].at<uchar>(v_up, u_right) > 0)
270  {
271  d_right = depth_map_up[s].at<float>(v_up, u_right);
272  break;
273  }
274  }
275  if (!is_nan_type<float>(d_left) && !is_nan_type<float>(d_right))
276  {
277  candidate_ds.push_back(d_left);
278  candidate_ds.push_back(d_right);
279  }
280  }
281  if (candidate_ds.size() > 1)
282  {
283  std::sort(candidate_ds.begin(), candidate_ds.end());
284  int nb_candidates = candidate_ds.size();
285  //int mid_idx = (int)std::floor((nb_candidates-1.0)/2);
286  // Modify dmin and dmax
287  dmin_map[s].at<float>(v, u) = candidate_ds[0];//candidate_ds[mid_idx];
288  dmax_map[s].at<float>(v, u) = candidate_ds.back();//candidate_ds[mid_idx+1];
289  }
290  }
291  }
292  }
293 
294  //~ std::cout << dmax_map[50] << std::endl;
295  }
296  }
297 }
298 
299 template<typename DataType>
300 void FineToCoarse<DataType>::get_results(Vec<Mat>& out_map_s_v_u_, Vec<Mat>& out_validity_s_v_u_)
301 {
302  std::cout << "Getting results..." << std::endl;
303 
304  Vec<Vec<Mat >> disp_pyr_p_s_v_u_;
305  Vec<Vec<Mat >> validity_indicators_p_s_v_u_;
306 
307  for (int p=0; p<m_computers.size(); p++)
308  {
309  disp_pyr_p_s_v_u_.push_back(m_computers[p]->get_depths_s_v_u());
310  validity_indicators_p_s_v_u_.push_back(m_computers[p]->get_valid_depths_mask_s_v_u());
311  }
312 
314  (
315  disp_pyr_p_s_v_u_,
316  validity_indicators_p_s_v_u_,
317  out_map_s_v_u_,
318  out_validity_s_v_u_
319  );
320 }
321 
322 template<typename DataType>
323 void FineToCoarse<DataType>::get_coloured_depth_maps(Vec<Mat>& out_plot_depth_s_v_u_, int cv_colormap, bool saturate)
324 {
325  std::cout << "Plot depth results..." << std::endl;
326 
327  Vec<Mat> out_map_s_v_u_;
328  Vec<Mat> out_validity_s_v_u_;
329 
331  (
332  out_map_s_v_u_,
333  out_validity_s_v_u_
334  );
335 
336  int dim_s = out_map_s_v_u_.size();
337  int dim_v = out_map_s_v_u_[0].rows;
338  int dim_u = out_map_s_v_u_[0].cols;
339 
340  ImageConverter_uchar image_converter;
341  image_converter.fit(out_map_s_v_u_[(int)std::round(dim_s/2.0)], saturate);
342 
343  for (int s=0; s<dim_s; s++)
344  {
345 
346  Mat disparity_map;
347  image_converter.copy_and_scale(out_map_s_v_u_[s], disparity_map);
348  cv::applyColorMap(disparity_map, disparity_map, cv_colormap);
349 
350  int dim_v = disparity_map.rows;
351  int dim_u = disparity_map.cols;
352 
353  // Threshold scores
354  disparity_map.setTo(0.0, out_validity_s_v_u_[s] == 0);
355 
356  // Get image norm view
357  Mat im_norm = Mat(dim_v, dim_u, CV_32FC1);
358  for (int v=0; v<dim_v; v++)
359  {
360  for (int u=0; u<dim_u; u++)
361  {
362  Mat tmp = m_computers[0]->get_epis()[v];
363  im_norm.at<float>(v, u) = norm<DataType>(tmp.at<DataType>(s, u));
364  }
365  }
366  disparity_map.setTo(0.0, im_norm < _SHADOW_NORMALIZED_LEVEL);
367 
368  out_plot_depth_s_v_u_.push_back(disparity_map);
369  }
370 
371 }
372 
373 template<typename DataType>
374 void FineToCoarse<DataType>::get_coloured_depth_maps_and_imgs(Vec<Mat>& out_plot_depth_s_v_u_, int cv_colormap, bool saturate)
375 {
376  Vec<Mat> tmp;
377  get_coloured_depth_maps(tmp, cv_colormap, saturate);
378  Vec<Mat> epis = m_computers[0]->get_epis();
379 
380  int dim_s = tmp.size();
381  int dim_v = tmp[0].rows;
382  int dim_u = tmp[0].cols;
383 
384  out_plot_depth_s_v_u_.clear();
385 
386  ImageConverter_uchar converter;
387 
388  for (int s=0; s<dim_s; s++)
389  {
390  // Get the corresponding image
391  Mat img = Mat(dim_v, dim_u, epis[0].type());
392  for (int v=0; v<dim_v; v++)
393  {
394  epis[v].row(s).copyTo(img.row(v));
395  }
396 
397  if (s==0)
398  converter.fit(img, false);
399 
400  converter.copy_and_scale(img, img);
401 
402  if (img.channels() == 1)
403  // Convert to RGB
404  cv::cvtColor(img, img, CV_GRAY2RGB);
405 
406  std::cout << "img: " << img.size() << ", " << rslf::type2str(img.type()) << std::endl;
407  std::cout << "tmp[s]: " << tmp[s].size() << ", " << rslf::type2str(tmp[s].type()) << std::endl;
408 
409  // Concatenate with the depth map
410  if (dim_u > dim_v)
411  {
412  // Concatenate rows
413  cv::vconcat(img, tmp[s], img);
414  }
415  else
416  {
417  // Concatenate cols
418  cv::hconcat(img, tmp[s], img);
419  }
420 
421  out_plot_depth_s_v_u_.push_back(img);
422  }
423 }
424 
425 template<typename DataType>
426 void FineToCoarse<DataType>::get_coloured_epi_pyr(Vec<Mat>& out_plot_epi_pyr_p_s_u_, int v, int cv_colormap, bool saturate)
427 {
428 
429  int m_pyr_size_ = m_computers.size();
430  int m_dim_v_orig_ = m_computers[0]->get_depths_s_v_u()[0].rows;
431 
432  if (v == -1)
433  v = (int)std::round(m_dim_v_orig_/2.0);
434 
435  ImageConverter_uchar image_converter;
436 
437  out_plot_epi_pyr_p_s_u_.clear();
438  for (int p=0; p<m_pyr_size_; p++)
439  {
440  int dim_s = m_computers[p]->get_depths_s_v_u().size();
441  int dim_v = m_computers[p]->get_depths_s_v_u()[0].rows;
442  int dim_u = m_computers[p]->get_depths_s_v_u()[0].cols;
443 
444  Mat tmp(dim_s, dim_u, CV_32FC1);
445 
446  int v_scaled = (int)std::round(1.0 * v * dim_v / m_dim_v_orig_);
447 
448  Vec<Mat> masks = m_computers[p]->get_valid_depths_mask_s_v_u();
449 
450  for (int s=0; s<dim_s; s++)
451  {
452  m_computers[p]->get_depths_s_v_u()[s].row(v_scaled).copyTo(tmp.row(s));
453  tmp.row(s).setTo(0.0, masks[s].row(v_scaled) == 0);
454  }
455 
456  if (p == 0)
457  image_converter.fit(tmp, saturate);
458 
459  image_converter.copy_and_scale(tmp, tmp);
460  cv::applyColorMap(tmp, tmp, cv_colormap);
461 
462  // Get epi norm view
463  Mat epi_norm = Mat(dim_s, dim_u, CV_32FC1);
464  for (int s=0; s<dim_s; s++)
465  {
466  for (int u=0; u<dim_u; u++)
467  {
468  Mat tmp = m_computers[0]->get_epis()[v];
469  epi_norm.at<float>(s, u) = norm<DataType>(tmp.at<DataType>(s, u));
470  }
471  }
472  tmp.setTo(0.0, epi_norm < _SHADOW_NORMALIZED_LEVEL);
473 
474  out_plot_epi_pyr_p_s_u_.push_back(tmp);
475  }
476 
477 }
478 
479 
480 template<typename DataType>
481 void FineToCoarse<DataType>::get_coloured_depth_pyr(Vec<Mat>& out_plot_depth_pyr_p_v_u_, int s, int cv_colormap, bool saturate) {
482 
483  int m_pyr_size_ = m_computers.size();
484  int dim_s = m_computers[0]->get_depths_s_v_u().size();
485 
486  if (s == -1)
487  s = (int)std::round(dim_s/2.0);
488 
489  ImageConverter_uchar image_converter;
490 
491  out_plot_depth_pyr_p_v_u_.clear();
492  for (int p=0; p<m_pyr_size_; p++)
493  {
494  Mat tmp = m_computers[p]->get_depths_s_v_u()[s].clone();
495 
496  if (p == 0)
497  image_converter.fit(tmp, saturate);
498 
499  image_converter.copy_and_scale(tmp, tmp);
500  cv::applyColorMap(tmp, tmp, cv_colormap);
501 
502  Vec<Mat> masks = m_computers[p]->get_valid_depths_mask_s_v_u();
503 
504  tmp.setTo(0.0, masks[s] == 0);
505 
506  out_plot_depth_pyr_p_v_u_.push_back(tmp);
507  }
508 }
509 
510 }
511 
512 #endif
Impelment a structure containing all the algorithm parameters.
Definition: rslf_depth_computation_core.hpp:65
Definition: rslf_fine_to_coarse.hpp:27
std::string type2str(int type)
Get an explicit form of an OpenCV type.
Definition: rslf_types.cpp:52
void fuse_disp_maps(const Vec< Vec< Mat >> &in_disp_pyr_p_s_v_u, const Vec< Vec< Mat > > &in_validity_indicators_p_s_v_u, Vec< Mat > &out_map_s_v_u, Vec< Mat > &out_validity_s_v_u)
Fuse a pyramid of depths into one depth map and apply a median filter on top of it.
Definition: rslf_fine_to_coarse_core.cpp:70
std::vector< T > Vec
RSLF Vector class (std::vector)
Definition: rslf_types.hpp:32
Image normalizer to be fitted on a given image, that will further scale images given the preceding fi...
Definition: rslf_plot.hpp:45
Definition: rslf_depth_computation.hpp:14
void downsample_EPIs(const Vec< Mat > &in_epis, Vec< Mat > &out_epis)
Downsample given EPIs by a factor 2 in the spatial dimensions.
Definition: rslf_fine_to_coarse_core.cpp:14
void get_coloured_depth_pyr(Vec< Mat > &out_plot_depth_pyr_p_v_u_, int s=-1, int cv_colormap=cv::COLORMAP_JET, bool saturate=true)
Get the disparity map pyramid with colors corresponding to computed disparities.
Definition: rslf_fine_to_coarse.hpp:481
Implement low-level fine-to-coarse functions.
void get_coloured_depth_maps_and_imgs(Vec< Mat > &out_plot_depth_s_v_u_, int cv_colormap=cv::COLORMAP_JET, bool saturate=true)
Get disparity maps with colors corresponding to the computed disparities, juxtaposed with the origina...
Definition: rslf_fine_to_coarse.hpp:374
cv::Mat Mat
RSLF Matrix class (cv::Mat)
Definition: rslf_types.hpp:26
void copy_and_scale(const Mat &src, Mat &dst)
Scales the input image to uchar and return a copy.
Definition: rslf_plot.cpp:100
void run()
Runs the algorithm.
Definition: rslf_fine_to_coarse.hpp:170
void get_coloured_depth_maps(Vec< Mat > &out_plot_depth_s_v_u_, int cv_colormap=cv::COLORMAP_JET, bool saturate=true)
Get disparity maps with colors corresponding to the computed disparities.
Definition: rslf_fine_to_coarse.hpp:323
void get_coloured_epi_pyr(Vec< Mat > &out_plot_epi_pyr_p_s_u_, int v=-1, int cv_colormap=cv::COLORMAP_JET, bool saturate=true)
Get the EPI pyramid with colors corresponding to computed slopes.
Definition: rslf_fine_to_coarse.hpp:426
void fit(const Mat &img, bool saturate=true)
Given an image, fit the internal normalization parameters.
Definition: rslf_plot.cpp:66
void get_results(Vec< Mat > &out_map_s_v_u_, Vec< Mat > &out_validity_s_v_u_)
Get the resulting disparity maps at the finest scale and the corresponding validity mask...
Definition: rslf_fine_to_coarse.hpp:300
Definition: rslf_depth_computation.hpp:167