DepthFromStereo.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #include "DepthFromStereo.h"
25 
26 // OpenCV
27 #include <opencv2/opencv.hpp>
28 
29 
30 // IVT
31 #include <Math/Math3d.h>
32 #include <Image/ByteImage.h>
33 #include <Image/ImageProcessor.h>
34 #include <Image/IplImageAdaptor.h>
35 #include <Image/StereoMatcher.h>
36 #include <Calibration/StereoCalibration.h>
37 #include <Calibration/Calibration.h>
38 #include <Calibration/Rectification.h>
39 #include <Threading/Threading.h>
40 
41 #include <opencv2/calib3d.hpp>
42 
43 #include <cmath>
44 #include <limits>
45 
46 
48 {
49 
50  static void doStereoSGBM(int minDisparity, int numDisparities, int nSADWindowSize, int P1, int P2, int disp12MaxDiff,
51  cv::Mat leftInput, cv::Mat rightInput, cv::Mat output)
52  {
53  int preFilterCap = 0;
54  int uniquenessRatio = 0;
55  int speckleWindowSize = 0;
56  int speckleRange = 0;
57 #if CV_MAJOR_VERSION == 2
58  bool fullDP = true;
59  cv::StereoSGBM stereoSGBM(minDisparity, numDisparities, nSADWindowSize, P1, P2, disp12MaxDiff, preFilterCap, uniquenessRatio, speckleWindowSize, speckleRange, fullDP);
60  stereoSGBM(leftInput, rightInput, output);
61 #else
62  cv::Ptr<cv::StereoSGBM> stereoSGBM = cv::StereoSGBM::create(minDisparity, numDisparities, nSADWindowSize, P1, P2, disp12MaxDiff, preFilterCap, uniquenessRatio, speckleWindowSize, speckleRange, cv::StereoSGBM::MODE_SGBM);
63  stereoSGBM->compute(leftInput, rightInput, output);
64 #endif
65  }
66 
67  void GetPointsFromDisparity(const CByteImage* pImageLeftColor, const CByteImage* pImageRightColor, const CByteImage* pImageLeftGrey, const CByteImage* pImageRightGrey,
68  const int nDisparityPointDistance, pcl::PointCloud<pcl::PointXYZRGBA>& aPointsFromDisparity, CByteImage* pDisparityImage,
69  const int imageWidth, const int imageHeight, CStereoCalibration* pStereoCalibration, bool imagesAreUndistorted, const bool smoothDisparities)
70  {
71  // rectify images
72  CByteImage* pRectifiedImageLeftGrey, *pRectifiedImageRightGrey, *pRectifiedImageLeftGreyHalfsize, *pRectifiedImageRightGreyHalfsize, *pRectifiedImageLeftGreyQuartersize, *pRectifiedImageRightGreyQuartersize;
73  IplImage* pRectifiedIplImageLeft, *pRectifiedIplImageRight, *pRectifiedIplImageLeftHalfsize, *pRectifiedIplImageRightHalfsize, *pRectifiedIplImageLeftQuartersize, *pRectifiedIplImageRightQuartersize;
74  CByteImage* pRectifiedImageLeftColorGaussFiltered;
75  cv::Mat mDispImg, mDispImgHalfsize, mDispImgQuartersize;
76  bool bGreyImagesReady = false;
77  bool bGreyImagesHalfsizeReady = false;
78  bool bGreyImagesQuartersizeReady = false;
79  const int nPenaltyDispDiffOneFactor = 8;
80  const int nPenaltyDispDiffBiggerOneFactor = 32;
81 
82  CStereoMatcher* pStereoMatcher = new CStereoMatcher();
83  CStereoCalibration* pStereoCalibrationCopy = new CStereoCalibration(*pStereoCalibration);
84  pStereoMatcher->InitCameraParameters(pStereoCalibrationCopy, false);
85 
86  const int nDispMin = pStereoMatcher->GetDisparityEstimate(8000);
87  const int nDispMax = pStereoMatcher->GetDisparityEstimate(400);
88 
89  const int imageOverlapCutoffLeft = 0; // 110
90  const int imageOverlapCutoffRight = 0; // 5
91  const int imageOverlapCutoffTop = 0; // 5
92  const int imageOverlapCutoffBottom = 0; // 5
93 
94  const bool fillHoles = false;
95 
96 
97  #pragma omp parallel sections
98  {
99  #pragma omp section
100  {
101  const CByteImage* ppOriginalImages[2];
102  ppOriginalImages[0] = pImageLeftGrey;
103  ppOriginalImages[1] = pImageRightGrey;
104  pRectifiedImageLeftGrey = new CByteImage(imageWidth, imageHeight, CByteImage::eGrayScale);
105  pRectifiedImageRightGrey = new CByteImage(imageWidth, imageHeight, CByteImage::eGrayScale);
106  CByteImage* ppRectifiedImages[2];
107  ppRectifiedImages[0] = pRectifiedImageLeftGrey;
108  ppRectifiedImages[1] = pRectifiedImageRightGrey;
109 
110  CRectification* pRectification = new CRectification(true, !imagesAreUndistorted);
111  pRectification->Init(pStereoCalibration);
112  pRectification->Rectify(ppOriginalImages, ppRectifiedImages);
113 
114  pRectifiedIplImageLeft = IplImageAdaptor::Adapt(pRectifiedImageLeftGrey);
115  pRectifiedIplImageRight = IplImageAdaptor::Adapt(pRectifiedImageRightGrey);
116  bGreyImagesReady = true;
117 
118  // half size
119  pRectifiedImageLeftGreyHalfsize = new CByteImage(imageWidth / 2, imageHeight / 2, CByteImage::eGrayScale);
120  pRectifiedImageRightGreyHalfsize = new CByteImage(imageWidth / 2, imageHeight / 2, CByteImage::eGrayScale);
121  ::ImageProcessor::Resize(pRectifiedImageLeftGrey, pRectifiedImageLeftGreyHalfsize);
122  ::ImageProcessor::Resize(pRectifiedImageRightGrey, pRectifiedImageRightGreyHalfsize);
123 
124  pRectifiedIplImageLeftHalfsize = IplImageAdaptor::Adapt(pRectifiedImageLeftGreyHalfsize);
125  pRectifiedIplImageRightHalfsize = IplImageAdaptor::Adapt(pRectifiedImageRightGreyHalfsize);
126  bGreyImagesHalfsizeReady = true;
127 
128  // quarter size
129  pRectifiedImageLeftGreyQuartersize = new CByteImage(imageWidth / 4, imageHeight / 4, CByteImage::eGrayScale);
130  pRectifiedImageRightGreyQuartersize = new CByteImage(imageWidth / 4, imageHeight / 4, CByteImage::eGrayScale);
131  ::ImageProcessor::Resize(pRectifiedImageLeftGrey, pRectifiedImageLeftGreyQuartersize);
132  ::ImageProcessor::Resize(pRectifiedImageRightGrey, pRectifiedImageRightGreyQuartersize);
133 
134  pRectifiedIplImageLeftQuartersize = IplImageAdaptor::Adapt(pRectifiedImageLeftGreyQuartersize);
135  pRectifiedIplImageRightQuartersize = IplImageAdaptor::Adapt(pRectifiedImageRightGreyQuartersize);
136  bGreyImagesQuartersizeReady = true;
137 
138  delete pRectification;
139  }
140 
141  #pragma omp section
142  {
143  const CByteImage* ppOriginalImages[2];
144  ppOriginalImages[0] = pImageLeftColor;
145  ppOriginalImages[1] = pImageRightColor;
146  CByteImage* pRectifiedImageLeftColor = new CByteImage(imageWidth, imageHeight, CByteImage::eRGB24);
147  CByteImage* pRectifiedImageRightColor = new CByteImage(imageWidth, imageHeight, CByteImage::eRGB24);
148  CByteImage* ppRectifiedImages[2];
149  ppRectifiedImages[0] = pRectifiedImageLeftColor;
150  ppRectifiedImages[1] = pRectifiedImageRightColor;
151 
152  CRectification* pRectification = new CRectification(true, !imagesAreUndistorted);
153  pRectification->Init(pStereoCalibration);
154  pRectification->Rectify(ppOriginalImages, ppRectifiedImages);
155 
156  pRectifiedImageLeftColorGaussFiltered = new CByteImage(imageWidth, imageHeight, CByteImage::eRGB24);
157  ::ImageProcessor::GaussianSmooth3x3(pRectifiedImageLeftColor, pRectifiedImageLeftColorGaussFiltered);
158 
159  delete pRectifiedImageLeftColor;
160  delete pRectifiedImageRightColor;
161  delete pRectification;
162  }
163 
164 
165  // get disparity using semi-global block matching
166 
167  #pragma omp section
168  {
169  while (!bGreyImagesReady)
170  {
171  Threading::YieldThread();
172  }
173 
174  // StereoSGBM::StereoSGBM(int minDisparity, int numDisparities, int SADWindowSize, int P1=0, int P2=0, int disp12MaxDiff=0,
175  // int preFilterCap=0, int uniquenessRatio=0, int speckleWindowSize=0, int speckleRange=0, bool fullDP=false)
176  //
177  // minDisparity – Minimum possible disparity value. Normally, it is zero but sometimes rectification algorithms can shift images, so this parameter needs to be adjusted accordingly.
178  // numDisparities – Maximum disparity minus minimum disparity. The value is always greater than zero. In the current implementation, this parameter must be divisible by 16.
179  // SADWindowSize – Matched block size. It must be an odd number >=1 . Normally, it should be somewhere in the 3..11 range.
180  // P1 – The first parameter controlling the disparity smoothness. See below.
181  // P2 – The second parameter controlling the disparity smoothness. The larger the values are, the smoother the disparity is. P1 is the penalty on the disparity change by plus or minus 1 between neighbor pixels. P2 is the penalty on the disparity change by more than 1 between neighbor pixels. The algorithm requires P2 > P1 . See stereo_match.cpp sample where some reasonably good P1 and P2 values are shown (like 8*number_of_image_channels*SADWindowSize*SADWindowSize and 32*number_of_image_channels*SADWindowSize*SADWindowSize , respectively).
182  // disp12MaxDiff – Maximum allowed difference (in integer pixel units) in the left-right disparity check. Set it to a non-positive value to disable the check.
183  // preFilterCap – Truncation value for the prefiltered image pixels. The algorithm first computes x-derivative at each pixel and clips its value by [-preFilterCap, preFilterCap] interval. The result values are passed to the Birchfield-Tomasi pixel cost function.
184  // uniquenessRatio – Margin in percentage by which the best (minimum) computed cost function value should “win” the second best value to consider the found match correct. Normally, a value within the 5-15 range is good enough.
185  // speckleWindowSize – Maximum size of smooth disparity regions to consider their noise speckles and invalidate. Set it to 0 to disable speckle filtering. Otherwise, set it somewhere in the 50-200 range.
186  // speckleRange – Maximum disparity variation within each connected component. If you do speckle filtering, set the parameter to a positive value, multiple of 16. Normally, 16 or 32 is good enough.
187  // fullDP – Set it to true to run the full-scale two-pass dynamic programming algorithm. It will consume O(W*H*numDisparities) bytes, which is large for 640x480 stereo and huge for HD-size pictures. By default, it is set to false.
188  const cv::Mat mLeftImg = cv::cvarrToMat(pRectifiedIplImageLeft);
189  const cv::Mat mRightImg = cv::cvarrToMat(pRectifiedIplImageRight);
190  const int nSADWindowSize = 7; // 11
191  const int nPenaltyDispDiffOne = nPenaltyDispDiffOneFactor * 3 * nSADWindowSize * nSADWindowSize; // 8
192  const int nPenaltyDispDiffBiggerOne = nPenaltyDispDiffBiggerOneFactor * 3 * nSADWindowSize * nSADWindowSize; // 32
193 
194  doStereoSGBM(1, 8 * 16, nSADWindowSize, nPenaltyDispDiffOne, nPenaltyDispDiffBiggerOne, 4, mLeftImg, mRightImg, mDispImg);
195  }
196 
197 
198  #pragma omp section
199  {
200  while (!bGreyImagesHalfsizeReady)
201  {
202  Threading::YieldThread();
203  }
204 
205  const cv::Mat mLeftImg = cv::cvarrToMat(pRectifiedIplImageLeftHalfsize);
206  const cv::Mat mRightImg = cv::cvarrToMat(pRectifiedIplImageRightHalfsize);
207  const int nSADWindowSize = 7;
208  const int nPenaltyDispDiffOne = nPenaltyDispDiffOneFactor * 3 * nSADWindowSize * nSADWindowSize; // 8
209  const int nPenaltyDispDiffBiggerOne = nPenaltyDispDiffBiggerOneFactor * 3 * nSADWindowSize * nSADWindowSize; // 32
210  doStereoSGBM(1, 4 * 16, nSADWindowSize, nPenaltyDispDiffOne, nPenaltyDispDiffBiggerOne, 4, mLeftImg, mRightImg, mDispImgHalfsize);
211  }
212 
213 
214  #pragma omp section
215  {
216  while (!bGreyImagesQuartersizeReady)
217  {
218  Threading::YieldThread();
219  }
220 
221  const cv::Mat mLeftImg = cv::cvarrToMat(pRectifiedIplImageLeftQuartersize);
222  const cv::Mat mRightImg = cv::cvarrToMat(pRectifiedIplImageRightQuartersize);
223  const int nSADWindowSize = 7;
224  const int nPenaltyDispDiffOne = nPenaltyDispDiffOneFactor * 3 * nSADWindowSize * nSADWindowSize; // 8
225  const int nPenaltyDispDiffBiggerOne = nPenaltyDispDiffBiggerOneFactor * 3 * nSADWindowSize * nSADWindowSize; // 32
226 
227  doStereoSGBM(1, 4 * 16, nSADWindowSize, nPenaltyDispDiffOne, nPenaltyDispDiffBiggerOne, 4, mLeftImg, mRightImg, mDispImgQuartersize);
228  }
229  }
230 
231 
232  // combine disparities
233  float* pDisparities = new float[imageWidth * imageHeight];
234  #pragma omp parallel for schedule(static, 80)
235  for (int i = 0; i < imageHeight; i++)
236  {
237  for (int j = 0; j < imageWidth; j++)
238  {
239  int nDispFullsize = mDispImg.at<short>(i, j) / 16;
240  int nDispHalfsize = 2 * mDispImgHalfsize.at<short>(i / 2, j / 2) / 16;
241  int nDispQuartersize = 4 * mDispImgQuartersize.at<short>(i / 4, j / 4) / 16;
242 
243  int nDisp = 0;
244  float fDisp = 0;
245  int nNumValidDisparities = 0;
246 
247  if ((nDispFullsize > nDispMin) && (nDispFullsize < nDispMax))
248  {
249  nDisp += nDispFullsize;
250  nNumValidDisparities++;
251  }
252 
253  if ((nDispHalfsize > nDispMin) && (nDispHalfsize < nDispMax))
254  {
255  nDisp += nDispHalfsize;
256  nNumValidDisparities++;
257  }
258 
259  if ((nDispQuartersize > nDispMin) && (nDispQuartersize < nDispMax))
260  {
261  nDisp += nDispQuartersize;
262  nNumValidDisparities++;
263  }
264 
265  if (nNumValidDisparities > 0)
266  {
267  fDisp = (float)nDisp / (float)nNumValidDisparities;
268  }
269 
270  pDisparities[i * imageWidth + j] = fDisp;
271  }
272  }
273 
274 
275  // fill holes
276  if (fillHoles)
277  {
278  std::vector<int> pDisparitiesCopy(imageWidth * imageHeight);
279 
280  for (int i = 0; i < imageHeight * imageWidth; i++)
281  {
282  pDisparitiesCopy[i] = pDisparities[i];
283  }
284 
285  const int nMargin = 10;
286  const int nHoleFillingAveragingRadius = 5;
287 
288  for (int i = nMargin; i < imageHeight - nMargin; i++)
289  {
290  for (int j = nMargin; j < imageWidth - nMargin; j++)
291  {
292  if (pDisparitiesCopy[i * imageWidth + j] == 0)
293  {
294  int nSum = 0;
295  int nNumValidDisparities = 0;
296 
297  for (int k = -nHoleFillingAveragingRadius; k <= nHoleFillingAveragingRadius; k++)
298  {
299  for (int l = -nHoleFillingAveragingRadius; l <= nHoleFillingAveragingRadius; l++)
300  {
301  if (pDisparitiesCopy[(i + k)*imageWidth + (j + l)] > 0)
302  {
303  nSum += pDisparitiesCopy[(i + k) * imageWidth + (j + l)];
304  nNumValidDisparities++;
305  }
306  }
307  }
308 
309  if (nNumValidDisparities > 0)
310  {
311  pDisparities[i * imageWidth + j] = nSum / nNumValidDisparities;
312  }
313  }
314  }
315  }
316  }
317 
318 
319 
320  // get smoothed disparity
321  float* pSmoothedDisparity = pDisparities;
322 
323  if (smoothDisparities)
324  {
325  pSmoothedDisparity = new float[imageWidth * imageHeight];
326  float* pSmoothedDisparity1 = new float[imageWidth * imageHeight];
327  float* pSmoothedDisparity2 = new float[imageWidth * imageHeight];
328  float* pSmoothedDisparity3 = new float[imageWidth * imageHeight];
329  float* pSmoothedDisparity4 = new float[imageWidth * imageHeight];
330 
331  #pragma omp parallel sections
332  {
333  #pragma omp section
334  {
335  CalculateSmoothedDisparityImage(pDisparities, pSmoothedDisparity1, imageWidth, imageHeight, 1);
336  }
337 
338  #pragma omp section
339  {
340  CalculateSmoothedDisparityImage(pDisparities, pSmoothedDisparity2, imageWidth, imageHeight, 2);
341  }
342 
343  #pragma omp section
344  {
345  //CalculateSmoothedDisparityImage(pDisparities, pSmoothedDisparity3, imageWidth, imageHeight, 3);
346  }
347 
348  #pragma omp section
349  {
350  //CalculateSmoothedDisparityImage(pDisparities, pSmoothedDisparity4, imageWidth, imageHeight, 4);
351  }
352  }
353 
354  for (int i = 0; i < imageWidth * imageHeight; i++)
355  {
356  pSmoothedDisparity[i] = 0.8f * pDisparities[i] + 0.15f * pSmoothedDisparity1[i] + 0.05f * pSmoothedDisparity2[i];// + 0.0f * pSmoothedDisparity3[i] + 0.0f * pSmoothedDisparity4[i];
357  }
358 
359  delete[] pSmoothedDisparity1;
360  delete[] pSmoothedDisparity2;
361  delete[] pSmoothedDisparity3;
362  delete[] pSmoothedDisparity4;
363  }
364 
365 
366  // cut of the edges to avoid noise points
367  for (int i = 0; i < imageHeight; i++)
368  {
369  for (int j = 0; j < imageWidth; j++)
370  {
371  if (i < imageOverlapCutoffTop || i >= imageHeight - imageOverlapCutoffBottom || j < imageOverlapCutoffLeft || j > imageWidth - imageOverlapCutoffRight)
372  {
373  pSmoothedDisparity[i * imageWidth + j] = 0;
374  }
375  }
376  }
377 
378 
379 
380  // visualize
381  if (pDisparityImage)
382  {
383  CByteImage* pRectifiedDisparityImage = new CByteImage(imageWidth, imageHeight, CByteImage::eGrayScale);
384 
385  for (int i = 0; i < imageHeight; i++)
386  {
387  for (int j = 0; j < imageWidth; j++)
388  {
389  int nDisp = pSmoothedDisparity[i * imageWidth + j];
390  pRectifiedDisparityImage->pixels[i * imageWidth + j] = (nDisp > 255) ? 255 : nDisp;
391  }
392  }
393 
394  // get unrectified disparity image
395  ::ImageProcessor::Zero(pDisparityImage);
396  Vec2d vRectPos, vUnRectPos;
397  Mat3d mRectificationHomography = pStereoCalibration->rectificationHomographyLeft;
398 
399  for (int i = 0; i < imageHeight; i++)
400  {
401  for (int j = 0; j < imageWidth; j++)
402  {
403  vRectPos.x = j;
404  vRectPos.y = i;
405  Math2d::ApplyHomography(mRectificationHomography, vRectPos, vUnRectPos);
406 
407  if (0 <= vUnRectPos.y && vUnRectPos.y < imageHeight && 0 <= vUnRectPos.x && vUnRectPos.x < imageWidth)
408  {
409  pDisparityImage->pixels[(int)vUnRectPos.y * imageWidth + (int)vUnRectPos.x] = pRectifiedDisparityImage->pixels[i * imageWidth + j];
410  }
411  }
412  }
413 
414  FillHolesGray(pDisparityImage, pRectifiedDisparityImage, imageWidth, imageHeight, 1);
415  FillHolesGray(pRectifiedDisparityImage, pDisparityImage, imageWidth, imageHeight, 1);
416  delete pRectifiedDisparityImage;
417  }
418 
419 
420 
421  Vec2d vImgPointLeft, vImgPointRight;
422  Vec3d vPoint3D;
423  const float fDispMin = nDispMin;
424  const float fDispMax = nDispMax;
425  aPointsFromDisparity.width = ceil((float)imageWidth / (float)nDisparityPointDistance);
426  aPointsFromDisparity.height = ceil((float)imageHeight / (float)nDisparityPointDistance);
427  aPointsFromDisparity.resize(aPointsFromDisparity.width * aPointsFromDisparity.height);
428 
429  int index = 0;
430 
431  for (int i = 0; i < imageHeight; i += nDisparityPointDistance)
432  {
433  for (int j = 0; j < imageWidth; j += nDisparityPointDistance, index++)
434  {
435 
436  float fDisp = pSmoothedDisparity[i * imageWidth + j];
437 
438  if ((fDisp > fDispMin) && (fDisp < fDispMax))
439  {
440  vImgPointLeft.x = j;
441  vImgPointLeft.y = i;
442  vImgPointRight.x = j - fDisp;
443  vImgPointRight.y = i;
444 
445  pStereoCalibration->Calculate3DPoint(vImgPointLeft, vImgPointRight, vPoint3D, true, false);
446 
447  // create point descriptor
448  aPointsFromDisparity.points[index].x = vPoint3D.x;
449  aPointsFromDisparity.points[index].y = vPoint3D.y;
450  aPointsFromDisparity.points[index].z = vPoint3D.z;
451  aPointsFromDisparity.points[index].r = pRectifiedImageLeftColorGaussFiltered->pixels[3 * (i * imageWidth + j)];
452  aPointsFromDisparity.points[index].g = pRectifiedImageLeftColorGaussFiltered->pixels[3 * (i * imageWidth + j) + 1];
453  aPointsFromDisparity.points[index].b = pRectifiedImageLeftColorGaussFiltered->pixels[3 * (i * imageWidth + j) + 2];
454  aPointsFromDisparity.points[index].a = 1.0f;
455  }
456  // else if (false)
457  // {
458  // aPointsFromDisparity.points[index].x = std::numeric_limits<float>::quiet_NaN();
459  // aPointsFromDisparity.points[index].y = std::numeric_limits<float>::quiet_NaN();
460  // aPointsFromDisparity.points[index].z = std::numeric_limits<float>::quiet_NaN();
461  // aPointsFromDisparity.points[index].r = std::numeric_limits<float>::quiet_NaN();
462  // aPointsFromDisparity.points[index].g = std::numeric_limits<float>::quiet_NaN();
463  // aPointsFromDisparity.points[index].b = std::numeric_limits<float>::quiet_NaN();
464  // aPointsFromDisparity.points[index].a = std::numeric_limits<float>::quiet_NaN();
465  // }
466  else
467  {
468  aPointsFromDisparity.points[index].x = 0;
469  aPointsFromDisparity.points[index].y = 0;
470  aPointsFromDisparity.points[index].z = 0;
471  aPointsFromDisparity.points[index].r = 0;
472  aPointsFromDisparity.points[index].g = 0;
473  aPointsFromDisparity.points[index].b = 0;
474  aPointsFromDisparity.points[index].a = 0;
475  }
476  }
477  }
478 
479  delete pRectifiedImageLeftGrey;
480  delete pRectifiedImageRightGrey;
481  delete pRectifiedImageLeftGreyHalfsize;
482  delete pRectifiedImageRightGreyHalfsize;
483  delete pRectifiedImageLeftGreyQuartersize;
484  delete pRectifiedImageRightGreyQuartersize;
485  delete pRectifiedImageLeftColorGaussFiltered;
486  delete pStereoMatcher;
487  delete pStereoCalibrationCopy;
488  cvReleaseImageHeader(&pRectifiedIplImageLeft);
489  cvReleaseImageHeader(&pRectifiedIplImageRight);
490 
491  if (pSmoothedDisparity != pDisparities)
492  {
493  delete[] pSmoothedDisparity;
494  }
495 
496  delete[] pDisparities;
497  }
498 
499 
500 
501 
502  void FillHolesGray(const CByteImage* pInputImage, CByteImage* pOutputImage, const int imageWidth, const int imageHeight, const int nRadius)
503  {
504 
505  for (int i = 0; i < imageWidth * imageHeight; i++)
506  {
507  pOutputImage->pixels[i] = pInputImage->pixels[i];
508  }
509 
510  for (int i = nRadius; i < imageHeight - nRadius; i++)
511  {
512  for (int j = nRadius; j < imageWidth - nRadius; j++)
513  {
514  int nIndex = i * imageWidth + j;
515 
516  if (pInputImage->pixels[nIndex] == 0)
517  {
518  int nSum = 0;
519  int nNumPixels = 0;
520 
521  for (int l = -nRadius; l <= nRadius; l++)
522  {
523  for (int k = -nRadius; k <= nRadius; k++)
524  {
525  int nTempIndex = nIndex + l * imageWidth + k;
526 
527  if (pInputImage->pixels[nTempIndex] != 0)
528  {
529  nSum += pInputImage->pixels[nTempIndex];
530  nNumPixels++;
531  }
532  }
533  }
534 
535  if (nNumPixels > 0)
536  {
537  pOutputImage->pixels[nIndex] = nSum / nNumPixels;
538  }
539  }
540  }
541  }
542  }
543 
544 
545 
546 
547  void CalculateSmoothedDisparityImage(float* pInputDisparity, float* pSmoothedDisparity, const int imageWidth, const int imageHeight, const int nRadius)
548  {
549 
550  for (int i = 0; i < imageWidth * imageHeight; i++)
551  {
552  pSmoothedDisparity[i] = pInputDisparity[i];
553  }
554 
555  for (int i = nRadius; i < imageHeight - nRadius; i++)
556  {
557  for (int j = nRadius; j < imageWidth - nRadius; j++)
558  {
559  int nIndex = i * imageWidth + j;
560 
561  if (pInputDisparity[nIndex] != 0)
562  {
563  float fSum = 0;
564  int nNumPixels = 0;
565 
566  for (int l = -nRadius; l <= nRadius; l++)
567  {
568  for (int k = -nRadius; k <= nRadius; k++)
569  {
570  int nTempIndex = nIndex + l * imageWidth + k;
571 
572  if (pInputDisparity[nTempIndex] != 0)
573  {
574  fSum += pInputDisparity[nTempIndex];
575  nNumPixels++;
576  }
577  }
578  }
579 
580  pSmoothedDisparity[nIndex] = fSum / (float)nNumPixels;
581  }
582  }
583  }
584  }
585 
586 }
587 
visionx::depthfromstereo::FillHolesGray
void FillHolesGray(const CByteImage *pInputImage, CByteImage *pOutputImage, const int imageWidth, const int imageHeight, const int nRadius)
Definition: DepthFromStereo.cpp:502
index
uint8_t index
Definition: EtherCATFrame.h:59
GfxTL::Vec2d
VectorXD< 2, double > Vec2d
Definition: VectorXD.h:694
visionx::depthfromstereo::CalculateSmoothedDisparityImage
void CalculateSmoothedDisparityImage(float *pInputDisparity, float *pSmoothedDisparity, const int imageWidth, const int imageHeight, const int nRadius)
Definition: DepthFromStereo.cpp:547
visionx::depthfromstereo::GetPointsFromDisparity
void GetPointsFromDisparity(const CByteImage *pImageLeftColor, const CByteImage *pImageRightColor, const CByteImage *pImageLeftGrey, const CByteImage *pImageRightGrey, const int nDisparityPointDistance, pcl::PointCloud< pcl::PointXYZRGBA > &aPointsFromDisparity, CByteImage *pDisparityImage, const int imageWidth, const int imageHeight, CStereoCalibration *pStereoCalibration, bool imagesAreUndistorted, const bool smoothDisparities)
Definition: DepthFromStereo.cpp:67
GfxTL::Vec3d
VectorXD< 3, double > Vec3d
Definition: VectorXD.h:695
float
#define float
Definition: 16_Level.h:22
DepthFromStereo.h
visionx::depthfromstereo
Definition: DepthFromStereo.cpp:47