stereo-vision
All Data Structures Namespaces Functions Modules Pages
StereoMatcher.cpp
1 
2 
3 #include "fastBilateral.hpp"
4 #include "StereoMatcher.h"
5 #include <opencv2/opencv.hpp>
6 
7 using cv::Ptr;
8 using cv::StereoSGBM;
9 using namespace cv::ximgproc;
10 
11 
12 Rect computeROI2(Size2i src_sz, Ptr<StereoMatcher> matcher_instance)
13 {
14  int min_disparity = matcher_instance->getMinDisparity();
15  int num_disparities = matcher_instance->getNumDisparities();
16  int block_size = matcher_instance->getBlockSize();
17 
18  int bs2 = block_size/2;
19  int minD = min_disparity, maxD = min_disparity + num_disparities - 1;
20 
21  int xmin = maxD + bs2;
22  int xmax = src_sz.width + minD - bs2;
23  int ymin = bs2;
24  int ymax = src_sz.height - bs2;
25 
26  Rect r(xmin, ymin, xmax - xmin, ymax - ymin);
27 
28  return r;
29 }
30 
31 
32 void StereoMatcherNew::setParameters(int minDisparity, int numberOfDisparities, int SADWindowSize,
33  int disp12MaxDiff, int preFilterCap, int uniquenessRatio,
34  int speckleWindowSize, int speckleRange, double sigmaColorBLF,
35  double sigmaSpaceBLF, double wls_lambda, double wls_sigma,
36  SM_BLF_FILTER BLFfiltering, SM_WLS_FILTER WLSfiltering,
37  SM_MATCHING_ALG stereo_matching)
38 {
39  this->stereo_parameters.minDisparity = minDisparity;
40  this->stereo_parameters.numberOfDisparities = numberOfDisparities;
41  this->stereo_parameters.SADWindowSize = SADWindowSize;
42  this->stereo_parameters.disp12MaxDiff = disp12MaxDiff;
43  this->stereo_parameters.preFilterCap = preFilterCap;
44  this->stereo_parameters.uniquenessRatio = uniquenessRatio;
45  this->stereo_parameters.speckleWindowSize = speckleWindowSize;
46  this->stereo_parameters.speckleRange = speckleRange;
47  this->stereo_parameters.sigmaColorBLF = sigmaColorBLF;
48  this->stereo_parameters.sigmaSpaceBLF = sigmaSpaceBLF;
49  this->stereo_parameters.wls_lambda = wls_lambda;
50  this->stereo_parameters.wls_sigma = wls_sigma;
51  this->stereo_parameters.BLFfiltering = BLFfiltering;
52  this->stereo_parameters.WLSfiltering = WLSfiltering;
53  this->stereo_parameters.stereo_matching = stereo_matching;
54 }
55 
56 
57 void StereoMatcherNew::compute()
58 {
59  // prepares the StereoCamera and
60  // rectifies the input images
61 
62  this->stereo->updateMappings();
63  this->stereo->rectifyImages();
64 
65  // runs the selected stereo matching algorithm
66 
67  switch(this->stereo_parameters.stereo_matching)
68  {
69  case SM_MATCHING_ALG::SGBM_OPENCV:
70  this->matchSGBM();
71  break;
72  case SM_MATCHING_ALG::SGBM_CUDA:
73  this->matchSGBMCUDA();
74  break;
75  case SM_MATCHING_ALG::LIBELAS:
76  this->matchLIBELAS();
77  break;
78  }
79 }
80 
81 
82 void StereoMatcherNew::filterBLF(string kind = "base")
83 {
84 
85  cv::Mat input = this->getDisparity(kind);
86  cv::Mat input16 = this->getDisparity16(kind);
87 
88  switch(this->stereo_parameters.BLFfiltering)
89  {
90  case SM_BLF_FILTER::BLF_ORIGINAL:
91 
93  this->disparity16_blf,
94  this->stereo_parameters.sigmaColorBLF,
95  this->stereo_parameters.sigmaSpaceBLF);
96 
97  getDisparityVis(this->disparity16_blf, this->disparity_blf, 3);
98 
99  break;
100 
101  case SM_BLF_FILTER::BLF_CUDA:
102  {
103  cv::Mat grayL = this->stereo->getLRectified();
104  cv::cvtColor(grayL, grayL, CV_BGR2GRAY);
105 
106  imageGpu.upload(grayL);
107  gpuDisp.upload(input16);
108 
109  pCudaBilFilter->apply(gpuDisp, imageGpu, filtGpu);
110 
111  filtGpu.download(this->disparity16_blf);
112 
113  getDisparityVis(this->disparity16_blf, this->disparity_blf, 3);
114 
115  break;
116  }
117  case SM_BLF_FILTER::BLF_DISABLED:
118  default:
119 
120  this->disparity_blf = input.clone();
121  this->disparity16_blf = input16.clone();
122  break;
123  }
124 }
125 
126 
127 void StereoMatcherNew::filterWLS(string kind = "base")
128 {
129  cv::Mat input = this->getDisparity(kind);
130  cv::Mat input16 = this->getDisparity16(kind);
131  cv::Rect ROI;
132 
133  if(this->stereo_parameters.WLSfiltering != SM_WLS_FILTER::WLS_DISABLED)
134  {
135 
136  Ptr<StereoSGBM> sgbm =cv::StereoSGBM::create(this->stereo_parameters.minDisparity,
137  this->stereo_parameters.numberOfDisparities,
138  this->stereo_parameters.SADWindowSize,
139  8*3*this->stereo_parameters.SADWindowSize*this->stereo_parameters.SADWindowSize,
140  32*3*this->stereo_parameters.SADWindowSize*this->stereo_parameters.SADWindowSize,
141  this->stereo_parameters.disp12MaxDiff,
142  this->stereo_parameters.preFilterCap,
143  this->stereo_parameters.uniquenessRatio,
144  this->stereo_parameters.speckleWindowSize,
145  this->stereo_parameters.speckleRange,
146  this->useBestDisp?StereoSGBM::MODE_HH:StereoSGBM::MODE_SGBM);
147 
148  cv::Mat left_rect = this->stereo->getLRectified();
149 
150  switch(this->stereo_parameters.WLSfiltering)
151  {
152  case SM_WLS_FILTER::WLS_ENABLED:
153 
154  wls_filter->setLambda(this->stereo_parameters.wls_lambda);
155  wls_filter->setSigmaColor(this->stereo_parameters.wls_sigma);
156  wls_filter->setDepthDiscontinuityRadius((int)ceil(0.5*this->stereo_parameters.SADWindowSize));
157  ROI = computeROI2(left_rect.size(),sgbm);
158 
159  wls_filter->filter(input,left_rect,this->disparity_wls,Mat(),ROI);
160  wls_filter->filter(input16,left_rect,this->disparity16_wls,Mat(),ROI);
161 
162  break;
163 
164  case SM_WLS_FILTER::WLS_LRCHECK:
165 
166  if(this->stereo_matching == SM_MATCHING_ALG::SGBM_OPENCV)
167  {
168 
169  wls_filter->setLambda(this->stereo_parameters.wls_lambda);
170  wls_filter->setSigmaColor(this->stereo_parameters.wls_sigma);
171 
172  cv::Mat right_disp;
173 
174  Ptr<StereoMatcher> right_matcher = cv::ximgproc::createRightMatcher(sgbm);
175 
176  right_matcher->compute(this->stereo->getRRectified(),this->stereo->getLRectified(), right_disp);
177 
178  wls_filter->filter(input,left_rect,this->disparity_wls,right_disp);
179  wls_filter->filter(input16,left_rect,this->disparity16_wls,right_disp);
180 
181  }
182  else
183  this->disparity_wls = input.clone();
184  this->disparity16_wls = input16.clone();
185 
186  break;
187 
188  default:
189 
190  break;
191  }
192  }
193  else
194  {
195  this->disparity_wls = input.clone();
196  this->disparity16_wls = input16.clone();
197  }
198 }
199 
200 
201 cv::Mat StereoMatcherNew::getDisparity(string kind="base")
202 {
203  // return the disparity map specified
204  // via the "kind" parameter
205 
206  if(kind == "base")
207  return this->disparity;
208  else if(kind == "blf")
209  return this->disparity_blf;
210  else if(kind == "wls")
211  return this->disparity_wls;
212  else
213  {
214  std::cout << "[StereoMatcherNew] !! Disparity kind " << kind << " not found, returning BASE disparity." << std::endl;
215  return this->disparity;
216  }
217 }
218 
219 
220 
221 cv::Mat StereoMatcherNew::getDisparity16(string kind="base")
222 {
223  // return the disparity map specified
224  // via the "kind" parameter
225 
226  if(kind == "base")
227  return this->disparity16;
228  else if(kind == "blf")
229  return this->disparity16_blf;
230  else if(kind == "wls")
231  return this->disparity16_wls;
232  else
233  {
234  std::cout << "[StereoMatcherNew] !! Disparity16 kind " << kind << " not found, returning BASE disparity16." << std::endl;
235  return this->disparity16;
236  }
237 }
238 
239 
240 void StereoMatcherNew::setAlgorithm(string name)
241 {
242  // set the stereo matching algorithm used, defaults
243  // to OpenCV SGBM in case an unknown name is given
244 
245  if(name == "sgbm")
246  this->stereo_parameters.stereo_matching = SM_MATCHING_ALG::SGBM_OPENCV;
247  else if(name == "sgbm_cuda")
248  this->stereo_parameters.stereo_matching = SM_MATCHING_ALG::SGBM_CUDA;
249  else if(name == "libelas")
250  this->stereo_parameters.stereo_matching = SM_MATCHING_ALG::LIBELAS;
251  else
252  {
253  std::cout << "[StereoMatcherNew] !! Stereo Matching algorithm " << name << " not found, defaulting to SGBM." << std::endl;
254  this->stereo_parameters.stereo_matching = SM_MATCHING_ALG::SGBM_OPENCV;
255  }
256 }
257 
258 
259 StereoMatcherNew::StereoMatcherNew(yarp::os::ResourceFinder &rf, StereoCamera * stereo)
260 {
261  // initializes the StereoMatcherNew object
262  // and a few internal parameters and objects
263 
264  this->stereo = stereo;
265  this->wls_filter = cv::ximgproc::createDisparityWLSFilterGeneric(false);
266  this->initELAS(rf);
267  this->initCUDAbilateralFilter();
268 }
269 
270 
271 void StereoMatcherNew::updateCUDAParams()
272 {
273  // updates the parameters for the CUDA matching algorithm
274  // in the corresponding struct, together to those related
275  // to the CUDA bilateral filter
276 
277  this->cuda_params.preFilterCap = this->stereo_parameters.preFilterCap;
278  this->cuda_params.BlockSize = this->stereo_parameters.SADWindowSize;
279  this->cuda_params.P1 = 8 * this->cuda_params.BlockSize * this->cuda_params.BlockSize;
280  this->cuda_params.P2 = 32 * this->cuda_params.BlockSize * this->cuda_params.BlockSize;
281  this->cuda_params.uniquenessRatio = this->stereo_parameters.uniquenessRatio;
282  this->cuda_params.disp12MaxDiff = this->stereo_parameters.disp12MaxDiff;
283  this->cuda_params.numberOfDisparities = this->stereo_parameters.numberOfDisparities;
284 
285  cuda_init(&this->cuda_params);
286 
287  pCudaBilFilter->setSigmaRange(this->stereo_parameters.sigmaColorBLF);
288  pCudaBilFilter->setNumDisparities(this->stereo_parameters.numberOfDisparities);
289 }
290 
291 
292 void StereoMatcherNew::initCUDAbilateralFilter()
293 {
294  // initializes the values for the CUDA bilateral filtering
295 
296  int radius = 7;
297  int iters = 2;
298 
299  this->pCudaBilFilter = cuda::createDisparityBilateralFilter(this->stereo_parameters.numberOfDisparities, radius, iters);
300  this->pCudaBilFilter->setSigmaRange(this->stereo_parameters.sigmaColorBLF);
301 }
302 
303 
304 void StereoMatcherNew::initELAS(yarp::os::ResourceFinder &rf)
305 {
306  // initializes the parameters for the stereo
307  // matching algorithm implemented in libElas
308 
309  string elas_string = rf.check("elas_setting",Value("ROBOTICS")).asString();
310 
311  double disp_scaling_factor = rf.check("disp_scaling_factor",Value(1.0)).asFloat64();
312 
313  this->elaswrap = new elasWrapper(disp_scaling_factor, elas_string);
314 
315  if (rf.check("elas_subsampling"))
316  elaswrap->set_subsampling(true);
317 
318  if (rf.check("elas_add_corners"))
319  elaswrap->set_add_corners(true);
320 
321  elaswrap->set_ipol_gap_width(40);
322  if (rf.check("elas_ipol_gap_width"))
323  elaswrap->set_ipol_gap_width(rf.find("elas_ipol_gap_width").asInt32());
324 
325  if (rf.check("elas_support_threshold"))
326  elaswrap->set_support_threshold(rf.find("elas_support_threshold").asFloat64());
327 
328  if(rf.check("elas_gamma"))
329  elaswrap->set_gamma(rf.find("elas_gamma").asFloat64());
330 
331  if (rf.check("elas_sradius"))
332  elaswrap->set_sradius(rf.find("elas_sradius").asFloat64());
333 
334  if (rf.check("elas_match_texture"))
335  elaswrap->set_match_texture(rf.find("elas_match_texture").asInt32());
336 
337  if (rf.check("elas_filter_median"))
338  elaswrap->set_filter_median(rf.find("elas_filter_median").asBool());
339 
340  if (rf.check("elas_filter_adaptive_mean"))
341  elaswrap->set_filter_adaptive_mean(rf.find("elas_filter_adaptive_mean").asBool());
342 
343 
344  // the following code to print the libElas parameters has
345  // been commented, still is left here in case it's needed
346  // in the future
347 
348  // cout << endl << "ELAS parameters:" << endl << endl;
349 
350  // cout << "disp_scaling_factor: " << disp_scaling_factor << endl;
351 
352  // cout << "setting: " << elas_string << endl;
353 
354  // cout << "postprocess_only_left: " << elaswrap->get_postprocess_only_left() << endl;
355  // cout << "subsampling: " << elaswrap->get_subsampling() << endl;
356 
357  // cout << "add_corners: " << elaswrap->get_add_corners() << endl;
358 
359  // cout << "ipol_gap_width: " << elaswrap->get_ipol_gap_width() << endl;
360 
361  // cout << "support_threshold: " << elaswrap->get_support_threshold() << endl;
362  // cout << "gamma: " << elaswrap->get_gamma() << endl;
363  // cout << "sradius: " << elaswrap->get_sradius() << endl;
364 
365  // cout << "match_texture: " << elaswrap->get_match_texture() << endl;
366 
367  // cout << "filter_median: " << elaswrap->get_filter_median() << endl;
368  // cout << "filter_adaptive_mean: " << elaswrap->get_filter_adaptive_mean() << endl;
369 
370  // cout << endl;
371 }
372 
373 
374 
375 void StereoMatcherNew::matchLIBELAS()
376 {
377  // runs the computation of the disparity map using the libElas wrapper
378 
379  cv::Mat map;
380 
381  bool success = elaswrap->compute_disparity(this->stereo->getLRectified(), this->stereo->getRRectified(), this->disparity, this->stereo_parameters.numberOfDisparities);
382 
383  if (success)
384  map = this->disparity * (255.0 / this->stereo_parameters.numberOfDisparities);
385 
386  this->disparity.convertTo(this->disparity16, CV_16SC1, 16.0);
387 
388  getDisparityVis(this->disparity16, this->disparity, 3);
389 }
390 
391 
392 void StereoMatcherNew::matchSGBM()
393 {
394  // computes the disparity map using the implementation
395  // of SGBM available in OpenCV
396 
397  cv::Mat map, disp;
398 
399  Ptr<StereoSGBM> sgbm =cv::StereoSGBM::create(this->stereo_parameters.minDisparity,
400  this->stereo_parameters.numberOfDisparities,
401  this->stereo_parameters.SADWindowSize,
402  8*3*this->stereo_parameters.SADWindowSize*this->stereo_parameters.SADWindowSize,
403  32*3*this->stereo_parameters.SADWindowSize*this->stereo_parameters.SADWindowSize,
404  this->stereo_parameters.disp12MaxDiff,
405  this->stereo_parameters.preFilterCap,
406  this->stereo_parameters.uniquenessRatio,
407  this->stereo_parameters.speckleWindowSize,
408  this->stereo_parameters.speckleRange,
409  this->useBestDisp?StereoSGBM::MODE_HH:StereoSGBM::MODE_SGBM);
410 
411 
412  sgbm->compute(this->stereo->getLRectified(), this->stereo->getRRectified(), disp);
413 
414  this->disparity16 = disp;
415 
416  getDisparityVis(disp, this->disparity, 3);
417 }
418 
419 
420 void StereoMatcherNew::matchSGBMCUDA()
421 {
422  // runs the SGBM stereo matching algorithm implemented in CUDA
423 
424  cv::Mat outputDm;
425 
426  cv::Mat grayL = this->stereo->getLRectified();
427  cv::Mat grayR = this->stereo->getRRectified();
428 
429  cv::cvtColor(grayL, grayL, CV_BGR2GRAY);
430  cv::cvtColor(grayR, grayR, CV_BGR2GRAY);
431 
432  outputDm = zy_remap(grayL, grayR);
433 
434  cv::Mat map;
435  outputDm.convertTo(map,CV_32FC1,255/(this->stereo_parameters.numberOfDisparities*16.));
436 
437  getDisparityVis(outputDm, this->disparity, 3);
438 
439  this->disparity16 = outputDm;
440 }
441 
442 
443 StereoMatcherNew::~StereoMatcherNew()
444 {
445 
446 }
The base class defining stereo camera.
Definition: stereoCamera.h:92
void bilateralFilter(cv::InputArray src, cv::OutputArray dst, double sigmaColor, double sigmaSpace)
Implementation.